/*
* 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;
}