Skip to content

Instantly share code, notes, and snippets.

@ryonagana
Last active November 25, 2021 20:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryonagana/586e54bdb2b98e04d5928b63eb7e554d to your computer and use it in GitHub Desktop.
Save ryonagana/586e54bdb2b98e04d5928b63eb7e554d to your computer and use it in GitHub Desktop.
Space Invaders
#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