OSPRITE2.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OSPRITE2.CPP
  21. //Description : Object Sprite
  22. #include <ALL.h>
  23. #include <OSYS.h>
  24. #include <OVGA.h>
  25. #include <OREMOTE.h>
  26. #include <OUNIT.h>
  27. #include <OSPRITE.h>
  28. #include <OSERES.h>
  29. #ifdef DEBUG
  30. static int check_dir1, check_dir2;
  31. /*static int check_dir(int curX, int curY, int destX, int destY)
  32. {
  33. if( destX == curX )
  34. {
  35. if( destY > curY )
  36. return DIR_S;
  37. else
  38. return DIR_N;
  39. }
  40. else if( destX < curX )
  41. {
  42. if( destY == curY )
  43. return DIR_W;
  44. else if( destY > curY )
  45. return DIR_SW;
  46. else
  47. return DIR_NW;
  48. }
  49. else
  50. {
  51. if( destY == curY )
  52. return DIR_E;
  53. else if( destY > curY )
  54. return DIR_SE;
  55. else
  56. return DIR_NE;
  57. }
  58. }*/
  59. #endif
  60. //--- Define no. of pixels per direction move (N, NE, E, SE, S, SW, W, NW) ---//
  61. static short move_x_pixel_array[] = { 0, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, ZOOM_LOC_WIDTH, 0, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH, -ZOOM_LOC_WIDTH };
  62. static short move_y_pixel_array[] = { -ZOOM_LOC_HEIGHT, -ZOOM_LOC_HEIGHT, 0, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, ZOOM_LOC_HEIGHT, 0, -ZOOM_LOC_HEIGHT };
  63. //--------- Begin of function Sprite::sprite_move --------//
  64. //
  65. // <int> desX, desY - the destination coordination
  66. //
  67. void Sprite::sprite_move(int desX, int desY)
  68. {
  69. if( cur_action != SPRITE_MOVE )
  70. {
  71. cur_action = SPRITE_MOVE;
  72. cur_frame = 1;
  73. }
  74. err_when(desX<0 || desY<0 || desX>=MAX_WORLD_X_LOC*ZOOM_LOC_WIDTH || desY>=MAX_WORLD_Y_LOC*ZOOM_LOC_HEIGHT);
  75. #ifdef DEBUG
  76. short vectorX=desX-next_x;
  77. short vectorY=desY-next_y;
  78. if(vectorX && vectorY) // both are non-zero
  79. {
  80. err_if(abs(vectorX) != abs(vectorY))
  81. err_here();
  82. }
  83. #endif
  84. go_x = desX;
  85. go_y = desY;
  86. //----------- determine the movement direction ---------//
  87. set_dir(cur_x, cur_y, go_x, go_y);
  88. //------ set the next tile to move towards -------//
  89. int stepMagn = move_step_magn();
  90. set_next(cur_x+stepMagn*move_x_pixel_array[final_dir], cur_y+stepMagn*move_y_pixel_array[final_dir], -stepMagn);
  91. err_when(cur_action==SPRITE_MOVE && (cur_x!=next_x || cur_y!=next_y) &&
  92. final_dir!=(check_dir1=get_dir(cur_x, cur_y, next_x, next_y)));
  93. }
  94. //---------- End of function Sprite::sprite_move --------//
  95. //------ Begin of function Sprite::match_dir -------//
  96. // return 1 if matched
  97. // return 0 otherwise
  98. //
  99. int Sprite::match_dir()
  100. {
  101. err_when(final_dir<0 || final_dir>MAX_SPRITE_DIR_TYPE);
  102. if(!sprite_info->need_turning)
  103. {
  104. cur_dir = final_dir;
  105. err_when(turn_delay);
  106. return 1;
  107. }
  108. static char turn_amount[10] = {60, 30, 20, 15, 12, 10, 9, 8, 7, 6};
  109. #define HALF_SPRITE_DIR_TYPE MAX_SPRITE_DIR_TYPE/2
  110. #define TURN_REQUIRE_AMOUNT 60
  111. if(cur_dir==final_dir) // same direction
  112. {
  113. turn_delay = 0;
  114. return 1;
  115. }
  116. char turnAmount = turn_amount[sprite_info->need_turning];
  117. if((cur_dir+HALF_SPRITE_DIR_TYPE)%MAX_SPRITE_DIR_TYPE == final_dir) // opposite direction
  118. {
  119. cur_dir += (final_dir%2 ? 1 : -1);
  120. cur_dir = cur_dir%MAX_SPRITE_DIR_TYPE;
  121. }
  122. else
  123. {
  124. err_when(cur_dir==final_dir || ((cur_dir+HALF_SPRITE_DIR_TYPE)%MAX_SPRITE_DIR_TYPE)==final_dir);
  125. UCHAR dirDiff = (final_dir - cur_dir + MAX_SPRITE_DIR_TYPE) % MAX_SPRITE_DIR_TYPE;
  126. if(dirDiff<HALF_SPRITE_DIR_TYPE)
  127. {
  128. turn_delay += turnAmount;
  129. if(turn_delay>=TURN_REQUIRE_AMOUNT)
  130. {
  131. cur_dir = (cur_dir+1)%MAX_SPRITE_DIR_TYPE;
  132. turn_delay = 0;
  133. }
  134. }
  135. else
  136. {
  137. turn_delay -= turnAmount;
  138. if(turn_delay<=-TURN_REQUIRE_AMOUNT)
  139. {
  140. cur_dir = (cur_dir-1+MAX_SPRITE_DIR_TYPE)%MAX_SPRITE_DIR_TYPE;
  141. turn_delay = 0;
  142. }
  143. }
  144. }
  145. err_when(final_dir<0 || final_dir>MAX_SPRITE_DIR_TYPE);
  146. err_when(cur_dir<0 || cur_dir>MAX_SPRITE_DIR_TYPE);
  147. err_when(final_dir==cur_dir && turn_delay);
  148. return (final_dir==cur_dir);
  149. }
  150. //---------- End of function Sprite::match_dir --------//
  151. //------ Begin of function Sprite::set_dir -------//
  152. void Sprite::set_dir(int curX, int curY, int destX, int destY)
  153. {
  154. UCHAR newDir = get_dir(curX, curY, destX, destY);
  155. if(newDir != final_dir)
  156. {
  157. final_dir = newDir;
  158. turn_delay = 0;
  159. }
  160. if(!sprite_info->need_turning)
  161. cur_dir = final_dir;
  162. else
  163. match_dir(); // start turning
  164. }
  165. //---------- End of function Sprite::set_dir --------//
  166. //------ Begin of function Sprite::set_dir -------//
  167. void Sprite::set_dir(UCHAR newDir)
  168. {
  169. if(newDir != final_dir)
  170. {
  171. final_dir = newDir;
  172. turn_delay = 0;
  173. }
  174. if(!sprite_info->need_turning)
  175. cur_dir = final_dir;
  176. else
  177. match_dir();
  178. }
  179. //---------- End of function Sprite::set_dir --------//
  180. //------ Begin of function Sprite::is_dir_correct -------//
  181. int Sprite::is_dir_correct()
  182. {
  183. //### begin alex 1/8 ###//
  184. //return (cur_dir==final_dir);
  185. return (cur_dir==final_dir && turn_delay==0);
  186. //#### end alex 1/8 ####//
  187. }
  188. //---------- End of function Sprite::is_dir_correct --------//
  189. //------ Begin of function Sprite::get_dir -------//
  190. //
  191. // Compare the current and destination locations and
  192. // return which direction the sprite should move towards or attack at.
  193. //
  194. int Sprite::get_dir(int curX, int curY, int destX, int destY)
  195. {
  196. unsigned xDiff( abs(destX - curX) );
  197. unsigned yDiff( abs(destY - curY) );
  198. unsigned squSize = max(xDiff, yDiff); // the size of the square we consider
  199. if( destX == curX )
  200. {
  201. if( destY > curY )
  202. return DIR_S;
  203. else
  204. return DIR_N;
  205. }
  206. else if( destX < curX )
  207. {
  208. // west side
  209. if( destY > curY )
  210. { // south west quadrant
  211. if(2*xDiff <= squSize)
  212. return DIR_S;
  213. else if(2*yDiff <= squSize)
  214. return DIR_W;
  215. else
  216. return DIR_SW;
  217. }
  218. else
  219. { // north west quadrant
  220. if(2*xDiff <= squSize)
  221. return DIR_N;
  222. else if(2*yDiff <= squSize)
  223. return DIR_W;
  224. else
  225. return DIR_NW;
  226. }
  227. }
  228. else // destX > curX
  229. {
  230. // east side
  231. if( destY > curY )
  232. { // south east quadrant
  233. if(2*xDiff <= squSize)
  234. return DIR_S;
  235. else if(2*yDiff <= squSize)
  236. return DIR_E;
  237. else
  238. return DIR_SE;
  239. }
  240. else
  241. {
  242. // north east quadrant
  243. if(2*xDiff <= squSize)
  244. return DIR_N;
  245. else if(2*yDiff <= squSize)
  246. return DIR_E;
  247. else
  248. return DIR_NE;
  249. }
  250. }
  251. return DIR_N;
  252. }
  253. //------- End of function Sprite::get_dir --------//
  254. //--------- Begin of function Sprite::process_idle --------//
  255. void Sprite::process_idle()
  256. {
  257. //-------- If it's an air unit --------//
  258. // note : most land units do have have stop frame,
  259. // so cur_sprite_stop->frame_count is 0
  260. if( ++cur_frame > cur_sprite_stop()->frame_count )
  261. cur_frame = 1;
  262. }
  263. //---------- End of function Sprite::process_idle ----------//
  264. //--------- Begin of function Sprite::process_move --------//
  265. void Sprite::process_move()
  266. {
  267. #ifdef DEBUG
  268. int debugStepMagn1 = move_step_magn();
  269. err_when(abs(cur_x-next_x)>ZOOM_LOC_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>ZOOM_LOC_HEIGHT*debugStepMagn1);
  270. #endif
  271. //---- for some sprite (e.g. elephant), move one step per a few frames ----//
  272. if( --remain_frames_per_step > 0 )
  273. return;
  274. else
  275. remain_frames_per_step = sprite_info->frames_per_step;
  276. err_when(cur_x < 0 || cur_y < 0 || cur_x >= ZOOM_X_PIXELS || cur_y >= ZOOM_Y_PIXELS);
  277. err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
  278. //----- if the sprite has reach the destintion ----//
  279. if( cur_x==go_x && cur_y==go_y)
  280. {
  281. cur_action = SPRITE_IDLE;
  282. set_next(cur_x, cur_y); //********* BUGHERE
  283. #ifdef DEBUG
  284. char h, w, blocked=0;
  285. short x, y;
  286. for(h=0, y=next_y_loc(); h<sprite_info->loc_height&&!blocked; h++, y++)
  287. {
  288. for(w=0, x=next_x_loc(); w<sprite_info->loc_width&&!blocked; w++, x++)
  289. blocked = world.get_unit_recno(x,y,mobile_type) != sprite_recno;
  290. }
  291. err_if(blocked)
  292. err_here();
  293. #endif
  294. cur_frame = 1;
  295. return;
  296. }
  297. err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
  298. //---- set the next tile the sprite will be moving towards ---//
  299. static short vector_x_array[] = { 0, 1, 1, 1, 0, -1, -1, -1 }; // default vectors, temporary only
  300. static short vector_y_array[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
  301. short stepX = sprite_info->speed;//abs(vectorX); //********* improve later
  302. short stepY = sprite_info->speed;//abs(vectorY);
  303. if( next_x != go_x || next_y != go_y ) // if next_x==go_x & next_y==go_y, reach destination already, don't move further.
  304. {
  305. if( abs(cur_x-next_x) <= stepX && abs(cur_y-next_y) <= stepY )
  306. {
  307. int stepMagn = move_step_magn();
  308. set_next(next_x+stepMagn*move_x_pixel_array[final_dir], next_y+stepMagn*move_y_pixel_array[final_dir], -stepMagn);
  309. }
  310. }
  311. err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y));
  312. //---- if the is blocked, cur_action is changed to SPRITE_WAIT, return now ----//
  313. if( cur_action != SPRITE_MOVE )
  314. return;
  315. //-------------- update position -----------------//
  316. //
  317. // If it gets very close to the destination, fit it
  318. // to the destination ingoring the normal vector.
  319. //
  320. //------------------------------------------------//
  321. short vectorX = vector_x_array[final_dir] * sprite_info->speed; // cur_dir may be changed in the above set_next() call
  322. short vectorY = vector_y_array[final_dir] * sprite_info->speed;
  323. if( abs(cur_x-go_x) <= stepX )
  324. cur_x = go_x;
  325. else
  326. cur_x += vectorX;
  327. if( abs(cur_y-go_y) <= stepY )
  328. cur_y = go_y;
  329. else
  330. cur_y += vectorY;
  331. err_when(cur_x-next_x!=0 && cur_y-next_y!=0 && abs(next_x-cur_x)!=abs(next_y-cur_y)); // is a better checking if speed in all direction is equal
  332. #ifdef DEBUG
  333. int debugStepMagn2 = move_step_magn();
  334. err_when(abs(cur_x-next_x)>ZOOM_LOC_WIDTH*debugStepMagn1 || abs(cur_y-next_y)>ZOOM_LOC_HEIGHT*debugStepMagn1);
  335. #endif
  336. //-------- check boundary ---------//
  337. err_when(cur_x < 0 || cur_y < 0 || cur_x >= ZOOM_X_PIXELS || cur_y >= ZOOM_Y_PIXELS);
  338. //------- update frame id. --------//
  339. if( ++cur_frame > cur_sprite_move()->frame_count )
  340. cur_frame = 1;
  341. }
  342. //---------- End of function Sprite::process_move ----------//
  343. //--------- Begin of function Sprite::process_attack --------//
  344. //
  345. // Return: <int> 1 - if the sprite just finished its current attack
  346. // 0 - other statuses - either waiting for next attack
  347. // or is attacking.
  348. //
  349. int Sprite::process_attack()
  350. {
  351. if(remain_attack_delay && cur_frame==1)
  352. return 0;
  353. //------- next attack frame --------//
  354. SpriteAttack* spriteAttack = cur_sprite_attack();
  355. // ------ sound effect --------//
  356. char action[] = "A1";
  357. action[1] += cur_attack;
  358. se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S', sprite_id, action);
  359. if( ++cur_frame > spriteAttack->frame_count )
  360. {
  361. ((Unit *)this)->cycle_eqv_attack(); // assume only unit can attack
  362. cur_frame = 1;
  363. return 1;
  364. }
  365. return 0;
  366. }
  367. //---------- End of function Sprite::process_attack ----------//
  368. //--------- Begin of function Sprite::process_turn --------//
  369. void Sprite::process_turn()
  370. {
  371. err_when(!sprite_info->need_turning);
  372. match_dir();
  373. }
  374. //---------- End of function Sprite::process_turn ----------//
  375. //--------- Begin of function Sprite::process_die --------//
  376. //
  377. // return : <int> 1 - dying animation completes.
  378. // 0 - still dying
  379. //
  380. int Sprite::process_die()
  381. {
  382. //--------- next frame ---------//
  383. if( sys.frame_count%3 == 0 )
  384. {
  385. se_res.sound(cur_x_loc(), cur_y_loc(), cur_frame, 'S',sprite_id,"DIE");
  386. if( ++cur_frame > sprite_info->die.frame_count )
  387. return 1;
  388. }
  389. return 0;
  390. }
  391. //---------- End of function Sprite::process_die ----------//
  392. //--------- Begin of function Sprite::set_remain_attack_delay --------//
  393. void Sprite::set_remain_attack_delay()
  394. {
  395. Unit* unitPtr = (Unit*) this; //**BUGHERE, assuming all Sprite that call process_attack() are Unit
  396. remain_attack_delay = unitPtr->attack_info_array[unitPtr->cur_attack].attack_delay;
  397. }
  398. //---------- End of function Sprite::set_remain_attack_delay ----------//
  399. //--------- Begin of function Sprite::move_step_magn --------//
  400. // return the magnitude of each step in moving
  401. // i.e 1 for unit_land, 2 for unit_sea and unit_air
  402. //
  403. int Sprite::move_step_magn()
  404. {
  405. return (mobile_type==UNIT_LAND) ? 1 : 2;
  406. }
  407. //---------- End of function Sprite::move_step_magn ----------//
  408. //--------- Begin of function Sprite::set_next --------//
  409. //
  410. void Sprite::set_next(int nextX, int nextY, int para, int blockedChecked)
  411. {
  412. err_here(); //**BUGHERE, for now, we don't have any pure Sprites, all functions should call Unit::set_next() instead of Sprite::set_next()
  413. next_x = nextX;
  414. next_y = nextY;
  415. }
  416. //---------- End of function Sprite::set_next ----------//
  417. //--------- Begin of function Sprite::set_guard_on --------//
  418. //
  419. void Sprite::set_guard_on()
  420. {
  421. err_when( !sprite_info->can_stand_guard() && !sprite_info->can_move_guard());
  422. guard_count = 1;
  423. }
  424. //--------- End of function Sprite::set_guard_on --------//
  425. //--------- Begin of function Sprite::set_guard_off --------//
  426. //
  427. void Sprite::set_guard_off()
  428. {
  429. guard_count = 0;
  430. }
  431. //--------- End of function Sprite::set_guard_off --------//