Input (first pass)
Some checks failed
Build Dusk / build-linux (push) Failing after 1m16s
Build Dusk / build-psp (push) Failing after 1m14s

This commit is contained in:
2025-12-23 17:33:46 +10:00
parent ee3d27fda3
commit bfdc0e8462
53 changed files with 516 additions and 495 deletions

View File

@@ -12,7 +12,7 @@ endif()
file(STRINGS "${ENV_FILE}" ENV_LINES)
set(HEADER_CONTENT "#pragma once\n#include \"dusk.hpp\"\n\n")
set(HEADER_CONTENT "#pragma once\n#include \"Dusk.hpp\"\n\n")
foreach(line IN LISTS ENV_LINES)
# Skip comments and empty lines (allow whitespace before # or ;)

View File

@@ -37,8 +37,24 @@ target_include_directories(${DUSK_TARGET_NAME}
target_sources(${DUSK_TARGET_NAME}
PRIVATE
main.cpp
Engine.cpp
TimeManager.cpp
)
# Compiler defs
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
TIME_SDL2=1
TIME_FIXED=0
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
TIME_FIXED=1
)
endif()
# Defs
add_defs(duskdefs.env duskdefs.hpp)
@@ -47,13 +63,11 @@ add_subdirectory(assert)
add_subdirectory(asset)
add_subdirectory(debug)
add_subdirectory(display)
add_subdirectory(engine)
add_subdirectory(input)
add_subdirectory(locale)
add_subdirectory(rpg)
add_subdirectory(scene)
add_subdirectory(script)
add_subdirectory(thread)
add_subdirectory(time)
add_subdirectory(ui)
add_subdirectory(util)

View File

