diff options
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 265 |
1 files changed, 265 insertions, 0 deletions
@@ -0,0 +1,265 @@ +#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; +} |
