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

  1. // CPerson.cpp: implementation of the CPerson class.
  2. //
  3. //////////////////////////////////////////////////////////////////////
  4. #include "CPerson.h"
  5. extern Bitmap *g_paBmDirtyBkg;
  6. CPerson::CPerson()
  7. {
  8. m_flStepRadius=0.0f;
  9. m_flStepWidth=0.0f;
  10. m_eLastStep=eStepLeft;
  11. m_paFoot=NULL;
  12. m_paBlended=NULL;
  13. m_paIndented=NULL;
  14. m_nSnapshotSize=0;
  15. m_nFootWidth=0;
  16. m_nFootHeight=0;
  17. ZeroMemory(&m_vLastStep,sizeof(m_vLastStep));
  18. ZeroMemory(&m_rDesktop,sizeof(m_rDesktop));
  19. }
  20. CPerson::~CPerson()
  21. {
  22. Destroy();
  23. }
  24. void CPerson::Destroy()
  25. {
  26. if (m_paFoot!=NULL) {
  27. delete m_paFoot;
  28. m_paFoot=NULL;
  29. }
  30. if (m_paBlended!=NULL) {
  31. delete m_paBlended;
  32. m_paBlended=NULL;
  33. }
  34. if (m_paIndented!=NULL) {
  35. delete m_paIndented;
  36. m_paIndented=NULL;
  37. }
  38. }
  39. BOOL CPerson::Init(HWND hWnd)
  40. {
  41. int nRand;
  42. float flWidth;
  43. float flHeight;
  44. Destroy();
  45. // Get desktop dimensions, top/left can be negative on multimon
  46. GetClientRect(hWnd,&m_rDesktop);
  47. flWidth=(float)m_rDesktop.right;
  48. flHeight=(float)m_rDesktop.bottom;
  49. m_rDesktop.top+=GetSystemMetrics(SM_YVIRTUALSCREEN);
  50. m_rDesktop.bottom+=GetSystemMetrics(SM_YVIRTUALSCREEN);
  51. m_rDesktop.left+=GetSystemMetrics(SM_XVIRTUALSCREEN);
  52. m_rDesktop.right+=GetSystemMetrics(SM_XVIRTUALSCREEN);
  53. // Randomly pick picture to use as foot
  54. nRand=rand();
  55. if (nRand<RAND_MAX/4) {
  56. m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BAREFOOT));
  57. }
  58. else if (nRand<2*RAND_MAX/4) {
  59. m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BOOT));
  60. }
  61. else if (nRand<3*RAND_MAX/4) {
  62. m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_BOOT2));
  63. }
  64. else {
  65. m_paFoot=LoadTGAResource(MAKEINTRESOURCE(IDR_DOG));
  66. }
  67. if (m_paFoot==NULL) { return false; }
  68. m_nFootWidth=m_paFoot->GetWidth();
  69. m_nFootHeight=m_paFoot->GetHeight();
  70. m_nSnapshotSize=(int)sqrt(m_nFootWidth*m_nFootWidth+m_nFootHeight*m_nFootHeight);
  71. m_paBlended=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppARGB);
  72. m_paIndented=new Bitmap(m_nSnapshotSize,m_nSnapshotSize,PixelFormat32bppARGB);
  73. nRand=rand();
  74. // Here we assume m_rDesktop.left<=0, m_rDesktop.top<=0, m_rDesktop.right>=0, m_rDesktop.bottom>=0
  75. if (nRand<RAND_MAX/4) { // Start walking from the left side of desktop
  76. m_vPos.X=(float)m_rDesktop.left;
  77. m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
  78. m_vVel.X=((float)rand()/(float)RAND_MAX)*5.0f;
  79. m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  80. }
  81. else if (nRand<2*RAND_MAX/4) { // Start walking from the right side of desktop
  82. m_vPos.X=(float)m_rDesktop.right;
  83. m_vPos.Y=((float)rand()/(float)RAND_MAX)*flHeight+m_rDesktop.top;
  84. m_vVel.X=((float)rand()/(float)RAND_MAX)*-5.0f;
  85. m_vVel.Y=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  86. }
  87. else if (nRand<3*RAND_MAX/4) { // Start walking from the top side of desktop
  88. m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
  89. m_vPos.Y=(float)m_rDesktop.top;
  90. m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  91. m_vVel.Y=((float)rand()/(float)RAND_MAX)*5.0f;
  92. }
  93. else { // Start walking from the bottom side of desktop
  94. m_vPos.X=((float)rand()/(float)RAND_MAX)*flWidth+m_rDesktop.left;
  95. m_vPos.Y=(float)m_rDesktop.bottom;
  96. m_vVel.X=((float)rand()/(float)RAND_MAX)*10.0f-5.0f;
  97. m_vVel.Y=((float)rand()/(float)RAND_MAX)*-5.0f;
  98. }
  99. m_vAcc.X=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
  100. m_vAcc.Y=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
  101. m_flStepRadius=((float)rand()/(float)RAND_MAX)*10.0f+45.0f;
  102. m_flStepWidth=((float)rand()/(float)RAND_MAX)*10.0f+35.0f;
  103. m_flVelMax=((float)rand()/(float)RAND_MAX)*10.0f+20.0f;
  104. m_vLastStep=m_vPos;
  105. return true;
  106. }
  107. BOOL CPerson::Move(Graphics *g)
  108. // Returns true if moved on screen, false if moved outside screen
  109. {
  110. float flAngle;
  111. float flOldAngle;
  112. float flAngleDist;
  113. float flMagnitude;
  114. flOldAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  115. // Move position and update variables
  116. m_vPos=m_vPos+m_vVel;
  117. m_vVel=m_vVel+m_vAcc;
  118. if (Magnitude(m_vVel)>m_flVelMax) {
  119. m_vVel.X=Normalize(m_vVel).X*m_flVelMax;
  120. m_vVel.Y=Normalize(m_vVel).Y*m_flVelMax;
  121. }
  122. // If outside desktop, return false (which will terminate the person)
  123. if ((m_vPos.X<(float)m_rDesktop.left-m_flStepRadius) ||
  124. (m_vPos.X>(float)m_rDesktop.right+m_flStepRadius) ||
  125. (m_vPos.Y<(float)m_rDesktop.top-m_flStepRadius) ||
  126. (m_vPos.Y>(float)m_rDesktop.bottom+m_flStepRadius)) {
  127. return false;
  128. }
  129. // Make sure we don't step more than 45 degrees away from original direction
  130. flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  131. flAngleDist=flAngle-flOldAngle;
  132. while (flAngleDist<0.0f) { flAngleDist+=360.0f; }
  133. while (flAngleDist>=360.0f) { flAngleDist-=360.0f; }
  134. if ((flAngleDist>45.0f) && (flAngleDist<=180.0f)) {
  135. flAngle=flOldAngle+45.0f;
  136. flMagnitude=Magnitude(m_vVel);
  137. m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*flMagnitude;
  138. m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*flMagnitude;
  139. }
  140. else if ((flAngleDist<315.0f) && (flAngleDist>=180.0f)) {
  141. flAngle=flOldAngle-45.0f;
  142. flMagnitude=Magnitude(m_vVel);
  143. m_vVel.X=(float)cos(flAngle*3.1415f/180.0f)*flMagnitude;
  144. m_vVel.Y=(float)sin(flAngle*3.1415f/180.0f)*flMagnitude;
  145. }
  146. // Is it time for another step?
  147. if (Magnitude(m_vLastStep-m_vPos)>m_flStepRadius) {
  148. DrawStep(g);
  149. if (m_eLastStep==eStepLeft) {
  150. m_eLastStep=eStepRight;
  151. }
  152. else {
  153. m_eLastStep=eStepLeft;
  154. }
  155. // Took a step, update acceleration (random)
  156. m_vLastStep=m_vPos;
  157. m_vAcc.X=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
  158. m_vAcc.Y=((float)rand()/(float)RAND_MAX)*2.0f-1.0f;
  159. }
  160. return true;
  161. }
  162. void CPerson::DrawStep(Graphics *g)
  163. {
  164. Rect rBitmapSize(0,0,m_nSnapshotSize,m_nSnapshotSize);
  165. Point ptPixel;
  166. Color Pixel;
  167. int nAlpha;
  168. Point ptCenter;
  169. Point ptOffset;
  170. float flAngle=((float)atan2(m_vVel.Y,m_vVel.X)*180.0f/3.1415f);
  171. Graphics *gBlended;
  172. Graphics *gIndented;
  173. int i,j;
  174. // Find out center of where the foot will land
  175. g->ResetTransform();
  176. g->TranslateTransform(m_vPos.X,m_vPos.Y);
  177. g->RotateTransform(flAngle+270.0f);
  178. if (m_eLastStep==eStepLeft) {
  179. g->TranslateTransform(-m_flStepWidth,0.0f);
  180. }
  181. else {
  182. g->TranslateTransform(m_flStepWidth,0.0f);
  183. }
  184. ptCenter.X=m_nSnapshotSize/2;
  185. ptCenter.Y=m_nSnapshotSize/2;
  186. g->TransformPoints(CoordinateSpaceDevice,CoordinateSpaceWorld,&ptCenter,1);
  187. // Take snapshot of larger area where foot will land
  188. gBlended=new Graphics(m_paBlended);
  189. 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);
  190. // Draw stamp (dirt) of foot on that snapshot
  191. gBlended->SetSmoothingMode(SmoothingModeAntiAlias);
  192. gBlended->SetInterpolationMode(InterpolationModeNearestNeighbor);//Bicubic);
  193. gBlended->TranslateTransform((float)(m_nSnapshotSize/2),(float)(m_nSnapshotSize/2));
  194. gBlended->RotateTransform(flAngle+270.0f);
  195. if (m_eLastStep==eStepLeft) {
  196. gBlended->ScaleTransform(-1,1);
  197. }
  198. gBlended->TranslateTransform(-(float)(m_nFootWidth/2),-(float)(m_nFootHeight/2));
  199. gBlended->DrawImage(m_paFoot,0,0,0,0,m_paFoot->GetWidth(),m_paFoot->GetHeight(),UnitPixel);
  200. gBlended->ResetTransform();
  201. // Blit that snapshot to another temporary surface
  202. gIndented=new Graphics(m_paIndented);
  203. gIndented->SetCompositingMode(CompositingModeSourceCopy);
  204. gIndented->DrawImage(m_paBlended,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
  205. delete gBlended;
  206. delete gIndented;
  207. // Get the transform from snapshot to foot surface
  208. g->ResetTransform();
  209. g->TranslateTransform((float)(m_nFootWidth/2),(float)(m_nFootHeight/2));
  210. if (m_eLastStep==eStepRight) {
  211. g->ScaleTransform(-1,1);
  212. }
  213. g->RotateTransform(-flAngle-270.0f);
  214. g->TranslateTransform(-(float)(m_nSnapshotSize/2),-(float)(m_nSnapshotSize/2));
  215. // Create indent 3D look by bringing pixels closer to center depending on
  216. // their distance relative to the alpha
  217. for (i=0;i<m_nSnapshotSize;i++) {
  218. for (j=0;j<m_nSnapshotSize;j++) {
  219. ptPixel.X=i;
  220. ptPixel.Y=j;
  221. g->TransformPoints(CoordinateSpaceDevice,CoordinateSpaceWorld,&ptPixel,1);
  222. // Find out if pixel is on the foot surface
  223. if ((ptPixel.X>=0) && (ptPixel.X<(int)m_nFootWidth) &&
  224. (ptPixel.Y>=0) && (ptPixel.Y<(int)m_nFootHeight)) {
  225. // If it is, find out if the alpha is > 0
  226. m_paFoot->GetPixel(ptPixel.X,ptPixel.Y,&Pixel);
  227. nAlpha=Pixel.GetA();
  228. if (nAlpha>0) {
  229. // If it is, move that pixel closer to middle of foot depending on the distance and alpha
  230. m_paBlended->GetPixel(i,j,&Pixel);
  231. ptOffset.X=(int)((m_nSnapshotSize/2-i)*(1.0f-(float)nAlpha/1024.0f));
  232. ptOffset.Y=(int)((m_nSnapshotSize/2-j)*(1.0f-(float)nAlpha/1024.0f));
  233. m_paIndented->SetPixel(m_nSnapshotSize/2-ptOffset.X,m_nSnapshotSize/2-ptOffset.Y,Pixel);
  234. }
  235. }
  236. }
  237. }
  238. // Draw the foot print result on the screen
  239. g->ResetTransform();
  240. g->TranslateTransform((float)(ptCenter.X-m_nSnapshotSize/2-m_rDesktop.left),(float)(ptCenter.Y-m_nSnapshotSize/2-m_rDesktop.top));
  241. g->DrawImage(m_paIndented,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
  242. // Draw the foot print result on the dirty background as well
  243. g=new Graphics(g_paBmDirtyBkg);
  244. g->TranslateTransform((float)(ptCenter.X-m_nSnapshotSize/2-m_rDesktop.left),(float)(ptCenter.Y-m_nSnapshotSize/2-m_rDesktop.top));
  245. g->DrawImage(m_paIndented,rBitmapSize,0,0,m_nSnapshotSize,m_nSnapshotSize,UnitPixel);
  246. delete g;
  247. }