#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "game.h"
struct MainGame *game;
static const char *game_name = "Highnoon";
void process_events(void)
{
SDL_Event e;
int x, y;
while( SDL_PollEvent(&e) )
{
switch(e.type)
{
case SDL_QUIT:
game->state = QUIT;
break;
case SDL_MOUSEBUTTONDOWN:
SDL_GetMouseState(&x, &y);
process_widget_events(MOUSE_BUTTON, x, y);
break;
case SDL_MOUSEMOTION:
process_widget_events(MOUSE_MOTION, e.motion.x, e.motion.y);
break;
}
}
if(game->state == RUNNING && game->keys[SDL_SCANCODE_ESCAPE])
{
game->state = MENU;
game->current_layer = MENU_LAYER;
}
}
void unload_game(void)
{
int i;
struct Resources *res = &game->resources;
for(i = 0; i < res->num_textures; i ++)
SDL_DestroyTexture(res->textures[i]);
for(i = 0; i < res->num_audios; i ++)
Mix_FreeChunk(res->audios[i]);
TTF_CloseFont(res->font);
}
static void play_button_callback(struct Widget *w)
{
game->state = RUNNING;
game->current_layer = GAME_LAYER;
}
static void quit_button_callback(struct Widget *w)
{
game->state = QUIT;
}
void load_menu(void)
{
struct Color c = {255, 255, 255};
struct Color on_hover = {255, 255, 0};
game->menu.play_button = add_button(MENU_LAYER, "Play", POSITION_CENTERED,
150, play_button_callback);
set_color(game->menu.play_button, c);
game->menu.play_button->on_hover_color = on_hover;
game->menu.quit_button = add_button(MENU_LAYER, "Quit", POSITION_CENTERED,
190, quit_button_callback);
set_color(game->menu.quit_button, c);
game->menu.quit_button->on_hover_color = on_hover;
add_label(MENU_LAYER, game_name, (struct Color){255, 255, 255}, POSITION_CENTERED, 50);
}
void load_game(void)
{
int i;
struct PlayerKeys keys[2] =
{
{
.jump = SDL_SCANCODE_W,
.left = SDL_SCANCODE_A,
.right = SDL_SCANCODE_D,
.fire = SDL_SCANCODE_F,
.reload = SDL_SCANCODE_R,
.weaponds = {SDL_SCANCODE_1, SDL_SCANCODE_2, SDL_SCANCODE_3}
},
{
.jump = SDL_SCANCODE_UP,
.left = SDL_SCANCODE_LEFT,
.right = SDL_SCANCODE_RIGHT,
.fire = SDL_SCANCODE_K,
.reload = SDL_SCANCODE_L,
.weaponds = {SDL_SCANCODE_B, SDL_SCANCODE_N, SDL_SCANCODE_M}
}
};
game->guns[0] = load_texture("resources/revolver.png");
game->guns[1] = load_texture("resources/rifle.png");
game->guns[2] = load_texture("resources/shotgun.png");
game->revolver_sound = load_sound("resources/revolver.ogg");
game->rifle_sound = load_sound("resources/rifle.ogg");
game->num_players = 2;
game->bullets_left = MAX_BULLETS;
game->keys = SDL_GetKeyboardState(NULL);
init_player(&game->players[0], &keys[0], 200.0f, 200.0f, "Player1");
init_player(&game->players[1], &keys[1], 500.0f, 200.0f, "Player2");
game->bullet_texture = load_texture("resources/bullet.png");
srand(time(NULL));
game->score = add_label(GAME_LAYER, "",
(struct Color){255, 255, 255}, POSITION_CENTERED, 0);
update_score();
for(i = 0; i < 3; i ++)
{
game->players[0].hearts[i] = add_image(GAME_LAYER, load_texture("resources/heart.png"),
20 + i * 80, 100, 64, 64);
game->players[0].hearts[i]->use_src_rect = true;
game->players[0].hearts[i]->src_rect = (SDL_Rect){0, 0, 16, 16};
}
int w, h;
SDL_QueryTexture(game->guns[0], NULL, NULL, &w, &h);
game->players[0].gun = add_image(GAME_LAYER, game->guns[0], 0, 0, w * 2, h * 2);
game->players[1].gun = add_image(GAME_LAYER, game->guns[0], 400, 0, w * 2, h * 2);
for(i = 0; i < 3; i ++)
{
game->players[1].hearts[i] = add_image(GAME_LAYER, load_texture("resources/heart.png"),
(game->width - 250) + i * 80, 100, 64, 64);
game->players[1].hearts[i]->use_src_rect = true;
game->players[1].hearts[i]->src_rect = (SDL_Rect){0, 0, 16, 16};
}
load_config("config");
game->camera.rect.x = WINDOW_WIDTH / 2;
game->camera.rect.y = WINDOW_HEIGHT / 2;
game->camera.rect.w = WINDOW_WIDTH;
game->camera.rect.h = WINDOW_HEIGHT;
}
static const unsigned int ticks_per_frame = 1000 / 75;
/*
To make things easier with collision we can have moveable and unmoveable
entities. If a entity is unmoveable then under collisions it should stay in
place and we only have to go back with the moveable
*/
int main(int argc, char **argv)
{
int i;
unsigned int start_ticks, frame_ticks;
game = calloc( 1, sizeof(struct MainGame) );
SDL_Init(SDL_INIT_EVERYTHING);
Mix_Init(MIX_INIT_OGG);
if( TTF_Init() != 0)
die("Error while initializing SDL2_ttf\n", TTF_GetError());
game->window = SDL_CreateWindow(game_name, SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH, WINDOW_HEIGHT, 0);
game->renderer = SDL_CreateRenderer(game->window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if(game->window == NULL || game->renderer == NULL)
{
die("Error while creating the window and/or renderer:\n%s\n",
SDL_GetError());
}
SDL_SetRenderDrawColor(game->renderer, 92, 51, 23, 255);
if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 4096) == -1)
die("Audio could not be opened: %s", Mix_GetError());
game->width = WINDOW_WIDTH;
game->height = WINDOW_HEIGHT;
game->gravity = 1200.0f;
game->state = MENU;
game->current_layer = MENU_LAYER;
game->resources.font = TTF_OpenFont("resources/font.ttf", 40);
load_menu();
load_game();
struct Widget w = {};
/* game->players[0].guns[2].max_bullets = 100; */
/* game->players[0].guns[2].projectiles_per_shot = 10; */
/* game->players[0].guns[2].cooldown = .5f; */
while(game->state != QUIT)
{
//game->camera.rect.x = game->players[0].entity.x;
//game->camera.rect.y = game->players[0].entity.y;
game->num_entities = 0;
start_ticks = SDL_GetTicks();
process_events();
if(game->current_layer == GAME_LAYER)
{
update_player(&game->players[0]);
update_player(&game->players[1]);
update_bullets();
for(i = 0; i < game->num_tiles; i ++)
game->entities[game->num_entities ++] = &game->tiles[i];
check_collisions();
}
render_begin();
if(game->state == RUNNING)
render_entities();
char text[50];
sprintf(text, "%hhd -- %hhd",
game->players[0].guns[game->players[0].current_gun].bullets,
game->players[1].guns[game->players[1].current_gun].bullets);
set_text(&w, text);
if (w.texture) {
SDL_Rect rect = {0, 200, 100, 50};
SDL_RenderCopyEx(game->renderer, w.texture, NULL, &rect, 0,
NULL, SDL_FLIP_NONE);
}
render_flush();
frame_ticks = SDL_GetTicks() - start_ticks;
if( frame_ticks < ticks_per_frame )
SDL_Delay(ticks_per_frame - frame_ticks);
// Frame time in seconds
game->frame_time = (float)frame_ticks / 1000.0f;
}
SDL_DestroyRenderer(game->renderer);
SDL_DestroyWindow(game->window);
unload_game();
free(game);
SDL_Quit();
TTF_Quit();
Mix_Quit();
return 0;
}