/* * Copyright (C) 2021 P. J. McDermott * * This file is part of Dodge Balls * * Dodge Balls is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Dodge Balls is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Dodge Balls. If not, see . */ #include #include #include "ball.h" #include "level.h" #include "map.h" #include "output.h" struct db_level { char *game_id; char *level_id; struct db_level *next; struct db_map *map; SDL_Texture *map_texture; struct db_tileset *tilesets; int player_x; int player_y; int player_r; int player_a; int player_s; int player_gid; int target_x; int target_y; int target_r; int target_gid; struct db_ball *balls; }; struct db_level * db_level_new(const char *game_id, const char *level_id, struct db_level *prev) { struct db_level *level; level = calloc(1, sizeof(*level)); if (level == NULL) { db_err("Failed to allocate memory"); return NULL; } level->game_id = strdup(game_id); if (level->game_id == NULL) { db_err("Failed to allocate memory"); free(level); return NULL; } level->level_id = strdup(level_id); if (level->level_id == NULL) { db_err("Failed to allocate memory"); free(level->game_id); free(level); return NULL; } if (prev != NULL) { prev->next = level; } return level; } static void _db_level_render(SDL_Renderer *renderer, struct db_level *level) { SDL_Rect dstrect; SDL_RenderClear(renderer); SDL_RenderCopy(renderer, level->map_texture, NULL, NULL); dstrect.x = level->player_x - level->player_r; dstrect.y = level->player_y - level->player_r; dstrect.w = level->player_r * 2; dstrect.h = level->player_r * 2; db_tile_render(level->tilesets, renderer, level->player_gid, &dstrect); dstrect.x = level->target_x - level->target_r; dstrect.y = level->target_y - level->target_r; dstrect.w = level->target_r * 2; dstrect.h = level->target_r * 2; db_tile_render(level->tilesets, renderer, level->target_gid, &dstrect); db_balls_render(level->balls, renderer); SDL_RenderPresent(renderer); } int db_level_play(SDL_Renderer *renderer, struct db_level *level) { int fr; Uint32 prv_ticks; Uint32 cur_ticks; Uint32 delay; SDL_Event event; db_dbg("Playing %s/%s", level->game_id, level->level_id); level->map = db_map_new(level->game_id, level->level_id); if (level->map == NULL) { return -1; } level->map_texture = db_map_render(level->map, renderer); level->tilesets = db_map_get_tilesets(level->map); db_map_get_player(level->map, &level->player_x, &level->player_y, &level->player_r, &level->player_gid); db_map_get_target(level->map, &level->target_x, &level->target_y, &level->target_r, &level->target_gid); level->balls = db_map_get_balls(level->map); fr = db_map_get_framerate(level->map); prv_ticks = SDL_GetTicks(); while (1) { while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_QUIT: return -1; default: break; } } db_balls_move(level->balls); db_balls_collisions(level->balls); _db_level_render(renderer, level); cur_ticks = SDL_GetTicks(); if ((Uint32) (1000 / fr) > (cur_ticks - prv_ticks)) { delay = 1000 / fr - (cur_ticks - prv_ticks); } else { db_warn("Frame took longer than frame period"); delay = 0; } db_dbg("Frame took %u ms, delaying %u ms", cur_ticks - prv_ticks, delay); SDL_Delay(delay); prv_ticks = cur_ticks; } return 0; } struct db_level * db_level_next(struct db_level *level) { return level->next; }