123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- /*
- * Seven Kingdoms: Ancient Adversaries
- *
- * Copyright 1997,1998 Enlight Software Ltd.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- *
- */
- //Filename : OSPRITE.CPP
- //Description : Object Sprite
- #include <ALL.h>
- #include <OSTR.h>
- #include <OVGA.h>
- #include <OINFO.h>
- #include <OGAME.h>
- #include <ONATION.h>
- #include <OSPRITE.h>
- #include <OCOLTBL.h>
- //----------- Define static class member variables -----------//
- short Sprite::abs_x1, Sprite::abs_y1; // the absolute postion, taking in account of sprite offset
- short Sprite::abs_x2, Sprite::abs_y2;
- //-------- Begin of function Sprite::Sprite --------//
- Sprite::Sprite()
- {
- // preserve virtual pointer
- memset( (char *)this + sizeof(void *), 0, sizeof(Sprite) - sizeof(void *) );
- }
- //--------- End of function Sprite::Sprite --------//
- //-------- Begin of function Sprite::~Sprite --------//
- Sprite::~Sprite()
- {
- deinit();
- }
- //--------- End of function Sprite::~Sprite --------//
- //--------- Begin of function Sprite::init ---------//
- //
- void Sprite::init(short spriteId, short startXLoc, short startYLoc)
- {
- sprite_id = spriteId;
- cur_x = startXLoc * ZOOM_LOC_WIDTH;
- cur_y = startYLoc * ZOOM_LOC_HEIGHT;
- go_x = next_x = cur_x;
- go_y = next_y = cur_y;
- cur_attack = 0;
- cur_action = SPRITE_IDLE;
- cur_dir = m.random(MAX_SPRITE_DIR_TYPE); // facing any of the eight directions
- cur_frame = 1;
- final_dir = cur_dir;
- //----- clone vars from sprite_res for fast access -----//
- sprite_info = sprite_res[sprite_id];
- sprite_info->load_bitmap_res();
- //------------- init other vars --------------//
- remain_attack_delay = 0;
- remain_frames_per_step = sprite_info->frames_per_step;
- }
- //----------- End of function Sprite::init -----------//
- //--------- Begin of function Sprite::deinit ---------//
- //
- void Sprite::deinit()
- {
- if( sprite_id && cur_x >= 0 )
- {
- sprite_info->free_bitmap_res();
- sprite_id = 0;
- }
- }
- //----------- End of function Sprite::deinit -----------//
- //--------- Begin of function Sprite::cur_sprite_frame ---------//
- //
- // Return the current frame of the sprite
- //
- SpriteFrame* Sprite::cur_sprite_frame(int *needMirror)
- {
- UCHAR curDir = display_dir();
- if( needMirror)
- *needMirror = need_mirror(curDir);
- // do not update cur_dir as curDir
- err_when(curDir<0 || curDir>=3*MAX_SPRITE_DIR_TYPE);
- switch( cur_action )
- {
- case SPRITE_MOVE:
- //### begin alex 14/4 ###//
- case SPRITE_SHIP_EXTRA_MOVE:
- //#### end alex 14/4 ####//
- if( guard_count)
- {
- if( curDir >= MAX_SPRITE_DIR_TYPE)
- {
- err_here();
- curDir %= MAX_SPRITE_DIR_TYPE;
- }
- return sprite_frame_res[sprite_info->guard_move_array[curDir].first_frame_recno+cur_frame-1];
- }
- else
- return sprite_frame_res[sprite_info->move_array[curDir].first_frame_recno+cur_frame-1];
- case SPRITE_ATTACK:
- err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
- if( guard_count )
- {
- SpriteGuardStop *guardStopAction = sprite_info->guard_stop_array + curDir;
- return sprite_frame_res[guardStopAction->first_frame_recno+
- min(guard_count,guardStopAction->frame_count)-1];
- }
- else
- return sprite_frame_res[sprite_info->attack_array[cur_attack][curDir].first_frame_recno+cur_frame-1];
- case SPRITE_TURN:
- case SPRITE_IDLE:
- case SPRITE_WAIT:
- // air unit needs it own stop frames to float on air
- {
- if( guard_count )
- {
- if( curDir >= MAX_SPRITE_DIR_TYPE)
- {
- // if the sprite is turning, adjust direction to next
- if( turn_delay > 0)
- curDir ++;
- curDir %= MAX_SPRITE_DIR_TYPE;
- }
- SpriteGuardStop *guardStopAction = sprite_info->guard_stop_array + curDir;
- return sprite_frame_res[guardStopAction->first_frame_recno+
- min(guard_count,guardStopAction->frame_count)-1];
- }
- else
- {
- SpriteStop *stopAction= sprite_info->stop_array +curDir;
- if(cur_frame > stopAction->frame_count)
- return sprite_frame_res[stopAction->frame_recno]; // first frame
- else // only few sprite has stopAction->frame_count > 1
- return sprite_frame_res[stopAction->frame_recno+cur_frame-1];
- }
- }
- case SPRITE_DIE:
- if(sprite_info->die.first_frame_recno) // only if this sprite has dying frame
- {
- if( needMirror)
- *needMirror = 0; // no need to mirror at any direction
- return sprite_frame_res[sprite_info->die.first_frame_recno+cur_frame-1];
- }
- default:
- return sprite_frame_res[sprite_info->move_array[curDir].first_frame_recno+cur_frame-1];
- }
- }
- //----------- End of function Sprite::cur_sprite_frame -----------//
- //--------- Begin of function Sprite::update_abs_pos ---------//
- //
- // Update the cur_width & cur_height vars of the sprite for later faster access.
- //
- // [SpriteFrame *] spriteFrame pointer to the current (default : NULL)
- void Sprite::update_abs_pos(SpriteFrame *spriteFrame)
- {
- if( !spriteFrame )
- spriteFrame = cur_sprite_frame();
- abs_x1 = cur_x + spriteFrame->offset_x; // absolute position
- abs_y1 = cur_y + spriteFrame->offset_y;
- abs_x2 = abs_x1 + spriteFrame->width - 1;
- abs_y2 = abs_y1 + spriteFrame->height - 1;
- }
- //----------- End of function Sprite::update_abs_pos -----------//
- //--------- Begin of function Sprite::draw ---------//
- //
- void Sprite::draw()
- {
- //--------- draw sprite on the zoom window ---------//
- int needMirror;
- SpriteFrame* spriteFrame = cur_sprite_frame(&needMirror);
- update_abs_pos(spriteFrame);
- err_when( !sprite_info->res_bitmap.init_flag );
- char* bitmapPtr = sprite_info->res_bitmap.read_imported(spriteFrame->bitmap_offset);
- //-------- check if the sprite is inside the view area --------//
- int x1 = abs_x1-World::view_top_x; // the sprite's position in the view window
- if( x1 <= -spriteFrame->width || x1 >= ZOOM_WIDTH ) // out of the view area, not even a slight part of it appears in the view area
- return;
- int y1 = abs_y1-World::view_top_y;
- if( y1 <= -spriteFrame->height || y1 >= ZOOM_HEIGHT )
- return;
- //------- decide which approach to use for displaying -----//
- int x2 = abs_x2-World::view_top_x;
- int y2 = abs_y2-World::view_top_y;
- //---- only portion of the sprite is inside the view area ------//
- if( x1 < 0 || x2 >= ZOOM_WIDTH || y1 < 0 || y2 >= ZOOM_HEIGHT )
- {
- if( needMirror ) // if this direction needed to be mirrored
- {
- if( !sprite_info->remap_bitmap_flag )
- {
- vga_back.put_bitmap_area_trans_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
- max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
- }
- else
- {
- vga_back.remap_bitmap_area_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
- vga.vga_color_table->get_table_array(),
- max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
- }
- }
- else
- {
- if( !sprite_info->remap_bitmap_flag )
- {
- vga_back.put_bitmap_area_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
- max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
- }
- else
- {
- vga_back.remap_bitmap_area( x1+ZOOM_X1, y1+ZOOM_Y1, bitmapPtr,
- vga.vga_color_table->get_table_array(),
- max(0,x1)-x1, max(0,y1)-y1, min(ZOOM_WIDTH-1,x2)-x1, min(ZOOM_HEIGHT-1,y2)-y1 );
- }
- }
- }
- //---- the whole sprite is inside the view area ------//
- else
- {
- //------ mirror-bilting for certain directions ------//
- if( needMirror ) // if this direction needed to be mirrored
- {
- if( !sprite_info->remap_bitmap_flag )
- {
- vga_back.put_bitmap_trans_decompress_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1,
- bitmapPtr );
- }
- else
- {
- vga_back.remap_bitmap_hmirror( x1+ZOOM_X1, y1+ZOOM_Y1,
- bitmapPtr, vga.vga_color_table->get_table_array() );
- }
- }
- else
- {
- if( !sprite_info->remap_bitmap_flag )
- {
- vga_back.put_bitmap_trans_decompress( x1+ZOOM_X1, y1+ZOOM_Y1,
- bitmapPtr );
- }
- else
- {
- vga_back.remap_bitmap( x1+ZOOM_X1, y1+ZOOM_Y1,
- bitmapPtr, vga.vga_color_table->get_table_array() );
- }
- }
- }
- }
- //----------- End of function Sprite::draw -----------//
- // ---------- Begin of function Sprite::display_dir ---------//
- UCHAR Sprite::display_dir()
- {
- UCHAR curDir = cur_dir;
- switch( sprite_info->turn_resolution)
- {
- case 0: // fall through
- case 1:
- curDir &= ~7; // direction less, remain upward or downard, but set to north
- break;
- case 8:
- // cur_dir can be 0 to 3*MAX_SPRITE_DIR_TYPE-1, such as projectile;
- // curDir = cur_dir;
- break;
- case 16:
- err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
- // curDir should be (from due north, clockwisely) { 0,8,1,9,2,10,3,11,4,12,5,13,6,14,7,15 }
- if( turn_delay <= -30)
- {
- curDir = ((curDir+7) & 7) + 8;
- }
- else if( turn_delay >= 30)
- {
- curDir += 8;
- }
- break;
- case 24:
- err_when(curDir<0 || curDir>=MAX_SPRITE_DIR_TYPE);
- // curDir should be (from due north, clockwisely)
- // { 0,8,16,1,9,17,2,10,18,3,11,19,4,12,20,5,13,21,6,14,22,7,15,23 }
- if( turn_delay <= -20)
- {
- if( turn_delay <= -40)
- curDir = ((curDir+7) & 7) + 8;
- else
- curDir = ((curDir+7) & 7) + 16;
- }
- else if( turn_delay >= 20)
- {
- if( turn_delay >= 40 )
- curDir += 16;
- else
- curDir += 8;
- }
- break;
- default:
- err_here();
- }
- return curDir;
- }
- // ---------- End of function Sprite::display_dir ---------//
- // ---------- Begin of function Sprite::need_mirror --------//
- int Sprite::need_mirror(UCHAR dispDir)
- {
- return (dispDir < 8 || sprite_info->turn_resolution <= 8) ? (dispDir & 7) >= 5 : (dispDir & 7) >= 4;
- }
- // ---------- End of function Sprite::need_mirror --------//
- // ---------- Begin of function Sprite::is_shealth --------//
- int Sprite::is_shealth()
- {
- // if the visibility of location is just explored, consider shealth
- return config.fog_of_war && world.get_loc(cur_x_loc(), cur_y_loc())->visibility() <= EXPLORED_VISIBILITY;
- }
- // ---------- End of function Sprite::is_shealth --------//
|