PageRenderTime 50ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/src/PlanetSurfaceObject.cpp

http://starflighttlc.googlecode.com/
C++ | 679 lines | 513 code | 116 blank | 50 comment | 79 complexity | 92567a1c7856ce8d8fcc0431c23c0357 MD5 | raw file
  1. #include "PlanetSurfaceObject.h"
  2. #include "ModulePlanetSurface.h"
  3. #include "Sprite.h"
  4. #include "Game.h"
  5. #include "GameState.h"
  6. #include "Events.h"
  7. #include "Util.h"
  8. using namespace std;
  9. int PlanetSurfaceObject::maxX, PlanetSurfaceObject::minX, PlanetSurfaceObject::maxY, PlanetSurfaceObject::minY = 0;
  10. std::map<std::string, BITMAP*> PlanetSurfaceObject::graphics;
  11. PlanetSurfaceObject::PlanetSurfaceObject() :
  12. image(NULL),
  13. itemType(IT_INVALID),
  14. name(""),
  15. value(0.0),
  16. size(0.0),
  17. danger(0.0),
  18. damage(0.0),
  19. stunCount(0),
  20. health(0),
  21. itemAge(IA_INVALID),
  22. shipRepairMetal(false),
  23. blackMarketItem(false),
  24. UseAlpha(false),
  25. alive(1),
  26. scanned(false),
  27. selected(false),
  28. direction(0),
  29. animColumns(1),
  30. animStartX(0),
  31. animStartY(0),
  32. state(0),
  33. objectType(0),
  34. x(0.0f),
  35. y(0.0f),
  36. width(0),
  37. height(0),
  38. colHalfWidth(0),
  39. colHalfHeight(0),
  40. frameWidth(0),
  41. frameHeight(0),
  42. scale(1),
  43. delayX(0),
  44. delayY(0),
  45. countX(0),
  46. countY(0),
  47. velX(0.0),
  48. velY(0.0),
  49. speed(0.0),
  50. currFrame(0),
  51. totalFrames(1),
  52. frameCount(0),
  53. frameDelay(10),
  54. animDir(1),
  55. faceAngle(0),
  56. moveAngle(0),
  57. angleOffset(0),
  58. counter1(0),
  59. counter2(0),
  60. counter3(0),
  61. threshold1(0),
  62. threshold2(0),
  63. threshold3(0),
  64. minimapColor(BRTORANGE),
  65. minimapSize(1)
  66. {
  67. defaultAnim = new Animation(0, 1, 0);
  68. activeAnim = defaultAnim;
  69. }
  70. PlanetSurfaceObject::PlanetSurfaceObject(lua_State* LuaVM, std::string ScriptName) :
  71. scriptName(ScriptName),
  72. luaVM(LuaVM),
  73. itemType(IT_INVALID),
  74. id(0),
  75. name(""),
  76. value(0.0),
  77. size(0.0),
  78. danger(0.0),
  79. damage(0.0),
  80. stunCount(0),
  81. health(0),
  82. itemAge(IA_INVALID),
  83. shipRepairMetal(false),
  84. blackMarketItem(false),
  85. image(NULL),
  86. selected(false),
  87. UseAlpha(false),
  88. alive(1),
  89. scanned(false),
  90. direction(0),
  91. animColumns(1),
  92. animStartX(0),
  93. animStartY(0),
  94. state(0),
  95. objectType(0),
  96. x(0.0f),
  97. y(0.0f),
  98. width(0),
  99. height(0),
  100. colHalfWidth(0),
  101. colHalfHeight(0),
  102. frameWidth(0),
  103. frameHeight(0),
  104. scale(1),
  105. delayX(0),
  106. delayY(0),
  107. countX(0),
  108. countY(0),
  109. velX(0.0),
  110. velY(0.0),
  111. speed(0.0),
  112. currFrame(0),
  113. totalFrames(1),
  114. frameCount(0),
  115. frameDelay(10),
  116. animDir(1),
  117. faceAngle(0),
  118. moveAngle(0),
  119. angleOffset(0),
  120. counter1(0),
  121. counter2(0),
  122. counter3(0),
  123. threshold1(0),
  124. threshold2(0),
  125. threshold3(0),
  126. minimapColor(BRTORANGE),
  127. minimapSize(1)
  128. {
  129. defaultAnim = new Animation(0, 1, 0);
  130. activeAnim = defaultAnim;
  131. }
  132. PlanetSurfaceObject::~PlanetSurfaceObject()
  133. {
  134. //We only need to delete the defaultAnim, not the activeAnim
  135. if (defaultAnim != NULL)
  136. {
  137. delete defaultAnim;
  138. defaultAnim = NULL;
  139. }
  140. //the static graphics map will clean up all the graphics
  141. for (animationsIt = regAnimations.begin(); animationsIt != regAnimations.end(); ++animationsIt)
  142. {
  143. delete animationsIt->second;
  144. animationsIt->second = NULL;
  145. }
  146. regAnimations.clear();
  147. }
  148. void PlanetSurfaceObject::setX(double initX)
  149. {
  150. if (initX < minX)
  151. {
  152. x = minX;
  153. }
  154. else if (initX > maxX)
  155. {
  156. x = maxX;
  157. }
  158. else
  159. {
  160. x = initX;
  161. }
  162. }
  163. void PlanetSurfaceObject::setY(double initY)
  164. {
  165. if (initY < minY)
  166. {
  167. y = minY;
  168. }
  169. else if (initY > maxY)
  170. {
  171. y = maxY;
  172. }
  173. else
  174. {
  175. y = initY;
  176. }
  177. }
  178. void PlanetSurfaceObject::setXOffset(double initXOffset) { setX(initXOffset - (frameWidth * scale)/2); }
  179. void PlanetSurfaceObject::setYOffset(double initYOffset) { setY(initYOffset - (frameHeight * scale)/2); }
  180. void PlanetSurfaceObject::setPos(double initX, double initY) { setX(initX); setY(initY); }
  181. void PlanetSurfaceObject::setPosOffset(double initX, double initY) { setX(initX - (frameWidth * scale)/2); setY(initY - (frameHeight * scale)/2); }
  182. void PlanetSurfaceObject::Initialize()
  183. {
  184. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  185. /* the function name */
  186. string fname = this->GetScriptName();
  187. fname += "Initialize";
  188. lua_getglobal(luaVM, fname.c_str());
  189. // call the function
  190. lua_call(luaVM, 0, 0);
  191. }
  192. int PlanetSurfaceObject::load(const char *filename)
  193. {
  194. std::map<std::string, BITMAP*>::iterator it = graphics.find(filename);
  195. if (it == graphics.end())
  196. {
  197. this->image = load_bitmap(filename, NULL);
  198. if (!this->image) {
  199. std::string msg = "Error loading sprite file ";
  200. msg += filename;
  201. g_game->message(msg);
  202. return 0;
  203. }
  204. graphics[filename] = image;
  205. }
  206. else
  207. {
  208. this->image = it->second;
  209. }
  210. this->width = image->w;
  211. this->height = image->h;
  212. //default frame size equals whole image size unless manually changed
  213. this->frameWidth = this->width;
  214. this->frameHeight = this->height;
  215. this->colHalfWidth = this->width/2;
  216. this->colHalfHeight = this->height/2;
  217. set_alpha_blender();
  218. return 1;
  219. }
  220. void PlanetSurfaceObject::Move()
  221. {
  222. moved = false;
  223. //update x position
  224. if (++countX > delayX) {
  225. countX = 0;
  226. setX(x + speed * velX);
  227. if (speed != 0 && velX != 0)
  228. moved = true;
  229. }
  230. //update y position
  231. if (++countY > delayY) {
  232. countY = 0;
  233. setY(y + speed * velY);
  234. if (speed != 0 && velY != 0)
  235. moved = true;
  236. }
  237. if (moved)
  238. g_game->PlanetSurfaceHolder->CheckForCollisions(this);
  239. }
  240. void PlanetSurfaceObject::Animate()
  241. {
  242. //update frame based on animdir
  243. if (++frameCount > activeAnim->GetDelay())
  244. {
  245. frameCount = 0;
  246. currFrame += 1;
  247. if (currFrame < activeAnim->GetStartFrame())
  248. {
  249. currFrame = activeAnim->GetEndFrame();
  250. }
  251. if (currFrame > activeAnim->GetEndFrame())
  252. {
  253. currFrame = activeAnim->GetStartFrame();
  254. }
  255. }
  256. }
  257. void PlanetSurfaceObject::Update()
  258. {
  259. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  260. /* the function name */
  261. lua_getglobal(luaVM, (this->GetScriptName().append("Update")).c_str());
  262. // call the function
  263. lua_call(luaVM, 0, 0);
  264. }
  265. void PlanetSurfaceObject::TimedUpdate()
  266. {
  267. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  268. /* the function name */
  269. lua_getglobal(luaVM, (this->GetScriptName().append("TimedUpdate")).c_str());
  270. // call the function
  271. lua_call(luaVM, 0, 0);
  272. }
  273. void PlanetSurfaceObject::Draw()
  274. {
  275. if (selected)
  276. ellipse(g_game->GetBackBuffer(), (int)(getXOffset() - g_game->gameState->player->posPlanet.x), (int)(getYOffset() - g_game->gameState->player->posPlanet.y), (int)(width * scale)/2, (int)(height * scale)/2, GREEN);
  277. Draw(g_game->GetBackBuffer());
  278. //rect(g_game->GetBackBuffer(), getXOffset() - g_game->gameState->player->posPlanet.x - getColHalfWidth(), getYOffset() - g_game->gameState->player->posPlanet.y - getColHalfHeight(), getXOffset() - g_game->gameState->player->posPlanet.x + getColHalfWidth(), getYOffset() - g_game->gameState->player->posPlanet.y + getColHalfHeight(), RED);
  279. }
  280. void PlanetSurfaceObject::Draw(BITMAP *dest)
  281. {
  282. if (!image) return;
  283. float angle = faceAngle + angleOffset;
  284. bool scaled = (scale != 1);
  285. bool rotated = (angle != 0);
  286. BITMAP *scrapFrame = NULL;
  287. BITMAP *finalFrame = NULL;
  288. int fx = animStartX + (currFrame % animColumns) * frameWidth;
  289. int fy = animStartY + (currFrame / animColumns) * frameHeight;
  290. if (!scaled && !rotated && !UseAlpha)
  291. {
  292. //draw normally
  293. masked_blit(image, dest, fx, fy, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y), frameWidth, frameHeight);
  294. return;
  295. }
  296. else if (!scaled && !rotated && UseAlpha)
  297. {
  298. scrapFrame = create_bitmap(frameWidth, frameHeight);
  299. blit(image, scrapFrame, fx, fy, 0, 0, frameWidth, frameHeight);
  300. draw_trans_sprite(dest, scrapFrame, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y));
  301. destroy_bitmap(scrapFrame);
  302. return;
  303. }
  304. else if (scaled && rotated && !UseAlpha)
  305. {
  306. //scrapFrame = create_bitmap(frameWidth, frameHeight);
  307. finalFrame = create_bitmap((int)(frameWidth * scale), (int)(frameHeight * scale));
  308. stretch_blit(image, finalFrame, fx, fy, frameWidth, frameHeight, 0, 0, (int)(frameWidth * scale), (int)(frameHeight * scale));
  309. //masked_stretch_blit(image, finalFrame, fx, fy, frameWidth, frameHeight, 0, 0, frameWidth * scale, frameHeight * scale);
  310. //draw rotated image in scale frame onto rotate frame
  311. //adjust for Allegro's 16.16 fixed trig (256 / 360 = 0.7) then divide by 2 radians
  312. //rotate_sprite(finalFrame, scrapFrame, (int)x, (int)y, itofix((int)(angle / 0.7f / 2.0f)));
  313. rotate_sprite(dest, finalFrame, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y), itofix((int)(angle / 0.7f / 2.0f)));
  314. destroy_bitmap(finalFrame);
  315. //destroy_bitmap(scrapFrame);
  316. return;
  317. }
  318. else if (scaled && !rotated)
  319. {
  320. finalFrame = create_bitmap((int)(frameWidth * scale), (int)(frameHeight * scale));
  321. //Scale paste
  322. stretch_blit(image, finalFrame, fx, fy, frameWidth, frameHeight, 0, 0, (int)(frameWidth * scale), (int)(frameHeight * scale));
  323. }
  324. else if (!scaled && rotated && !UseAlpha)
  325. {
  326. scrapFrame = create_bitmap(frameWidth, frameHeight);
  327. blit(image, scrapFrame, fx, fy, 0, 0, frameWidth, frameHeight);
  328. //adjust for Allegro's 16.16 fixed trig (256 / 360 = 0.7) then divide by 2 radians
  329. //rotate_sprite(finalFrame, scrapFrame, 0, 0, itofix((int)(angle / 0.7f / 2.0f)));
  330. rotate_sprite(dest, scrapFrame, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y), itofix((int)(angle / 0.7f / 2.0f)));
  331. destroy_bitmap(scrapFrame);
  332. return;
  333. }
  334. else if (!scaled && rotated && UseAlpha)
  335. {
  336. scrapFrame = create_bitmap(frameWidth, frameHeight);
  337. if (frameWidth < frameHeight)
  338. {
  339. finalFrame = create_bitmap(frameHeight, frameHeight);
  340. }
  341. else
  342. {
  343. finalFrame = create_bitmap(frameWidth, frameWidth);
  344. }
  345. blit(image, scrapFrame, fx, fy, 0, 0, frameWidth, frameHeight);
  346. clear_bitmap(finalFrame);
  347. //adjust for Allegro's 16.16 fixed trig (256 / 360 = 0.7) then divide by 2 radians
  348. rotate_sprite(finalFrame, scrapFrame, 0, 0, itofix((int)(angle / 0.7f / 2.0f)));
  349. //rotate_sprite(dest, scrapFrame, (int)x - g_game->gameState->player->posPlanet.x, (int)y - g_game->gameState->player->posPlanet.y, itofix((int)(angle / 0.7f / 2.0f)));
  350. destroy_bitmap(scrapFrame);
  351. }
  352. if (!UseAlpha)
  353. {
  354. //draw normally
  355. masked_blit(finalFrame, dest, 0, 0, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y), (int)(frameWidth * scale), (int)(frameHeight * scale));
  356. }
  357. else
  358. {
  359. draw_trans_sprite(dest, finalFrame, (int)(x - g_game->gameState->player->posPlanet.x), (int)(y - g_game->gameState->player->posPlanet.y));
  360. }
  361. destroy_bitmap(finalFrame);
  362. }
  363. bool PlanetSurfaceObject::CheckCollision(PlanetSurfaceObject * otherPSO)
  364. {
  365. //Use the "gets" so the scale of the object is taken into consideration
  366. double psoHalfWidth = getColHalfWidth();
  367. double otherPSOHalfWidth = otherPSO->getColHalfWidth();
  368. //Offsets are the origin of the object, with scale calculated in
  369. double xDistance = abs((int)(otherPSO->getXOffset() - this->getXOffset()));
  370. //the purpose of the projection code is to cause a collided object to slide around it's collision circle
  371. if ( psoHalfWidth + otherPSOHalfWidth > xDistance )
  372. {
  373. //Then we have a X axis collision, but we need both a x and a y collision for there to be an actual collision ;)
  374. double psoHalfHeight = getColHalfHeight();
  375. double otherPSOHalfHeight = otherPSO->getColHalfHeight();
  376. double yDistance = abs((int)(otherPSO->getYOffset() - this->getYOffset()));
  377. if ( psoHalfHeight + otherPSOHalfHeight > yDistance )
  378. {
  379. double adjustment = 0;
  380. int axis = 0;
  381. //yeah! we have a collision, but now we need to find our projection vector
  382. if (psoHalfWidth + otherPSOHalfWidth - xDistance < psoHalfHeight + otherPSOHalfHeight - yDistance)
  383. {
  384. //we have a projection vector on the x axis
  385. adjustment = psoHalfWidth + otherPSOHalfWidth - xDistance;
  386. axis = 0;
  387. }
  388. else
  389. {
  390. //we have a projection vector on the y axis
  391. adjustment = psoHalfHeight + otherPSOHalfHeight - yDistance;
  392. axis = 1;
  393. }
  394. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  395. lua_pushnumber(luaVM, adjustment);
  396. lua_setglobal(luaVM, "adjustment");
  397. lua_pushnumber(luaVM, otherPSO->getXOffset());
  398. lua_setglobal(luaVM, "otherPSOx");
  399. lua_pushnumber(luaVM, otherPSO->getYOffset());
  400. lua_setglobal(luaVM, "otherPSOy");
  401. //find the item in the planet surface objects list
  402. int id = -1;
  403. for (int i=0; i < (int) g_game->PlanetSurfaceHolder->surfaceObjects.size(); ++i)
  404. {
  405. if (otherPSO == g_game->PlanetSurfaceHolder->surfaceObjects[i])
  406. {
  407. id = i;
  408. break;
  409. }
  410. }
  411. lua_pushnumber( luaVM, id);
  412. lua_setglobal(luaVM, "otherPSOid");
  413. lua_pushnumber( luaVM, otherPSO->getObjectType());
  414. lua_setglobal(luaVM, "otherPSOtype");
  415. lua_pushnumber(luaVM, axis);
  416. lua_setglobal(luaVM, "axis");
  417. /* the function name */
  418. lua_getglobal(luaVM, (this->GetScriptName().append("CollisionOccurred")).c_str());
  419. // call the function
  420. lua_call(luaVM, 0, 0);
  421. return true;
  422. }
  423. }
  424. return false;
  425. }
  426. bool PlanetSurfaceObject::CheckCollision(int x, int y, int width, int height)
  427. {
  428. //Use the "gets" so the scale of the object is taken into consideration
  429. double psoHalfWidth = getColHalfWidth();
  430. double recHalfWidth = width/2;
  431. //Offsets are the origin of the object, with scale calculated in
  432. double xDistance = abs( (int)(x + recHalfWidth - this->getXOffset()));
  433. if ( psoHalfWidth + recHalfWidth > xDistance )
  434. {
  435. //Then we have a X axis collision, but we need both a x and a y collision for there to be an actual collision ;)
  436. double psoHalfHeight = getColHalfHeight();
  437. double recHalfHeight = height/2;
  438. double yDistance = abs((int)(y + recHalfHeight - this->getYOffset()));
  439. if ( psoHalfHeight + recHalfHeight > yDistance )
  440. {
  441. double adjustment = 0;
  442. int axis = 0;
  443. //yeah! we have a collision, but now we need to find our projection vector
  444. if (psoHalfWidth + recHalfWidth - xDistance < psoHalfHeight + recHalfHeight - yDistance)
  445. {
  446. //we have a projection vector on the x axis
  447. adjustment = psoHalfWidth + recHalfWidth - xDistance;
  448. axis = 0;
  449. }
  450. else
  451. {
  452. //we have a projection vector on the y axis
  453. adjustment = psoHalfHeight + recHalfHeight - yDistance;
  454. axis = 1;
  455. }
  456. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  457. lua_pushnumber(luaVM, adjustment);
  458. lua_setglobal(luaVM, "adjustment");
  459. lua_pushnumber(luaVM, x);
  460. lua_setglobal(luaVM, "otherPSOx");
  461. lua_pushnumber(luaVM, y);
  462. lua_setglobal(luaVM, "otherPSOy");
  463. lua_pushnumber( luaVM, -1);
  464. lua_setglobal(luaVM, "otherPSOid");
  465. lua_pushnumber( luaVM, -14);
  466. lua_setglobal(luaVM, "otherPSOtype");
  467. lua_pushnumber(luaVM, axis);
  468. lua_setglobal(luaVM, "axis");
  469. /* the function name */
  470. lua_getglobal(luaVM, (this->GetScriptName().append("CollisionOccurred")).c_str());
  471. // call the function
  472. lua_call(luaVM, 0, 0);
  473. return true;
  474. }
  475. }
  476. return false;
  477. }
  478. void PlanetSurfaceObject::AddAnimation(std::string name, int startFrame, int endFrame, int delay)
  479. {
  480. regAnimations[name] = new Animation(startFrame, endFrame, delay);
  481. }
  482. void PlanetSurfaceObject::SetActiveAnimation(std::string name)
  483. {
  484. animationsIt = regAnimations.find(name);
  485. if (animationsIt != regAnimations.end())
  486. activeAnim = animationsIt->second;
  487. }
  488. void PlanetSurfaceObject::OnMouseMove(int x, int y)
  489. {
  490. }
  491. bool PlanetSurfaceObject::OnMouseReleased(int button, int x, int y)
  492. {
  493. if (button == 0)
  494. {
  495. if (PointInside(x,y))
  496. {
  497. if (g_game->PlanetSurfaceHolder->selectedPSO != NULL)
  498. {
  499. g_game->PlanetSurfaceHolder->selectedPSO->setSelected(false);
  500. }
  501. g_game->PlanetSurfaceHolder->selectedPSO = this;
  502. this->getActions();
  503. selected = true;
  504. }
  505. else
  506. {
  507. if (selected)
  508. {
  509. g_game->PlanetSurfaceHolder->selectedPSO = NULL;
  510. g_game->PlanetSurfaceHolder->activeButtons = 0;
  511. }
  512. selected = false;
  513. }
  514. }
  515. return selected;
  516. }
  517. void PlanetSurfaceObject::getActions()
  518. {
  519. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  520. /* the function name */
  521. lua_getglobal(luaVM, (this->GetScriptName().append("GetActions")).c_str());
  522. // call the function
  523. lua_call(luaVM, 0, 0);
  524. }
  525. void PlanetSurfaceObject::OnEvent(int event)
  526. {
  527. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  528. lua_pushnumber(luaVM, event);
  529. lua_setglobal(luaVM, "event");
  530. /* the function name */
  531. lua_getglobal(luaVM, (this->GetScriptName().append("OnEvent")).c_str());
  532. // call the function
  533. lua_call(luaVM, 0, 0);
  534. }
  535. void PlanetSurfaceObject::Scan()
  536. {
  537. g_game->PlanetSurfaceHolder->psObjectHolder = this;
  538. /* the function name */
  539. lua_getglobal(luaVM, (this->GetScriptName().append("Scan")).c_str());
  540. // call the function
  541. lua_call(luaVM, 0, 0);
  542. }
  543. int PlanetSurfaceObject::Inside(int x,int y,int left,int top,int right,int bottom)
  544. {
  545. if (x > left && x < right && y > top && y < bottom)
  546. return 1;
  547. else
  548. return 0;
  549. }
  550. int PlanetSurfaceObject::PointInside(int px,int py)
  551. {
  552. return Inside(px, py, (int)x, (int)y, (int)(x+(width * scale)), (int)(y+(height * scale)));
  553. }
  554. void PlanetSurfaceObject::EmptyGraphics()
  555. {
  556. std::map<std::string, BITMAP*>::iterator it;
  557. for (it = graphics.begin(); it != graphics.end(); ++it)
  558. {
  559. destroy_bitmap(it->second);
  560. it->second = NULL;
  561. }
  562. graphics.clear();
  563. }