OSPRITE.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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 : OSPRITE.CPP
  21. //Description : Object Sprite
  22. #include <ALL.h>
  23. #include <OSTR.h>
  24. #include <OVGA.h>
  25. #include <OINFO.h>
  26. #include <OGAME.h>
  27. #include <ONATION.h>
  28. #include <OSPRITE.h>
  29. #include <OCOLTBL.h>
  30. //----------- Define static class member variables -----------//
  31. short Sprite::abs_x1, Sprite::abs_y1; // the absolute postion, taking in account of sprite offset
  32. short Sprite::abs_x2, Sprite::abs_y2;
  33. //-------- Begin of function Sprite::Sprite --------//
  34. Sprite::Sprite()
  35. {
  36. // preserve virtual pointer
  37. memset( (char *)this + sizeof(void *), 0, sizeof(Sprite) - sizeof(void *) );
  38. }
  39. //--------- End of function Sprite::Sprite --------//
  40. //-------- Begin of function Sprite::~Sprite --------//
  41. Sprite::~Sprite()
  42. {
  43. deinit();
  44. }
  45. //--------- End of function Sprite::~Sprite --------//
  46. //--------- Begin of function Sprite::init ---------//
  47. //
  48. void Sprite::init(short spriteId, short startXLoc, short startYLoc)
  49. {
  50. sprite_id = spriteId;
  51. cur_x = startXLoc * ZOOM_LOC_WIDTH;
  52. cur_y = startYLoc * ZOOM_LOC_HEIGHT;
  53. go_x = next_x = cur_x;
  54. go_y = next_y = cur_y;
  55. cur_attack = 0;
  56. cur_action = SPRITE_IDLE;
  57. cur_dir = m.random(MAX_SPRITE_DIR_TYPE); // facing any of the eight directions
  58. cur_frame = 1;
  59. final_dir = cur_dir;
  60. //----- clone vars from sprite_res for fast access -----//
  61. sprite_info = sprite_res[sprite_id];
  62. sprite_info->load_bitmap_res();
  63. //------------- init other vars --------------//
  64. remain_attack_delay = 0;
  65. remain_frames_per_step = sprite_info->frames_per_step;
  66. }
  67. //----------- End of function Sprite::init -----------//
  68. //--------- Begin of function Sprite::deinit ---------//
  69. //
  70. void Sprite::deinit()
  71. {
  72. if( sprite_id && cur_x >= 0 )
  73. {
  74. sprite_info->free_bitmap_res();
  75. sprite_id = 0;
  76. }
  77. }
  78. //----------- End of function Sprite::deinit -----------//
  79. //--------- Begin of function Sprite::cur_sprite_frame ---------//
  80. //
  81. // Return the current frame of the sprite
  82. //
  83. SpriteFrame* Sprite::cur_sprite_frame(int *needMirror)
  84. {
  85. UCHAR curDir = display_dir();
  86. if( needMirror)
  87. *needMirror = need_mirror(curDir);
  88. // do not update cur_dir as curDir
  89. err_when(curDir<0 || curDir>=3*MAX_SPRITE_DIR_TYPE);
  90. switch( cur_action )
  91. {
  92. case SPRITE_MOVE:
  93. //### begin alex 14/4 ###//
  94. case SPRITE_SHIP_EXTRA_MOVE:
  95. //#### end alex 14/4 ####//
  96. if( guard_count)
  97. {
  98. if( curDir >= MAX_SPRITE_DIR_TYPE)
  99. {
  100. err_here();
  101. curDir %= MAX_SPRITE_DIR_TYPE;
  102. }
  103. return sprite_frame_res[sprite_info->guard_move_array[curDir].first_frame_recno+cur_frame-1];
  104. }
  105. else
  106. return sprite_frame_res[sprite_info->move_array[curDir].first_frame_recno+cur_frame-1];
  107. case SPRITE_ATTACK:
  108. err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
  109. if( guard_count )
  110. {
  111. SpriteGuardStop *guardStopAction = sprite_info->guard_stop_array + curDir;
  112. return sprite_frame_res[guardStopAction->first_frame_recno+
  113. min(guard_count,guardStopAction->frame_count)-1];
  114. }
  115. else
  116. return sprite_frame_res[sprite_info->attack_array[cur_attack][curDir].first_frame_recno+cur_frame-1];
  117. case SPRITE_TURN:
  118. case SPRITE_IDLE:
  119. case SPRITE_WAIT:
  120. // air unit needs it own stop frames to float on air
  121. {
  122. if( guard_count )
  123. {
  124. if( curDir >= MAX_SPRITE_DIR_TYPE)
  125. {
  126. // if the sprite is turning, adjust direction to next
  127. if( turn_delay > 0)
  128. curDir ++;
  129. curDir %= MAX_SPRITE_DIR_TYPE;
  130. }
  131. SpriteGuardStop *guardStopAction = sprite_info->guard_stop_array + curDir;
  132. return sprite_frame_res[guardStopAction->first_frame_recno+
  133. min(guard_count,guardStopAction->frame_count)-1];
  134. }
  135. else
  136. {
  137. SpriteStop *stopAction= sprite_info->stop_array +curDir;
  138. if(cur_frame > stopAction->frame_count)
  139. return sprite_frame_res[stopAction->frame_recno]; // first frame
  140. else // only few sprite has stopAction->frame_count > 1
  141. return sprite_frame_res[stopAction->frame_recno+cur_frame-1];
  142. }
  143. }
  144. case SPRITE_DIE:
  145. if(sprite_info->die.first_frame_recno) // only if this sprite has dying frame
  146. {
  147. if( needMirror)
  148. *needMirror = 0; // no need to mirror at any direction
  149. return sprite_frame_res[sprite_info->die.first_frame_recno+cur_frame-1];
  150. }
  151. default:
  152. return sprite_frame_res[sprite_info->move_array[curDir].first_frame_recno+cur_frame-1];
  153. }
  154. }
  155. //----------- End of function Sprite::cur_sprite_frame -----------//
  156. //--------- Begin of function Sprite::update_abs_pos ---------//
  157. //
  158. // Update the cur_width & cur_height vars of the sprite for later faster access.
  159. //
  160. // [SpriteFrame *] spriteFrame pointer to the current (default : NULL)
  161. void Sprite::update_abs_pos(SpriteFrame *spriteFrame)
  162. {
  163. if( !spriteFrame )
  164. spriteFrame = cur_sprite_frame();
  165. abs_x1 = cur_x + spriteFrame->offset_x; // absolute position
  166. abs_y1 = cur_y + spriteFrame->offset_y;
  167. abs_x2 = abs_x1 + spriteFrame->width - 1;
  168. abs_y2 = abs_y1 + spriteFrame->height - 1;
  169. }
  170. //----------- End of function Sprite::update_abs_pos -----------//
  171. //--------- Begin of function Sprite::draw ---------//
  172. //
  173. void Sprite::draw()
  174. {
  175. //--------- draw sprite on the zoom window ---------//
  176. int needMirror;
  177. SpriteFrame* spriteFrame = cur_sprite_frame(&needMirror);
  178. update_abs_pos(spriteFrame);
  179. err_when( !sprite_info->res_bitmap.init_flag );
  180. char* bitmapPtr = sprite_info->res_bitmap.read_imported(spriteFrame->bitmap_offset);
  181. //-------- check if the sprite is inside the view area --------//
  182. int x1 = abs_x1-World::view_top_x; // the sprite's position in the view window
  183. if( x1 <= -spriteFrame->width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area
  184. return;
  185. int y1 = abs_y1-World::view_top_y;
  186. if( y1 <= -spriteFrame->height || y1 >= ZOOM_HEIGHT )
  187. return;
  188. //------- decide which approach to use for displaying -----//
  189. int x2 = abs_x2-World::view_top_x;
  190. int y2 = abs_y2-World::view_top_y;
  191. //---- only portion of the sprite is inside the view area ------//
  192. if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
  193. {
  194. if( needMirror ) // if this direction needed to be mirrored
  195. {
  196. if( !sprite_info->remap_bitmap_flag )
  197. {
  198. vga_back.put_bitmap_area_trans_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
  199. max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
  200. }
  201. else
  202. {
  203. vga_back.remap_bitmap_area_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
  204. vga.vga_color_table->get_table_array(),
  205. max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
  206. }
  207. }
  208. else
  209. {
  210. if( !sprite_info->remap_bitmap_flag )
  211. {
  212. vga_back.put_bitmap_area_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
  213. max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
  214. }
  215. else
  216. {
  217. vga_back.remap_bitmap_area( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
  218. vga.vga_color_table->get_table_array(),
  219. max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
  220. }
  221. }
  222. }
  223. //---- the whole sprite is inside the view area ------//
  224. else
  225. {
  226. //------ mirror-bilting for certain directions ------//
  227. if( needMirror ) // if this direction needed to be mirrored
  228. {
  229. if( !sprite_info->remap_bitmap_flag )
  230. {
  231. vga_back.put_bitmap_trans_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1,
  232. bitmapPtr );
  233. }
  234. else
  235. {
  236. vga_back.remap_bitmap_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1,
  237. bitmapPtr, vga.vga_color_table->get_table_array() );
  238. }
  239. }
  240. else
  241. {
  242. if( !sprite_info->remap_bitmap_flag )
  243. {
  244. vga_back.put_bitmap_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1,
  245. bitmapPtr );
  246. }
  247. else
  248. {
  249. vga_back.remap_bitmap( x1+ZOOM_X1, y1+ZOOM_Y1,
  250. bitmapPtr, vga.vga_color_table->get_table_array() );
  251. }
  252. }
  253. }
  254. }
  255. //----------- End of function Sprite::draw -----------//
  256. // ---------- Begin of function Sprite::display_dir ---------//
  257. UCHAR Sprite::display_dir()
  258. {
  259. UCHAR curDir = cur_dir;
  260. switch( sprite_info->turn_resolution)
  261. {
  262. case 0: // fall through
  263. case 1:
  264. curDir &= ~7; // direction less, remain upward or downard, but set to north
  265. break;
  266. case 8:
  267. // cur_dir can be 0 to 3*MAX_SPRITE_DIR_TYPE-1, such as projectile;
  268. // curDir = cur_dir;
  269. break;
  270. case 16:
  271. err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
  272. // curDir should be (from due north, clockwisely) { 0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15 }
  273. if( turn_delay <= -30)
  274. {
  275. curDir = ((curDir+7) & 7) + 8;
  276. }
  277. else if( turn_delay >= 30)
  278. {
  279. curDir += 8;
  280. }
  281. break;
  282. case 24:
  283. err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
  284. // curDir should be (from due north, clockwisely)
  285. // { 0,8,16,1,9,17,2,10,18,3,11,19,4,12,20,5,13,21,6,14,22,7,15,23 }
  286. if( turn_delay <= -20)
  287. {
  288. if( turn_delay <= -40)
  289. curDir = ((curDir+7) & 7) + 8;
  290. else
  291. curDir = ((curDir+7) & 7) + 16;
  292. }
  293. else if( turn_delay >= 20)
  294. {
  295. if( turn_delay >= 40 )
  296. curDir += 16;
  297. else
  298. curDir += 8;
  299. }
  300. break;
  301. default:
  302. err_here();
  303. }
  304. return curDir;
  305. }
  306. // ---------- End of function Sprite::display_dir ---------//
  307. // ---------- Begin of function Sprite::need_mirror --------//
  308. int Sprite::need_mirror(UCHAR dispDir)
  309. {
  310. return (dispDir < 8 || sprite_info->turn_resolution <= 8) ? (dispDir & 7) >= 5 : (dispDir & 7) >= 4;
  311. }
  312. // ---------- End of function Sprite::need_mirror --------//
  313. // ---------- Begin of function Sprite::is_shealth --------//
  314. int Sprite::is_shealth()
  315. {
  316. // if the visibility of location is just explored, consider shealth
  317. return config.fog_of_war && world.get_loc(cur_x_loc(), cur_y_loc())->visibility() <= EXPLORED_VISIBILITY;
  318. }
  319. // ---------- End of function Sprite::is_shealth --------//