/****************************************************************
SPACE INVADERS (V1.0), BY AHARON HILLEL.
gcc version 3.2 (mingw special 20020817-1)
ALLEGRO VERSION: 4.1.12 (WIP)
ALLEGRO DATE: 2003-11-10
****************************************************************/
#include "inv.h"
/***********************************************
PLACE ALL CLASSES THAT ARE USED BY INVADERS
GAME IN THIS FILE.
***********************************************/
st_bullet_params inv_formation::bullet_params = { 0 }; // Will be initialized b4 game starts.
st_pixel inv_formation::bullet_test_pixles[] = { 3,15, 4,15, 0,12, 7,12, 0,0, 7,0 };
st_colors inv_formation::bullet_test_colors = { 1, 15 };
inv_formation::inv_formation(BITMAP *dst, const int l, const st_formation_param &p) : formation(p), level(l)
{
dest = dst;
RLE_SPRITE *m_ship_sprite = (*game_sprites->images)[(*game_sprites).inv_mother_ship];
mother_ship.ship = NULL;
mother_ship.time_for_mother_ship = MOTHER_SHIP_TIME_EXPR;
mother_ship.e.index_low = (*game_sprites).inv_mother_ship;
mother_ship.e.index_high = mother_ship.e.index_low + 3;
mother_ship.e.x_min = -(m_ship_sprite->w);
mother_ship.e.y_min = MOTHER_SHIP_Y_TOP;
mother_ship.e.x_max = SCREEN_W + (m_ship_sprite->w);
mother_ship.e.y_max = MOTHER_SHIP_Y_TOP + (m_ship_sprite->h);
mother_ship.e.anim_type = ANIM_NONE;
invaders_landed_on_earth = G_FALSE;
next_bullet = 120;
n_fire_options = 0;
fire_options = (st_pixel *) malloc(get_cols() * sizeof(st_pixel));
memset(fire_options, 0, get_cols());
frame_rate_index = 7;
frame_rate_n_items[7] = get_live_items() - (get_live_items() / 6);
frame_rate_n_items[6] = get_live_items() - (get_live_items() / 4);
frame_rate_n_items[5] = get_live_items() - (get_live_items() / 3);
frame_rate_n_items[4] = get_live_items() - (get_live_items() / 2);
frame_rate_n_items[3] = (get_live_items() / 2) - (get_live_items() / 4);
frame_rate_n_items[2] = 4;
frame_rate_n_items[1] = 2;
frame_rate_n_items[0] = 0;
s_frame_rate = get_frame_rate() << 2;
};
int inv_formation::destroy_mother_ship(int hit_x_pos)
{
RLE_SPRITE *m_ship_sprite = (*game_sprites->images)[(*game_sprites).inv_mother_ship];
int m_ship_half_w = (m_ship_sprite->w >> 1);
int score;
int x = mother_ship.ship->get_x_pos();
int y = mother_ship.ship->get_y_pos();
int criteria = (int) (m_ship_sprite->w / 6);
class explosion *e = new explosion(&(*game_sprites->images)[0], dest, (*game_sprites).inv_mother_ship_explosion, (*game_sprites).inv_mother_ship_explosion+2, x+((m_ship_sprite->w) >> 1), y+((m_ship_sprite->h) >> 1), EXPLOSION_Z_ORDER, 4, G_TRUE, G_FALSE);
if(e)
explosions_list.push_back(e);
/* The more to the center - the higher-score */
if(abs(hit_x_pos - (x + m_ship_half_w)) > criteria)
{
score = 150;
e = new explosion(&(*game_sprites->images)[0], dest, (*game_sprites).inv_mother_ship_150, (*game_sprites).inv_mother_ship_150+2, x+((m_ship_sprite->w) >> 1), y+((m_ship_sprite->h) >> 1), EXPLOSION_Z_ORDER, 10, G_TRUE, G_FALSE);
if(e)
explosions_list.push_back(e);
}
else
{
score = 300;
e = new explosion(&(*game_sprites->images)[0], dest, (*game_sprites).inv_mother_ship_300, (*game_sprites).inv_mother_ship_300+2, x+((m_ship_sprite->w) >> 1), y+((m_ship_sprite->h) >> 1), EXPLOSION_Z_ORDER, 10, G_TRUE, G_FALSE);
if(e)
explosions_list.push_back(e);
}
if(sound_flag & SOUND_INVADERS)
{
stop_sample((SAMPLE *) s_data[S_INV_MOTHER_SHIP].dat);
play_sample((SAMPLE *) s_data[S_INV_MOTHER_SHIP_EXP].dat, 255, 128, 1000, 0);
}
delete (mother_ship.ship);
mother_ship.ship = NULL;
mother_ship.time_for_mother_ship = MOTHER_SHIP_TIME_EXPR;
return score;
};
void inv_formation::move_mother_ship(void)
{
int x_pos = mother_ship.ship->get_x_pos();
if((x_pos >= mother_ship.e.x_max) || (x_pos <= mother_ship.e.x_min))
{ // Destroy mother ship, and start count for new one.
delete (mother_ship.ship);
mother_ship.ship = NULL;
mother_ship.time_for_mother_ship = MOTHER_SHIP_TIME_EXPR;
if(sound_flag)
stop_sample((SAMPLE *) s_data[S_INV_MOTHER_SHIP].dat);
return;
}
mother_ship.ship->play_anim();
mother_ship.ship->set_pos(x_pos + mother_ship.x_inc, mother_ship.ship->get_y_pos(), G_FALSE);
}
void inv_formation::action()
{
if(mother_ship.time_for_mother_ship)
{
mother_ship.time_for_mother_ship--;
if((mother_ship.time_for_mother_ship == 0) && enemy::get_enemies())
{ // Create mother ship.
if(get_live_items() & 0x1)
{ // mother ship from right to left.
mother_ship.e.anim_type = ANIM_HIGH_LOW;
mother_ship.x_start = mother_ship.e.x_max;
mother_ship.x_inc = -2;
}
else
{ // mother ship from left to right.
mother_ship.e.anim_type = ANIM_LOW_HIGH;
mother_ship.x_start = mother_ship.e.x_min;
mother_ship.x_inc = 2;
}
mother_ship.ship = new enemy(&(*game_sprites->images)[0], dest, mother_ship.x_start+mother_ship.x_inc, mother_ship.e.y_min, 0, G_FALSE, G_FALSE, mother_ship.e);
if(sound_flag & SOUND_INVADERS)
play_sample((SAMPLE *) s_data[S_INV_MOTHER_SHIP].dat, 72, 128, 1000, 1);
}
}
if(mother_ship.ship)
move_mother_ship();
int l_items = get_live_items();
if(l_items == 0)
return;
if(!(attack_ok))
return; // Halt when no attack.
if(test_formation_bottom())
{ // Invaders landed on EARTH.
formation::clear_attack_ok();
invaders_landed_on_earth = G_TRUE;
return;
}
if(l_items < frame_rate_n_items[frame_rate_index])
{ // Decriment frame-rate for faster move.
set_frame_rate(get_frame_rate()-1);
if(frame_rate_index)
frame_rate_index--;
}
if(next_bullet)
next_bullet--;
else
{ // Handle invaders fire
next_bullet = (rand()) % 30;
get_fire_options(fire_options, get_cols(), &n_fire_options);
if(n_fire_options)
{ // Do fire.
int bullet_col = (rand() >> 3) % n_fire_options;
class bullet *p = new bullet(&(*game_sprites->images)[0], get_dest_bitmap(), NULL, (*game_sprites).inv_missile, fire_options[bullet_col].x-((*game_sprites->images)[(*game_sprites).inv_missile]->w >> 1), fire_options[bullet_col].y, PLAYER_BULLET_Z_ORDER, G_TRUE, G_FALSE, bullet_params);
if(p)
e_bullets_list.push_back(p);
}
}
s_frame_rate--;
if(!s_frame_rate)
{
s_frame_rate = get_frame_rate() << 2;
if(sound_flag & SOUND_INVADERS)
play_sample((SAMPLE *) s_data[S_INV_FORMATION].dat, 64, 128, 1000, 0);
}
return formation::action();
};
inv_formation::~inv_formation()
{
free(fire_options);
if(mother_ship.ship)
delete (mother_ship.ship);
};
class inv_formation *create_invaders_formation(unsigned char game_type, int level, RLE_SPRITE **dt, int index, BITMAP *dst)
{
st_formation_param p;
st_item *list; // To be deleted in formation destructor
st_formation_move *moves; // To be deleted in formation destructor
int formation_y_start;
int inv_types[INV_TYPES] = { 0, 1, 4, 11, 6, 7, 16, 8, 10, 15, 9, 5, 2, 14, 13, 12, 3, 17 };
if(!(game_type & BIT_INVADERS))
return NULL;
p.frame_rate = 8;
p.buffer = dst;
p.x_left_border = 0;
p.x_right_border = SCREEN_W;
p.y_top_border = 0;
p.y_bottom_border = GAME_FOOTER_BORDER_LINE-1;
if(game_type & BIT_GALAXIANS)
{
formation_y_start = GAL_INVADERS_FORMATION_Y_START;
p.cols = GAL_INVADERS_COLS;
p.rows = INV_GLAVADERS_ROWS; // GALVADERS game
}
else
{
formation_y_start = INV_INVADERS_FORMATION_Y_START;
p.cols = INVADERS_COLS;
p.rows = INVADERS_ROWS;
}
moves = new st_formation_move[5];
if(!moves)
return NULL;
// Move down initially.
int max_initial_moves_down = (((GAME_FOOTER_BORDER_LINE-1) - (formation_y_start+(p.rows*30))) / 30)-1;
moves[0].x_inc = 0; moves[0].y_inc = 5;moves[0].int_to_next_move = 1;
if(level < max_initial_moves_down)
moves[0].times = 6 * level;
else
moves[0].times = max_initial_moves_down * 6;
// move right.
moves[1].x_inc = 4; moves[1].y_inc = 0; moves[1].times = 1000; moves[1].int_to_next_move = 1;
// move down 1 row
moves[2].x_inc = 0; moves[2].y_inc = 5; moves[2].times = 6; moves[2].int_to_next_move = 1;
// move left.
moves[3].x_inc = -4; moves[3].y_inc = 0; moves[3].times = 1000; moves[3].int_to_next_move = 1;
// move down 1 row, and back to move right.
moves[4].x_inc = 0; moves[4].y_inc = 5; moves[4].times = 6; moves[4].int_to_next_move = -3;
list = new st_item[p.rows * p.cols];
if(!list)
{
delete(moves);
return NULL;
}
memset(list, 0, p.rows*p.cols*sizeof(st_item));
/* To be deleted when formation object comes out of scoop */
p.list = list;
p.moves = moves;
/* Allocate enemy sprites */
st_enemy_params e;
e.x_min = e.y_min = 0;
e.x_max = SCREEN_W;
e.y_max = SCREEN_H;
int offset;
for(int i = 0 ; i < p.rows ; i++)
for(int j = 0; j < p.cols; j++)
{ // set st_enemy_params properly, then create the object.
e.index_low = index+inv_types[(((level-1)+(p.rows-i-1)) / 2) % INV_TYPES];
switch(e.index_low)
{
case 0 : // 0-10 are two phase, incremental index animation
case 1 : // sprites.
case 2 :
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
case 8 :
case 9 :
case 10: e.index_low *= 2;
e.index_high = e.index_low+1;
e.anim_type = ANIM_LOW_HIGH;
break;
case 11: // 11, 12, 14,15,16 are four phase, ping-pong index animation
case 12:
case 14:
case 15: // sprites.
case 16: e.index_low = 22+((e.index_low - 11)*4);
e.index_high = e.index_low+3;
e.anim_type = ANIM_PING_PONG;
break;
case 13: // 13,17 are four phase, incremental index animation
case 17: e.index_low = 22+((e.index_low - 11)*4);
e.index_high = e.index_low+3;
e.anim_type = ANIM_LOW_HIGH;
break;
default: e.index_low = index; e.index_high = e.index_low+1; e.anim_type = ANIM_LOW_HIGH;
} // End of switch
offset = (p.cols*i)+j;
list[offset].x = j * INVADER_W;
list[offset].y = formation_y_start + (INVADER_H * i);
list[offset].sample = S_INV_DEAD_INVADER;
list[offset].state = ITEM_IN_FORMATION;
list[offset].score = (p.rows-i) * 5;
list[offset].sprite = new class enemy(dt, dst, list[offset].x, list[offset].y, INVADERS_Z_ORDER, G_FALSE, G_TRUE, e);
if(!(list[offset].sprite)) // Failed to allocate, don't use this one.
list[offset].state = ITEM_IS_DEAD;
} // End of for(j...
return new class inv_formation(dst, level, p);
}
END_OF_FUNCTION(create_invaders_formation);
|