Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

277 lines
9.3 KiB

// CPerson.cpp: implementation of the CPerson class.
//
//////////////////////////////////////////////////////////////////////
#include "CPerson.h"
extern Bitmap *g_paBmDirtyBkg;
CPerson::CPerson()
{
m_flStepRadius=0.0f;
m_flStepWidth=0.0f;
m_eLastStep=eStepLeft;
m_paFoot=NULL;
m_paBlended=NULL;
m_paIndented=NULL;
m_nSnapshotSize=0;
m_nFootWidth=0;
m_nFootHeight=0;
ZeroMemory(&m_vLastStep,sizeof(m_vLastStep));
ZeroMemory(&m_rDesktop,sizeof(m_rDesktop));
}
CPerson::~CPerson()
{
Destroy();
}
void CPerson::Destroy()
{
if (m_paFoot!=NULL) {
delete m_paFoot;
m_paFoot=NULL;
}
if (m_paBlended!=NULL) {
delete m_paBlended;
m_paBlended=NULL;
}
if (m_paIndented!=NULL) {
delete m_paIndented;
m_paIndented=NULL;
}
}
BOOL CPerson::Init(HWND hWnd)
{
int nRand;
float flWidth;
float flHeight;
Destroy();
// Get desktop dimensions, top/left can be negative on multimon
GetClientRect(hWnd,&m_rDesktop);
flWidth=(float)m_rDesktop.right;
flHeight=(float)m_rDesktop.bottom;
m_rDesktop.top+=GetSystemMetrics(SM_YVIRTUALSCREEN);
m_rDesktop.bottom+=GetSystemMetrics(SM_YVIRTUALSCREEN);
m_rDesktop.left+=GetSystemMetrics(SM_XVIRTUALSCREEN);
m_rDesktop.right+=GetSystemMetrics(SM_XVIRTUALSCREEN);
// Randomly pick picture to use as foot
nRand=rand();
if (nRand<RAND_MAX/4) {
m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BAREFOOT));
}
else if (nRand<2*RAND_MAX/4) {
m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BOOT));
}
else if (nRand<3*RAND_MAX/4) {
m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BOOT2));
}
else {
m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_DOG));
}
if (m_paFoot==NULL) { return false; }
m_nFootWidth=m_paFoot->GetWidth();
m_nFootHeight=m_paFoot->GetHeight();
m_nSnapshotSize=(int)sqrt(m_nFootWidth*m_nFootWidth+m_nFootHeight*m_nFootHeight);
m_paBlended=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppARGB);
m_paIndented=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppARGB);
nRand=rand();
// Here we assume m_rDesktop.left<=0, m_rDesktop.top<=0, m_rDesktop.right>=0, m_rDesktop.bottom>=0
if (nRand<RAND_MAX/4) { // Start walking from the left side of desktop
m_vPos.X=(float)m_rDesktop.left;
m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
m_vVel.X=((float)rand()/(float)RAND_MAX)*5.0f;
m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
}
else if (nRand<2*RAND_MAX/4) { // Start walking from the right side of desktop
m_vPos.X=(float)m_rDesktop.right;
m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
m_vVel.X=((float)rand()/(float)RAND_MAX)*-5.0f;
m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
}
else if (nRand<3*RAND_MAX/4) { // Start walking from the top side of desktop
m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
m_vPos.Y=(float)m_rDesktop.top;
m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
m_vVel.Y=((float)rand()/(float)RAND_MAX)*5.0f;
}
else { // Start walking from the bottom side of desktop
m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
m_vPos.Y=(float)m_rDesktop.bottom;
m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
m_vVel.Y=((float)rand()/(float)RAND_MAX)*-5.0f;
}
m_vAcc.X=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
m_vAcc.Y=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
m_flStepRadius=((float)rand()/(float)RAND_MAX)*10.0f+45.0f;
m_flStepWidth=((float)rand()/(float)RAND_MAX)*10.0f+35.0f;
m_flVelMax=((float)rand()/(float)RAND_MAX)*10.0f+20.0f;
m_vLastStep=m_vPos;
return true;
}
BOOL CPerson::Move(Graphics *g)
// Returns true if moved on screen, false if moved outside screen
{
float flAngle;
float flOldAngle;
float flAngleDist;
float flMagnitude;
flOldAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
// Move position and update variables
m_vPos=m_vPos+m_vVel;
m_vVel=m_vVel+m_vAcc;
if (Magnitude(m_vVel)>m_flVelMax) {
m_vVel.X=Normalize(m_vVel).X*m_flVelMax;
m_vVel.Y=Normalize(m_vVel).Y*m_flVelMax;
}
// If outside desktop, return false (which will terminate the person)
if ((m_vPos.X<(float)m_rDesktop.left-m_flStepRadius) ||
(m_vPos.X>(float)m_rDesktop.right+m_flStepRadius) ||
(m_vPos.Y<(float)m_rDesktop.top-m_flStepRadius) ||
(m_vPos.Y>(float)m_rDesktop.bottom+m_flStepRadius)) {
return false;
}
// Make sure we don't step more than 45 degrees away from original direction
flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
flAngleDist=flAngle-flOldAngle;
while (flAngleDist<0.0f) { flAngleDist+=360.0f; }
while (flAngleDist>=360.0f) { flAngleDist-=360.0f; }
if ((flAngleDist>45.0f) && (flAngleDist<=180.0f)) {
flAngle=flOldAngle+45.0f;
flMagnitude=Magnitude(m_vVel);
m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*flMagnitude;
m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*flMagnitude;
}
else if ((flAngleDist<315.0f) && (flAngleDist>=180.0f)) {
flAngle=flOldAngle-45.0f;
flMagnitude=Magnitude(m_vVel);
m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*flMagnitude;
m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*flMagnitude;
}
// Is it time for another step?
if (Magnitude(m_vLastStep-m_vPos)>m_flStepRadius) {
DrawStep(g);
if (m_eLastStep==eStepLeft) {
m_eLastStep=eStepRight;
}
else {
m_eLastStep=eStepLeft;
}
// Took a step, update acceleration (random)
m_vLastStep=m_vPos;
m_vAcc.X=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
m_vAcc.Y=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
}
return true;
}
void CPerson::DrawStep(Graphics *g)
{
Rect rBitmapSize(0,0,m_nSnapshotSize,m_nSnapshotSize);
Point ptPixel;
Color Pixel;
int nAlpha;
Point ptCenter;
Point ptOffset;
float flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
Graphics *gBlended;
Graphics *gIndented;
int i,j;
// Find out center of where the foot will land
g->ResetTransform();
g->TranslateTransform(m_vPos.X,m_vPos.Y);
g->RotateTransform(flAngle+270.0f);
if (m_eLastStep==eStepLeft) {
g->TranslateTransform(-m_flStepWidth,0.0f);
}
else {
g->TranslateTransform(m_flStepWidth,0.0f);
}
ptCenter.X=m_nSnapshotSize/2;
ptCenter.Y=m_nSnapshotSize/2;
g->TransformPoints(CoordinateSpaceDevice,CoordinateSpaceWorld,&ptCenter,1);
// Take snapshot of larger area where foot will land
gBlended=new Graphics(m_paBlended);
gBlended->DrawImage(g_paBmDirtyBkg,0,0,ptCenter.X-m_nSnapshotSize/2-m_rDesktop.left,ptCenter.Y-m_nSnapshotSize/2-m_rDesktop.top,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
// Draw stamp (dirt) of foot on that snapshot
gBlended->SetSmoothingMode(SmoothingModeAntiAlias);
gBlended->SetInterpolationMode(InterpolationModeNearestNeighbor);//Bicubic);
gBlended->TranslateTransform((float)(m_nSnapshotSize/2),(float)(m_nSnapshotSize/2));
gBlended->RotateTransform(flAngle+270.0f);
if (m_eLastStep==eStepLeft) {
gBlended->ScaleTransform(-1,1);
}
gBlended->TranslateTransform(-(float)(m_nFootWidth/2),-(float)(m_nFootHeight/2));
gBlended->DrawImage(m_paFoot,0,0,0,0,m_paFoot->GetWidth(),m_paFoot->GetHeight(),UnitPixel);
gBlended->ResetTransform();
// Blit that snapshot to another temporary surface
gIndented=new Graphics(m_paIndented);
gIndented->SetCompositingMode(CompositingModeSourceCopy);
gIndented->DrawImage(m_paBlended,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
delete gBlended;
delete gIndented;
// Get the transform from snapshot to foot surface
g->ResetTransform();
g->TranslateTransform((float)(m_nFootWidth/2),(float)(m_nFootHeight/2));
if (m_eLastStep==eStepRight) {
g->ScaleTransform(-1,1);
}
g->RotateTransform(-flAngle-270.0f);
g->TranslateTransform(-(float)(m_nSnapshotSize/2),-(float)(m_nSnapshotSize/2));
// Create indent 3D look by bringing pixels closer to center depending on
// their distance relative to the alpha
for (i=0;i<m_nSnapshotSize;i++) {
for (j=0;j<m_nSnapshotSize;j++) {
ptPixel.X=i;
ptPixel.Y=j;
g->TransformPoints(CoordinateSpaceDevice,CoordinateSpaceWorld,&ptPixel,1);
// Find out if pixel is on the foot surface
if ((ptPixel.X>=0) && (ptPixel.X<(int)m_nFootWidth) &&
(ptPixel.Y>=0) && (ptPixel.Y<(int)m_nFootHeight)) {
// If it is, find out if the alpha is > 0
m_paFoot->GetPixel(ptPixel.X,ptPixel.Y,&Pixel);
nAlpha=Pixel.GetA();
if (nAlpha>0) {
// If it is, move that pixel closer to middle of foot depending on the distance and alpha
m_paBlended->GetPixel(i,j,&Pixel);
ptOffset.X=(int)((m_nSnapshotSize/2-i)*(1.0f-(float)nAlpha/1024.0f));
ptOffset.Y=(int)((m_nSnapshotSize/2-j)*(1.0f-(float)nAlpha/1024.0f));
m_paIndented->SetPixel(m_nSnapshotSize/2-ptOffset.X,m_nSnapshotSize/2-ptOffset.Y,Pixel);
}
}
}
}
// Draw the foot print result on the screen
g->ResetTransform();
g->TranslateTransform((float)(ptCenter.X-m_nSnapshotSize/2-m_rDesktop.left),(float)(ptCenter.Y-m_nSnapshotSize/2-m_rDesktop.top));
g->DrawImage(m_paIndented,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
// Draw the foot print result on the dirty background as well
g=new Graphics(g_paBmDirtyBkg);
g->TranslateTransform((float)(ptCenter.X-m_nSnapshotSize/2-m_rDesktop.left),(float)(ptCenter.Y-m_nSnapshotSize/2-m_rDesktop.top));
g->DrawImage(m_paIndented,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
delete g;
}