#include #include #include #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; }