From 9080d731d73b8ffbb1598f622e3bdd05e8f1938e Mon Sep 17 00:00:00 2001 From: P. J. McDermott Date: Sun, 08 Aug 2021 19:37:53 -0400 Subject: char: New "class", absorbing player --- (limited to 'src') 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 . */ -#ifndef MF_PLAYER_H_ -#define MF_PLAYER_H_ +#ifndef MF_CHAR_H +#define MF_CHAR_H -struct mf_player; +#include +#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 . + */ + +#include +#include +#include +#include +#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 . + */ + +#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 . + */ + +#include +#include +#include +#include +#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 #include #include +#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 . - */ - -#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; - 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; -} -- cgit v0.9.1