/* * Copyright (C) 2021 P. J. McDermott * * This file is part of Maze Fight * * Maze Fight 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. * * Maze Fight 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 Maze Fight. If not, see . */ #include #include #include #include #include "defs.h" #include "maze.h" #include "player.h" enum _mf_player_dir { MF_PLAYER_DIR_N_, MF_PLAYER_DIR_U_, MF_PLAYER_DIR_D_, MF_PLAYER_DIR_L_, MF_PLAYER_DIR_R_ }; struct mf_player { struct mf_maze *maze; int cell_width; int speed; enum _mf_player_dir cur_dir; enum _mf_player_dir new_dir; int turning; int cur_x; int cur_y; int new_x; int new_y; int travel; }; struct mf_player * mf_player_new(struct mf_maze *maze, int cell_width) { struct mf_player *p; p = calloc(1, sizeof(*p)); if (p == NULL) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't create player: %s", strerror(errno)); return NULL; } p->maze = maze; p->cell_width = cell_width; p->speed = MF_PLAYER_SPEED; p->new_dir = MF_PLAYER_DIR_N_; p->turning = 0; p->cur_x = 0; p->cur_y = 0; p->travel = 0; if (mf_maze_is_wall(maze, 0, 0, 1, 0)) { p->cur_dir = MF_PLAYER_DIR_D_; } else { p->cur_dir = MF_PLAYER_DIR_R_; } return p; } static void _mf_player_move(struct mf_player *p, enum _mf_player_dir dir) { p->new_dir = dir; } void mf_player_key_event(struct mf_player *p, SDL_Event *e) { switch (e->type) { case SDL_KEYDOWN: switch (e->key.keysym.sym) { case SDLK_UP: _mf_player_move(p, MF_PLAYER_DIR_U_); break; case SDLK_DOWN: _mf_player_move(p, MF_PLAYER_DIR_D_); break; case SDLK_LEFT: _mf_player_move(p, MF_PLAYER_DIR_L_); break; case SDLK_RIGHT: _mf_player_move(p, MF_PLAYER_DIR_R_); break; default: break; } default: break; } } int mf_player_update(struct mf_player *p) { int dx; int dy; if (p->travel > 0) { /* Currently moving */ p->travel += p->speed; if (p->travel >= p->cell_width) { /* Reached next cell */ p->cur_x = p->new_x; p->cur_y = p->new_y; if (p->cur_dir == p->new_dir) { /* Want to continue straight */ p->travel -= p->cell_width; } else { /* Want to stop or turn */ p->travel = 0; } } else { /* Farther to go */ return 0; } } if (p->new_dir != MF_PLAYER_DIR_N_ && p->cur_dir != p->new_dir) { /* Want to turn */ p->cur_dir = p->new_dir; p->new_dir = MF_PLAYER_DIR_N_; p->turning = MF_PLAYER_TURN_TIME + 1; } if (p->turning > 0) { /* Turning */ --p->turning; } if (p->turning == 0) { /* Done turning */ if (p->new_dir != MF_PLAYER_DIR_N_) { /* Want to move */ switch (p->new_dir) { case MF_PLAYER_DIR_U_: dx = 0; dy = -1; break; case MF_PLAYER_DIR_D_: dx = 0; dy = 1; break; case MF_PLAYER_DIR_L_: dx = -1; dy = 0; break; case MF_PLAYER_DIR_R_: dx = 1; dy = 0; break; default: dx = 0; dy = 0; break; } p->new_dir = MF_PLAYER_DIR_N_; if (mf_maze_is_wall(p->maze, p->cur_x, p->cur_y, dx, dy)) { return 0; } p->new_x = p->cur_x + dx; p->new_y = p->cur_y + dy; p->travel += p->speed; } } return 0; } int mf_player_render(struct mf_player *p, SDL_Renderer *renderer) { int x; int y; if (SDL_SetRenderDrawColor(renderer, MF_COLOR_PLYR_R, MF_COLOR_PLYR_G, MF_COLOR_PLYR_B, MF_COLOR_PLYR_A) < 0) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Couldn't render player: %s", SDL_GetError()); return -1; } x = p->cur_x * p->cell_width + p->cell_width / 2; y = p->cur_y * p->cell_width + p->cell_width / 2; switch (p->cur_dir) { case MF_PLAYER_DIR_U_: y -= p->travel; break; case MF_PLAYER_DIR_D_: y += p->travel; break; case MF_PLAYER_DIR_L_: x -= p->travel; break; case MF_PLAYER_DIR_R_: x += p->travel; break; default: break; } return SDL_RenderDrawPoint(renderer, x, y); } void mf_player_destroy(struct mf_player **p_p) { struct mf_player *p; if (p_p == NULL || *p_p == NULL) { return; } p = *p_p; free(p); p = NULL; }