Last active
November 25, 2021 20:21
-
-
Save ryonagana/586e54bdb2b98e04d5928b63eb7e554d to your computer and use it in GitHub Desktop.
Space Invaders
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <allegro5/allegro.h> | |
#include <allegro5/allegro_acodec.h> | |
#include <allegro5/allegro_audio.h> | |
#include <allegro5/allegro_font.h> | |
#include <allegro5/allegro_image.h> | |
#include <allegro5/allegro_primitives.h> | |
#include <allegro5/allegro_ttf.h> | |
#include <allegro5/allegro_native_dialog.h> | |
#include <stdio.h> | |
static void write_log(const char *fmt,...); | |
#define ENEMY_COUNT 25 | |
static ALLEGRO_TEXTLOG *log_window = NULL; | |
#define SCREEN_W 800 | |
#define SCREEN_H 600 | |
#define TILE_SIZE 32 | |
#define LOGW(x, ...) write_log(x"\n",##__VA_ARGS__); | |
#define ENEMY_ROW 5 | |
#define ENEMY_COL 5 | |
struct PLAYER { | |
float x; | |
float y; | |
float vel_x; | |
float vel_y; | |
int alive; | |
int health; | |
}; | |
typedef struct PLAYER PLAYER; | |
struct ENEMY { | |
float x; | |
float y; | |
int hitpoints; | |
int type; | |
int alive; | |
}; | |
typedef struct ENEMY ENEMY; | |
#define MAX_BULLETS 50 | |
struct BULLET { | |
float x; | |
float y; | |
float vel_x; | |
float vel_y; | |
int ttl; | |
int alive; | |
int type; | |
}; | |
typedef struct BULLET BULLET; | |
BULLET player_bullets[MAX_BULLETS] = {0}; | |
int bullet_counter = 0; | |
static ALLEGRO_DISPLAY* display = NULL; | |
static ALLEGRO_EVENT_QUEUE* queue = NULL; | |
static ALLEGRO_BITMAP* screen = NULL; | |
static ALLEGRO_KEYBOARD_STATE kbdstate; | |
static ALLEGRO_TIMER* timer = NULL; | |
static ALLEGRO_BITMAP* background = NULL; | |
static ALLEGRO_BITMAP *enemy_spr01 = NULL; | |
static ALLEGRO_BITMAP *player_sprite = NULL; | |
static ALLEGRO_BITMAP *enemy_shot = NULL; | |
static ALLEGRO_BITMAP *player_shot = NULL; | |
static float shot_time = 0; | |
enum { | |
KEY_UP, | |
KEY_DOWN, | |
KEY_LEFT, | |
KEY_RIGHT, | |
KEY_FIRE | |
}; | |
static ENEMY s_enemy_list[ENEMY_COUNT] = {0}; | |
static int keys[6] = {0}; | |
enum{ | |
PLAYER_1, | |
PLAYER_2 | |
}; | |
static PLAYER player = {0}; | |
static void write_log(const char *fmt,...){ | |
char buffer[1024] = {0}; | |
va_list lst; | |
va_start(lst, fmt); | |
vsnprintf(buffer, sizeof(buffer), fmt, lst); | |
va_end(lst); | |
if(!log_window){ | |
fprintf(stdout, buffer); | |
return; | |
} | |
al_append_native_text_log(log_window, buffer); | |
} | |
void init_player(){ | |
player.x = (SCREEN_W / 2) - TILE_SIZE; | |
player.y = (SCREEN_H / 2) + 140; | |
player.vel_x = 2.5f; | |
player.vel_y = 0.0; | |
} | |
int collision_rect(float xa, float ya, int wa, int ha, float xb, float yb, int wb, int hb) | |
{ | |
if (xa < xb + wb && xa + wa > xb && ya < yb + hb && ha + ya > yb){ | |
return 1; | |
} | |
return 0; | |
} | |
void init_enemies(){ | |
int gx,gy; | |
for(gy = 0; gy < ENEMY_ROW;gy++){ | |
for(gx = 0; gx < ENEMY_COL;gx++){ | |
ENEMY *en = &s_enemy_list[gy * ENEMY_ROW + gx]; | |
en->x = gx * TILE_SIZE; | |
en->y = gy * TILE_SIZE; | |
en->hitpoints = 3; | |
en->alive = 1; | |
en->type = 1; | |
} | |
} | |
} | |
int init_allegro(void) | |
{ | |
if (!al_init()) { | |
goto error_critical; | |
} | |
if (!al_install_keyboard()) { | |
goto error_critical; | |
} | |
if (!al_install_mouse()) { | |
goto error_critical; | |
} | |
if (!al_init_native_dialog_addon()){ | |
LOGW("Cannot Load NATIVE DIALOG"); | |
} | |
if (!al_init_font_addon()) { | |
LOGW("Cannot Init Fonts!"); | |
} | |
if (!al_init_ttf_addon()) { | |
LOGW("Cannot Init TTF Fonts!"); | |
} | |
if (!al_init_primitives_addon()) { | |
LOGW("Failed to load primitives"); | |
} | |
if (!al_install_audio()) { | |
LOGW("Audio not found"); | |
} | |
if (!al_init_acodec_addon()) { | |
LOGW("Audio not found"); | |
} | |
if(!al_init_image_addon()) { | |
LOGW("Images Loaded"); | |
} | |
log_window = al_open_native_text_log("DEBUG:", ALLEGRO_TEXTLOG_NO_CLOSE|ALLEGRO_TEXTLOG_MONOSPACE); | |
return 1; | |
error_critical: | |
al_uninstall_system(); | |
fprintf(stdout, "Error Critical!"); | |
return 0; | |
} | |
void register_events() | |
{ | |
al_register_event_source(queue, al_get_display_event_source(display)); | |
al_register_event_source(queue, al_get_timer_event_source(timer)); | |
al_register_event_source(queue, al_get_keyboard_event_source()); | |
al_register_event_source(queue, al_get_mouse_event_source()); | |
} | |
ALLEGRO_BITMAP *image_safe_mode(){ | |
ALLEGRO_BITMAP *tmp = al_create_bitmap(32,32); | |
al_set_target_bitmap(tmp); | |
ALLEGRO_FONT *fnt = al_create_builtin_font(); | |
al_clear_to_color(al_map_rgb(255,0,0)); | |
al_draw_text(fnt,al_map_rgb(255,255,255), 0,0,0,"TMP"); | |
al_set_target_backbuffer(display); | |
al_destroy_font(fnt); | |
return tmp; | |
} | |
void load_sprites() | |
{ | |
background = al_load_bitmap("assets//bg01.bmp"); | |
if (!background) { | |
background = enemy_spr01 = image_safe_mode(); | |
return; | |
} | |
enemy_spr01 = al_load_bitmap("assets//enemy01.bmp"); | |
if (!enemy_spr01){ | |
enemy_spr01 = image_safe_mode(); | |
} | |
player_sprite = al_load_bitmap("assets//cannon.bmp"); | |
if(!player_sprite){ | |
player_sprite = image_safe_mode(); | |
} | |
player_shot = al_load_bitmap("assets//pshot.bmp"); | |
enemy_shot = al_load_bitmap("assets//eshot.bmp"); | |
al_convert_mask_to_alpha(enemy_spr01, al_map_rgb(255,0,255)); | |
al_convert_mask_to_alpha(player_sprite, al_map_rgb(255,0,255)); | |
al_convert_mask_to_alpha(player_shot, al_map_rgb(255,0,255)); | |
al_convert_mask_to_alpha(enemy_shot, al_map_rgb(255,0,255)); | |
} | |
void draw_enemies(){ | |
for(int i = 0; i < ENEMY_COUNT;i++){ | |
if (s_enemy_list[i].alive){ | |
al_draw_bitmap(enemy_spr01, s_enemy_list[i].x,s_enemy_list[i].y,0); | |
} | |
} | |
} | |
int create_window(int w, int h, int fullscreen) | |
{ | |
al_set_new_display_flags(ALLEGRO_WINDOWED | ALLEGRO_OPENGL); | |
display = al_create_display(w, h); | |
if(!display) { | |
LOGW("display failed to be created, error"); | |
return 0; | |
} | |
LOGW("display created with %dx%d", w, h); | |
queue = al_create_event_queue(); | |
if(!queue) { | |
LOGW("display queue failed to be created!"); | |
return 0; | |
} | |
al_get_keyboard_state(&kbdstate); | |
timer = al_create_timer(1.0 / 60.0); | |
al_start_timer(timer); | |
al_set_window_title(display, "SPACE INVADERS?"); | |
register_events(); | |
return 1; | |
} | |
void unload_assets(){ | |
if(background) al_destroy_bitmap(background); | |
if(enemy_spr01) al_destroy_bitmap(enemy_spr01); | |
} | |
void destroy_window(){ | |
unload_assets(); | |
if(display) al_destroy_display(display); | |
if(queue) al_destroy_event_queue(queue); | |
if(screen) al_destroy_bitmap(screen); | |
if(timer) al_destroy_timer(timer); | |
if(log_window) al_close_native_text_log(log_window); | |
} | |
void draw_background() | |
{ | |
for(int i = 0; i < al_get_display_width(display) / 32; i++) { | |
// al_draw_bitmap(background,i * 32,0,0); | |
int sw = al_get_bitmap_width(background); | |
int sh = al_get_bitmap_height(background); | |
al_draw_scaled_bitmap(background,0, 0, sw, sh, i * TILE_SIZE, 0, TILE_SIZE, al_get_display_height(display), 0); | |
} | |
} | |
void update_player_pos(){ | |
if(player.x > SCREEN_W - TILE_SIZE){ | |
player.x = SCREEN_W - TILE_SIZE; | |
} | |
if(player.x <= 0){ | |
player.x = 0; | |
} | |
} | |
void draw_player(){ | |
al_draw_bitmap(player_sprite, player.x, player.y,0); | |
} | |
void bullet_fire(BULLET bullets[MAX_BULLETS], float x, float y){ | |
if(bullet_counter >= MAX_BULLETS){ | |
bullet_counter = 0; | |
} | |
if(!bullets[bullet_counter].alive){ | |
bullets[bullet_counter].x = player.x; | |
bullets[bullet_counter].y = (SCREEN_H - 140); | |
bullets[bullet_counter].alive = 1; | |
bullets[bullet_counter].vel_x = 0; | |
bullets[bullet_counter].vel_y = 4.5; | |
LOGW("%ld", al_get_timer_count(timer)); | |
bullet_counter++; | |
} | |
} | |
void bullet_delete(BULLET *bullet){ | |
if(bullet){ | |
bullet->alive = 0; | |
bullet->ttl = 0; | |
bullet->x = 0; | |
bullet->y = 0; | |
} | |
} | |
void bullet_update(BULLET bullets[MAX_BULLETS]){ | |
for(int i = 0; i < MAX_BULLETS; i++){ | |
if(bullets[i].y < -10 ){ // OUT OF THE SCREEN | |
//LOGW("[%d] bullet is dead",i) | |
bullet_delete(&bullets[i]); | |
} | |
if(bullets[i].alive){ | |
bullets[i].x += bullets[i].vel_x; | |
bullets[i].y += -bullets[i].vel_y; | |
bullets[i].ttl--; | |
} | |
} | |
} | |
void draw_bullets(BULLET bullets[MAX_BULLETS]){ | |
for(int i = 0; i < MAX_BULLETS; i++){ | |
BULLET *b = & bullets[i]; | |
if(b->alive){ | |
al_draw_bitmap(player_shot, b->x, b->y,0); | |
} | |
} | |
} | |
void collision_bullet_to_enemies(BULLET bullets[MAX_BULLETS], ENEMY enemies[ENEMY_COUNT]){ | |
for(int i = 0; i < ENEMY_COUNT;i++){ | |
for(int j = 0; j < MAX_BULLETS;j++){ | |
BULLET *b = &bullets[j]; | |
ENEMY *e = &enemies[i]; | |
if(collision_rect(b->x,b->y,10,10, e->x,e->y, TILE_SIZE, TILE_SIZE) && b->alive && e->alive){ | |
LOGW("collisao"); | |
b->alive = 0; | |
e->alive = 0; | |
} | |
} | |
} | |
} | |
void player_input_keyboard(ALLEGRO_EVENT *ev){ | |
if(ev->type == ALLEGRO_EVENT_KEY_DOWN){ | |
if(ev->keyboard.keycode == ALLEGRO_KEY_W){ | |
keys[KEY_UP] = 1; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_S){ | |
keys[KEY_DOWN] = 1; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_A){ | |
keys[KEY_LEFT] = 1; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_D){ | |
keys[KEY_RIGHT] = 1; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_SPACE || ev->keyboard.keycode == ALLEGRO_KEY_RCTRL){ | |
keys[KEY_FIRE] = 1; | |
} | |
} | |
if(ev->type == ALLEGRO_EVENT_KEY_UP){ | |
if(ev->keyboard.keycode == ALLEGRO_KEY_W){ | |
keys[KEY_UP] = 0; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_S){ | |
keys[KEY_DOWN] = 0; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_A){ | |
keys[KEY_LEFT] = 0; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_D){ | |
keys[KEY_RIGHT] = 0; | |
} | |
if(ev->keyboard.keycode == ALLEGRO_KEY_SPACE||ev->keyboard.keycode == ALLEGRO_KEY_RCTRL){ | |
keys[KEY_FIRE] = 0; | |
} | |
} | |
} | |
void update(){ | |
if(keys[KEY_LEFT]){ | |
player.x -= player.vel_x * 2.5; | |
} | |
if(keys[KEY_RIGHT]){ | |
player.x += player.vel_x * 2.5; | |
} | |
if(keys[KEY_FIRE] && (al_get_timer_count(timer) / 10) > shot_time ){ | |
LOGW("FIRE - %d", (al_get_timer_count(timer) / 60)); | |
shot_time = (al_get_timer_count(timer) / 10) + 1; | |
bullet_fire(player_bullets, player.x, SCREEN_H - 140); | |
} | |
update_player_pos(); | |
bullet_update(player_bullets); | |
collision_bullet_to_enemies(player_bullets, s_enemy_list); | |
} | |
int main(int argc, char** argv) | |
{ | |
if(!init_allegro()) { | |
LOGW("Allegro Failed!"); | |
} | |
LOGW("Allegro Loaded with Success!"); | |
create_window(SCREEN_W, SCREEN_H, 0); | |
load_sprites(); | |
init_player(); | |
init_enemies(); | |
int is_closed = 0; | |
int redraw = 0; | |
while(!is_closed) { | |
ALLEGRO_EVENT ev; | |
al_wait_for_event(queue, &ev); | |
if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { | |
is_closed = 1; | |
break; | |
} | |
if(ev.type == ALLEGRO_EVENT_TIMER) { | |
update(); | |
redraw = 1; | |
} | |
player_input_keyboard(&ev); | |
if(redraw && al_event_queue_is_empty(queue)) { | |
al_clear_to_color(al_map_rgb(0, 0, 0)); | |
draw_background(); | |
draw_enemies(); | |
draw_player(); | |
draw_bullets(player_bullets); | |
//al_draw_bitmap(enemy_spr01,0,0,0); | |
al_flip_display(); | |
redraw = 0; | |
} | |
} | |
destroy_window(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment