/****************************************************************
GLAXIANS (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 <math.h>
#include "galaxy.h"
/***********************************************
PLACE ALL CLASSES THAT ARE USED BY GLAXIANS
GAME IN THIS FILE.
***********************************************/
st_pixel gal_formation::bullet_test_pixles[] = { 2,11 ,4,11 ,0,8 ,6,8, 2,0, 4,0 };
st_colors gal_formation::bullet_test_colors = { 1, 15 };
st_bullet_params gal_formation::bullet_params = { 0 }; // Will be initialized b4 game starts.
int gal_attack::attacks = 0;
int gal_attack::player_half_width = 0;
int gal_attack::lowest_y_shooting_point = 0;
int gal_attack::states[5][5] = { 2,2,0,8,8, 2,2,1,8,8, 3,3,5,7,7, 9,4,5,6,10, 9,9,5,10,10 };
int gal_attack::home_rotation_states[12] = { 4,4,4,3,3,3,2,2,2,1,1,0 };
#define ADD_LEFT_EXIT_ROTATION(MOVES,MOVE) \
{ \
MOVE.x = 0; MOVE.y = -2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = -2; MOVE.y = -2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = -2; MOVE.y = 0; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = -2; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 0; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
}
#define ADD_RIGHT_EXIT_ROTATION(MOVES,MOVE) \
{ \
MOVE.x = 0; MOVE.y = -2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 2; MOVE.y = -2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 2; MOVE.y = 0; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 2; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 0; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
}
#define ADD_RIGHT_TO_LEFT_ROTATE(MOVES,MOVE,TOP_Y) \
{ \
MOVE.x = 2; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 0; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = -2; MOVE.y = 2; MOVE.times = 8; \
MOVES.push_back(MOVE); \
TOP_Y += 32; \
}
#define ADD_LEFT_TO_RIGHT_ROTATE(MOVES,MOVE,TOP_Y) \
{ \
MOVE.x = -2; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 0; MOVE.y = 2; MOVE.times = 4; \
MOVES.push_back(MOVE); \
MOVE.x = 2; MOVE.y = 2; MOVE.times = 8; \
MOVES.push_back(MOVE); \
TOP_Y += 32; \
}
gal_attack::gal_attack(st_item **attack_sprites, unsigned int f_min, unsigned int f_max, int n)
{ /* Build the attack pattern */
int i;
home_rotation_state = 0;
mode = GALAXY_ATTACK_MODE_ATTACKING;
n_items = n;
frame_rate_min = f_min;
frame_rate_max = f_max;
items = (st_attack_item *) calloc(n_items, sizeof(st_attack_item)); // Delete in destructor.
base_counter = galaxians->get_counter();
for(i = 0; i < n_items; i++)
{
items[i].item = attack_sprites[i];
items[i].item->sprite->set_bg_flag();
items[i].item->state = ITEM_IN_ATTACK;
items[i].state_before_attack = attack_sprites[i]->sprite->get_sprite_index();
items[i].base_index = attack_sprites[i]->sprite->get_index_low();
}
leftmost_x = items[0].item->sprite->get_x_pos();
top_y = items[0].item->sprite->get_y_pos();
if(items[0].item->score == 100)
if(n_items > 1)
items[0].item->score <<= (n_items-1);
fire_rate = 35 - (galaxians->get_level());
if(fire_rate < 20)
fire_rate = 20;
fire_counter = fire_rate + (rand() & 7);
attacks++;
build_attack_script(G_TRUE);
}
void gal_attack::build_attack_script(int exit_from_formation)
{
int x_inc;
int y_inc;
int t;
st_attack_move m;
frame_rate = frame_counter = frame_rate_min;
moves.clear();
/* if attack originate from leftmost/rightmost quarter of screen: */
/* commit 1st type of attack, otherwise (middle) 2nd type. */
if(!exit_from_formation)
{ // Will go faster when attacking from top-screen.
frame_rate = frame_counter = frame_rate_max;
top_y = 0; // Start from top of screen.
}
y_inc = 2;
if(leftmost_x < (SCREEN_W >> 1))
{
if(exit_from_formation)
ADD_LEFT_EXIT_ROTATION(moves,m)
x_inc = 4;
if(leftmost_x > (SCREEN_W >> 2))
{
x_inc = 2; y_inc = 4;
}
}
else
{
if(exit_from_formation)
ADD_RIGHT_EXIT_ROTATION(moves,m)
x_inc = -4;
if((SCREEN_W - leftmost_x) > (SCREEN_W >> 2))
{
x_inc = -2; y_inc = 4;
}
}
t = top_y >> 1;
t += rand() % (SCREEN_H >> 3);
if((top_y + (t * y_inc)) > SCREEN_H)
t = ((SCREEN_H - top_y) / y_inc);
/* Add first attack phase */
m.x = x_inc; m.y = y_inc; m.times = t;
moves.push_back(m);
top_y += (t * y_inc);
/* Transition from 1st phase to second */
if(x_inc < 0)
ADD_LEFT_TO_RIGHT_ROTATE(moves,m,top_y)
else
ADD_RIGHT_TO_LEFT_ROTATE(moves,m,top_y)
/* Computer for 2nd phase. */
x_inc = -x_inc;
if(y_inc < 4)
{
x_inc /= 2;
y_inc = 4;
}
else
x_inc *= 2;
t = ((SCREEN_H - top_y) / y_inc);
if(t > 0)
{ /* Add second attack phase */
m.x = x_inc; m.y = y_inc; m.times = t;
moves.push_back(m);
}
iter = moves.begin();
times = iter->times;
if(sound_flag & SOUND_GALAXY)
play_sample((SAMPLE *) s_data[S_GALAXY_CHARCHING].dat, 192, 128, 1000, 0);
}
void gal_attack::remove(void)
{
for(int i = n_items-1; i >= 0; i--)
if(items[i].item->state != ITEM_IS_DEAD)
items[i].item->sprite->remove();
}
void gal_attack::draw(void)
{
for(int i = 0; i < n_items; i++)
if(items[i].item->state != ITEM_IS_DEAD)
items[i].item->sprite->draw();
}
void gal_attack::do_attack(void)
{ /* Play the attack script */
st_attack_item *p_item;
int i;
int x_inc;
int y_inc;
int live_items;
class enemy *shooting_item = NULL;
if(frame_counter == 0)
{ // Skip a frame every "frame_rate" count.
frame_counter = frame_rate;
return;
}
frame_counter--;
switch(mode)
{
case GALAXY_ATTACK_MODE_ROTATE_BACK:
live_items = 0;
for(i = 0; i < n_items; i++)
{
p_item = &items[i];
if(p_item->item->state != ITEM_IS_DEAD)
{
live_items++;
p_item->item->sprite->set_sprite_index(p_item->base_index+home_rotation_states[home_rotation_state]);
p_item->item->sprite->set_pos(p_item->item->x,p_item->item->y, G_FALSE);
}
}
if(!live_items) /* all are dead, destroy */
{
mode = -1; // Attack DONE!
return;
}
if(home_rotation_state == 11)
{
for(i = 0; i < n_items; i++)
{
p_item = &items[i];
if(p_item->item->state != ITEM_IS_DEAD)
{
p_item->item->sprite->set_sprite_index(p_item->state_before_attack);
if((galaxians->get_counter() - base_counter) & 1)
p_item->item->sprite->play_anim(); // sync with everybody.
p_item->item->sprite->clear_bg_flag();
p_item->item->state = ITEM_IN_FORMATION;
if(p_item->item->score > 100)
p_item->item->score = 100;
}
}
mode = -1; // Attack DONE!
return;
}
home_rotation_state++;
return;
case GALAXY_ATTACK_MODE_BACK_HOME:
y_inc = 3;
live_items = 0;
for(i = 0; i < n_items; i++)
{
p_item = &items[i];
if(p_item->item->state != ITEM_IS_DEAD)
{
if(abs(p_item->item->sprite->get_y_pos() - p_item->item->y) < 5)
{ // Transition to back-home-rotation state.
mode = GALAXY_ATTACK_MODE_ROTATE_BACK;
home_rotation_state = 0;
return;
}
live_items++;
p_item->item->sprite->set_sprite_index(p_item->base_index+states[(y_inc >> 1) +2][2]);
p_item->item->sprite->set_pos(p_item->item->x,p_item->item->sprite->get_y_pos() + y_inc, G_FALSE);
}
}
if(!live_items) /* all are dead, destroy */
{
mode = -1; // Attack DONE!
return;
}
break;
case GALAXY_ATTACK_MODE_ATTACKING:
if(times)
{
live_items = 0;
x_inc = iter->x;
y_inc = iter->y;
for(i = 0; i < n_items; i++)
{
p_item = &items[i];
if(p_item->item->state != ITEM_IS_DEAD)
{
live_items++;
shooting_item = p_item->item->sprite;
shooting_item->set_sprite_index(p_item->base_index+states[(y_inc >> 1) +2][(x_inc >> 1) +2]);
shooting_item->set_pos(shooting_item->get_x_pos() + x_inc,shooting_item->get_y_pos() + y_inc, G_FALSE);
}
}
times--;
if(!live_items) /* all are dead, destroy */
mode = -1; /* Attack DONE! */
if(fire_counter)
fire_counter--;
else
{ // Do fire.
fire_counter = fire_rate + (rand() & 7);
if(shooting_item)
{
int x_fire_source = shooting_item->get_x_pos()+((*game_sprites->images)[(*game_sprites).gal_bullet]->w >> 1);
int y_fire_source = shooting_item->get_y_pos()+((*game_sprites->images)[shooting_item->get_sprite_index()]->h >> 1);
int x_gap_1 = SCREEN_W;
int x_gap_2 = SCREEN_W;
if(y_fire_source < lowest_y_shooting_point)
{ // Commit fire only over this point.
if(player_1->get_lives())
x_gap_1 = (player_1->get_x_pos()+player_half_width) - x_fire_source;
if(player_2->get_lives())
x_gap_2 = (player_2->get_x_pos()+player_half_width) - x_fire_source;
if(abs(x_gap_1) <= abs(x_gap_2))
galaxians->bullet_params.x_inc = (int) (x_gap_1 / ((SCREEN_H - y_fire_source) / galaxians->bullet_params.y_inc));
else
galaxians->bullet_params.x_inc = (int)(x_gap_2 / ((SCREEN_H - y_fire_source) / galaxians->bullet_params.y_inc));
if(galaxians->bullet_params.x_inc > 4)
galaxians->bullet_params.x_inc = 4;
if(galaxians->bullet_params.x_inc < -4)
galaxians->bullet_params.x_inc = -4;
class bullet *p = new bullet(&(*game_sprites->images)[0], shooting_item->get_dest_bitmap(), NULL, (*game_sprites).gal_bullet, x_fire_source, y_fire_source, PLAYER_BULLET_Z_ORDER, G_TRUE, G_FALSE, galaxians->bullet_params);
if(p)
e_bullets_list.push_back(p);
}
}
}
return;
}
if(iter != moves.end())
{
iter++;
if(iter != moves.end())
{
times = iter->times;
}
else
{ /* Finished attack, go back home */
for(i = n_items-1; i >= 0; i--)
if(items[i].item->state != ITEM_IS_DEAD)
{ // Go back to top of screen.
leftmost_x = items[i].item->x;
items[i].item->sprite->set_pos(leftmost_x,items[i].item->sprite->get_y_pos() - SCREEN_H,G_FALSE);
}
if((formation::get_attack_ok()) && (galaxians->get_live_items() <= (galaxians->get_max_attacks()+1)))
return build_attack_script(G_FALSE);
else
{ // Slow down when going back home.
frame_rate = frame_counter = frame_rate_min;
mode = GALAXY_ATTACK_MODE_BACK_HOME;
}
return;
}
}
break;
} /* End of switch */
}
gal_attack::~gal_attack()
{
attacks--;
free(items);
}
gal_formation::gal_formation(const int l, const st_formation_param &p) : formation(p), level(l)
{
attack_counter = 0;
frame_rate_index = 2;
frame_rate_n_items[2] = (get_live_items() / 3) * 2;
frame_rate_n_items[1] = get_live_items() / 3;
frame_rate_n_items[0] = 0;
if(level > 20)
wave_rate = 10;
else
wave_rate = 50 - (level * 2);
if(level < 9)
{ // Moderate game under level 9.
attack_min_speed = attack_max_speed = 6 + level;
}
else
{ // Fast game from level 9.
attack_min_speed = 15;
attack_max_speed = 1000;
}
wave_counter = (wave_rate << 1);
max_attacks = level;
if(max_attacks > 5)
max_attacks = 5;
attack_row[0] = attack_row[1] = get_rows()-1;
};
void gal_formation::action()
{
int l_items = get_live_items();
if(l_items == 0)
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--;
}
/***** Canceled, no sound for galaxian-moving-formation.
if(gal_attack::attacks == 0) // Sound formation.
if((!voice_check(S_GALAXY_FORMATION)) && (sound_flag & SOUND_GALAXY)) // If currently NOT played.
play_sample((SAMPLE *) s_data[S_GALAXY_FORMATION].dat, 255, 128, 1000, 0);
******/
// Stop attack at full capacity.
if(gal_attack::attacks == max_attacks)
wave_counter = (wave_rate << 1);
// Let player get ready before going back to attack.
if(!(attack_ok))
wave_counter = 120;
if(wave_counter)
{
wave_counter--;
return formation::action();
}
/* Let player rest every max-attacks */
if(attack_counter % max_attacks)
wave_counter = wave_rate;
else
wave_counter = 120;
/* Finally it time to attack! */
st_item *atk_items[3];
int n_atk_items = 0;
int atk_col;
int *atk_row;
*atk_items = NULL;
if(attack_counter & 1)
{ /* Attack starts from right. */
atk_row = &attack_row[1];
if((attack_counter & 3) == 3)
*atk_row = 0; // Jump to bonus every 3 attacks.
for( ; ((!n_atk_items) && ((*atk_row) >= 0)) ; (*atk_row)--)
for(atk_col = get_cols()-1 ; atk_col >= 0 ; atk_col--)
{ // Once fond attack item break from both loops.
*atk_items = get_item((*atk_row), atk_col);
if(*atk_items)
if((*atk_items)->state == ITEM_IN_FORMATION)
{
n_atk_items++;
break;
}
}
}
else
{ /* Attack starts from left. */
atk_row = &attack_row[0];
if((attack_counter & 3) == 3)
*atk_row = 0; // Jump to bonus every 3 attacks.
for( ; ((!n_atk_items) && (*atk_row) >= 0) ; (*atk_row)--)
for(atk_col = 0 ; atk_col < get_cols(); atk_col++)
{ // Once fond attack item break from both loops.
*atk_items = get_item((*atk_row), atk_col);
if(*atk_items)
if((*atk_items)->state == ITEM_IN_FORMATION)
{
n_atk_items++;
break;
}
}
}
(*atk_row)++; // Fix redundant decriment.
if((n_atk_items) && ((*atk_row) == 0))
{ /* Build triplet attack. */
if(atk_col)
atk_col--;
for(int j = 0; (j < 3); j++,atk_col++)
{
if(n_atk_items >= 3)
break;
if(atk_col == get_cols())
break;
atk_items[n_atk_items] = get_item(1, atk_col);
if(atk_items[n_atk_items])
if(atk_items[n_atk_items]->state == ITEM_IN_FORMATION)
n_atk_items++;
}
}
(*atk_row)--;
if((*atk_row) < 0)
(*atk_row) = get_rows()-1;
attack_counter++;
if(n_atk_items)
{
class gal_attack *p = new class gal_attack(atk_items, attack_min_speed, attack_max_speed, n_atk_items);
if(p)
gal_attack_list.push_back(p);
}
return formation::action();
};
gal_formation::~gal_formation()
{
};
class gal_formation *create_galaxian_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;
if(!(game_type & BIT_GALAXIANS))
return NULL;
p.buffer = dst;
p.x_left_border = 0;
p.x_right_border = SCREEN_W;
p.y_top_border = 0;
p.y_bottom_border = SCREEN_H;
p.frame_rate = 7;
p.cols = GALAXY_COLS;
if(game_type & BIT_INVADERS)
{
formation_y_start = GALVADERS_GALAXY_FORMATION_Y_START;
p.rows = GAL_GALVADERS_ROWS; // GALVADERS game
}
else
{
formation_y_start = GAL_GALAXY_FORMATION_Y_START;
p.rows = GALAXY_ROWS;
}
moves = new st_formation_move[4];
if(!moves)
return NULL;
// move right.
moves[0].x_inc = 4; moves[0].y_inc = 0; moves[0].times = 1000; moves[0].int_to_next_move = 1;
// move down 35 pix (1 row = 30 pix)
moves[1].x_inc = 0; moves[1].y_inc = 5; moves[1].times = 6; moves[1].int_to_next_move = 1;
// move left.
moves[2].x_inc = -4; moves[2].y_inc = 0; moves[2].times = 1000; moves[2].int_to_next_move = 1;
// move down 35 pix (1 row = 30 pix), and back to move right.
moves[3].x_inc = 0; moves[3].y_inc = -5; moves[3].times = 6; moves[3].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 top_row_sprites[] = { 3, 6, 4, 5, 2, 7 };
int offset,i ,j;
int e_per_row;
e_per_row = 1 + (level % 18); // 1-more elian every 3 levels.
if(e_per_row > 6)
e_per_row = 6;
/* Do the top row (bonus items) */
e.index_low = index;
e.index_high = e.index_low+1;
e.anim_type = ANIM_LOW_HIGH;
int t_score = 100; // Bonus items start at 100pts.
for(i = 0; i < e_per_row; i++)
{
list[top_row_sprites[i]].x = (top_row_sprites[i]) * GALAXY_W;
list[top_row_sprites[i]].y = formation_y_start; // First row.
list[top_row_sprites[i]].sample = S_GALAXY_BONUS;
list[top_row_sprites[i]].state = ITEM_IN_FORMATION;
list[top_row_sprites[i]].score = t_score;
list[top_row_sprites[i]].sprite = new class enemy(dt, dst, list[top_row_sprites[i]].x, list[top_row_sprites[i]].y, GALAXY_Z_ORDER, G_FALSE, G_TRUE, e);
if(!(list[top_row_sprites[i]].sprite)) // Failed to allocate, don't use this one.
list[top_row_sprites[i]].state = ITEM_IS_DEAD;
}
#define DO_ROW_ITEMS(SAMPLE) { \
offset = (p.cols*i)+j; \
list[offset].x = j * GALAXY_W; \
list[offset].y = (i * GALAXY_H) + formation_y_start; \
list[offset].sample = SAMPLE; \
list[offset].state = ITEM_IN_FORMATION; \
list[offset].score = t_score; \
list[offset].sprite = new class enemy(dt, dst, list[offset].x, list[offset].y, GALAXY_Z_ORDER, G_FALSE, G_TRUE, e); \
if(!(list[offset].sprite)) \
list[offset].state = ITEM_IS_DEAD; \
}
/* Do the 2nd row */
t_score = 40;
e_per_row = 6; i = 1;
e.index_low = index + GALAXY_INC_ROW_SPRITE;
e.index_high = e.index_low+1;
e.anim_type = ANIM_LOW_HIGH;
for(j = 2 ; j < (2+e_per_row) ; j++)
DO_ROW_ITEMS(S_GALAXY_DEAD_FLY);
/* Do the 3rd, 4th rows */
t_score = 30;
e_per_row = 8; i = 2;
e.index_low = index + (2*GALAXY_INC_ROW_SPRITE);
e.index_high = e.index_low+1;
e.anim_type = ANIM_LOW_HIGH;
for(i = 2; i < 4; i++)
for(j = 1 ; j < (1+e_per_row) ; j++)
DO_ROW_ITEMS(S_GALAXY_DEAD_BEE);
/* Do 5,6 rows */
t_score = 20;
e_per_row = 10;
e.index_low = index + (3*GALAXY_INC_ROW_SPRITE);
e.index_high = e.index_low+1;
e.anim_type = ANIM_LOW_HIGH;
for(i = 4; i < p.rows; i++)
for(j = 0 ; j < e_per_row ; j++)
DO_ROW_ITEMS(S_GALAXY_DEAD_FLY);
return new class gal_formation(level, p);
}
END_OF_FUNCTION(create_galaxian_formation);
/* START - Class stars */
stars::stars()
{
dest = NULL;
stars_info = NULL;
colors = NULL;
n_colors = 0;
};
stars::stars(BITMAP *d_bmp, int n, int x_low, int y_low, int x_high, int y_high, int y_speed, int f_show, int f_blank, int color, int d)
{
dest = d_bmp;
n_stars = n;
x_min = x_low;
y_min = y_low;
x_max = x_high;
y_max = inc_color_every = y_high;
y_inc = y_speed;
frames_show = f_show;
frames_blank = f_blank;
visible = d;
n_colors = 1;
colors = (int *) malloc(sizeof(int) * n_colors);
memcpy(colors, &color, sizeof(int) * n_colors);
stars_info = create_stars();
if(visible)
draw();
}
stars::stars(BITMAP *d_bmp, int n, int x_low, int y_low, int x_high, int y_high, int y_speed, int f_show, int f_blank, int *col, int n_col, int col_s, int d)
{
dest = d_bmp;
n_stars = n;
x_min = x_low;
y_min = y_low;
x_max = x_high;
y_max = inc_color_every = y_high;
y_inc = y_speed;
frames_show = f_show;
frames_blank = f_blank;
visible = d;
if(col_s)
inc_color_every = (y_max - y_min) / col_s;
n_colors = n_col;
colors = (int *) malloc(sizeof(int) * n_colors);
memcpy(colors, col, sizeof(int) * n_colors);
stars_info = create_stars();
if(visible)
draw();
}
stars::stars(const class stars &other)
{
dest = other.dest;
n_stars = other.n_stars;
x_min = other.x_min;
y_min = other.y_min;
x_max = other.x_max;
y_max = other.y_max;
y_inc = other.y_inc;
inc_color_every = other.inc_color_every;
frames_show = other.frames_show;
frames_blank = other.frames_blank;
visible = other.visible;
stars_info = NULL;
colors = NULL;
if(other.stars_info)
{
stars_info = (st_star *) malloc(n_stars * sizeof(st_star));
memcpy(stars_info, other.stars_info, n_stars * sizeof(st_star));
}
if(other.colors)
{
colors = (int *) malloc(n_colors * sizeof(int));
memcpy(colors, other.colors, n_colors * sizeof(int));
}
if(visible)
draw();
}
void stars::remove(void)
{
if(!stars_info)
return;
st_star *p = stars_info;
st_star *e = &stars_info[n_stars];
while(p < e)
{
if(p->visible)
{ // remove only stars that are not behind anything.
dest->line[p->y][p->x] = 0;
p->visible = G_FALSE;
}
p++;
}
visible = G_FALSE;
}
void stars::draw(void)
{
if(!stars_info)
return;
st_star *p = stars_info;
st_star *e = &stars_info[n_stars];
unsigned int frames = frames_blank + frames_show;
while(p < e)
{
if(p->frame)
{ // if using blinking-stars
p->frame--;
if(!p->frame)
p->frame = frames;
}
if(((p->frame > frames_blank) || p->frame == 0))
if(!(dest->line[p->y][p->x]))
{ // Draw only stars that are not behind anything.
dest->line[p->y][p->x] = p->color;
p->visible = G_TRUE;
}
p++;
}
visible = G_TRUE;
}
void stars::move(void)
{
if(!stars_info)
return;
st_star *p = stars_info;
st_star *e = &stars_info[n_stars];
while(p < e)
{
p->y += y_inc;
if(p->y > y_max)
{ // Reset y and change star-color
p->y = (p->y - y_max);
p->next_inc_color = inc_color_every;
p->color = colors[rand() % n_colors];
}
if((p->y) > (p->next_inc_color))
{
p->color++;
p->next_inc_color += inc_color_every;
}
p++;
}
}
stars::~stars()
{
if(stars_info)
free(stars_info);
if(colors)
free(colors);
}
st_star *stars::create_stars(void)
{
st_star *star;
st_star *p = (st_star *) malloc(n_stars * sizeof(st_star));
if(!p)
return NULL;
memset(p, 0, n_stars * sizeof(st_star));
int i,j;
int tiles = (int) sqrt(n_stars);
int tile_x = (x_max - x_min) / tiles;
int tile_y = (y_max - y_min) / tiles;
j = 0;
star = p;
st_star *e = &(p[n_stars]);
while(star < e)
{ // Spread stars evenly on sreen area.
for(i = 0; i < tiles; i++)
{
star->x = (i*tile_x)+(rand() % tile_x);
star->y = (j*tile_y)+(rand() % tile_y);
star->frame = rand() % (frames_show + frames_blank);
star->color = colors[rand() % n_colors];
star->next_inc_color = inc_color_every;
star++;
if(star == e)
break;
}
j++;
if(j == tiles)
j = 0;
}
return p;
}
/* END - Class stars */
|