cRaceCar.cpp
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:29k
源码类别:

游戏

开发平台:

Visual C++

  1. // RACE X
  2. //
  3. // Written by Mauricio Teichmann Ritter
  4. //
  5. // Copyright (C) 2002, Brazil. All rights reserved.
  6. // 
  7. //
  8. #include "stdafx.h"
  9. #include "RaceX.h"
  10. #include "cRaceCar.h"
  11. #include ".applibckeyboard.h"
  12. #include <math.h>
  13. #include <stdio.h>
  14. #include "cRaceTrack.h"
  15. #define CARBOUND_POINTS 4
  16. //////////////////////////////////////////////////////////////////////
  17. // Construction/Destruction
  18. //////////////////////////////////////////////////////////////////////
  19. cRaceCar::cRaceCar()
  20. {
  21. m_iMaxSpeed = 270;
  22. m_iSpeed = 0;
  23. m_fDirectionY = -9;
  24. m_fDirectionX = 0;
  25. m_fIncrementY = 1;
  26. m_fIncrementX = 1;
  27. m_fBackupIncrementX = 1;
  28. m_fBackupIncrementY = 1;
  29. m_iBackupDistanceToNextCheckPoint = 0;
  30. m_fBackupDirectionY = -9;
  31. m_fBackupDirectionX = 0;
  32. m_iBackupAngle = 0;
  33. m_iAngle = 0;
  34. m_iCheckPoint = -1;
  35. m_iLaps = 0;
  36. m_pBound = (POINT*) malloc(sizeof(POINT) * CARBOUND_POINTS);
  37. m_lLastTurn = 0;
  38. m_lLastSpeedIncr = 0;
  39. m_iCarState = CARSTATE_OK;
  40. POINT tmpPoints[] = { {12,4},  {26,4},  {26,29}, {12,29}};
  41. m_pBound =(POINT*)  memcpy((void*) m_pBound,(void*) &tmpPoints, sizeof(POINT)* CARBOUND_POINTS);
  42. m_hcRaceCar.CreatePolygonBound(m_pBound, CARBOUND_POINTS);
  43. }
  44. cRaceCar::~cRaceCar()
  45. {
  46. free(m_pBound);
  47. m_hcRaceCar.Destroy();
  48. }
  49. void cRaceCar::SetPos(int iX, int iY)
  50. {
  51. m_fPosX = (float)iX;
  52. m_fPosY = (float)iY;
  53. }
  54. void cRaceCar::Create(int iColor)
  55. {
  56. m_sprCar.Create(GetMainApp()->m_hInst, iColor, 360, 160, RGB(0,0,0), 40, 40);
  57. m_hcRaceCar.CreateRectBound(40,40);
  58. iCrashTime = 0;
  59. m_iColor = iColor;
  60. m_pSound.Create(MAKEINTRESOURCE(IDR_ENGINE), DSBCAPS_CTRL3D | DSBCAPS_CTRLFREQUENCY, DS3DALG_HRTF_LIGHT);
  61. m_pSound.m_pSoundBuffer->SetCurrentPosition( 0 );
  62. m_pCrashSound.Create(MAKEINTRESOURCE(IDR_EXPLODE), DSBCAPS_CTRL3D, DS3DALG_HRTF_LIGHT);
  63. m_pCrashSound.m_pSoundBuffer->SetCurrentPosition( 0 );
  64. m_lCurrentTime = 0;
  65. m_bRemoteKeyboardStatus = 0;
  66. m_bLastSent_Speed = -1;
  67. m_bLastSent_Position = -1;
  68. m_bLastSent_CarState = -1;
  69. m_bLastSent_Laps = -1;
  70. m_bLastSent_Angle = -1;
  71. m_dwLastSent_LastLapTime = -1;
  72. m_nLastSent_PosX = -1;
  73. m_nLastSent_PosY = -1;
  74. }
  75. void cRaceCar::Destroy()
  76. {
  77. m_sprCar.Destroy();
  78. m_hcRaceCar.Destroy();
  79. m_sprCarExplode_0.Destroy();
  80. m_sprCarExplode_135.Destroy();
  81. m_sprCarExplode_180.Destroy();
  82. m_sprCarExplode_225.Destroy();
  83. m_sprCarExplode_270.Destroy();
  84. m_sprCarExplode_315.Destroy();
  85. m_sprCarExplode_45.Destroy();
  86. m_sprCarExplode_90.Destroy();
  87. m_pSound.Destroy();
  88. m_pCrashSound.Destroy();
  89. }
  90. void cRaceCar::Draw(int iViewX, int iViewY)
  91. {
  92. // Draw the car based on the current position in the map
  93. int iClipX = 0, iClipY = 0;
  94. int iClipWidth = 40, iClipHeight = 40;
  95. int iX = (int)m_fPosX - iViewX;
  96. int iY = (int) m_fPosY - iViewY;
  97. if((int)m_fPosX - iViewX > 640)
  98. return;
  99. if((int)m_fPosX - iViewX + 40 < 0)
  100. return;
  101. if((int) m_fPosY - iViewY > 460)
  102. return;
  103. if((int) m_fPosY - iViewY +40 < 0)
  104. return;
  105. if((int) m_fPosY - iViewY + 40 > 460)
  106. iClipHeight = 40-((int) m_fPosY - iViewY + 40 - 460);
  107. if((int) m_fPosX - iViewX + 40 > 640)
  108. iClipWidth = 40-((int) m_fPosX - iViewX + 40 - 640);
  109. if((int)m_fPosX - iViewX < 0)
  110. {
  111. iClipX = abs((int)m_fPosX - iViewX);
  112. iClipWidth -= iClipX;
  113. iX = 0;
  114. }
  115. if((int)m_fPosY - iViewY < 0)
  116. {
  117. iClipY = abs((int)m_fPosY - iViewY);
  118. iClipHeight -= iClipY;
  119. iY = 0;
  120. }
  121. if(m_iCarState == CARSTATE_CRASHED_WALL)
  122. {
  123. // If we crashed, play the explosion sprite
  124. if(m_iAngle == 0)
  125. m_sprCarExplode_0.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_0.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  126. if(m_iAngle > 0 && m_iAngle < 90)
  127. m_sprCarExplode_45.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_45.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  128. if(m_iAngle == 90)
  129. m_sprCarExplode_90.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_90.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  130. if(m_iAngle > 90 && m_iAngle < 180)
  131. m_sprCarExplode_135.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_135.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  132. if(m_iAngle == 180)
  133. m_sprCarExplode_180.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_180.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  134. if(m_iAngle > 180 && m_iAngle < 270)
  135. m_sprCarExplode_225.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_225.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  136. if(m_iAngle == 270)
  137. m_sprCarExplode_270.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_270.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  138. if(m_iAngle > 270 && m_iAngle < 360)
  139. m_sprCarExplode_315.Draw(GetMainApp()->m_pBackBuffer, iX, iY,m_sprCarExplode_315.IsEnd() ? FALSE : TRUE, iClipX, iClipY, iClipWidth, iClipHeight);
  140. }
  141. else
  142. {
  143. // otherwise, blit the normal car, in its current angle
  144. m_sprCar.Draw(GetMainApp()->m_pBackBuffer, iX, iY, FALSE, iClipX, iClipY, iClipWidth, iClipHeight);
  145. }
  146. // If you want to see the car bounding rect, uncomment this
  147. /*HDC hdc;
  148. GetMainApp()->m_pBackBuffer->GetDC(&hdc);
  149. OffsetRgn(m_hcRaceCar.hBoundingPoly, (int)m_fPosX - iViewX, (int) m_fPosY - iViewY);
  150. FillRgn(hdc, m_hcRaceCar.hBoundingPoly, (HBRUSH) GetStockObject(BLACK_BRUSH));
  151. OffsetRgn(m_hcRaceCar.hBoundingPoly, -1*((int)m_fPosX - iViewX), -1*((int) m_fPosY - iViewY));
  152. GetMainApp()->m_pBackBuffer->ReleaseDC(hdc);
  153. */
  154. }
  155. void cRaceCar::Process(void* pTrack)
  156. {
  157. #define SPEEDXTURN 70
  158. #define TURN_TIME  45
  159. #define RAISESPEED_TIME 85
  160. #define MAX_SPEED_FOR_CURVE 180
  161. #define MAX_SPEED_FOR_IDLE  200
  162. //升高速度量从而降低游戏速度
  163. //降低速度量从而使游戏更快速
  164. #define _SPEED_FACTOR_ 17
  165. int iX, iY;
  166. static long lLastMessage;
  167. //iTurnCar = TURN_RIGHT;
  168. cRaceTrack* theTrack = (cRaceTrack*)pTrack;
  169. cKeyboard pKeyboard;
  170. //如果赛车不在正常状态
  171. if(m_iCarState != CARSTATE_OK)
  172. {
  173. //赛车发生碰撞,需要调入爆炸的声音
  174. if(iCrashTime == 0)
  175. {
  176. iCrashTime = GetTickCount();
  177. if(m_iCarState != CARSTATE_RACECOMPLETED)
  178. m_pCrashSound.Play();
  179. }
  180. //爆炸
  181. Crashed();
  182. if(m_iCarState == CARSTATE_RACECOMPLETED)
  183. {
  184. }
  185. else
  186. {
  187. if(GetTickCount() - iCrashTime > 2500)
  188. {
  189. // Crash time elapse, return the car to the backuped position
  190. m_sprCarExplode_0.Destroy();
  191. m_sprCarExplode_135.Destroy();
  192. m_sprCarExplode_180.Destroy();
  193. m_sprCarExplode_225.Destroy();
  194. m_sprCarExplode_270.Destroy();
  195. m_sprCarExplode_315.Destroy();
  196. m_sprCarExplode_45.Destroy();
  197. m_sprCarExplode_90.Destroy();
  198. if( (GetRaceXApp()->m_bIsMultiplayer == TRUE && GetRaceXApp()->GetMultiplayer()->IsHosting()) ||
  199. GetRaceXApp()->m_bIsMultiplayer == FALSE)
  200. {
  201. m_fDirectionX = m_fBackupDirectionX;
  202. m_fDirectionY = m_fBackupDirectionY;
  203. m_fIncrementX = m_fBackupIncrementX;
  204. m_fIncrementY = m_fBackupIncrementY;
  205. m_iDistanceToNextCheckPoint = m_iBackupDistanceToNextCheckPoint;
  206. iTurnCar = iBackupTurnCar;
  207. m_iAngle = m_iBackupAngle;
  208. m_fPosX = m_fBackupPosX;
  209. m_fPosY = m_fBackupPosY;
  210. m_sprCar.m_iAbsolutePosition = m_iBackupSprite;
  211. if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ2 ||
  212.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ0P3 ||
  213.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ0P2)
  214. {
  215. m_fPosY+=10;
  216. }
  217. if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ3||
  218.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P3 ||
  219.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P2)
  220. {
  221. m_fPosY-=10;
  222. }
  223. if(theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_ROADQ0 ||
  224.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P1 ||
  225.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ2P2)
  226. {
  227. m_fPosX+=10;
  228. }
  229. if(theTrack->GetRoadType((int)m_fPosX+10,(int) m_fPosY+10) == ID_ROADTYPE_ROADQ1 ||
  230.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ3P1 ||
  231.    theTrack->GetRoadType((int)m_fPosX+10, (int)m_fPosY+10) == ID_ROADTYPE_MEDIUMCURVEQ3P2)
  232. {
  233. m_fPosX-=10;
  234. }
  235. RotateBound(m_iAngle);
  236. iX = 0;
  237. iY = 0;
  238. m_iDistanceToNextCheckPoint = 999999999;
  239. do
  240. {
  241. iX = iX / 40;
  242. iY = iY / 40;
  243. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  244. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  245. {
  246. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  247. }
  248. if(iX != -1)
  249. iX += 40;
  250. }while(iX>0);
  251. for(int i=0;i<theTrack->GetNumberOfCars();i++)
  252. {
  253. if(m_bID != theTrack->m_pRaceCars[i]->GetID())
  254. {
  255. int iSrcX, iSrcY;
  256. theTrack->m_pRaceCars[i]->GetPos(&iSrcX, &iSrcY);
  257. if(m_hcRaceCar.HaveHitted(&theTrack->m_pRaceCars[i]->m_hcRaceCar, m_fPosX, m_fPosY, iSrcX, iSrcY) == FALSE)
  258. {
  259. m_iCarState = CARSTATE_OK;
  260. iCrashTime = 0;
  261. }
  262. }
  263. }
  264. }
  265. }
  266. }
  267. }
  268. else
  269. {
  270. int i;
  271. iCrashTime = 0;
  272. //如果赛车由人控制,则读取键盘值,判断用户意图
  273. if(m_iControlType == CTRL_USER)
  274. {
  275. if(pKeyboard.CheckKey(DIK_RIGHT))
  276. {
  277. TurnCarRight();
  278. }
  279. if(pKeyboard.CheckKey(DIK_LEFT))
  280. {
  281. TurnCarLeft();
  282. }
  283. if(pKeyboard.CheckKey(DIK_DOWN))
  284. {
  285. BreakCar();
  286. }
  287. if(pKeyboard.CheckKey(DIK_UP))
  288. {
  289. Accelerate();
  290. }
  291. else
  292. {
  293. Idle();
  294. }
  295. }/*USER CONTROL*/
  296. //远端用户,发送键盘消息到主机
  297. if(m_iControlType == CTRL_NETWORK_REMOTE &&
  298. GetRaceXApp()->m_bIsMultiplayer == TRUE &&
  299. GetRaceXApp()->GetMultiplayer()->IsHosting() )
  300. {
  301. // 键盘状态是一个字节变量,设置某些位从而判断哪个键被按下
  302. if(m_bRemoteKeyboardStatus & 0x01)
  303. {
  304. TurnCarRight();
  305. }
  306. if(m_bRemoteKeyboardStatus & 0x02)
  307. {
  308. TurnCarLeft();
  309. }
  310. if(m_bRemoteKeyboardStatus & 0x04)
  311. {
  312. BreakCar();
  313. }
  314. if(m_bRemoteKeyboardStatus & 0x08)
  315. {
  316. Accelerate();
  317. }
  318. else
  319. {
  320. Idle();
  321. }
  322. }
  323. //电脑控制的赛车
  324. if(m_iControlType == CTRL_COMPUTER)
  325. {
  326. BOOL bCanBrake = FALSE;
  327. //如果当前地图中贴片的角度和当前赛车的行进角度不一样,则需调整赛车的行进角度
  328. if(m_iAngle != theTrack->GetAngle(m_fPosX+20, m_fPosY+20) &&
  329.    theTrack->GetAngle(m_fPosX+20, m_fPosY+20) != 370)
  330. {
  331. int iValue1 = (360-m_iAngle)+theTrack->GetAngle(m_fPosX+20, m_fPosY+20);
  332. if(iValue1 > 360)
  333. {
  334. iValue1 = iValue1 % 360;
  335. }
  336. int iValue2 = (m_iAngle-theTrack->GetAngle(m_fPosX+20, m_fPosY+20));
  337. if(iValue2 < 0)
  338. {
  339. iValue2+=360;
  340. }
  341. if(iValue1 < iValue2)
  342. {
  343. TurnCarRight();
  344. bCanBrake = TRUE;
  345. }
  346. else
  347. {
  348. TurnCarLeft();
  349. bCanBrake = TRUE;
  350. }
  351. }
  352. //如果速度过快,则刹车
  353. if(m_iSpeed > 270)
  354. {
  355. if(theTrack->CarHittedRoad(this, (int) m_fPosX+20+(m_iSpeed * (m_fDirectionX/9.0f)), (int) m_fPosY+20+ (m_iSpeed * (m_fDirectionY/9.0f))) == TRUE)
  356. BreakCar();
  357. }
  358. if(bCanBrake == TRUE)
  359. {
  360. for(i=m_iSpeed-30;i>=0;i-=40)
  361. {
  362. if(theTrack->CarHittedRoad(this,(int)m_fPosX+20+(i*(m_fDirectionX/9.0f)),(int)m_fPosY+20+ (i * (m_fDirectionY/9.0f))) == TRUE)
  363. {
  364. BreakCar();
  365. }
  366. }
  367. }
  368. Accelerate();
  369. }/*COMPUTER CONTROL*/
  370. }
  371. //如果赛车被一个远端用户控制
  372. if(m_iControlType == CTRL_NETWORK_LOCAL &&
  373. GetRaceXApp()->m_bIsMultiplayer == TRUE &&
  374. !GetRaceXApp()->GetMultiplayer()->IsHosting() )
  375. {
  376. m_bRemoteKeyboardStatus = 0;
  377. //从远端读取键盘状态值
  378. if(pKeyboard.CheckKey(DIK_RIGHT))
  379. {
  380. m_bRemoteKeyboardStatus |= 0x01;
  381. }
  382. if(pKeyboard.CheckKey(DIK_LEFT))
  383. {
  384. m_bRemoteKeyboardStatus |= 0x02;
  385. }
  386. if(pKeyboard.CheckKey(DIK_DOWN))
  387. {
  388. m_bRemoteKeyboardStatus |= 0x04;
  389. }
  390. if(pKeyboard.CheckKey(DIK_UP))
  391. {
  392. m_bRemoteKeyboardStatus |= 0x08;
  393. }
  394. if(GetRaceXApp()->m_bSendKeyboard == TRUE || GetTickCount()-lLastMessage > 100)
  395. {
  396. GetRaceXApp()->GetMultiplayer()->SendTo(GetRaceXApp()->GetMultiplayer()->GetHost(), MSG_KEYBOARD_STATUS, &m_bRemoteKeyboardStatus, 1, 0/*DPNSEND_SYNC*/);
  397. GetRaceXApp()->m_bSendKeyboard = FALSE;
  398. lLastMessage = GetTickCount();
  399. }
  400. }
  401. if((GetRaceXApp()->m_bIsMultiplayer==TRUE&&GetRaceXApp()->GetMultiplayer()->IsHosting())||
  402. GetRaceXApp()->m_bIsMultiplayer == FALSE)
  403. {
  404. //处理完用户/电脑/网络输入后,重新定位赛车位置
  405. m_fPosY = m_fPosY + ((float)m_fDirectionY / 9.0f) * ((float)m_iSpeed / _SPEED_FACTOR_);
  406. m_fPosX = m_fPosX + ((float)m_fDirectionX / 9.0f) * ((float)m_iSpeed / _SPEED_FACTOR_);
  407. // Track control goes here
  408. // Check if we are passing throught a checkpoint or how far we are from thw
  409. // next check point
  410. if(m_iCarState == CARSTATE_OK)
  411. {
  412. if(m_iCheckPoint == -1)
  413. {
  414. if(theTrack->GetCheckPoint((int)m_fPosX+10,(int) m_fPosY+18) == 1)
  415. {
  416. m_iCheckPoint = 1;
  417. m_lCurrentTime = GetTickCount();
  418. iX = 0;
  419. iY = 0;
  420. m_iDistanceToNextCheckPoint = 999999999;
  421. do
  422. {
  423. iX = iX / 40;
  424. iY = iY / 40;
  425. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  426. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  427. {
  428. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  429. }
  430. if(iX != -1)
  431. iX += 40;
  432. }while(iX>0);
  433. }
  434. }
  435. else
  436. {
  437. if(theTrack->GetCheckPoint((int)m_fPosX+10, (int)m_fPosY+18) <= m_iCheckPoint)
  438. {
  439. if(theTrack->GetCheckPoint((int)m_fPosX+10, (int)m_fPosY+18) == 1 &&
  440.    m_iCheckPoint == theTrack->GetMaxCheckPoint())
  441. {
  442. m_vcLapTimes.push_back(GetTickCount()-m_lCurrentTime);
  443. m_lCurrentTime = GetTickCount();
  444. m_iCheckPoint = 1;
  445. iX = 0;
  446. iY = 0;
  447. m_iDistanceToNextCheckPoint = 999999999;
  448. do
  449. {
  450. iX = iX / 40;
  451. iY = iY / 40;
  452. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  453. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  454. {
  455. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  456. }
  457. if(iX != -1)
  458. iX += 40;
  459. }while(iX>0);
  460. m_iLaps++;
  461. if(m_iLaps == theTrack->GetNumberOfLaps())
  462. {
  463. m_iCarState = CARSTATE_RACECOMPLETED;
  464. }
  465. else
  466. {
  467. if(m_iControlType == CTRL_USER)
  468. theTrack->m_sndSemaphore.Play();
  469. }
  470. }
  471. else
  472. {
  473. iX = 0;
  474. iY = 0;
  475. m_iDistanceToNextCheckPoint = 999999999;
  476. do
  477. {
  478. iX = iX / 40;
  479. iY = iY / 40;
  480. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  481. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  482. {
  483. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  484. }
  485. if(iX != -1)
  486. iX += 40;
  487. }while(iX>0);
  488. }
  489. }
  490. else
  491. {
  492. if(theTrack->GetCheckPoint((int)m_fPosX+10, (int)m_fPosY+18) == m_iCheckPoint+1)
  493. {
  494. m_iCheckPoint++;
  495. iX = 0;
  496. iY = 0;
  497. m_iDistanceToNextCheckPoint = 999999999;
  498. do
  499. {
  500. iX = iX / 40;
  501. iY = iY / 40;
  502. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  503. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  504. {
  505. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  506. }
  507. if(iX != -1)
  508. iX += 40;
  509. }while(iX>0);
  510. m_fBackupDirectionX = m_fDirectionX;
  511. m_iBackupDistanceToNextCheckPoint = m_iDistanceToNextCheckPoint;
  512. m_fBackupDirectionY = m_fDirectionY;
  513. m_fBackupIncrementX = m_fIncrementX;
  514. m_fBackupIncrementY = m_fIncrementY;
  515. m_iBackupAngle = m_iAngle;
  516. m_fBackupPosX = m_fPosX;
  517. m_fBackupPosY = m_fPosY;
  518. m_iBackupSprite = m_sprCar.m_iAbsolutePosition;
  519. iBackupTurnCar = iTurnCar;
  520. }
  521. else
  522. {
  523. iX = 0;
  524. iY = 0;
  525. m_iDistanceToNextCheckPoint = 999999999;
  526. do
  527. {
  528. iX = iX / 40;
  529. iY = iY / 40;
  530. theTrack->GetCheckPointPosition(&iX, &iY, m_iCheckPoint+1);
  531. if(m_iDistanceToNextCheckPoint > (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)) ))
  532. {
  533. m_iDistanceToNextCheckPoint = (int) sqrt( ((m_fPosX - iX)*(m_fPosX - iX)) + ((m_fPosY - iY)*(m_fPosY - iY)));
  534. }
  535. if(iX != -1)
  536. iX += 40;
  537. }while(iX>0);
  538. }
  539. }
  540. }
  541. }
  542. }
  543. if(m_iControlType != CTRL_USER && m_iControlType != CTRL_NETWORK_LOCAL)
  544. {
  545. m_pSound.SetPosition(m_fPosX/200.0f, m_fPosY/200.0f, 0.0f);
  546. m_pCrashSound.SetPosition(m_fPosX/200.0f, m_fPosY/200.0f, 0.0f);
  547. //m_pSound.SetVelocity((float)m_iSpeed/27,(float)m_iSpeed/27, 0.0f);
  548. }
  549. DWORD dwFreq = 0;
  550. if(GetSpeed() != 0)
  551. {
  552. m_pSound.Play(0, DSBPLAY_LOOPING);
  553. dwFreq = 22050 + (GetSpeed() * 50);
  554. m_pSound.m_pSoundBuffer->SetFrequency(dwFreq);
  555. }
  556. else
  557. {
  558. m_pSound.Stop();
  559. }
  560. if(m_iControlType == CTRL_USER || m_iControlType == CTRL_NETWORK_LOCAL)
  561. {
  562. cSoundInterface pSInterface;
  563. pSInterface.SetListernerPosition( m_fPosX/200.0f, (m_fPosY/200.0f), 0.0f);
  564. }
  565. }
  566. void cRaceCar::GetPos(int *iX, int *iY)
  567. {
  568. *iX = (int) m_fPosX;
  569. *iY = (int) m_fPosY;
  570. }
  571. void cRaceCar::RotateBound(int iAngle)
  572. {
  573. #define PI 3.141592654f
  574. m_hcRaceCar.Destroy();
  575. POINT *pFirstPoint;
  576. POINT *pPoints;
  577. pPoints = (POINT*) malloc(CARBOUND_POINTS * sizeof(POINT));
  578. memcpy(pPoints, m_pBound,  CARBOUND_POINTS * sizeof(POINT));
  579. pFirstPoint = pPoints;
  580. // Move the vertices so that we made the center of the car the 0,0 axis
  581. for(int i=0;i<CARBOUND_POINTS;i++)
  582. {
  583. pPoints->x = pPoints->x - 19;
  584. pPoints->y = pPoints->y - 18;
  585. pPoints++;
  586. }
  587. // Rotate the points
  588. pPoints = pFirstPoint;
  589. for(i=0;i<CARBOUND_POINTS;i++)
  590. {
  591. double x,y;
  592. x = (cos(PI * (double)iAngle / 180.0) * (double)pPoints->x - sin(PI * (double)iAngle / 180.0) * (double) pPoints->y);
  593. y = (sin(PI * (double)iAngle / 180.0) * (double)pPoints->x + cos(PI * (double)iAngle / 180.0) * (double) pPoints->y);
  594. //x+=0.5;
  595. //y+=0.5;
  596. pPoints->x = (int)x;
  597. pPoints->y = (int)y;
  598. pPoints++;
  599. }
  600. pPoints = pFirstPoint;
  601. // Move the vertices back to the correct position
  602. for(i=0;i<CARBOUND_POINTS;i++)
  603. {
  604. pPoints->x = pPoints->x + 19;
  605. pPoints->y = pPoints->y + 18;
  606. pPoints++;
  607. }
  608. // Restore the original pointer
  609. pPoints = pFirstPoint;
  610. m_hcRaceCar.CreatePolygonBound(pPoints, CARBOUND_POINTS);
  611. free(pPoints);
  612. }
  613. void cRaceCar::SetLastCheckPoint(int iLastCheckPoint)
  614. {
  615. m_iCheckPoint = iLastCheckPoint;
  616. }
  617. int cRaceCar::GetLastCheckPoint()
  618. {
  619. return m_iCheckPoint;
  620. }
  621. int cRaceCar::GetSpeed()
  622. {
  623. return m_iSpeed;
  624. }
  625. void cRaceCar::SetControlType(int iType)
  626. {
  627. m_iControlType = iType;
  628. if(m_iControlType == CTRL_USER || m_iControlType == CTRL_NETWORK_LOCAL)
  629. {
  630. m_pSound.Create(MAKEINTRESOURCE(IDR_ENGINE), DSBCAPS_CTRLFREQUENCY, DS3DALG_DEFAULT);
  631. m_pCrashSound.Create(MAKEINTRESOURCE(IDR_EXPLODE), DSBCAPS_CTRLFREQUENCY, DS3DALG_DEFAULT);
  632. }
  633. }
  634. int cRaceCar::GetControlType()
  635. {
  636. return m_iControlType;
  637. }
  638. void cRaceCar::TurnCarLeft()
  639. {
  640. if(GetTickCount() - m_lLastTurn > TURN_TIME)
  641. {
  642. if(m_fDirectionY == 9)
  643. {
  644. m_fIncrementY = 1;
  645. }
  646. if(m_fDirectionY == -9)
  647. {
  648. m_fIncrementY = -1;
  649. }
  650. if(m_fDirectionX == 9)
  651. {
  652. m_fIncrementX = 1;
  653. }
  654. if(m_fDirectionX == -9)
  655. {
  656. m_fIncrementX = -1;
  657. }
  658. m_fDirectionX -= m_fIncrementX;
  659. m_fDirectionY -= m_fIncrementY;
  660. m_sprCar.Previous();
  661. m_iAngle -= 10;
  662. if(m_iAngle < 0)
  663. m_iAngle = 360 + m_iAngle;
  664. RotateBound(m_iAngle);
  665. m_lLastTurn = GetTickCount();
  666. }
  667. }
  668. void cRaceCar::TurnCarRight()
  669. {
  670. if(GetTickCount() - m_lLastTurn > TURN_TIME)
  671. {
  672. if(m_fDirectionY == 9)
  673. {
  674. m_fIncrementY = -1;
  675. }
  676. if(m_fDirectionY == -9)
  677. {
  678. m_fIncrementY = 1;
  679. }
  680. if(m_fDirectionX == 9)
  681. {
  682. m_fIncrementX = -1;
  683. }
  684. if(m_fDirectionX == -9)
  685. {
  686. m_fIncrementX = 1;
  687. }
  688. m_fDirectionX += m_fIncrementX;
  689. m_fDirectionY += m_fIncrementY;
  690. m_sprCar.Next();
  691. m_iAngle += 10;
  692. if(m_iAngle >= 360)
  693. m_iAngle = (m_iAngle - 360);
  694. RotateBound(m_iAngle);
  695. m_lLastTurn = GetTickCount();
  696. }
  697. }
  698. void cRaceCar::Accelerate()
  699. {
  700. // If its time to accelerate
  701. if(GetTickCount() - m_lLastSpeedIncr > (UINT)RAISESPEED_TIME )
  702. {
  703. m_iSpeed=m_iSpeed+5;
  704. // If the car is controlled by the computer and the level is above hard, make
  705. // the cars accelerate faster
  706. if(GetRaceXApp()->GetDifficultyLevel() > 40 && m_iControlType == CTRL_COMPUTER )
  707. {
  708. m_iSpeed += ((GetRaceXApp()->GetDifficultyLevel()-50)/10);
  709. }
  710. // If we haven磘 rechead the maximum speed, raise it up
  711. if(m_iSpeed > m_iMaxSpeed - (m_iControlType == CTRL_COMPUTER ? 40 - GetRaceXApp()->GetDifficultyLevel(): 0) )
  712. {
  713. m_iSpeed = m_iMaxSpeed - (m_iControlType == CTRL_COMPUTER ? 40 - GetRaceXApp()->GetDifficultyLevel() : 0);
  714. }
  715. m_lLastSpeedIncr = GetTickCount();
  716. }
  717. }
  718. void cRaceCar::HitCar()
  719. {
  720. // Car hitted something
  721. // Apply heat behavior in car (decrease speed and maintain angle)
  722. m_iSpeed=m_iSpeed-40;
  723. m_lLastSpeedIncr = GetTickCount();
  724. if(m_iSpeed < 0)
  725. {
  726. m_iSpeed = 0;
  727. }
  728. }
  729. void cRaceCar::BreakCar()
  730. {
  731. // Break car
  732. if(GetTickCount() - m_lLastSpeedIncr > (UINT)RAISESPEED_TIME )
  733. {
  734. m_iSpeed=m_iSpeed-20;
  735. if(m_iSpeed < 0)
  736. {
  737. m_iSpeed = 0;
  738. }
  739. m_lLastSpeedIncr = GetTickCount();
  740. }
  741. }
  742. void cRaceCar::Idle()
  743. {
  744. // User is not pressing anything
  745. if(GetTickCount() - m_lLastSpeedIncr > (UINT)RAISESPEED_TIME )
  746. {
  747. m_iSpeed=m_iSpeed-5;
  748. if(m_iSpeed < 0)
  749. {
  750. m_iSpeed = 0;
  751. }
  752. m_lLastSpeedIncr = GetTickCount();
  753. }
  754. }
  755. void cRaceCar::SetCarState(int iState)
  756. {
  757. m_iCarState = iState;
  758. // If we set the car to the crash state, we should
  759. // load the crash tiles, depending on the car color
  760. if(m_iCarState == CARSTATE_CRASHED_WALL)
  761. {
  762. switch(m_iColor)
  763. {
  764. case IDB_CAR_GREEN:
  765. if(m_iAngle == 0)
  766. m_sprCarExplode_0.Create(GetMainApp()->m_hInst, IDB_EXPLODE_0_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  767. if(m_iAngle > 0 && m_iAngle < 90)
  768. m_sprCarExplode_45.Create(GetMainApp()->m_hInst, IDB_EXPLODE_45_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  769. if(m_iAngle == 90)
  770. m_sprCarExplode_90.Create(GetMainApp()->m_hInst, IDB_EXPLODE_90_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  771. if(m_iAngle > 90 && m_iAngle < 180)
  772. m_sprCarExplode_135.Create(GetMainApp()->m_hInst, IDB_EXPLODE_135_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  773. if(m_iAngle == 180)
  774. m_sprCarExplode_180.Create(GetMainApp()->m_hInst, IDB_EXPLODE_180_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  775. if(m_iAngle > 180 && m_iAngle < 270)
  776. m_sprCarExplode_225.Create(GetMainApp()->m_hInst, IDB_EXPLODE_225_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  777. if(m_iAngle == 270)
  778. m_sprCarExplode_270.Create(GetMainApp()->m_hInst, IDB_EXPLODE_270_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  779. if(m_iAngle > 270 && m_iAngle < 360)
  780. m_sprCarExplode_315.Create(GetMainApp()->m_hInst, IDB_EXPLODE_315_GREEN, 320, 200, RGB(0,0,0), 40, 40);
  781. break;
  782. case IDB_CAR_RED:
  783. if(m_iAngle == 0)
  784. m_sprCarExplode_0.Create(GetMainApp()->m_hInst, IDB_EXPLODE_0_RED, 320, 200, RGB(0,0,0), 40, 40);
  785. if(m_iAngle > 0 && m_iAngle < 90)
  786. m_sprCarExplode_45.Create(GetMainApp()->m_hInst, IDB_EXPLODE_45_RED, 320, 200, RGB(0,0,0), 40, 40);
  787. if(m_iAngle == 90)
  788. m_sprCarExplode_90.Create(GetMainApp()->m_hInst, IDB_EXPLODE_90_RED, 320, 200, RGB(0,0,0), 40, 40);
  789. if(m_iAngle > 90 && m_iAngle < 180)
  790. m_sprCarExplode_135.Create(GetMainApp()->m_hInst, IDB_EXPLODE_135_RED, 320, 200, RGB(0,0,0), 40, 40);
  791. if(m_iAngle == 180)
  792. m_sprCarExplode_180.Create(GetMainApp()->m_hInst, IDB_EXPLODE_180_RED, 320, 200, RGB(0,0,0), 40, 40);
  793. if(m_iAngle > 180 && m_iAngle < 270)
  794. m_sprCarExplode_225.Create(GetMainApp()->m_hInst, IDB_EXPLODE_225_RED, 320, 200, RGB(0,0,0), 40, 40);
  795. if(m_iAngle == 270)
  796. m_sprCarExplode_270.Create(GetMainApp()->m_hInst, IDB_EXPLODE_270_RED, 320, 200, RGB(0,0,0), 40, 40);
  797. if(m_iAngle > 270 && m_iAngle < 360)
  798. m_sprCarExplode_315.Create(GetMainApp()->m_hInst, IDB_EXPLODE_315_RED, 320, 200, RGB(0,0,0), 40, 40);
  799. break;
  800. case IDB_CAR_YEALLOW:
  801. if(m_iAngle == 0)
  802. m_sprCarExplode_0.Create(GetMainApp()->m_hInst, IDB_EXPLODE_0_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  803. if(m_iAngle > 0 && m_iAngle < 90)
  804. m_sprCarExplode_45.Create(GetMainApp()->m_hInst, IDB_EXPLODE_45_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  805. if(m_iAngle == 90)
  806. m_sprCarExplode_90.Create(GetMainApp()->m_hInst, IDB_EXPLODE_90_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  807. if(m_iAngle > 90 && m_iAngle < 180)
  808. m_sprCarExplode_135.Create(GetMainApp()->m_hInst, IDB_EXPLODE_135_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  809. if(m_iAngle == 180)
  810. m_sprCarExplode_180.Create(GetMainApp()->m_hInst, IDB_EXPLODE_180_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  811. if(m_iAngle > 180 && m_iAngle < 270)
  812. m_sprCarExplode_225.Create(GetMainApp()->m_hInst, IDB_EXPLODE_225_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  813. if(m_iAngle == 270)
  814. m_sprCarExplode_270.Create(GetMainApp()->m_hInst, IDB_EXPLODE_270_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  815. if(m_iAngle > 270 && m_iAngle < 360)
  816. m_sprCarExplode_315.Create(GetMainApp()->m_hInst, IDB_EXPLODE_315_YEALLOW, 320, 200, RGB(0,0,0), 40, 40);
  817. break;
  818. case IDB_CAR_BLUE:
  819. if(m_iAngle == 0)
  820. m_sprCarExplode_0.Create(GetMainApp()->m_hInst, IDB_EXPLODE_0_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  821. if(m_iAngle > 0 && m_iAngle < 90)
  822. m_sprCarExplode_45.Create(GetMainApp()->m_hInst, IDB_EXPLODE_45_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  823. if(m_iAngle == 90)
  824. m_sprCarExplode_90.Create(GetMainApp()->m_hInst, IDB_EXPLODE_90_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  825. if(m_iAngle > 90 && m_iAngle < 180)
  826. m_sprCarExplode_135.Create(GetMainApp()->m_hInst, IDB_EXPLODE_135_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  827. if(m_iAngle == 180)
  828. m_sprCarExplode_180.Create(GetMainApp()->m_hInst, IDB_EXPLODE_180_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  829. if(m_iAngle > 180 && m_iAngle < 270)
  830. m_sprCarExplode_225.Create(GetMainApp()->m_hInst, IDB_EXPLODE_225_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  831. if(m_iAngle == 270)
  832. m_sprCarExplode_270.Create(GetMainApp()->m_hInst, IDB_EXPLODE_270_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  833. if(m_iAngle > 270 && m_iAngle < 360)
  834. m_sprCarExplode_315.Create(GetMainApp()->m_hInst, IDB_EXPLODE_315_BLUE, 320, 200, RGB(0,0,0), 40, 40);
  835. break;
  836. }
  837. }
  838. }
  839. int cRaceCar::GetCarState()
  840. {
  841. return m_iCarState;
  842. }
  843. void cRaceCar::Crashed()
  844. {
  845. // Car Crashed
  846. if(GetTickCount() - m_lLastSpeedIncr > (UINT)RAISESPEED_TIME )
  847. {
  848. if(m_iSpeed > 180)
  849. m_iSpeed=m_iSpeed-50;
  850. else
  851. m_iSpeed=m_iSpeed-25;
  852. if(m_iSpeed < 0)
  853. {
  854. m_iSpeed = 0;
  855. }
  856. m_lLastSpeedIncr = GetTickCount();
  857. }
  858. }
  859. int cRaceCar::GetPosition()
  860. {
  861. return m_iPosition;
  862. }
  863. void cRaceCar::SetPosition(int iPosition)
  864. {
  865. m_iPosition = iPosition;
  866. }
  867. int cRaceCar::GetDistanceToNextCheckPoint()
  868. {
  869. return m_iDistanceToNextCheckPoint;
  870. }
  871. long cRaceCar::GetLapElapseTime(int iLap)
  872. {
  873. // Return the elapse time of the lap
  874. if(iLap == -1)
  875. {
  876. if(m_lCurrentTime == 0 && m_iControlType != CTRL_NETWORK_LOCAL)
  877. return 0;
  878. else
  879. {
  880. if(m_iControlType == CTRL_NETWORK_LOCAL)
  881. return m_dwElapseTime;
  882. else
  883. return GetTickCount()-m_lCurrentTime;
  884. }
  885. }
  886. else
  887. return m_vcLapTimes[iLap];
  888. }
  889. long cRaceCar::GetLastLapTime()
  890. {
  891. if(m_vcLapTimes.size() == 0)
  892. return 0;
  893. else
  894. return m_vcLapTimes[m_vcLapTimes.size()-1];
  895. }
  896. int cRaceCar::GetCarColor()
  897. {
  898. return m_iColor;
  899. }
  900. void cRaceCar::SetID(BYTE iValue)
  901. {
  902. m_bID = iValue;
  903. }
  904. BYTE cRaceCar::GetID()
  905. {
  906. return m_bID;
  907. }
  908. void cRaceCar::SetSpeed(int iValue)
  909. {
  910. m_iSpeed = iValue;
  911. }
  912. void cRaceCar::AddLapTime(DWORD dwTime)
  913. {
  914. m_vcLapTimes.push_back(dwTime);
  915. }
  916. void cRaceCar::Backup()
  917. {
  918. // Backup all the current state of the car
  919. m_fBackupDirectionX = m_fDirectionX;
  920. m_iBackupDistanceToNextCheckPoint = m_iDistanceToNextCheckPoint;
  921. m_fBackupDirectionY = m_fDirectionY;
  922. m_fBackupIncrementX = m_fIncrementX;
  923. m_fBackupIncrementY = m_fIncrementY;
  924. m_iBackupAngle = m_iAngle;
  925. m_fBackupPosX = m_fPosX;
  926. m_fBackupPosY = m_fPosY;
  927. m_iBackupSprite = m_sprCar.m_iAbsolutePosition;
  928. iBackupTurnCar = iTurnCar;
  929. RotateBound(m_iAngle);
  930. }
  931. void cRaceCar::MoveForward(int iSpeed)
  932. {
  933. // Move the car forward, using an alternate speed
  934. // Used when someone hits your car
  935. m_fPosY = m_fPosY + ((float)m_fDirectionY / 9.0f) * ((float)iSpeed / _SPEED_FACTOR_);
  936. m_fPosX = m_fPosX + ((float)m_fDirectionX / 9.0f) * ((float)iSpeed / _SPEED_FACTOR_);
  937. }