Beispiel #1
0
//--------- Begin of function Bullet::init ---------//
//
// <char> parentType		- the type of object emits the bullet
// <short> parentRecno	- the recno of the object
// <short> targetXLoc	- the x loc of the target
// <short> targetYLoc	- the y loc of the target
//	<char> targetMobileType - target mobile type
//
void Bullet::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	parent_type = parentType;
	parent_recno = parentRecno;
	target_mobile_type = targetMobileType;

	//**** BUGHERE, using parentType and parentRecno to allow bullet by firm, town, etc.
	//**** BUGHERE, only allow bullet by unit for this version
	err_when(parent_type!=BULLET_BY_UNIT);
	Unit *parentUnit = unit_array[parentRecno];

	//---------- copy attack info from the parent unit --------//

	AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;

	attack_damage  = parentUnit->actual_damage();
	damage_radius  = attackInfo->bullet_radius;
	nation_recno   = parentUnit->nation_recno;
	// ###### begin Gilbert 26/6 ########## //
	fire_radius    = attackInfo->fire_radius;
	// ###### end Gilbert 26/6 ########## //

	//----- clone vars from sprite_res for fast access -----//

	sprite_id 	= attackInfo->bullet_sprite_id;
	sprite_info = sprite_res[sprite_id];

	sprite_info->load_bitmap_res();		// the sprite bitmap will be freed by ~Sprite(), so we don't have to add ~Bullet() to free it. 

	//--------- set the starting position of the bullet -------//

	cur_action = SPRITE_MOVE;
	cur_frame  = 1;
	set_dir(parentUnit->attack_dir);

	SpriteFrame* spriteFrame = cur_sprite_frame();

	origin_x = cur_x = parentUnit->cur_x;
	origin_y = cur_y = parentUnit->cur_y;

	//------ set the target position and bullet mobile_type -------//

	target_x_loc = targetXLoc;
	target_y_loc = targetYLoc;

	go_x = target_x_loc * ZOOM_LOC_WIDTH  + ZOOM_LOC_WIDTH/2  - spriteFrame->offset_x - spriteFrame->width/2;			// -spriteFrame->offset_x to make abs_x1 & abs_y1 = original x1 & y1. So the bullet will be centered on the target
	go_y = target_y_loc * ZOOM_LOC_HEIGHT + ZOOM_LOC_HEIGHT/2 - spriteFrame->offset_y - spriteFrame->height/2;

	mobile_type = parentUnit->mobile_type;

	//---------- set bullet movement steps -----------//

	int xStep 	= (go_x - cur_x)/attackInfo->bullet_speed;
	int yStep 	= (go_y - cur_y)/attackInfo->bullet_speed;

	total_step  = MAX(1, MAX(abs(xStep), abs(yStep)));
	cur_step    = 0;

	err_when( total_step < 0 );		// number overflow
}
Beispiel #2
0
// --------- begin of function BulletHoming::init --------//
void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);

	// ------- find the maximum range --------//

	//**** BUGHERE, using parentType and parentRecno to allow bullet by firm, town, etc.
	//**** BUGHERE, only allow bullet by unit for this version
	err_when(parent_type!=BULLET_BY_UNIT);
	Unit *parentUnit = unit_array[parentRecno];

	//---------- copy attack info from the parent unit --------//

	AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
	speed = attackInfo->bullet_speed;
	max_step = char((attackInfo->attack_range * ZOOM_LOC_WIDTH + speed-1)/ speed);

	//--------- keep backup of centre of the bullet ---------//
	SpriteFrame *spriteFrame = cur_sprite_frame();

	// origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
	origin_x += spriteFrame->offset_x + spriteFrame->width/2;
	origin_y += spriteFrame->offset_y + spriteFrame->height/2;
	origin2_x = origin_x; 
	origin2_y = origin_y;
	go_x += spriteFrame->offset_x + spriteFrame->width/2;
	go_y += spriteFrame->offset_y + spriteFrame->height/2;

	// ------- find the target_type and target_recno ------//
	Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
	//### begin alex 16/5 ###//
	//if( locPtr->has_unit(mobile_type) )
	if(locPtr->has_unit(targetMobileType))
	{
		target_type = BULLET_TARGET_UNIT;
		//target_recno = locPtr->unit_recno(mobile_type);
		target_recno = locPtr->unit_recno(targetMobileType);
	}
	//#### end alex 16/5 ####//
	else if( locPtr->is_town() )
	{
		target_type = BULLET_TARGET_TOWN;
		target_recno = locPtr->town_recno();
	}
	else if( locPtr->is_firm() )
	{
		target_type = BULLET_TARGET_FIRM;
		target_recno = locPtr->firm_recno();
	}
	else if( locPtr->is_wall() )
	{
		target_type = BULLET_TARGET_WALL;
	}
}
Beispiel #3
0
//--------- 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;
}
Beispiel #4
0
// --------- begin of function BulletHoming::init --------//
void BulletHoming::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);

	// ------- find the maximum range --------//

	BaseObj *baseObjPtr = base_obj_array[parent_base_obj_recno];
	if( baseObjPtr->cast_to_Unit() )
	{
		Unit *parentUnit = base_obj_array[parent_base_obj_recno]->cast_to_Unit();
		AttackInfo* attackInfo = parentUnit->attack_info_array+parentUnit->cur_attack;
		speed = attackInfo->bullet_speed;
		max_step = char((attackInfo->attack_range * LOCATE_WIDTH + speed-1)/ speed);
	}
	else if( baseObjPtr->cast_to_Firm() && baseObjPtr->cast_to_Firm()->cast_to_FirmFort() )
	{
		FirmFort *firmFort = baseObjPtr->cast_to_Firm()->cast_to_FirmFort();
		speed = firmFort->bullet_speed();
		max_step = 100;		// unlimited range
	}
	else
	{
		err_here();
	}

	//--------- keep backup of centre of the bullet ---------//
	SpriteFrame *spriteFrame = cur_sprite_frame();

	// origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
	origin_x += spriteFrame->offset_x + spriteFrame->width/2;
	origin_y += spriteFrame->offset_y + spriteFrame->height/2;
	origin2_x = origin_x; 
	origin2_y = origin_y;
	go_x += spriteFrame->offset_x + spriteFrame->width/2;
	go_y += spriteFrame->offset_y + spriteFrame->height/2;

	// ------- find the target_type and target_recno ------//

	Location *locPtr = world.get_loc(targetXLoc, targetYLoc);
	target_base_obj_recno = locPtr->base_obj_recno(targetMobileType);
}
Beispiel #5
0
// --------- Begin of function Projectile::init --------//
//### begin alex 3/5 ###//
void Projectile::init(char parentType, short parentRecno, short targetXLoc, short targetYLoc, char targetMobileType)
{
	Bullet::init(parentType, parentRecno, targetXLoc, targetYLoc, targetMobileType);
//#### end alex 3/5 ####//
	short spriteId = sprite_info->get_sub_sprite_info(1)->sprite_id;
	act_bullet.init( spriteId, cur_x_loc(), cur_y_loc() );
	short shadowSpriteId = sprite_info->get_sub_sprite_info(2)->sprite_id;
	bullet_shadow.init( shadowSpriteId, cur_x_loc(), cur_y_loc() );

	// calculate z_coff;
	z_coff = (float)1.0;
	/*
	float dz = z_coff * total_step;
	if( dz >= 10.0)
		cur_dir = cur_dir & 7 | 8;					// pointing up
	else if( dz <= -10.0)
		cur_dir = cur_dir & 7 | 16;				// pointing down
	else
		cur_dir &= 7;
	*/

	// --------- recalcuate spriteFrame pointer ----------//
	SpriteFrame* spriteFrame = cur_sprite_frame();
}
Beispiel #6
0
// --------- begin of function BulletHoming::process_move --------//
void BulletHoming::process_move()
{
	int actualStep = total_step;

	if(target_type == BULLET_TARGET_UNIT)
	{
		Unit *unitPtr;
		if( unit_array.is_deleted(target_recno) || 
			!(unitPtr = unit_array[target_recno]) || 
			!unitPtr->is_visible() )
		{
			// target lost/die, proceed to Bullet::process_move
			target_type = BULLET_TARGET_NONE;
		}
		else
		{
			// ---- calculate new target_x_loc, target_y_loc -----//	

			target_x_loc = unitPtr->next_x_loc();
			target_y_loc = unitPtr->next_y_loc();

			// ---- re-calculate go_x, go_y  ------//
			// go_x/y and origin2_x/y are pointing at the centre of the bullet bitmap
			// it is different from Bullet
			go_x = unitPtr->cur_x + ZOOM_LOC_WIDTH / 2;
			go_y = unitPtr->cur_y + ZOOM_LOC_HEIGHT /2;

			//---------- set bullet movement steps -----------//
			SpriteFrame *spriteFrame = cur_sprite_frame();
			int adjX = spriteFrame->offset_x+spriteFrame->width/2;
			int adjY = spriteFrame->offset_y+spriteFrame->height/2;

			int xStep 	= abs(go_x - (cur_x+adjX))/speed;
			int yStep 	= abs(go_y - (cur_y+adjY))/speed;
			total_step  = cur_step +  MAX(xStep, yStep);

			// a homing bullet has a limited range, if the target go outside the
			// the limit, the bullet can't attack the target
			// in this case, actualStep is the number step from the source
			// to the target; total_step is the max_step
			// otherwise, actualStep is as same as total_step
			
			actualStep = total_step;
			if( total_step > max_step )
			{
				total_step = max_step;
				// target_x_loc and target_y_loc is limited also
				target_x_loc = (cur_x + adjX) + (int)(go_x-(cur_x+adjX)) / (actualStep - total_step) / ZOOM_LOC_WIDTH;
				target_x_loc = (cur_y + adjY) + (int)(go_y-(cur_y+adjY)) / (actualStep - total_step) / ZOOM_LOC_HEIGHT;
			}
		}
	}

//	origin2_x = origin_x;
//	origin2_y = origin_y;

	// origin_x/y and origin2_x/y are pointing at the centre of the bullet bitmap //
	SpriteFrame *spriteFrame = cur_sprite_frame();
	short adjX = spriteFrame->offset_x + spriteFrame->width/2;
	short adjY = spriteFrame->offset_y + spriteFrame->height/2;
	origin_x = cur_x + adjX;
	origin_y = cur_y + adjY;

	cur_x = origin_x + (int)(go_x-origin_x) / (actualStep + 1 - cur_step);
	cur_y = origin_y + (int)(go_y-origin_y) / (actualStep + 1 - cur_step);
	// cur_x, cur_y is temporary pointing at the centre of bullet bitmap

	// detect changing direction
	if( cur_step > 3 )	// not allow changing direction so fast
		set_dir(origin2_x, origin2_y, cur_x, cur_y);

	// change cur_x, cur_y to bitmap reference point
	spriteFrame= cur_sprite_frame();
	adjX = spriteFrame->offset_x + spriteFrame->width/2;
	adjY = spriteFrame->offset_y + spriteFrame->height/2;
	cur_x -= adjX;
	cur_y -= adjY;

	cur_step++;

	//------- update frame id. --------//

	if( ++cur_frame > cur_sprite_move()->frame_count )
		cur_frame = 1;

	//----- if the sprite has reach the destintion ----//

	if( cur_step > total_step )
	{
		check_hit();

		cur_action = SPRITE_DIE;		// Explosion
		// ###### begin Gilbert 17/5 ########//
		// if it has die frame, adjust cur_x, cur_y to be align with the target_x_loc, target_y_loc
		if( sprite_info->die.first_frame_recno )
		{
			next_x = cur_x = target_x_loc * ZOOM_LOC_WIDTH;
			next_y = cur_y = target_y_loc * ZOOM_LOC_HEIGHT;
		}
		// ###### end Gilbert 17/5 ########//
		cur_frame = 1;
	}
	// change of total_step may not call warn_target, so call more warn_target
	else if( total_step - cur_step <= 1 )
	{
		warn_target();
	}
}
Beispiel #7
0
//--------- 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.initialized() );

	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() );
			}
		}
	}
}