@@ -7,7 +7,6 @@
#include "Engine.hpp"
#include "util/memory.hpp"
#include "input/input.hpp"
#include "locale/localemanager.hpp"
#include "display/display.hpp"
#include "scene/scenemanager.hpp"
@@ -26,7 +25,8 @@ Engine::Engine() :
running(false),
argc(0),
argv(nullptr),
time()
time(),
input()
{
}
@@ -36,7 +36,6 @@ void Engine::init(const int32_t argc, const char_t **argv) {
this->argv = argv;
// Init systems. Order is important.
inputInit();
assetInit();
localeManagerInit();
scriptManagerInit();
@@ -54,14 +53,14 @@ void Engine::init(const int32_t argc, const char_t **argv) {
void Engine::update() {
this->time.update();
inputUpdate();
this->input.update();
rpgUpdate();
uiUpdate();
sceneManagerUpdate();
displayUpdate();
if(inputPressed(INPUT_ACTION_RAGEQUIT)) this->running = false;
if(this->input.wasPressed(InputAction::RAGEQUIT)) this->running = false;
}
void Engine::dispose() {

View File

@@ -7,8 +7,8 @@
#pragma once
#include "display/display.hpp"// Important to be included first.
#include "time/TimeManager.hpp"
#include "TimeManager.hpp"
#include "input/InputManager.hpp"
namespace Dusk {
struct Engine {
@@ -22,6 +22,7 @@ namespace Dusk {
const char_t **argv;
TimeManager time;
InputManager input;
/**
* Initializes the engine.

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define TIME_STEP (1.0f / 60.0f) // 60 Ticks per second (what we are aiming for)

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#ifndef ASSERTIONS_FAKED
/**

View File

@@ -10,7 +10,7 @@
#include "util/string.hpp"
#include "assert/assert.hpp"
#include "asset/assettype.h"
#include "engine/Engine.hpp"
#include "Engine.hpp"
#include "debug/debug.hpp"
using namespace Dusk;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define ASSET_ALPHA_IMAGE_WIDTH_MAX 256
#define ASSET_ALPHA_IMAGE_HEIGHT_MAX 256

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define ASSET_PALETTE_IMAGE_WIDTH_MAX 128
#define ASSET_PALETTE_IMAGE_HEIGHT_MAX 128

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#include "duskdefs.hpp"
#include <zip.h>
#include "script/scriptcontext.hpp"

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
/**
* Prints a debug message to the debug console.

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#include "display/color.hpp"
#define CAMERA_COUNT_MAX 4

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef float_t colorchannelf_t;
typedef uint8_t colorchannelb_t;

View File

@@ -6,7 +6,7 @@
*/
#include "display/display.hpp"
#include "engine/Engine.hpp"
#include "Engine.hpp"
#include "display/framebuffer.hpp"
#include "scene/scenemanager.hpp"
#include "display/spritebatch.hpp"

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#include "display/framebuffer.hpp"
#include "display/camera.hpp"
#include "display/mesh/quad.hpp"

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef struct tileset_s {
const uint16_t tileWidth;

View File

@@ -1,10 +0,0 @@
# Copyright (c) 2025 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
Engine.cpp
)

View File

@@ -6,7 +6,7 @@
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
input.cpp
InputManager.cpp
inputbutton.cpp
inputaction.cpp
)

282
src/input/InputManager.cpp Normal file
View File

@@ -0,0 +1,282 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "InputManager.hpp"
#include "assert/assert.hpp"
#include "util/memory.hpp"
#include "util/string.hpp"
#include "util/math.hpp"
#include "Engine.hpp"
using namespace Dusk;
InputManager::InputManager() :
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
controller(nullptr),
#endif
#if INPUT_KEYBOARD == 1
keyboardState(nullptr),
#endif
#endif
actions{},
deadzone(0.2f)
{
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
this->actions[i].action = (InputAction)i;
this->actions[i].lastValue = 0.0f;
this->actions[i].currentValue = 0.0f;
}
// Setup Default Binds
#if INPUT_SDL2 == 1
#if INPUT_KEYBOARD == 1
this->bind(inputButtonGetByName("up"), InputAction::UP);
this->bind(inputButtonGetByName("down"), InputAction::DOWN);
this->bind(inputButtonGetByName("left"), InputAction::LEFT);
this->bind(inputButtonGetByName("right"), InputAction::RIGHT);
this->bind(inputButtonGetByName("w"), InputAction::UP);
this->bind(inputButtonGetByName("s"), InputAction::DOWN);
this->bind(inputButtonGetByName("a"), InputAction::LEFT);
this->bind(inputButtonGetByName("d"), InputAction::RIGHT);
this->bind(inputButtonGetByName("enter"), InputAction::ACCEPT);
this->bind(inputButtonGetByName("escape"), InputAction::RAGEQUIT);
this->bind(inputButtonGetByName("space"), InputAction::ACCEPT);
this->bind(inputButtonGetByName("backspace"), InputAction::CANCEL);
this->bind(inputButtonGetByName("e"), InputAction::ACCEPT);
this->bind(inputButtonGetByName("q"), InputAction::CANCEL);
#endif
#if INPUT_GAMEPAD == 1
#if PSP
this->deadzone = 0.2890625f;// Taken from the PSP firmware
this->bind(inputButtonGetByName("up"), InputAction::UP);
this->bind(inputButtonGetByName("down"), InputAction::DOWN);
this->bind(inputButtonGetByName("left"), InputAction::LEFT);
this->bind(inputButtonGetByName("right"), InputAction::RIGHT);
this->bind(inputButtonGetByName("circle"), InputAction::CANCEL);
this->bind(inputButtonGetByName("cross"), InputAction::ACCEPT);
this->bind(inputButtonGetByName("lstick_negative_y"), InputAction::UP);
this->bind(inputButtonGetByName("lstick_positive_y"), InputAction::DOWN);
this->bind(inputButtonGetByName("lstick_negative_x"), InputAction::LEFT);
this->bind(inputButtonGetByName("lstick_positive_x"), InputAction::RIGHT);
this->bind(inputButtonGetByName("select"), InputAction::RAGEQUIT);
#endif
#endif
#endif
}
void InputManager::update(void) {
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
this->controller = NULL;
for(int32_t i = 0; i < SDL_NumJoysticks(); i++) {
if(!SDL_IsGameController(i)) continue;
this->controller = SDL_GameControllerOpen(i);
if(this->controller != nullptr) break;
}
#endif
#if INPUT_KEYBOARD == 1
this->keyboardState = SDL_GetKeyboardState(NULL);
#endif
#endif
// Reset all actions
inputactiondata_t *action = &this->actions[0];
do {
#if TIME_FIXED == 0
action->lastDynamicValue = action->currentDynamicValue;
action->currentDynamicValue = 0.0f;
if(!Engine::ENGINE.time.dynamicUpdate) {
action->lastValue = action->currentValue;
action->currentValue = 0.0f;
}
#else
action->lastValue = action->currentValue;
action->currentValue = 0.0f;
#endif
action++;
} while(action < &this->actions[INPUT_ACTION_COUNT]);
// For each button...
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
do {
cur->lastVal = cur->curVal;
cur->curVal = this->getButtonValue(cur->button);
if(cur->curVal == 0.0f) {
cur++;
continue;
}
// Update current val.
#if TIME_FIXED == 0
this->actions[static_cast<uint8_t>(cur->action)].currentDynamicValue = (
mathMax(
cur->curVal,
this->actions[static_cast<uint8_t>(cur->action)].currentDynamicValue
)
);
if(!Engine::ENGINE.time.dynamicUpdate) {
this->actions[static_cast<uint8_t>(cur->action)].currentValue = mathMax(
cur->curVal,
this->actions[static_cast<uint8_t>(cur->action)].currentValue
);
}
#else
this->actions[static_cast<uint8_t>(cur->action)].currentValue = mathMax(
cur->curVal,
this->actions[static_cast<uint8_t>(cur->action)].currentValue
);
#endif
cur++;
} while(cur->name);
}
float_t InputManager::getButtonValue(const inputbutton_t button) {
switch(button.type) {
#if INPUT_KEYBOARD == 1
case INPUT_BUTTON_TYPE_KEYBOARD: {
#if INPUT_SDL2 == 1
return this->keyboardState[button.scancode] ? 1.0f : 0.0f;
#else
return 0.0f;
#endif
}
#endif
#if INPUT_GAMEPAD == 1
case INPUT_BUTTON_TYPE_GAMEPAD: {
#if INPUT_SDL2 == 1
if(this->controller == nullptr) return 0.0f;
if(SDL_GameControllerGetButton(this->controller, button.gpButton)) {
return 1.0f;
}
#endif
return 0.0f;
}
case INPUT_BUTTON_TYPE_GAMEPAD_AXIS: {
#if INPUT_SDL2 == 1
if(this->controller == nullptr) return 0.0f;
Sint16 axis = SDL_GameControllerGetAxis(
this->controller, button.gpAxis.axis
);
if(!button.gpAxis.positive) axis = -axis;
float_t value = (float_t)axis / 32767.0f;
if(value < this->deadzone) return 0.0f;
return value;
#endif
}
#endif
default: {
assertUnreachable("Unknown input button type");
return 0.0f;
}
}
}
float_t InputManager::getCurrentValue(const InputAction action) {
#if TIME_FIXED == 0
if(Engine::ENGINE.time.dynamicUpdate) {
return this->getCurrentValueDynamic(action);
}
#endif
assertTrue(
static_cast<uint8_t>(action) < INPUT_ACTION_COUNT,
"Input action out of bounds"
);
return this->actions[static_cast<uint8_t>(action)].currentValue;
}
float_t InputManager::getLastValue(const InputAction action) {
#if TIME_FIXED == 0
if(Engine::ENGINE.time.dynamicUpdate) {
return this->getLastValueDynamic(action);
}
#endif
assertTrue(
static_cast<uint8_t>(action) < INPUT_ACTION_COUNT,
"Input action out of bounds"
);
return this->actions[static_cast<uint8_t>(action)].lastValue;
}
#if TIME_FIXED == 0
float_t InputManager::getCurrentValueDynamic(const InputAction action) {
assertTrue(
static_cast<uint8_t>(action) < INPUT_ACTION_COUNT,
"Input action out of bounds"
);
return this->actions[static_cast<uint8_t>(action)].currentDynamicValue;
}
float_t InputManager::getLastValueDynamic(const InputAction action) {
assertTrue(
static_cast<uint8_t>(action) < INPUT_ACTION_COUNT,
"Input action out of bounds"
);
return this->actions[static_cast<uint8_t>(action)].lastDynamicValue;
}
#endif
bool_t InputManager::isDown(const InputAction action) {
return this->getCurrentValue(action) > 0.0f;
}
bool_t InputManager::wasDown(const InputAction action) {
return this->getLastValue(action) > 0.0f;
}
bool_t InputManager::wasPressed(const InputAction action) {
return this->isDown(action) && !this->wasDown(action);
}
bool_t InputManager::wasReleased(const InputAction action) {
return !this->isDown(action) && this->wasDown(action);
}
float_t InputManager::getAxis(const InputAction neg, const InputAction pos) {
assertTrue(
static_cast<uint8_t>(neg) < INPUT_ACTION_COUNT,
"Negative input action out of bounds"
);
assertTrue(
static_cast<uint8_t>(pos) < INPUT_ACTION_COUNT,
"Positive input action out of bounds"
);
return this->getCurrentValue(pos) - this->getCurrentValue(neg);
}
void InputManager::bind(const inputbutton_t button, const InputAction act) {
assertTrue(
static_cast<uint8_t>(act) < INPUT_ACTION_COUNT,
"Invalid input action"
);
// Get the button data for this button.
inputbuttondata_t *data = INPUT_BUTTON_DATA;
do {
if(memoryCompare(&data->button, &button, sizeof(inputbutton_t)) == 0) {
break;
}
data++;
} while(data->name != NULL);
assertNotNull(data->name, "Input button not found");
// Bind the action.
data->action = act;
}

135
src/input/InputManager.hpp Normal file
View File

@@ -0,0 +1,135 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "inputbutton.hpp"
#include "inputaction.hpp"
namespace Dusk {
struct InputManager {
private:
inputactiondata_t actions[INPUT_ACTION_COUNT];
public:
#if INPUT_GAMEPAD == 1
float_t deadzone;
#endif
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
SDL_GameController *controller;
#endif
#if INPUT_KEYBOARD == 1
const uint8_t *keyboardState;
#endif
#endif
/**
* Initializes the input manager.
*/
InputManager();
/**
* Updates the input state.
*/
void update();
/**
* Gets the value of a specific input button.
*
* @param button The input button to get the value for.
* @return The current value of the button (0.0f to 1.0f).
*/
float_t getButtonValue(const inputbutton_t button);
/**
* Gets the current value of a specific input action.
*
* @param action The input action to get the value for.
* @return The current value of the action (0.0f to 1.0f).
*/
float_t getCurrentValue(const InputAction action);
/**
* Gets the last value of a specific input action.
*
* @param action The input action to get the value for.
* @return The last value of the action (0.0f to 1.0f).
*/
float_t getLastValue(const InputAction action);
#if TIME_FIXED == 0
/**
* Gets the current value of a specific input action (dynamic timestep).
*
* @param action The input action to get the value for.
* @return The current value of the action (0.0f to 1.0f).
*/
float_t getCurrentValueDynamic(const InputAction action);
/**
* Gets the last value of a specific input action (dynamic timestep).
*
* @param action The input action to get the value for.
* @return The last value of the action (0.0f to 1.0f).
*/
float_t getLastValueDynamic(const InputAction action);
#endif
/**
* Checks if a specific input action is currently pressed.
*
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t isDown(const InputAction action);
/**
* Checks if a specific input action was pressed in the last update.
*
* @param action The input action to check.
* @return true if the action was pressed in the last update, false otherwise.
*/
bool_t wasDown(const InputAction action);
/**
* Checks if a specific input action was pressed this frame but not in the
* previous frame.
*
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t wasPressed(const InputAction action);
/**
* Checks if a specific input action was released this frame.
*
* @param action The input action to check.
* @return true if the action was released this frame, false otherwise.
*/
bool_t wasReleased(const InputAction action);
/**
* Gets the value of an input axis, defined by two actions (negative and
* positive).
*
* @param neg The action representing the negative direction of the axis.
* @param pos The action representing the positive direction of the axis.
* @return The current value of the axis (-1.0f to 1.0f).
*/
float_t getAxis(const InputAction neg, const InputAction pos);
/**
* Binds an input button to an action.
*
* @param button The input button to bind.
* @param action The input action to bind the button to.
*/
void bind(const inputbutton_t button, const InputAction act);
};
}

View File

@@ -1,209 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#include "input.hpp"
#include "assert/assert.hpp"
#include "util/memory.hpp"
#include "util/string.hpp"
#include "util/math.hpp"
#include "engine/Engine.hpp"
using namespace Dusk;
input_t INPUT;
void inputInit(void) {
memoryZero(&INPUT, sizeof(input_t));
for(uint8_t i = 0; i < INPUT_ACTION_COUNT; i++) {
INPUT.actions[i].action = (inputaction_t)i;
INPUT.actions[i].lastValue = 0.0f;
INPUT.actions[i].currentValue = 0.0f;
}
INPUT.deadzone = 0.2f;
// Setup Default Binds
#if INPUT_SDL2 == 1
#if INPUT_KEYBOARD == 1
inputBind(inputButtonGetByName("up"), INPUT_ACTION_UP);
inputBind(inputButtonGetByName("down"), INPUT_ACTION_DOWN);
inputBind(inputButtonGetByName("left"), INPUT_ACTION_LEFT);
inputBind(inputButtonGetByName("right"), INPUT_ACTION_RIGHT);
inputBind(inputButtonGetByName("w"), INPUT_ACTION_UP);
inputBind(inputButtonGetByName("s"), INPUT_ACTION_DOWN);
inputBind(inputButtonGetByName("a"), INPUT_ACTION_LEFT);
inputBind(inputButtonGetByName("d"), INPUT_ACTION_RIGHT);
inputBind(inputButtonGetByName("enter"), INPUT_ACTION_ACCEPT);
inputBind(inputButtonGetByName("escape"), INPUT_ACTION_RAGEQUIT);
inputBind(inputButtonGetByName("space"), INPUT_ACTION_ACCEPT);
inputBind(inputButtonGetByName("backspace"), INPUT_ACTION_CANCEL);
inputBind(inputButtonGetByName("e"), INPUT_ACTION_ACCEPT);
inputBind(inputButtonGetByName("q"), INPUT_ACTION_CANCEL);
#endif
#if INPUT_GAMEPAD == 1
#if PSP
INPUT.deadzone = 0.2890625f;// Taken from the PSP firmware
inputBind(inputButtonGetByName("up"), INPUT_ACTION_UP);
inputBind(inputButtonGetByName("down"), INPUT_ACTION_DOWN);
inputBind(inputButtonGetByName("left"), INPUT_ACTION_LEFT);
inputBind(inputButtonGetByName("right"), INPUT_ACTION_RIGHT);
inputBind(inputButtonGetByName("circle"), INPUT_ACTION_CANCEL);
inputBind(inputButtonGetByName("cross"), INPUT_ACTION_ACCEPT);
inputBind(inputButtonGetByName("lstick_negative_y"), INPUT_ACTION_UP);
inputBind(inputButtonGetByName("lstick_positive_y"), INPUT_ACTION_DOWN);
inputBind(inputButtonGetByName("lstick_negative_x"), INPUT_ACTION_LEFT);
inputBind(inputButtonGetByName("lstick_positive_x"), INPUT_ACTION_RIGHT);
inputBind(inputButtonGetByName("select"), INPUT_ACTION_RAGEQUIT);
#endif
#endif
#endif
}
void inputUpdate(void) {
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
INPUT.controller = NULL;
for(int32_t i = 0; i < SDL_NumJoysticks(); i++) {
if(!SDL_IsGameController(i)) continue;
INPUT.controller = SDL_GameControllerOpen(i);
if(INPUT.controller) break;
}
#endif
#if INPUT_KEYBOARD == 1
INPUT.keyboardState = SDL_GetKeyboardState(NULL);
#endif
#endif
// Reset all actions
inputactiondata_t *action = &INPUT.actions[0];
do {
#if TIME_FIXED == 0
action->lastDynamicValue = action->currentDynamicValue;
action->currentDynamicValue = 0.0f;
if(!Engine::ENGINE.time.dynamicUpdate) {
action->lastValue = action->currentValue;
action->currentValue = 0.0f;
}
#else
action->lastValue = action->currentValue;
action->currentValue = 0.0f;
#endif
action++;
} while(action < &INPUT.actions[INPUT_ACTION_COUNT]);
// For each button...
inputbuttondata_t *cur = &INPUT_BUTTON_DATA[0];
do {
cur->lastVal = cur->curVal;
cur->curVal = inputButtonGetValue(cur->button);
if(cur->curVal == 0.0f) {
cur++;
continue;
}
// Update current val.
#if TIME_FIXED == 0
INPUT.actions[cur->action].currentDynamicValue = mathMax(
cur->curVal, INPUT.actions[cur->action].currentDynamicValue
);
if(!Engine::ENGINE.time.dynamicUpdate) {
INPUT.actions[cur->action].currentValue = mathMax(
cur->curVal, INPUT.actions[cur->action].currentValue
);
}
#else
INPUT.actions[cur->action].currentValue = mathMax(
cur->curVal, INPUT.actions[cur->action].currentValue
);
#endif
cur++;
} while(cur->name);
}
float_t inputGetCurrentValue(const inputaction_t action) {
#if TIME_FIXED == 0
if(Engine::ENGINE.time.dynamicUpdate) {
return inputGetCurrentValueDynamic(action);
}
#endif
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].currentValue;
}
float_t inputGetLastValue(const inputaction_t action) {
#if TIME_FIXED == 0
if(Engine::ENGINE.time.dynamicUpdate) {
return inputGetLastValueDynamic(action);
}
#endif
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].lastValue;
}
#if TIME_FIXED == 0
float_t inputGetCurrentValueDynamic(const inputaction_t action) {
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].currentDynamicValue;
}
float_t inputGetLastValueDynamic(const inputaction_t action) {
assertTrue(action < INPUT_ACTION_COUNT, "Input action out of bounds");
return INPUT.actions[action].lastDynamicValue;
}
#endif
bool_t inputIsDown(const inputaction_t action) {
return inputGetCurrentValue(action) > 0.0f;
}
bool_t inputWasDown(const inputaction_t action) {
return inputGetLastValue(action) > 0.0f;
}
bool_t inputPressed(const inputaction_t action) {
return inputIsDown(action) && !inputWasDown(action);
}
bool_t inputReleased(const inputaction_t action) {
return !inputIsDown(action) && inputWasDown(action);
}
float_t inputAxis(const inputaction_t neg, const inputaction_t pos) {
assertTrue(neg < INPUT_ACTION_COUNT, "Negative input action out of bounds");
assertTrue(pos < INPUT_ACTION_COUNT, "Positive input action out of bounds");
return inputGetCurrentValue(pos) - inputGetCurrentValue(neg);
}
void inputBind(const inputbutton_t button, const inputaction_t act) {
assertTrue(
act < INPUT_ACTION_COUNT,
"Invalid input action"
);
// Get the button data for this button.
inputbuttondata_t *data = INPUT_BUTTON_DATA;
do {
if(memoryCompare(&data->button, &button, sizeof(inputbutton_t)) == 0) {
break;
}
data++;
} while(data->name != NULL);
assertNotNull(data->name, "Input button not found");
// Bind the action.
data->action = act;
}

View File

@@ -1,125 +0,0 @@
/**
* Copyright (c) 2025 Dominic Masters
*
* This software is released under the MIT License.
* https://opensource.org/licenses/MIT
*/
#pragma once
#include "inputbutton.hpp"
#include "inputaction.hpp"
typedef struct {
inputactiondata_t actions[INPUT_ACTION_COUNT];
#if INPUT_GAMEPAD == 1
float_t deadzone;
#endif
#if INPUT_SDL2 == 1
#if INPUT_GAMEPAD == 1
SDL_GameController *controller;
#endif
#if INPUT_KEYBOARD == 1
const uint8_t *keyboardState;
#endif
#endif
} input_t;
extern input_t INPUT;
/**
* Initialize the input system.
*/
void inputInit(void);
/**
* Updates the input state.
*/
void inputUpdate(void);
/**
* Gets the current value of a specific input action.
*
* @param action The input action to get the value for.
* @return The current value of the action (0.0f to 1.0f).
*/
float_t inputGetCurrentValue(const inputaction_t action);
/**
* Gets the last value of a specific input action.
*
* @param action The input action to get the value for.
* @return The last value of the action (0.0f to 1.0f).
*/
float_t inputGetLastValue(const inputaction_t action);
#if TIME_FIXED == 0
/**
* Gets the current value of a specific input action (dynamic timestep).
*
* @param action The input action to get the value for.
* @return The current value of the action (0.0f to 1.0f).
*/
float_t inputGetCurrentValueDynamic(const inputaction_t action);
/**
* Gets the last value of a specific input action (dynamic timestep).
*
* @param action The input action to get the value for.
* @return The last value of the action (0.0f to 1.0f).
*/
float_t inputGetLastValueDynamic(const inputaction_t action);
#endif
/**
* Checks if a specific input action is currently pressed.
*
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t inputIsDown(const inputaction_t action);
/**
* Checks if a specific input action was pressed in the last update.
*
* @param action The input action to check.
* @return true if the action was pressed in the last update, false otherwise.
*/
bool_t inputWasDown(const inputaction_t action);
/**
* Checks if a specific input action was down this frame but not in the the
* previous frame.
*
* @param action The input action to check.
* @return true if the action is currently pressed, false otherwise.
*/
bool_t inputPressed(const inputaction_t action);
/**
* Checks if a specific input action was released this frame.
*
* @param action The input action to check.
* @return true if the action was released this frame, false otherwise.
*/
bool_t inputReleased(const inputaction_t action);
/**
* Gets the value of an input axis, defined by two actions (negative and
* positive).
*
* @param neg The action representing the negative direction of the axis.
* @param pos The action representing the positive direction of the axis.
* @return The current value of the axis (-1.0f to 1.0f).
*/
float_t inputAxis(const inputaction_t neg, const inputaction_t pos);
/**
* Binds an input button to an action.
*
* @param button The input button to bind.
* @param action The input action to bind the button to.
*/
void inputBind(const inputbutton_t button, const inputaction_t act);

View File

@@ -6,22 +6,24 @@
*/
#pragma once
#include "time/TimeManager.hpp"
#include "TimeManager.hpp"
typedef uint8_t inputaction_t;
enum class InputAction : uint8_t {
UP,
DOWN,
LEFT,
RIGHT,
ACCEPT,
CANCEL,
RAGEQUIT,
#define INPUT_ACTION_NULL 0x00
#define INPUT_ACTION_UP 0x01
#define INPUT_ACTION_DOWN 0x02
#define INPUT_ACTION_LEFT 0x03
#define INPUT_ACTION_RIGHT 0x04
#define INPUT_ACTION_ACCEPT 0x05
#define INPUT_ACTION_CANCEL 0x06
#define INPUT_ACTION_RAGEQUIT 0x07
#define INPUT_ACTION_COUNT INPUT_ACTION_RAGEQUIT + 1
COUNT,
NONE = 0xFF
};
#define INPUT_ACTION_COUNT static_cast<uint8_t>(InputAction::COUNT)
typedef struct {
inputaction_t action;
InputAction action;
float_t lastValue;
float_t currentValue;

View File

@@ -6,7 +6,7 @@
*/
#include "inputbutton.hpp"
#include "input.hpp"
#include "InputManager.hpp"
#include "assert/assert.hpp"
#include "util/string.hpp"
@@ -189,45 +189,4 @@ inputbutton_t inputButtonGetByName(const char_t *name) {
}
return (inputbutton_t){ .type = INPUT_BUTTON_TYPE_NONE };
}
float_t inputButtonGetValue(const inputbutton_t button) {
switch(button.type) {
#if INPUT_KEYBOARD == 1
case INPUT_BUTTON_TYPE_KEYBOARD: {
#if INPUT_SDL2 == 1
return INPUT.keyboardState[button.scancode] ? 1.0f : 0.0f;
#else
return 0.0f;
#endif
}
#endif
#if INPUT_GAMEPAD == 1
case INPUT_BUTTON_TYPE_GAMEPAD: {
#if INPUT_SDL2 == 1
if(SDL_GameControllerGetButton(INPUT.controller, button.gpButton)) {
return 1.0f;
}
#endif
return 0.0f;
}
case INPUT_BUTTON_TYPE_GAMEPAD_AXIS: {
#if INPUT_SDL2 == 1
Sint16 axis = SDL_GameControllerGetAxis(INPUT.controller, button.gpAxis.axis);
if(!button.gpAxis.positive) axis = -axis;
float_t value = (float_t)axis / 32767.0f;
// Deadzone
if(value < INPUT.deadzone) return 0.0f;
return value;
#endif
}
#endif
default: {
assertUnreachable("Unknown input button type");
return 0.0f;
}
}
}

View File

@@ -66,23 +66,15 @@ typedef struct {
inputbutton_t button;
float_t curVal;
float_t lastVal;
inputaction_t action;
InputAction action;
} inputbuttondata_t;
extern inputbuttondata_t INPUT_BUTTON_DATA[];
/**
* Gets an input button by its name.
*
*
* @param name The name of the input button.
* @return The input button, or .type = INPUT_BUTTON_TYPE_NONE if not found.
* @return The input button, or a button with type INPUT_BUTTON_TYPE_NONE if not found.
*/
inputbutton_t inputButtonGetByName(const char_t *name);
/**
* Gets the current value of an input button.
*
* @param button The input button.
* @return The current value of the input button (0.0f to 1.0f).
*/
float_t inputButtonGetValue(const inputbutton_t button);
inputbutton_t inputButtonGetByName(const char_t *name);

View File

@@ -5,7 +5,7 @@
* https://opensource.org/licenses/MIT
*/
#include "engine/Engine.hpp"
#include "Engine.hpp"
using namespace Dusk;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef enum {
CUTSCENE_MODE_NONE,

View File

@@ -6,6 +6,6 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef void (*cutscenecallback_t)(void);

View File

@@ -6,6 +6,6 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef struct cutscene_s cutscene_t;

View File

@@ -6,8 +6,8 @@
*/
#include "rpg/cutscene/cutscenesystem.hpp"
#include "input/input.hpp"
#include "engine/Engine.hpp"
#include "input/InputManager.hpp"
#include "Engine.hpp"
using namespace Dusk;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef float_t cutscenewait_t;
typedef float_t cutscenewaitdata_t;

View File

@@ -11,7 +11,7 @@
#include "util/math.hpp"
#include "rpg/cutscene/cutscenemode.hpp"
#include "rpg/world/map.hpp"
#include "engine/Engine.hpp"
#include "Engine.hpp"
using namespace Dusk;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define ENTITY_ANIM_TURN_DURATION 0.06f
#define ENTITY_ANIM_WALK_DURATION 0.1f

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef struct entity_s entity_t;

View File

@@ -8,7 +8,9 @@
#include "entity.hpp"
#include "assert/assert.hpp"
#include "rpg/rpgcamera.hpp"
#include "util/memory.hpp"
#include "Engine.hpp"
using namespace Dusk;
void playerInit(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL");
@@ -20,21 +22,21 @@ void playerInput(entity_t *entity) {
// Turn
const playerinputdirmap_t *dirMap = PLAYER_INPUT_DIR_MAP;
do {
if(!inputIsDown(dirMap->action)) continue;
if(!Engine::ENGINE.input.isDown(dirMap->action)) continue;
if(entity->direction == dirMap->direction) continue;
return entityTurn(entity, dirMap->direction);
} while((++dirMap)->action != 0xFF);
} while((++dirMap)->action != InputAction::NONE);
// Walk
dirMap = PLAYER_INPUT_DIR_MAP;
do {
if(!inputIsDown(dirMap->action)) continue;
if(!Engine::ENGINE.input.isDown(dirMap->action)) continue;
if(entity->direction != dirMap->direction) continue;
return entityWalk(entity, dirMap->direction);
} while((++dirMap)->action != 0xFF);
} while((++dirMap)->action != InputAction::NONE);
// Interaction
if(inputPressed(INPUT_ACTION_ACCEPT)) {
if(Engine::ENGINE.input.wasPressed(InputAction::ACCEPT)) {
worldunit_t x, y, z;
{
worldunits_t relX, relY;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "input/input.hpp"
#include "input/InputManager.hpp"
typedef struct entity_s entity_t;
@@ -15,16 +15,16 @@ typedef struct {
} player_t;
typedef struct {
inputaction_t action;
InputAction action;
entitydir_t direction;
} playerinputdirmap_t;
static const playerinputdirmap_t PLAYER_INPUT_DIR_MAP[] = {
{ INPUT_ACTION_UP, ENTITY_DIR_NORTH },
{ INPUT_ACTION_DOWN, ENTITY_DIR_SOUTH },
{ INPUT_ACTION_LEFT, ENTITY_DIR_WEST },
{ INPUT_ACTION_RIGHT, ENTITY_DIR_EAST },
{ .action = 0xFF, .direction = 0xFF }
{ InputAction::UP, ENTITY_DIR_NORTH },
{ InputAction::DOWN, ENTITY_DIR_SOUTH },
{ InputAction::LEFT, ENTITY_DIR_WEST },
{ InputAction::RIGHT, ENTITY_DIR_EAST },
{ .action = InputAction::NONE, .direction = 0xFF }
};
/**

View File

@@ -13,7 +13,7 @@
#include "rpgtextbox.hpp"
#include "util/memory.hpp"
#include "assert/assert.hpp"
#include "engine/Engine.hpp"
#include "Engine.hpp"
using namespace Dusk;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
typedef struct {
int32_t nothing;

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define RPG_TEXTBOX_MAX_CHARS 256

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#include "duskdefs.hpp"
#define CHUNK_TILE_COUNT (CHUNK_WIDTH * CHUNK_HEIGHT * CHUNK_DEPTH)

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#include "display/color.hpp"
#define SCENE_FLAG_INITIALIZED (1 << 0)

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#define SCRIPT_VALUE_TYPE_NIL 0
#define SCRIPT_VALUE_TYPE_INT 1

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
#if THREAD_PTHREAD
#include <pthread.h>

View File

@@ -1,24 +0,0 @@
# Copyright (c) 2025 Dominic Masters
#
# This software is released under the MIT License.
# https://opensource.org/licenses/MIT
# Sources
target_sources(${DUSK_TARGET_NAME}
PRIVATE
TimeManager.cpp
)
# Compiler defs
if(DUSK_TARGET_SYSTEM STREQUAL "linux")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
TIME_SDL2=1
TIME_FIXED=0
)
elseif(DUSK_TARGET_SYSTEM STREQUAL "psp")
target_compile_definitions(${DUSK_TARGET_NAME}
PRIVATE
TIME_FIXED=1
)
endif()

View File

@@ -11,7 +11,7 @@
#include "display/screen.hpp"
#include "display/spritebatch.hpp"
#include "rpg/entity/entity.hpp"
#include "engine/Engine.hpp"
#include "Engine.hpp"
using namespace Dusk;
bool_t UI_DEBUG_DRAW = true;

View File

@@ -11,12 +11,15 @@
#include "rpg/rpgtextbox.hpp"
#include "display/screen.hpp"
#include "display/spritebatch.hpp"
#include "input/input.hpp"
#include "input/InputManager.hpp"
#include "Engine.hpp"
using namespace Dusk;
void uiTextboxUpdate() {
if(!rpgTextboxIsVisible()) return;
if(inputPressed(INPUT_ACTION_ACCEPT)) {
if(Engine::ENGINE.input.wasPressed(InputAction::ACCEPT)) {
rpgTextboxHide();
}
}

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
/**
* Updates the RPG textbox state.

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
/**
* Finds the next power of two greater than or equal to the given value.

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
/**
* Allocates memory.

View File

@@ -6,7 +6,7 @@
*/
#pragma once
#include "dusk.hpp"
#include "Dusk.hpp"
/**
* Determines if a character is whitespace.

View File

@@ -16,7 +16,7 @@ def processLanguageList():
# Language keys header data
headerKeys = "// Auto-generated language keys header file.\n"
headerKeys += "#pragma once\n"
headerKeys += "#include \"dusk.hpp\"\n\n"
headerKeys += "#include \"Dusk.hpp\"\n\n"
# This is the desired chunk groups list.. if a language key STARTS with any
# of the keys in this list we would "like to" put it in that chunk group.