/****************************************************************
GALVADERS (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 <string.h>
#include <baseimage.h>
#include "galvaders.h"
#include "samples.h"
/* Using STL */
#include <vector>
#include <list>
using namespace std;
/***********************************************
PLACE ALL CLASSES THAT ARE USED BY BOTH
INVADERS AND GLAXIANS IN THIS FILE.
***********************************************/
#if !defined( _BASE_H_ )
#define _BASE_H_
/* START - Game types */
struct st_pixel_type
{
int x;
int y;
};
typedef struct st_pixel_type st_pixel;
struct st_colors_type
{
int low_color;
int high_color;
};
typedef struct st_colors_type st_colors;
struct st_controls_type
{
unsigned char left;
unsigned char right;
unsigned char fire;
};
typedef struct st_controls_type st_controls;
struct st_bullet_params_type
{
int x_inc;
int y_inc;
int x_min;
int x_max;
int y_min;
int y_max;
st_pixel *hit_pixels;
int n_hit_pixels;
st_colors colors;
int hit_z_order_low;
int hit_z_order_high;
};
typedef st_bullet_params_type st_bullet_params;
typedef vector<RLE_SPRITE *> images_array;
typedef list<base_image *> sprite_list;
struct st_game_params_type
{ /* Holds game sprites information. */
images_array *images;
/* Integers to save sprite indexes as saved in the vector. */
int aharon_logo;
int allegro_logo;
int enemies;
int g_blast;
int gal_bullet;
int gal_players;
int halftone_gal_players;
int gal_player_blast;
int gal_players_small;
int i_blast;
int inv_missile;
int inv_missile_explosion;
int inv_players;
int halftone_inv_players;
int inv_player_blast;
int inv_players_small;
int inv_mother_ship;
int inv_mother_ship_explosion;
int inv_mother_ship_150;
int inv_mother_ship_300;
int inv_player_bullet;
int gal_player_bullet;
int shield;
int gal_bonus_200;
int gal_bonus_400;
int gal_bonus_800;
BITMAP *game_logo;
RGB game_pal[256];
char *dir;
};
typedef struct st_game_params_type st_game_params;
/* END - Game types */
extern DATAFILE *s_data;
extern st_game_params *game_sprites;
extern class player *player_1;
extern class player *player_2;
extern class inv_formation *invaders;
extern class gal_formation *galaxians;
extern sprite_list explosions_list;
extern sprite_list p_bullets_list;
extern sprite_list e_bullets_list;
extern unsigned int sound_flag;
void init_classes_static_data(unsigned char game_type);
// 0 1 2 3 4 5 6 7 menu_status_register
// | | | | | | | -> Game-Over 0x80
// | | | | | | ---> VSYNC() on/off 0x40
// | | | | | -----> Shields on/off 0x20
// | | | | -------> n-Bullets bit 2 0x10 2 = 4 bullets, 3 = 8 bullets
// | | | ---------> n-Bullets bit 1 0x08 0 = 1 bullets, 1 = 2 bullets
// | | -----------> Demo Mode 0x04
// | -------------> Galaxians 0x02 2 = Galaxy game, 3 = Galvaders game
// | -------------> Invaders 0x01 1 = Invaders game
#define BIT_GAME_OVER 0x80
#define BIT_VSYNC 0x40
#define BIT_SHIELDS 0x20
#define BIT_N_BULLETS_HIGH 0x10
#define BIT_N_BULLETS_LOW 0x08
#define BIT_DEMO_MODE 0x04
#define BIT_GALAXIANS 0x02
#define BIT_INVADERS 0x01
#define SOUND_INVADERS 1
#define SOUND_GALAXY 2
#define SOUND_GALVADERS 3
/* Place all game Z_ORDER defs here so able to chage in one place */
/* Z-ORDER values are not really used in this game since sprites are */
/* saved in various lists that handled according to list-z-order. */
#define INVADERS_Z_ORDER 1
#define GALAXY_Z_ORDER 2
#define GALAXY_ATTACK_Z_ORDER 3
#define PLAYER_Z_ORDER 4
#define PLAYER_BULLET_Z_ORDER 5
#define EXPLOSION_Z_ORDER 6
#define TEXT_RIGHT 1
#define TEXT_BOTTOM 1
#define TEXT_CENTER 2
#define TEXT_LEFT 3
#define TEXT_TOP 3
/*** START ********* recoreding marcors *******/
/* Recording will be done only for players. */
/* Each "data record" is contructed of short-int: */
/* Bits (high-nibble): */
/* BIT 13 - player key left. (on/off) */
/* BIT 14 - player key right. (on/off) */
/* BIT 15 - player key fire. (on/off) */
/* BITS 0-12 How many frames the key situation consists */
/* from 1-frame to 8191 frames. */
/* The MACROS are used by play_the_game(n) when recording */
/* and by player-class when playing a demo. */
#define GET_FRAME_COUNTER(S_INT) (S_INT & 0x1FFF)
#define SET_FRAME_KEYS(KEYS,FRAME,S_INT) S_INT = (((KEYS & 7) << 13) | (FRAME & 0x1FFF))
#define MAX_PLAYER_DATA 4095
/* Used by Demo-Mode routines */
#define BIT_KEY_LEFT 0x2000
#define BIT_KEY_RIGHT 0x4000
#define BIT_KEY_FIRE 0x8000
/*** END ********* recoreding marcors *******/
/* ANIMation values to be used in enemy class. */
#define ANIM_NONE 0
#define ANIM_LOW_HIGH 1
#define ANIM_HIGH_LOW 2
#define ANIM_PING_PONG 3
/* Some macors to work with lists */
#define RUN_LIST_REVERSE(LIST,ITER,FUNC) \
{ \
if(LIST.size()) /* if list is NOT empty. */ \
{ \
ITER = LIST.end(); \
do{ \
ITER--; \
(*ITER)->FUNC(); \
}while(ITER != LIST.begin()); \
} \
}
#define RUN_LIST_INCREMENTAL(LIST,ITER,FUNC) \
{ \
if(LIST.size()) /* if list is NOT empty. */ \
{ \
ITER = LIST.begin(); \
while(ITER != LIST.end()) \
{ (*ITER)->FUNC(); ITER++; }; \
} \
}
#define RUN_LIST_INCREMENTAL_WITH_REMOVE(LIST,ITER,ITER_REMOVE,FUNC,TEST) \
{ /* MACRO to do items action(), then remove dead items or do draw() */ \
if(LIST.size()) /* if list is NOT empty. */ \
{ \
ITER = LIST.begin(); \
while(ITER != LIST.end()) \
{ \
(*ITER)->FUNC(); \
ITER_REMOVE = ITER; \
ITER++; \
if((*ITER_REMOVE)->TEST() < 0) \
{ /* Remove a dead item from list */ \
delete(*ITER_REMOVE); \
LIST.erase(ITER_REMOVE); \
} \
} /* End of while loop */ \
} \
}
#define CLEAR_LIST(LIST,ITER,ITER_REMOVE) \
{ \
if(LIST.size()) /* if list is NOT empty. */ \
{ \
ITER = LIST.begin(); \
while(ITER != LIST.end()) \
{ \
ITER_REMOVE = ITER; \
ITER++; \
delete(*ITER_REMOVE); \
LIST.erase(ITER_REMOVE); \
} /* End of while loop */ \
} \
}
//--------- START -- CLASS text_msg -----------
class text_msg
{
private:
BITMAP *dest;
BITMAP *bg_buffer;
int background_w;
int background_h;
char *text;
unsigned int frames;
unsigned int blank_frames;
unsigned int frame_counter;
int show_text;
int x_pos;
int y_pos;
int length;
char **lines;
int n_lines;
char *longest_line;
int font_type;
int floating_text;
int text_color;
int x_text_orientation; // Left, Center, Right.
int y_text_orientation; // Bottom, Center, top.
int bg_color;
BITMAP *bg_tile; // Tile-BITMAP private copy is saved in this class.
int get_lines(void);
void compute_background_size(void);
public:
text_msg();
text_msg(BITMAP *dest_bmp);
text_msg(BITMAP *dest_bmp, char *t, int x, int y, int f, int float_flag, int tc, int bg_c, int txo, int tyo, BITMAP *bg_t, int d);
text_msg(BITMAP *dest_bmp, char *t, int x, int y, int f, int float_flag, int tc, int bg_c, int txo, int tyo, BITMAP *bg_t, unsigned int f_counter, unsigned int b_frames, int d);
text_msg(const text_msg &other);
inline void set_dest_bitmap(BITMAP *bmp) { dest = bmp; };
void draw(void);
void remove(void);
void set_bg_tile(BITMAP *tile);
inline int get_msg_width(void) { return background_w; };
inline int get_msg_height(void) { return background_h; };
inline void set_blinking_params(int f, int b_frames) { frames = frame_counter = f + b_frames; blank_frames = b_frames; };
inline void set_font(int new_font) { font_type = new_font; if(bg_buffer) destroy_bitmap(bg_buffer); bg_buffer = NULL; };
inline void set_text_color(int new_color) { text_color = new_color; };
inline void set_text_bg_color(int new_color) { bg_color = new_color; };
inline void set_text_orientation(int new_x_o, int new_y_o) { x_text_orientation = new_x_o; y_text_orientation = new_y_o; };
inline int get_x_pos(void) { return x_pos; };
inline int get_y_pos(void) { return y_pos; };
inline void set_show_text(int flag) { show_text = flag; };
inline void set_pos(int new_x, int new_y, int d) { x_pos = new_x; y_pos = new_y; if(d) draw(); };
inline void set_pos_ex(int new_x, int new_y, int new_float_flag, int d);
inline void set_floating_flag(void) { floating_text = G_TRUE; };
inline void clear_floating_flag(void) { floating_text = G_FALSE; if(bg_buffer) destroy_bitmap(bg_buffer); bg_buffer = NULL; };
int set_text(char *new_text);
~text_msg();
};
//--------- END -- CLASS text_msg -----------
int test_hit_pixels(BITMAP *bmp, const st_colors colors, int x, int y, st_pixel *hit_pixels, int n_hit_pixels);
int test_hit_pixels(BITMAP *bmp, const st_colors *colors, const int i_colors, int x, int y, st_pixel *hit_pixels, int n_hit_pixels);
struct st_enemy_params_type
{
int index_low;
int index_high;
int anim_type;
int x_min;
int y_min;
int x_max;
int y_max;
};
typedef struct st_enemy_params_type st_enemy_params;
class enemy : public base_image
{
private:
int index_low; // Play animation from between low and high
int index_high;
int anim_type; // NONE ; LOW->HIGH ; HIGH->LOW ; PING-PONG
int anim_dir; // Init by the value of anim_type
int x_min;
int y_min;
int x_max;
int y_max;
static int enemies;
public:
enemy();
enemy(RLE_SPRITE **dt, BITMAP *dst, const int x, const int y, const int z, const int bg_f, const int d, const st_enemy_params &p);
enemy(const enemy &other); // COPY constructor
~enemy();
int static get_enemies(void) { return enemies; };
inline void inc_index();
inline void dec_index();
inline void switch_anim_dir() { if((anim_type == ANIM_LOW_HIGH) || (anim_type == ANIM_HIGH_LOW)) anim_dir *= -1; };
inline int get_index_low() { return index_low; };
inline int get_index_high() { return index_high; };
void play_anim(void);
int kill(void);
int action(void);
};
//--------- END -- CLASS enemy -----------
//--------- START -- CLASS player -----------
#define PLAYER_BONUSES 4
struct st_player_params_type
{
st_controls *keys;
st_pixel *player_hit_pixels;
int n_player_hit_pixels;
int fire_sample;
int exp_sample;
int bonus_life_sample;
int halftone_sprite_index;
int bullet_sprite_index;
int exp_sprite_index_low;
int exp_sprite_index_high;
int bullets_max;
int x_min;
int x_max;
int x_inc;
int *player_bonus_scores;
unsigned short *demo_stream;
};
typedef struct st_player_params_type st_player_params;
class player : public base_image
{
private:
st_controls keys;
int lives;
int score;
int last_score_shown;
int halftone_counter;
int bullets; // How many shots in the air
int bullets_max; // How many shots allowed.
int start_x;
int start_y;
int x_min;
int x_max;
int fire_sample;
int exp_sample;
int bonus_life_sample;
int player_killed_by_enemy;
st_pixel *player_hit_pixels;
int n_player_hit_pixels;
int player_sprite_index;
int halftone_sprite_index;
int bullet_sprite_index;
int exp_sprite_index_low;
int exp_sprite_index_high;
int x_bullet_offset;
int y_bullet_start;
int shot_fired;
int x_speed;
int x_inc;
int killed;
class text_msg text_score_header;
class text_msg text_score;
class text_msg text_join;
RLE_SPRITE *player_small_sprite;
BITMAP *footer_bmp;
unsigned short *demo_stream;
unsigned short current_frame_counter;
unsigned int current_demo_index;
int current_bonus_index;
int player_bonus_scores[PLAYER_BONUSES];
static int players;
void inc_current_demo_index(void);
public:
static st_pixel inv_bullet_hit_pixles[];
static st_pixel gal_bullet_hit_pixles[];
static st_pixel inv_player_hit_pixles[];
static st_pixel gal_player_hit_pixles[];
static st_colors bullet_hit_colors;
static st_bullet_params bullet_params; // To be used for all player objects.
player();
player(RLE_SPRITE **dt, BITMAP *dst, BITMAP *footer_dst, const int s_index, const int x, const int y, const int z, const int l, const int bg_f, const int d, const st_player_params &p, const int g_font, char *txt_score_h, const int tx_score_h, const int ty_score_h, const int txo_score_h, const int tyo_score_h, char *txt_score, const int tx_score, const int ty_score, const int txo_score, const int tyo_score, char *txt_join, const int tx_join, const int ty_join, const int txo_join, const int tyo_join, const int s_index_small);
player(const player &other); // COPY constructor
~player();
int static get_players(void) { return players; };
void do_fire(void);
inline int draw(void) { if((lives == 0) || killed) return G_FALSE; if(halftone_counter < 80) if(halftone_counter & 8) return G_FALSE; return base_image::draw(); };
inline void set_controls(const st_controls &new_controls) { keys = new_controls; };
inline void inc_bullet_counter(void) { bullets++; };
inline int get_score(void) { return score; };
inline void set_score(int value) { score = value; }; // Used for demo.
inline int get_lives(void) { return lives; };
inline int get_player_killed_by_enemy(void) { return player_killed_by_enemy; };
inline void set_lives(int value) { lives = value; if(lives) text_score_header.set_blinking_params(18,6); else text_score_header.set_blinking_params(0,0); };
inline void clear_killed_flag(void) { killed = G_FALSE; };
void update_score(int value);
inline void set_max_bullets(int value) { bullets_max = value; };
inline int switch_to_halftone_sprite(int counter) { halftone_counter = counter; set_sprite_index(halftone_sprite_index); };
inline int switch_to_regular_sprite(void) { set_sprite_index(player_sprite_index); };
inline void go_to_start_pos(int visible) { set_pos(start_x, start_y, visible); };
inline void sync_blink_of_score_header(void) { text_score_header.set_blinking_params(18,6); };
inline int end_of_demo_input(void) { if(!demo_stream) return G_TRUE; return (current_demo_index == demo_stream[0]); };
int p_test_hit_pixels(void);
int kill(int more_players_on_field);
int action(void);
void remove_player_text(void);
void draw_player_text(unsigned char game_over);
void remove_player_lives(void);
void draw_player_lives(void);
};
//--------- END -- CLASS player -----------
//--------- START -- CLASS bullet -----------
class bullet : public base_image
{
private:
int x_inc;
int y_inc;
int x_min;
int x_max;
int y_min;
int y_max;
int score;
class player *owner;
st_pixel *hit_pixels;
int n_hit_pixels;
st_colors colors;
int hit_z_order_low;
int hit_z_order_high;
int test_collision_in_list(sprite_list *list, int sprite_index);
public:
bullet();
bullet(RLE_SPRITE **dt, BITMAP *dst, const int s_index, const int x, const int y, const int z, const int bg_f, const int d, const st_bullet_params &p);
bullet(RLE_SPRITE **dt, BITMAP *dst, class player *p_owner, const int s_index, const int x, const int y, const int z, const int bg_f, const int d, const st_bullet_params &p);
bullet(const bullet &other); // COPY constructor
~bullet();
int action(void);
};
//--------- END -- CLASS bullet -----------
//--------- START -- CLASS explosion --------
class explosion : public base_image
{
private:
int center_x;
int center_y;
unsigned int speed; // how many frames for each move.
unsigned int frame_cnt; // counter when = 0, next move.
int index_low;
int index_high;
public:
explosion();
explosion(RLE_SPRITE **dt, BITMAP *dst, const int i_low, const int i_high, const int x, const int y, const int z, const unsigned int f_speed, const int bg_f, const int d);
explosion(const explosion &other); // COPY constructor
~explosion();
int explosion::action(void);
};
//--------- END -- CLASS explosion --------
//--------- START -- CLASS formation --------
struct st_formation_move_type
{
int x_inc;
int y_inc;
int times;
int int_to_next_move;
};
typedef struct st_formation_move_type st_formation_move;
#define ITEM_IS_DEAD 0
#define ITEM_IN_FORMATION 1
#define ITEM_IN_ATTACK 2
struct st_item_type
{
int x;
int y;
int sample;
int score;
class enemy *sprite;
int state;
};
typedef struct st_item_type st_item;
struct st_formation_param_type
{
BITMAP *buffer; // On what BITMAP formation will be drawn.
st_item *list; // To be deleted in formation destructor
int x_left_border;
int x_right_border;
int y_top_border;
int y_bottom_border;
unsigned int frame_rate;
int rows;
int cols;
st_formation_move *moves; // To be deleted in formation destructor
};
typedef struct st_formation_param_type st_formation_param;
class formation
{
private:
BITMAP *buffer;
int counter;
st_item *items;
int live_items;
int x_left_border;
int x_right_border;
int y_top_border;
int y_bottom_border;
int rows;
int cols;
unsigned int frame_rate;
unsigned int frame_counter;
st_formation_move *moves;
int current_move;
int move_count;
void move_formation_right();
void move_formation_left();
void move_formation_up();
void move_formation_down();
protected:
int test_formation_left();
int test_formation_right();
int test_formation_top();
int test_formation_bottom();
static int attack_ok;
public:
formation();
formation(const st_formation_param &p);
~formation();
inline int get_cols(void) { return cols; };
inline int get_rows(void) { return rows; };
inline int get_counter(void) { return counter; };
inline int get_live_items(void) { return live_items; };
inline unsigned int get_frame_rate(void) { return frame_rate; };
inline int set_frame_rate(unsigned int value) { frame_rate = value; };
inline static int get_attack_ok(void) { return attack_ok; };
inline static void set_attack_ok(void) { attack_ok = G_TRUE; };
inline static void clear_attack_ok(void) { attack_ok = G_FALSE; };
void remove(void);
void draw();
inline st_item *get_item(int c, int r) { return &items[r]+(c * cols); };
inline BITMAP *get_dest_bitmap(void) { return buffer; };
int test_formation_for_hit(int x_pos, int y_pos, int bullet_index, int e_index_low, int e_index_high, unsigned int do_sound);
void get_fire_options(st_pixel *opt, int max_col, int *n_opt);
void action();
};
//--------- END -- CLASS formation --------
#define GAME_HEADER_LINE1_Y 0
#define GAME_HEADER_LINE2_Y 19
#define GAME_HEADER_BORDER_LINE 42
#define GAME_FOOTER_BORDER_LINE 455
#endif // _BASE_H_
|