Separate player movement from input event loop.
Wrote a keyboardinput object but decided against using it for the time being. I'll leave it in if I change my mind.
This commit is contained in:
parent
c4dc8382a9
commit
2813a571e4
|
@ -153,6 +153,7 @@ add_executable(breakhack
|
|||
src/menu
|
||||
src/collisions
|
||||
src/keyboard
|
||||
src/keyboardinput
|
||||
src/mixer
|
||||
src/io_util
|
||||
src/physfsrwops
|
||||
|
@ -215,6 +216,10 @@ IF (CMOCKA_FOUND)
|
|||
add_executable(test_hashtable test/test_hashtable src/hashtable src/util)
|
||||
target_link_libraries(test_hashtable ${CMOCKA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_test(test_hashtable test_hashtable)
|
||||
|
||||
add_executable(test_keyboardinput test/test_keyboardinput src/keyboardinput src/keyboard)
|
||||
target_link_libraries(test_keyboardinput ${CMOCKA_LIBRARY} ${CMAKE_THREAD_LIBS_INIT})
|
||||
add_test(test_keyboardinput test_keyboardinput)
|
||||
ENDIF (CMOCKA_FOUND )
|
||||
|
||||
# LINT:
|
||||
|
|
|
@ -19,12 +19,9 @@
|
|||
#include "keyboard.h"
|
||||
#include "util.h"
|
||||
|
||||
bool
|
||||
keyboard_direction_press(Direction dir, SDL_Event *event)
|
||||
static bool
|
||||
extract_key(Direction dir, SDL_Event *event)
|
||||
{
|
||||
if (event->type != SDL_KEYDOWN)
|
||||
return false;
|
||||
|
||||
Uint32 key = event->key.keysym.sym;
|
||||
switch (dir) {
|
||||
case UP:
|
||||
|
@ -48,6 +45,24 @@ keyboard_direction_press(Direction dir, SDL_Event *event)
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_direction_press(Direction dir, SDL_Event *event)
|
||||
{
|
||||
if (event->type != SDL_KEYDOWN)
|
||||
return false;
|
||||
|
||||
return extract_key(dir, event);
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_direction_release(Direction dir, SDL_Event *event)
|
||||
{
|
||||
if (event->type != SDL_KEYUP)
|
||||
return false;
|
||||
|
||||
return extract_key(dir, event);
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_press(Uint32 key, SDL_Event *event)
|
||||
{
|
||||
|
@ -57,6 +72,15 @@ keyboard_press(Uint32 key, SDL_Event *event)
|
|||
return key == (Uint32) event->key.keysym.sym;
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_release(Uint32 key, SDL_Event *event)
|
||||
{
|
||||
if (event->type != SDL_KEYUP)
|
||||
return false;
|
||||
|
||||
return key == (Uint32) event->key.keysym.sym;
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_mod_press(Uint32 key, Uint32 mod, SDL_Event *event)
|
||||
{
|
||||
|
|
|
@ -26,9 +26,15 @@
|
|||
bool
|
||||
keyboard_direction_press(Direction, SDL_Event*);
|
||||
|
||||
bool
|
||||
keyboard_direction_release(Direction, SDL_Event*);
|
||||
|
||||
bool
|
||||
keyboard_press(Uint32 key, SDL_Event*);
|
||||
|
||||
bool
|
||||
keyboard_release(Uint32 key, SDL_Event*);
|
||||
|
||||
bool
|
||||
keyboard_mod_press(Uint32 key, Uint32 mod, SDL_Event*);
|
||||
|
||||
|
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "keyboardinput.h"
|
||||
#include "keyboard.h"
|
||||
#include "vector2d.h"
|
||||
|
||||
void
|
||||
keyboardinput_init(KeyboardInput *input)
|
||||
{
|
||||
input->currentState = 0;
|
||||
input->lastState = 0;
|
||||
}
|
||||
|
||||
void
|
||||
keyboardinput_handle_event(KeyboardInput *input, SDL_Event *event)
|
||||
{
|
||||
if (keyboard_direction_press(UP, event)) {
|
||||
input->currentState |= KEY_UP;
|
||||
} else if (keyboard_direction_press(DOWN, event)) {
|
||||
input->currentState |= KEY_DOWN;
|
||||
} else if (keyboard_direction_press(LEFT, event)) {
|
||||
input->currentState |= KEY_LEFT;
|
||||
} else if (keyboard_direction_press(RIGHT, event)) {
|
||||
input->currentState |= KEY_RIGHT;
|
||||
} else if (keyboard_press(SDLK_0, event)) {
|
||||
input->currentState |= KEY_NUM1;
|
||||
}
|
||||
for (int i = SDLK_0; i <= SDLK_9; ++i) {
|
||||
if (keyboard_press(i, event))
|
||||
input->currentState |= (1 << i);
|
||||
}
|
||||
|
||||
if (keyboard_direction_release(UP, event)) {
|
||||
input->currentState &= ~KEY_UP;
|
||||
} else if (keyboard_direction_release(DOWN, event)) {
|
||||
input->currentState &= ~KEY_DOWN;
|
||||
} else if (keyboard_direction_release(LEFT, event)) {
|
||||
input->currentState &= ~KEY_LEFT;
|
||||
} else if (keyboard_direction_release(RIGHT, event)) {
|
||||
input->currentState &= ~KEY_RIGHT;
|
||||
} else if (keyboard_release(SDLK_0, event)) {
|
||||
input->currentState &= ~KEY_NUM1;
|
||||
}
|
||||
for (int i = SDLK_0; i <= SDLK_9; ++i) {
|
||||
if (keyboard_release(i, event))
|
||||
input->currentState &= ~(1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
key_is_pressed(KeyboardInput *input, Uint64 key)
|
||||
{
|
||||
return (input->currentState & key) && !(input->lastState & key);
|
||||
}
|
||||
|
||||
bool
|
||||
key_is_released(KeyboardInput *input, Uint64 key)
|
||||
{
|
||||
return (input->lastState & key) && !(input->currentState & key);
|
||||
}
|
||||
|
||||
bool
|
||||
key_is_down(KeyboardInput *input, Uint64 key)
|
||||
{
|
||||
return input->currentState & key;
|
||||
}
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef KEYBOARDINPUT_H_
|
||||
#define KEYBOARDINPUT_H_
|
||||
|
||||
#include <SDL.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define KEY_LEFT 1
|
||||
#define KEY_RIGHT 2
|
||||
#define KEY_UP 4
|
||||
#define KEY_DOWN 8
|
||||
#define KEY_NUM0 16
|
||||
#define KEY_NUM1 32
|
||||
#define KEY_NUM2 64
|
||||
#define KEY_NUM3 128
|
||||
#define KEY_NUM4 256
|
||||
#define KEY_NUM5 512
|
||||
#define KEY_NUM6 1024
|
||||
#define KEY_NUM7 2048
|
||||
#define KEY_NUM8 4096
|
||||
#define KEY_NUM9 8192
|
||||
|
||||
typedef struct KeyboardState {
|
||||
bool dir_left;
|
||||
bool dir_right;
|
||||
bool dir_up;
|
||||
bool dir_down;
|
||||
} KeyboardState;
|
||||
|
||||
typedef struct KeyboardInput {
|
||||
Uint64 currentState;
|
||||
Uint64 lastState;
|
||||
} KeyboardInput;
|
||||
|
||||
void
|
||||
keyboardinput_init(KeyboardInput *);
|
||||
|
||||
void
|
||||
keyboardinput_handle_event(KeyboardInput *, SDL_Event*);
|
||||
|
||||
bool
|
||||
key_is_pressed(KeyboardInput *, Uint64 key);
|
||||
|
||||
bool
|
||||
key_is_released(KeyboardInput *, Uint64 key);
|
||||
|
||||
bool
|
||||
key_is_down(KeyboardInput *, Uint64 key);
|
||||
|
||||
#endif // KEYBOARDINPUT_H_
|
||||
|
|
@ -412,8 +412,6 @@ handle_events(void)
|
|||
gPlayer->handle_event(gPlayer,
|
||||
gRoomMatrix,
|
||||
&event);
|
||||
camera_follow_position(gCamera, &gPlayer->sprite->pos);
|
||||
map_set_current_room(gMap, &gPlayer->sprite->pos);
|
||||
roommatrix_handle_event(gRoomMatrix, &event);
|
||||
skillbar_handle_event(gSkillBar, &event);
|
||||
} else if (gGameState == MENU) {
|
||||
|
@ -496,8 +494,10 @@ run_game(void)
|
|||
particle_engine_update(deltaTime);
|
||||
|
||||
actiontextbuilder_update(&updateData);
|
||||
map_update(&updateData);
|
||||
player_update(&updateData);
|
||||
camera_follow_position(gCamera, &gPlayer->sprite->pos);
|
||||
map_set_current_room(gMap, &gPlayer->sprite->pos);
|
||||
map_update(&updateData);
|
||||
|
||||
roommatrix_update_with_player(gRoomMatrix, gPlayer);
|
||||
if (currentTurn == PLAYER) {
|
||||
|
|
|
@ -401,6 +401,9 @@ monster_drop_loot(Monster *monster, Map *map, Player *player)
|
|||
void
|
||||
monster_render(Monster *m, Camera *cam)
|
||||
{
|
||||
if (m->stats.hp <= 0)
|
||||
return;
|
||||
|
||||
sprite_render(m->sprite, cam);
|
||||
if (m->stateIndicator.displayCount > 0)
|
||||
sprite_render(m->stateIndicator.sprite, cam);
|
||||
|
|
82
src/player.c
82
src/player.c
|
@ -209,41 +209,21 @@ player_sip_health(Player *player)
|
|||
}
|
||||
|
||||
static void
|
||||
handle_movement_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
||||
handle_next_move(Player *player, RoomMatrix *matrix)
|
||||
{
|
||||
static unsigned int step = 1;
|
||||
Vector2d direction = VECTOR2D_NODIR;
|
||||
if (!vector2d_equals(player->nextDirection, VECTOR2D_NODIR))
|
||||
move(player, matrix, player->nextDirection);
|
||||
|
||||
if (keyboard_direction_press(LEFT, event))
|
||||
direction = VECTOR2D_LEFT;
|
||||
if (keyboard_direction_press(RIGHT, event))
|
||||
direction = VECTOR2D_RIGHT;
|
||||
if (keyboard_direction_press(UP, event))
|
||||
direction = VECTOR2D_UP;
|
||||
if (keyboard_direction_press(DOWN, event))
|
||||
direction = VECTOR2D_DOWN;
|
||||
map_room_modifier_player_effect(player, matrix, &player->nextDirection, move);
|
||||
|
||||
if (!vector2d_equals(direction, VECTOR2D_NODIR))
|
||||
move(player, matrix, direction);
|
||||
|
||||
map_room_modifier_player_effect(player, matrix, &direction, move);
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
if (keyboard_mod_press(SDLK_SPACE, KMOD_CTRL, event)) {
|
||||
Position pos = player->sprite->pos;
|
||||
pos.x += 8;
|
||||
pos.y += 8;
|
||||
particle_engine_bloodspray(pos, (Dimension) { 8, 8 }, 200);
|
||||
player->stats.hp = 0;
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
if (!vector2d_equals(VECTOR2D_NODIR, direction)) {
|
||||
if (!vector2d_equals(VECTOR2D_NODIR, player->nextDirection)) {
|
||||
player->sprite->clip.x = 16*step;
|
||||
++step;
|
||||
step = step % 4;
|
||||
}
|
||||
|
||||
player->nextDirection = VECTOR2D_NODIR;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -293,8 +273,8 @@ check_skill_activation(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
|||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
check_skill_trigger(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
||||
static void
|
||||
check_skill_trigger(Player *player, RoomMatrix *matrix)
|
||||
{
|
||||
int activeSkill = -1;
|
||||
for (int i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
||||
|
@ -305,26 +285,34 @@ check_skill_trigger(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
|||
}
|
||||
|
||||
if (activeSkill < 0)
|
||||
return false;
|
||||
return;
|
||||
|
||||
Vector2d dir;
|
||||
if (keyboard_direction_press(UP, event))
|
||||
dir = VECTOR2D_UP;
|
||||
else if (keyboard_direction_press(DOWN, event))
|
||||
dir = VECTOR2D_DOWN;
|
||||
else if (keyboard_direction_press(LEFT, event))
|
||||
dir = VECTOR2D_LEFT;
|
||||
else if (keyboard_direction_press(RIGHT, event))
|
||||
dir = VECTOR2D_RIGHT;
|
||||
else
|
||||
return false;
|
||||
|
||||
SkillData skillData = { player, matrix, dir };
|
||||
if (vector2d_equals(player->nextDirection, VECTOR2D_NODIR))
|
||||
return;
|
||||
|
||||
SkillData skillData = { player, matrix, player->nextDirection };
|
||||
use_skill(player->skills[activeSkill], &skillData);
|
||||
|
||||
return true;
|
||||
player->nextDirection = VECTOR2D_NODIR;
|
||||
}
|
||||
|
||||
static void
|
||||
read_player_next_direction(Player *player, SDL_Event *event)
|
||||
{
|
||||
player->nextDirection = VECTOR2D_NODIR;
|
||||
|
||||
if (keyboard_direction_press(LEFT, event))
|
||||
player->nextDirection = VECTOR2D_LEFT;
|
||||
if (keyboard_direction_press(RIGHT, event))
|
||||
player->nextDirection = VECTOR2D_RIGHT;
|
||||
if (keyboard_direction_press(UP, event))
|
||||
player->nextDirection = VECTOR2D_UP;
|
||||
if (keyboard_direction_press(DOWN, event))
|
||||
player->nextDirection = VECTOR2D_DOWN;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
||||
{
|
||||
|
@ -338,8 +326,7 @@ handle_player_input(Player *player, RoomMatrix *matrix, SDL_Event *event)
|
|||
return;
|
||||
|
||||
check_skill_activation(player, matrix, event);
|
||||
if (!check_skill_trigger(player, matrix, event))
|
||||
handle_movement_input(player, matrix, event);
|
||||
read_player_next_direction(player, event);
|
||||
}
|
||||
|
||||
Player*
|
||||
|
@ -360,6 +347,7 @@ player_create(class_t class, SDL_Renderer *renderer)
|
|||
player->state = ALIVE;
|
||||
player->projectiles = linkedlist_create();
|
||||
player->animationTimer = timer_create();
|
||||
player->nextDirection = VECTOR2D_NODIR;
|
||||
|
||||
for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) {
|
||||
player->skills[i] = NULL;
|
||||
|
@ -476,6 +464,10 @@ player_reset_steps(Player *p)
|
|||
void player_update(UpdateData *data)
|
||||
{
|
||||
Player *player = data->player;
|
||||
|
||||
check_skill_trigger(player, data->matrix);
|
||||
handle_next_move(player, data->matrix);
|
||||
|
||||
if (player->state == FALLING && player->stats.hp > 0) {
|
||||
if (!timer_started(player->animationTimer)) {
|
||||
timer_start(player->animationTimer);
|
||||
|
|
|
@ -63,6 +63,7 @@ typedef struct Player_t {
|
|||
state_t state;
|
||||
Skill *skills[PLAYER_SKILL_COUNT];
|
||||
Timer *animationTimer;
|
||||
Vector2d nextDirection;
|
||||
void (*handle_event)(struct Player_t*, RoomMatrix*, SDL_Event*);
|
||||
} Player;
|
||||
|
||||
|
|
|
@ -44,14 +44,7 @@ pointer_handle_event(Pointer *p, SDL_Event *event)
|
|||
// Compensate for a small offset in the sprite
|
||||
p->sprite->pos.x = event->motion.x - 6;
|
||||
p->sprite->pos.y = event->motion.y - 6;
|
||||
//debug("Pointer pos: %dx%d", p->sprite->pos.x, p->sprite->pos.y);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (event->type == SDL_MOUSEBUTTONDOWN) {
|
||||
Dimension dim = { 10, 10 };
|
||||
particle_engine_sparkle(p->sprite->pos, dim);
|
||||
}
|
||||
#endif // DEBUG
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <setjmp.h>
|
||||
#include <cmocka.h>
|
||||
#include "../src/keyboardinput.h"
|
||||
|
||||
static KeyboardInput input = { 0, 0 };
|
||||
|
||||
static void
|
||||
test_keypress(void **state)
|
||||
{
|
||||
(void) state;
|
||||
input.lastState = 0;
|
||||
input.currentState = KEY_UP;
|
||||
assert_true(key_is_pressed(&input, KEY_UP));
|
||||
}
|
||||
|
||||
static void
|
||||
test_keyrelease(void **state)
|
||||
{
|
||||
(void) state;
|
||||
input.lastState = KEY_UP;
|
||||
input.currentState = 0;
|
||||
assert_true(key_is_released(&input, KEY_UP));
|
||||
}
|
||||
|
||||
static void
|
||||
test_keydown(void **state)
|
||||
{
|
||||
(void) state;
|
||||
input.currentState = KEY_UP;
|
||||
assert_true(key_is_down(&input, KEY_UP));
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_keypress),
|
||||
cmocka_unit_test(test_keyrelease),
|
||||
cmocka_unit_test(test_keydown),
|
||||
};
|
||||
|
||||
return cmocka_run_group_tests(tests, NULL, NULL);
|
||||
}
|
Loading…
Reference in New Issue