summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorP. J. McDermott <pj@pehjota.net>2021-08-08 19:37:53 (EDT)
committer P. J. McDermott <pj@pehjota.net>2021-08-08 19:37:53 (EDT)
commit9080d731d73b8ffbb1598f622e3bdd05e8f1938e (patch)
treefe19814b3c1365f72d9122f93677ce4a76bbe6bf /src
parentc2bac04684e11dad54cb1dba224fb860e879834c (diff)
downloadmazefight-9080d731d73b8ffbb1598f622e3bdd05e8f1938e.zip
mazefight-9080d731d73b8ffbb1598f622e3bdd05e8f1938e.tar.gz
mazefight-9080d731d73b8ffbb1598f622e3bdd05e8f1938e.tar.bz2
char: New "class", absorbing player
Diffstat (limited to 'src')
-rw-r--r--src/char.h (renamed from src/player.h)23
-rw-r--r--src/char/char.c327
-rw-r--r--src/char/char.h74
-rw-r--r--src/char/local.mk4
-rw-r--r--src/char/player.c136
-rw-r--r--src/game.c16
-rw-r--r--src/local.mk3
-rw-r--r--src/player.c407
8 files changed, 563 insertions, 427 deletions
diff --git a/src/player.h b/src/char.h
index b180e20..bf5e85b 100644
--- a/src/player.h
+++ b/src/char.h
@@ -17,28 +17,31 @@
* along with Maze Fight. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef MF_PLAYER_H_
-#define MF_PLAYER_H_
+#ifndef MF_CHAR_H
+#define MF_CHAR_H
-struct mf_player;
+#include <SDL.h>
+#include "maze.h"
-struct mf_player *
+struct mf_char;
+
+struct mf_char *
mf_player_new(struct mf_maze *maze, int cell_width);
void
-mf_player_get_vector(struct mf_player *p, int *x, int *y, int *travel,
+mf_char_get_vector(struct mf_char *c, int *x, int *y, int *travel,
int *dx, int *dy);
void
-mf_player_key_event(struct mf_player *p, SDL_Event *e);
+mf_player_key_event(struct mf_char *c, SDL_Event *e);
int
-mf_player_update(struct mf_player *p);
+mf_char_update(struct mf_char *c);
int
-mf_player_render(struct mf_player *p, SDL_Renderer *renderer);
+mf_char_render(struct mf_char *c, SDL_Renderer *renderer);
void
-mf_player_destroy(struct mf_player **p_p);
+mf_char_destroy(struct mf_char **c_c);
-#endif /* MF_PLAYER_H_ */
+#endif /* MF_CHAR_H */
diff --git a/src/char/char.c b/src/char/char.c
new file mode 100644
index 0000000..09aa6bd
--- /dev/null
+++ b/src/char/char.c
@@ -0,0 +1,327 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <SDL.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../char.h"
+#include "char.h"
+
+struct mf_char *
+mf_char_new(size_t size)
+{
+ struct mf_char *c;
+
+ c = calloc(1, size);
+ if (c == NULL) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't create character: %s",
+ strerror(errno));
+ return NULL;
+ }
+
+ return c;
+}
+
+void
+mf_char_get_vector(struct mf_char *c, int *x, int *y, int *travel,
+ int *dx, int *dy)
+{
+ *x = c->cur_x;
+ *y = c->cur_y;
+ *travel = c->travel;
+ switch (c->cur_dir) {
+ case MF_CHAR_DIR_U_: *dx = 0; *dy = -1; break;
+ case MF_CHAR_DIR_D_: *dx = 0; *dy = 1; break;
+ case MF_CHAR_DIR_L_: *dx = -1; *dy = 0; break;
+ case MF_CHAR_DIR_R_: *dx = 1; *dy = 0; break;
+ default: *dx = 0; *dy = 0; break;
+ }
+}
+
+int
+mf_char_update(struct mf_char *c)
+{
+ int dx;
+ int dy;
+
+ if (c->travel > 0) {
+ /* Currently moving */
+ c->travel += c->speed;
+ if (c->travel >= c->cell_width) {
+ /* Reached next cell */
+ c->cur_x = c->new_x;
+ c->cur_y = c->new_y;
+ if (c->cur_dir == c->new_dir) {
+ /* Want to continue straight */
+ c->travel -= c->cell_width;
+ } else {
+ /* Want to stop or turn */
+ c->travel = 0;
+ }
+ } else {
+ /* Farther to go */
+ goto end;
+ }
+ }
+ if (c->new_dir != MF_CHAR_DIR_N_ && c->cur_dir != c->new_dir) {
+ /* Want to turn */
+ c->old_dir = c->cur_dir;
+ c->cur_dir = c->new_dir;
+ c->new_dir = MF_CHAR_DIR_N_;
+ c->turning = c->turn_time + 1;
+ }
+ if (c->turning > 0) {
+ /* Turning */
+ --c->turning;
+ }
+ if (c->turning == 0) {
+ /* Done turning */
+ if (c->new_dir != MF_CHAR_DIR_N_) {
+ /* Want to move */
+ switch (c->new_dir) {
+ case MF_CHAR_DIR_U_: dx = 0; dy = -1; break;
+ case MF_CHAR_DIR_D_: dx = 0; dy = 1; break;
+ case MF_CHAR_DIR_L_: dx = -1; dy = 0; break;
+ case MF_CHAR_DIR_R_: dx = 1; dy = 0; break;
+ default: dx = 0; dy = 0; break;
+ }
+ c->new_dir = MF_CHAR_DIR_N_;
+ if (mf_maze_is_wall(c->maze, c->cur_x, c->cur_y,
+ dx, dy)) {
+ goto end;
+ }
+ c->new_x = c->cur_x + dx;
+ c->new_y = c->cur_y + dy;
+ c->travel += c->speed;
+ }
+ }
+
+ end:
+ return c->update(c);
+}
+
+int
+mf_char_render(struct mf_char *c, SDL_Renderer *renderer)
+{
+ int e = 0;
+ int cx;
+ int cy;
+ double fx;
+ double ofx;
+ int r;
+ int x;
+ int y;
+ int i;
+ int oy;
+ int fr;
+ int hy;
+ int ox;
+
+ cx = c->cur_x * c->cell_width + c->cell_width / 2;
+ cy = c->cur_y * c->cell_width + c->cell_width / 2;
+ switch (c->cur_dir) {
+ case MF_CHAR_DIR_U_:
+ cy -= c->travel;
+ if (c->old_dir == MF_CHAR_DIR_L_) {
+ fx = -2.0;
+ } else {
+ fx = 2.0;
+ }
+ break;
+ case MF_CHAR_DIR_D_: cy += c->travel; fx = 0.0; break;
+ case MF_CHAR_DIR_L_: cx -= c->travel; fx = -1.0; break;
+ case MF_CHAR_DIR_R_: cx += c->travel; fx = 1.0; break;
+ default: fx = 0.0; break;
+ }
+ switch (c->old_dir) {
+ case MF_CHAR_DIR_U_:
+ if (c->cur_dir == MF_CHAR_DIR_L_) {
+ ofx = -2.0;
+ } else {
+ ofx = 2.0;
+ }
+ break;
+ case MF_CHAR_DIR_D_: ofx = 0.0; break;
+ case MF_CHAR_DIR_L_: ofx = -1.0; break;
+ case MF_CHAR_DIR_R_: ofx = 1.0; break;
+ default: ofx = 0.0; break;
+ }
+ r = c->cell_width / 2 - c->padding;
+ fx = ofx + (fx - ofx) * (c->turn_time - c->turning) / c->turn_time;
+ fx *= r;
+
+ /*
+ * Head
+ */
+
+ if (SDL_SetRenderDrawColor(renderer,
+ c->head_color.r, c->head_color.g,
+ c->head_color.b, c->head_color.a) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't render character: %s",
+ SDL_GetError());
+ e = -1;
+ }
+
+#define _mf_char_px(X, Y) \
+ do { \
+ if (SDL_RenderDrawPoint(renderer, cx + X, cy + Y) < 0) { \
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
+ "Couldn't render widget: %s", \
+ SDL_GetError()); \
+ e = -1; \
+ } \
+ } while (0)
+
+ /* TODO: This is one pixel larger than it should be. */
+ for (x = 0, y = r; y > x; ++x) {
+ y = round(sqrt((r-0.5)*(r-0.5) - (x-0.5)*(x-0.5)) + 0.5);
+ for (i = 0; i <= y; ++i) _mf_char_px( x, i);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px(0-x, i);
+ for (i = 0; i >= 0-y; --i) _mf_char_px(0-x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px( i, x);
+ for (i = 0; i <= y; ++i) _mf_char_px( i, 0-x);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( i, x);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( i, 0-x);
+ }
+
+#undef _mf_char_px
+
+ /*
+ * Smile
+ */
+
+ if (SDL_SetRenderDrawColor(renderer,
+ c->smil_color.r, c->smil_color.g,
+ c->smil_color.b, c->smil_color.a) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't render character: %s",
+ SDL_GetError());
+ e = -1;
+ }
+
+ oy = r * c->smile_y;
+ fr = r * c->smile_r;
+
+#define _mf_char_px(X, Y) \
+ do { \
+ hy = round(sqrt((r-0.5)*(r-0.5) - \
+ (X+fx-0.5)*(X+fx-0.5)) + 0.5); \
+ if (Y + oy < 0-hy || Y + oy > hy) continue; \
+ if (SDL_RenderDrawPoint(renderer, cx + fx + X, cy + oy + Y) \
+ < 0) { \
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
+ "Couldn't render widget: %s", \
+ SDL_GetError()); \
+ e = -1; \
+ } \
+ } while (0)
+
+ for (x = 0, y = fr; y > x; ++x) {
+ y = round(sqrt((fr-0.5)*(fr-0.5) - (x-0.5)*(x-0.5)) + 0.5);
+ for (i = 0; i <= y; ++i) _mf_char_px( x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px(0-x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px( i, x);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( i, x);
+ }
+
+#undef _mf_char_px
+
+ /*
+ * Eyes
+ */
+
+ if (SDL_SetRenderDrawColor(renderer,
+ c->eyes_color.r, c->eyes_color.g,
+ c->eyes_color.b, c->eyes_color.a) < 0) {
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Couldn't render character: %s",
+ SDL_GetError());
+ e = -1;
+ }
+
+ ox = r * c->eye_x;
+ oy = r * c->eye_y;
+ fr = r * c->eye_r;
+
+#define _mf_char_px(X, Y) \
+ do { \
+ hy = round(sqrt((r-0.5)*(r-0.5) - \
+ (X+fx-ox-0.5)*(X+fx-ox-0.5)) + 0.5); \
+ if (Y - oy >= 0-hy && Y - oy <= hy) { \
+ if (SDL_RenderDrawPoint(renderer, \
+ cx + fx - ox + X, cy - oy + Y) \
+ < 0) { \
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
+ "Couldn't render widget: %s", \
+ SDL_GetError()); \
+ e = -1; \
+ } \
+ } \
+ hy = round(sqrt((r-0.5)*(r-0.5) - \
+ (X+fx+ox-0.5)*(X+fx+ox-0.5)) + 0.5); \
+ if (Y - oy >= 0-hy && Y - oy <= hy) { \
+ if (SDL_RenderDrawPoint(renderer, \
+ cx + fx + ox + X, cy - oy + Y) \
+ < 0) { \
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
+ "Couldn't render widget: %s", \
+ SDL_GetError()); \
+ e = -1; \
+ } \
+ } \
+ } while (0)
+
+ for (x = 0, y = fr; y > x; ++x) {
+ y = round(sqrt((fr-0.5)*(fr-0.5) - (x-0.5)*(x-0.5)) + 0.5);
+ for (i = 0; i <= y; ++i) _mf_char_px( x, i);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px(0-x, i);
+ for (i = 0; i >= 0-y; --i) _mf_char_px(0-x, i);
+ for (i = 0; i <= y; ++i) _mf_char_px( i, x);
+ for (i = 0; i <= y; ++i) _mf_char_px( i, 0-x);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( i, x);
+ for (i = 0; i >= 0-y; --i) _mf_char_px( i, 0-x);
+ }
+
+#undef _mf_char_px
+
+ if (e < 0) {
+ return e;
+ }
+ return c->render(c, renderer);
+}
+
+void
+mf_char_destroy(struct mf_char **c_p)
+{
+ struct mf_char *c;
+
+ if (c_p == NULL || *c_p == NULL) {
+ return;
+ }
+ c = *c_p;
+
+ c->destroy(c);
+ free(c);
+ c = NULL;
+}
diff --git a/src/char/char.h b/src/char/char.h
new file mode 100644
index 0000000..f6c6b9f
--- /dev/null
+++ b/src/char/char.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef MF_CHAR_CHAR_H
+#define MF_CHAR_CHAR_H
+
+enum _mf_char_dir {
+ MF_CHAR_DIR_N_,
+ MF_CHAR_DIR_U_,
+ MF_CHAR_DIR_D_,
+ MF_CHAR_DIR_L_,
+ MF_CHAR_DIR_R_
+};
+
+struct mf_char {
+ struct mf_maze *maze;
+ int cell_width;
+ int speed;
+ enum _mf_char_dir cur_dir;
+ enum _mf_char_dir new_dir;
+ enum _mf_char_dir old_dir;
+ int turning;
+ int turn_time;
+ int cur_x;
+ int cur_y;
+ int new_x;
+ int new_y;
+ int travel;
+ int padding;
+ double smile_y;
+ double smile_r;
+ double eye_x;
+ double eye_y;
+ double eye_r;
+ SDL_Color head_color;
+ SDL_Color smil_color;
+ SDL_Color eyes_color;
+ int (*update)(struct mf_char *);
+ int (*render)(struct mf_char *, SDL_Renderer *);
+ void (*destroy)(struct mf_char *);
+};
+
+struct mf_char *
+mf_char_new(size_t size);
+
+#define mf_char_init(c, t_c, name) \
+ do { \
+ c = mf_char_new(sizeof(struct mf_##name)); \
+ if (c == NULL) { \
+ return NULL; \
+ }; \
+ c->update = &_mf_##name##_update; \
+ c->render = &_mf_##name##_render; \
+ c->destroy = &_mf_##name##_destroy; \
+ t_c = (struct mf_##name *) c; \
+ } while (0)
+
+#endif /* MF_CHAR_CHAR_H */
diff --git a/src/char/local.mk b/src/char/local.mk
new file mode 100644
index 0000000..92134a8
--- /dev/null
+++ b/src/char/local.mk
@@ -0,0 +1,4 @@
+mazefight_SOURCES += \
+ %reldir%/char.c \
+ %reldir%/char.h \
+ %reldir%/player.c
diff --git a/src/char/player.c b/src/char/player.c
new file mode 100644
index 0000000..9f6123d
--- /dev/null
+++ b/src/char/player.c
@@ -0,0 +1,136 @@
+/*
+ * 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include <SDL.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include "../char.h"
+#include "../defs.h"
+#include "../maze.h"
+#include "char.h"
+
+struct mf_player {
+ struct mf_char parent;
+};
+
+static int
+_mf_player_update(struct mf_char *c)
+{
+ int dx;
+ int dy;
+ int x;
+ int y;
+
+ switch (c->cur_dir) {
+ case MF_CHAR_DIR_U_: dx = 0; dy = -1; break;
+ case MF_CHAR_DIR_D_: dx = 0; dy = 1; break;
+ case MF_CHAR_DIR_L_: dx = -1; dy = 0; break;
+ case MF_CHAR_DIR_R_: dx = 1; dy = 0; break;
+ default: dx = 0; dy = 0; break;
+ }
+ x = c->cur_x - dx, y = c->cur_y - dy;
+ do {
+ x += dx, y += dy;
+ mf_maze_reveal_wall(c->maze, x, y, -1, 0);
+ mf_maze_reveal_wall(c->maze, x, y, 1, 0);
+ mf_maze_reveal_wall(c->maze, x, y, 0, -1);
+ mf_maze_reveal_wall(c->maze, x, y, 0, 1);
+ } while (!mf_maze_is_wall(c->maze, x, y, dx, dy));
+
+ return 0;
+}
+
+static int
+_mf_player_render(struct mf_char *c __attribute__((__unused__)),
+ SDL_Renderer *renderer __attribute__((__unused__)))
+{
+ return 0;
+}
+
+static void
+_mf_player_destroy(struct mf_char *c __attribute__((__unused__)))
+{
+}
+
+struct mf_char *
+mf_player_new(struct mf_maze *maze, int cell_width)
+{
+ struct mf_char *c;
+ struct mf_player *p __attribute__((__unused__));
+
+ mf_char_init(c, p, player);
+
+ c->maze = maze;
+ c->cell_width = cell_width;
+ c->speed = MF_PLAYER_SPEED;
+ c->new_dir = MF_CHAR_DIR_N_;
+ c->turning = 0;
+ c->turn_time = MF_PLAYER_TURN_TIME;
+ c->cur_x = 0;
+ c->cur_y = 0;
+ c->travel = 0;
+ c->padding = MF_PLAYER_P;
+ c->smile_y = MF_PLAYER_SMILE_Y;
+ c->smile_r = MF_PLAYER_SMILE_R;
+ c->eye_x = MF_PLAYER_EYE_X;
+ c->eye_y = MF_PLAYER_EYE_Y;
+ c->eye_r = MF_PLAYER_EYE_R;
+
+ c->head_color.r = MF_COLOR_PLYR_R, c->head_color.g = MF_COLOR_PLYR_G;
+ c->head_color.b = MF_COLOR_PLYR_B, c->head_color.a = MF_COLOR_PLYR_A;
+ c->smil_color.r = MF_COLOR_PSML_R, c->smil_color.g = MF_COLOR_PSML_G;
+ c->smil_color.b = MF_COLOR_PSML_B, c->smil_color.a = MF_COLOR_PSML_A;
+ c->eyes_color.r = MF_COLOR_PEYE_R, c->eyes_color.g = MF_COLOR_PEYE_G;
+ c->eyes_color.b = MF_COLOR_PEYE_B, c->eyes_color.a = MF_COLOR_PEYE_A;
+
+ if (mf_maze_is_wall(maze, 0, 0, 1, 0)) {
+ c->old_dir = c->cur_dir = MF_CHAR_DIR_D_;
+ } else {
+ c->old_dir = c->cur_dir = MF_CHAR_DIR_R_;
+ }
+
+ return c;
+}
+
+void
+mf_player_key_event(struct mf_char *c, SDL_Event *e)
+{
+ switch (e->type) {
+ case SDL_KEYDOWN:
+ switch (e->key.keysym.sym) {
+ case SDLK_UP:
+ c->new_dir = MF_CHAR_DIR_U_;
+ break;
+ case SDLK_DOWN:
+ c->new_dir = MF_CHAR_DIR_D_;
+ break;
+ case SDLK_LEFT:
+ c->new_dir = MF_CHAR_DIR_L_;
+ break;
+ case SDLK_RIGHT:
+ c->new_dir = MF_CHAR_DIR_R_;
+ break;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/src/game.c b/src/game.c
index 5a410e2..8fb6637 100644
--- a/src/game.c
+++ b/src/game.c
@@ -21,11 +21,11 @@
#include <SDL_ttf.h>
#include <errno.h>
#include <string.h>
+#include "char.h"
#include "defs.h"
#include "dirs.h"
#include "game.h"
#include "maze.h"
-#include "player.h"
#include "tk.h"
#include "util.h"
@@ -143,7 +143,7 @@ int
mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
{
struct mf_maze *maze = NULL;
- struct mf_player *player = NULL;
+ struct mf_char *player = NULL;
SDL_Color maze_color;
char *font_path = NULL;
TTF_Font *text_font = NULL;
@@ -228,8 +228,8 @@ mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
}
}
if (won == SDL_FALSE) {
- mf_player_update(player);
- mf_player_get_vector(player, &game.player_cx,
+ mf_char_update(player);
+ mf_char_get_vector(player, &game.player_cx,
&game.player_cy, &game.player_travel,
&game.player_dx, &game.player_dy);
game.player_x = game.player_cx * MF_WINDOW_H / size;
@@ -245,7 +245,7 @@ mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
MF_COLOR_BACK_R, MF_COLOR_BACK_G,
MF_COLOR_BACK_B, MF_COLOR_BACK_A);
SDL_RenderClear(renderer);
- mf_player_render(player, renderer);
+ mf_char_render(player, renderer);
if (fow == SDL_TRUE && _mf_game_fow(renderer, &game, maze,
MF_WINDOW_H / size) < 0) {
goto err;
@@ -283,7 +283,7 @@ mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
TTF_CloseFont(text_font);
text_font = NULL;
mf_maze_destroy(&maze);
- mf_player_destroy(&player);
+ mf_char_destroy(&player);
return 0;
quit:
@@ -291,7 +291,7 @@ mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
TTF_CloseFont(text_font);
text_font = NULL;
mf_maze_destroy(&maze);
- mf_player_destroy(&player);
+ mf_char_destroy(&player);
return 1;
err:
@@ -303,6 +303,6 @@ mf_game(long seed, int size, int fow, int reveal, SDL_Renderer *renderer)
}
mftk_window_destroy(&win);
mf_maze_destroy(&maze);
- mf_player_destroy(&player);
+ mf_char_destroy(&player);
return -1;
}
diff --git a/src/local.mk b/src/local.mk
index 8a20a79..5f34457 100644
--- a/src/local.mk
+++ b/src/local.mk
@@ -9,10 +9,9 @@ mazefight_SOURCES += \
%reldir%/maze.h \
%reldir%/menu.c \
%reldir%/menu.h \
- %reldir%/player.c \
- %reldir%/player.h \
%reldir%/tk.h \
%reldir%/util.c \
%reldir%/util.h
+include %reldir%/char/local.mk
include %reldir%/tk/local.mk
diff --git a/src/player.c b/src/player.c
deleted file mode 100644
index a6bab2e..0000000
--- a/src/player.c
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * 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 <http://www.gnu.org/licenses/>.
- */
-
-#include <SDL.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <string.h>
-#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;
- enum _mf_player_dir old_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->old_dir = p->cur_dir = MF_PLAYER_DIR_D_;
- } else {
- p->old_dir = p->cur_dir = MF_PLAYER_DIR_R_;
- }
-
- return p;
-}
-
-void
-mf_player_get_vector(struct mf_player *p, int *x, int *y, int *travel,
- int *dx, int *dy)
-{
- *x = p->cur_x;
- *y = p->cur_y;
- *travel = p->travel;
- switch (p->cur_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;
- }
-}
-
-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:
- p->new_dir = MF_PLAYER_DIR_U_;
- break;
- case SDLK_DOWN:
- p->new_dir = MF_PLAYER_DIR_D_;
- break;
- case SDLK_LEFT:
- p->new_dir = MF_PLAYER_DIR_L_;
- break;
- case SDLK_RIGHT:
- p->new_dir = MF_PLAYER_DIR_R_;
- break;
- default:
- break;
- }
- default:
- break;
- }
-}
-
-int
-mf_player_update(struct mf_player *p)
-{
- int dx;
- int dy;
- int x;
- int y;
-
- 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 */
- goto end;
- }
- }
- if (p->new_dir != MF_PLAYER_DIR_N_ && p->cur_dir != p->new_dir) {
- /* Want to turn */
- p->old_dir = p->cur_dir;
- 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)) {
- goto end;
- }
- p->new_x = p->cur_x + dx;
- p->new_y = p->cur_y + dy;
- p->travel += p->speed;
- }
- }
-
- end:
- switch (p->cur_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;
- }
- x = p->cur_x - dx, y = p->cur_y - dy;
- do {
- x += dx, y += dy;
- mf_maze_reveal_wall(p->maze, x, y, -1, 0);
- mf_maze_reveal_wall(p->maze, x, y, 1, 0);
- mf_maze_reveal_wall(p->maze, x, y, 0, -1);
- mf_maze_reveal_wall(p->maze, x, y, 0, 1);
- } while (!mf_maze_is_wall(p->maze, x, y, dx, dy));
-
- return 0;
-}
-
-int
-mf_player_render(struct mf_player *p, SDL_Renderer *renderer)
-{
- int e = 0;
- int cx;
- int cy;
- double fx;
- double ofx;
- int r;
- int x;
- int y;
- int i;
- int oy;
- int fr;
- int hy;
- int ox;
-
- cx = p->cur_x * p->cell_width + p->cell_width / 2;
- cy = p->cur_y * p->cell_width + p->cell_width / 2;
- switch (p->cur_dir) {
- case MF_PLAYER_DIR_U_:
- cy -= p->travel;
- if (p->old_dir == MF_PLAYER_DIR_L_) {
- fx = -2.0;
- } else {
- fx = 2.0;
- }
- break;
- case MF_PLAYER_DIR_D_: cy += p->travel; fx = 0.0; break;
- case MF_PLAYER_DIR_L_: cx -= p->travel; fx = -1.0; break;
- case MF_PLAYER_DIR_R_: cx += p->travel; fx = 1.0; break;
- default: fx = 0; break;
- }
- switch (p->old_dir) {
- case MF_PLAYER_DIR_U_:
- if (p->cur_dir == MF_PLAYER_DIR_L_) {
- ofx = -2.0;
- } else {
- ofx = 2.0;
- }
- break;
- case MF_PLAYER_DIR_D_: ofx = 0.0; break;
- case MF_PLAYER_DIR_L_: ofx = -1.0; break;
- case MF_PLAYER_DIR_R_: ofx = 1.0; break;
- default: ofx = 0.0; break;
- }
- r = p->cell_width / 2 - MF_PLAYER_P;
- fx = ofx + (fx - ofx) * (MF_PLAYER_TURN_TIME - p->turning) /
- MF_PLAYER_TURN_TIME;
- fx *= r;
-
- /*
- * Head
- */
-
- 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());
- e = -1;
- }
-
-#define _mf_player_px(X, Y) \
- do { \
- if (SDL_RenderDrawPoint(renderer, cx + X, cy + Y) < 0) { \
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
- "Couldn't render widget: %s", \
- SDL_GetError()); \
- e = -1; \
- } \
- } while (0)
-
- /* TODO: This is one pixel larger than it should be. */
- for (x = 0, y = r; y > x; ++x) {
- y = round(sqrt((r-0.5)*(r-0.5) - (x-0.5)*(x-0.5)) + 0.5);
- for (i = 0; i <= y; ++i) _mf_player_px( x, i);
- for (i = 0; i >= 0-y; --i) _mf_player_px( x, i);
- for (i = 0; i <= y; ++i) _mf_player_px(0-x, i);
- for (i = 0; i >= 0-y; --i) _mf_player_px(0-x, i);
- for (i = 0; i <= y; ++i) _mf_player_px( i, x);
- for (i = 0; i <= y; ++i) _mf_player_px( i, 0-x);
- for (i = 0; i >= 0-y; --i) _mf_player_px( i, x);
- for (i = 0; i >= 0-y; --i) _mf_player_px( i, 0-x);
- }
-
-#undef _mf_player_px
-
- /*
- * Smile
- */
-
- if (SDL_SetRenderDrawColor(renderer,
- MF_COLOR_PSML_R, MF_COLOR_PSML_G,
- MF_COLOR_PSML_B, MF_COLOR_PSML_A) < 0) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
- "Couldn't render player: %s",
- SDL_GetError());
- e = -1;
- }
-
- oy = r * MF_PLAYER_SMILE_Y;
- fr = r * MF_PLAYER_SMILE_R;
-
-#define _mf_player_px(X, Y) \
- do { \
- hy = round(sqrt((r-0.5)*(r-0.5) - \
- (X+fx-0.5)*(X+fx-0.5)) + 0.5); \
- if (Y + oy < 0-hy || Y + oy > hy) continue; \
- if (SDL_RenderDrawPoint(renderer, cx + fx + X, cy + oy + Y) \
- < 0) { \
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
- "Couldn't render widget: %s", \
- SDL_GetError()); \
- e = -1; \
- } \
- } while (0)
-
- for (x = 0, y = fr; y > x; ++x) {
- y = round(sqrt((fr-0.5)*(fr-0.5) - (x-0.5)*(x-0.5)) + 0.5);
- for (i = 0; i <= y; ++i) _mf_player_px( x, i);
- for (i = 0; i <= y; ++i) _mf_player_px(0-x, i);
- for (i = 0; i <= y; ++i) _mf_player_px( i, x);
- for (i = 0; i >= 0-y; --i) _mf_player_px( i, x);
- }
-
-#undef _mf_player_px
-
- /*
- * Eyes
- */
-
- if (SDL_SetRenderDrawColor(renderer,
- MF_COLOR_PEYE_R, MF_COLOR_PEYE_G,
- MF_COLOR_PEYE_B, MF_COLOR_PEYE_A) < 0) {
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
- "Couldn't render player: %s",
- SDL_GetError());
- e = -1;
- }
-
- ox = r * MF_PLAYER_EYE_X;
- oy = r * MF_PLAYER_EYE_Y;
- fr = r * MF_PLAYER_EYE_R;
-
-#define _mf_player_px(X, Y) \
- do { \
- hy = round(sqrt((r-0.5)*(r-0.5) - \
- (X+fx-ox-0.5)*(X+fx-ox-0.5)) + 0.5); \
- if (Y - oy >= 0-hy && Y - oy <= hy) { \
- if (SDL_RenderDrawPoint(renderer, \
- cx + fx - ox + X, cy - oy + Y) \
- < 0) { \
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
- "Couldn't render widget: %s", \
- SDL_GetError()); \
- e = -1; \
- } \
- } \
- hy = round(sqrt((r-0.5)*(r-0.5) - \
- (X+fx+ox-0.5)*(X+fx+ox-0.5)) + 0.5); \
- if (Y - oy >= 0-hy && Y - oy <= hy) { \
- if (SDL_RenderDrawPoint(renderer, \
- cx + fx + ox + X, cy - oy + Y) \
- < 0) { \
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, \
- "Couldn't render widget: %s", \
- SDL_GetError()); \
- e = -1; \
- } \
- } \
- } while (0)
-
- for (x = 0, y = fr; y > x; ++x) {
- y = round(sqrt((fr-0.5)*(fr-0.5) - (x-0.5)*(x-0.5)) + 0.5);
- for (i = 0; i <= y; ++i) _mf_player_px( x, i);
- for (i = 0; i >= 0-y; --i) _mf_player_px( x, i);
- for (i = 0; i <= y; ++i) _mf_player_px(0-x, i);
- for (i = 0; i >= 0-y; --i) _mf_player_px(0-x, i);
- for (i = 0; i <= y; ++i) _mf_player_px( i, x);
- for (i = 0; i <= y; ++i) _mf_player_px( i, 0-x);
- for (i = 0; i >= 0-y; --i) _mf_player_px( i, x);
- for (i = 0; i >= 0-y; --i) _mf_player_px( i, 0-x);
- }
-
-#undef _mf_player_px
-
- return e;
-}
-
-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;
-}