aboutsummaryrefslogtreecommitdiff
#ifndef __GAME_H__
#define __GAME_H__

#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_mixer.h>

#include <stdbool.h>

#define MAX_AUDIOS 10
#define MAX_TEXTURES 100
#define MAX_WIDGETS_PER_LAYER 10
#define MAX_ENTITIES 128
#define MAX_TILES 64

#define MAX_BULLETS 32
#define BULLET_WIDTH 8

#define MENU_LAYER 0
#define GAME_LAYER 1

#define MOUSE_BUTTON 0
#define MOUSE_MOTION 1

#define POSITION_CENTERED -1

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

enum GameStates
  {
    QUIT = 0,
    RUNNING = 1,
    MENU = 2
  };

struct Entity
{
  float x, y;
  float dx, dy; // Velocity
  float d2x, d2y; // Acceleration
  
  int w, h;

  bool collidable;
  bool mirror;
  bool fixed;
  bool use_src_rect;
  int i, j;
  SDL_Rect src_rect;

  SDL_Texture *texture;
  char *name;
  void (*on_collision)(struct Entity *this, struct Entity *other);
};

struct Camera
{
  SDL_Rect rect;
};

struct Color
{
  unsigned char r, g, b;
};

struct Widget
{
  bool use_src_rect;
  SDL_Rect rect, src_rect;
  SDL_Texture *texture;
  
  struct Color color;
  struct Color on_hover_color;
  struct Color default_color;
  
  bool is_hover;
  bool is_focus;
  bool is_blended;
  int initial_x;
  int initial_y;

  void (*callback)(struct Widget *);
};

enum GunType
  {
    REVOLVER = 0,
    RIFLE = 1,
    SHOTGUN = 2
  };

struct Gun
{
  unsigned char type;
  float angle;
  unsigned char projectiles_per_shot;
  bool ready;
  float cooldown;
  float cooldown_elapsed;

  unsigned char damage;
  unsigned char bullets;
  unsigned char max_bullets;
  
  Mix_Chunk *sound_effect;
};

struct PlayerKeys
{
  unsigned char jump;
  unsigned char left, right;
  unsigned char fire, reload;
  unsigned char weaponds[3];
};

struct Player
{
  struct Entity entity;

  unsigned char current_gun;
  struct Gun guns[3];

  bool facing_left;
  bool on_ground;
  bool reloading;

  char life;
  char score;
  float reload_time;

  char name[16];
  struct PlayerKeys keys;

  struct Widget *hearts[3];
  struct Widget *gun;
  int counter;
};

struct Bullet
{ 
  struct Entity entity;
  struct Player *owner;

  struct Bullet *next;

  unsigned char index;
  unsigned char damage;
};

struct Layer
{
  //int num_entities;
  //struct Entity *entities[MAX_ENTITIES_PER_LAYER];

  int num_widgets;
  struct Widget widgets[MAX_WIDGETS_PER_LAYER];
};

struct Menu
{
  struct Widget *play_button;
  struct Widget *quit_button;
};

struct TextureContainer
{
  char name[16];
  SDL_Texture *texture;
};

struct Resources
{
  int num_textures;
  SDL_Texture *textures[MAX_TEXTURES];

  int num_stored_textures;
  struct TextureContainer contained_textures[MAX_TEXTURES];

  int num_audios;
  Mix_Chunk *audios[MAX_AUDIOS];
    
  TTF_Font *font;
};

struct MainGame
{
  SDL_Window *window;
  SDL_Renderer *renderer;
  int width, height;

  unsigned char state;
  int gravity;

  int num_players;
  struct Player players[2];
  
  // 0 -> game, 1 -> menu
  struct Layer layers[2];
  unsigned char current_layer;

  struct Resources resources;

  struct Menu menu;
  const Uint8 *keys;

  unsigned int bullets_left;
  SDL_Texture *bullet_texture;
  struct Bullet *bullets[MAX_BULLETS];

  int num_entities;
  struct Entity *entities[MAX_ENTITIES];

  int num_tiles;
  struct Entity tiles[MAX_TILES];
  
  float frame_time;
  SDL_Texture *guns[3];
  Mix_Chunk *revolver_sound, *rifle_sound;
  
  struct Widget *score;

  struct Camera camera;
};

extern struct MainGame *game;

/* Util */
SDL_Texture *load_texture(const char *name);
Mix_Chunk *load_sound(const char *name);
void die(const char *error, ...) __attribute__ ((noreturn));

/* GUI */
struct Widget *add_button(unsigned char layer,
			  const char *label,
			  int x, int y,
			  void (*callback)(struct Widget *));

struct Widget *add_image(unsigned char layer, SDL_Texture *image,
			 int x, int y, int w, int h);

void process_widget_events(unsigned char type, int x, int y);
void set_color(struct Widget *w, struct Color color);
void set_text(struct Widget *w, const char *text);
struct Widget *add_label(unsigned char layer,
			 const char *text,
			 struct Color color,
			 int x, int y);

/* Renderer */
void render_begin(void);
void render_entities(void);
void render_flush(void);

/* Bullets */
void init_bullets(void);
void shoot_bullet(struct Player *owner);
void update_bullets(void);

/* Players */
void init_player(struct Player *p, struct PlayerKeys *keys,
		 float x, float y, const char *name);
void update_player(struct Player *p);
void update_score(void);

/* Collisions */
void check_collisions(void);

void load_config(const char *config);

#endif