@@ -1,4 +1,4 @@ | |||||
cmake_minimum_required(VERSION 3.20) | |||||
cmake_minimum_required(VERSION 3.21) | |||||
# Set your project name here | # Set your project name here | ||||
project(izanagi C) | project(izanagi C) | ||||
@@ -9,6 +9,7 @@ include_directories( | |||||
"${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" | "${PROJECT_SOURCE_DIR}/dependencies/SDL2/include" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" | "${PROJECT_SOURCE_DIR}/dependencies/minIni/dev" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" | "${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common" | |||||
) | ) | ||||
if (WIN32) | if (WIN32) | ||||
@@ -21,20 +22,21 @@ endif () | |||||
link_directories( | link_directories( | ||||
"${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" | "${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}" | ||||
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release" | |||||
) | ) | ||||
add_executable( | add_executable( | ||||
game | game | ||||
dependencies/minIni/dev/minIni.h | dependencies/minIni/dev/minIni.h | ||||
dependencies/minIni/dev/minIni.c | dependencies/minIni/dev/minIni.c | ||||
src/packages/game/config/IZ_config.h | |||||
src/packages/game/config/IZ_config.c | |||||
src/packages/game/output/IZ_video.h | |||||
src/packages/game/output/IZ_video.c | |||||
src/packages/game/IZ_common.h | src/packages/game/IZ_common.h | ||||
src/packages/game/IZ_action.h | src/packages/game/IZ_action.h | ||||
src/packages/game/IZ_app.h | src/packages/game/IZ_app.h | ||||
src/packages/game/IZ_app.c | src/packages/game/IZ_app.c | ||||
src/packages/game/main.c | src/packages/game/main.c | ||||
) | |||||
src/packages/game/input/IZ_joystick.c src/packages/game/input/IZ_joystick.h src/packages/game/input/IZ_keyboard.c src/packages/game/input/IZ_keyboard.h src/packages/game/IZ_config.c src/packages/game/IZ_config.h) | |||||
target_link_libraries( | target_link_libraries( | ||||
game | game | ||||
SDL2main | SDL2main | ||||
@@ -43,11 +45,11 @@ target_link_libraries( | |||||
add_executable( | add_executable( | ||||
game-test | game-test | ||||
src/packages/game/config/IZ_config.h | |||||
src/packages/game/config/IZ_config.c | |||||
dependencies/bdd-for-c/bdd-for-c.h | dependencies/bdd-for-c/bdd-for-c.h | ||||
src/packages/game-test/config/IZ_config.c | |||||
) | |||||
src/packages/game/output/IZ_video.h | |||||
src/packages/game/output/IZ_video.c | |||||
src/packages/game/output/IZ_config.test.c | |||||
src/packages/test/IZ_mock.h) | |||||
if (WIN32) | if (WIN32) | ||||
add_custom_command(TARGET game POST_BUILD | add_custom_command(TARGET game POST_BUILD | ||||
@@ -1,2 +1,3 @@ | |||||
https://github.com/compuphase/minIni | https://github.com/compuphase/minIni | ||||
https://github.com/grassator/bdd-for-c | https://github.com/grassator/bdd-for-c | ||||
https://github.com/PortMidi/portmidi |
@@ -1,12 +1,12 @@ | |||||
[Video] | [Video] | ||||
Width=640 | Width=640 | ||||
Height=480 | Height=480 | ||||
[Controls.0.Keyboard] | |||||
MaxFps=30 | |||||
[Keyboard.0.ControlMapping] | |||||
Up=Up | |||||
Right=Right | Right=Right | ||||
Down=Down | Down=Down | ||||
Left=Left | Left=Left | ||||
Up=Up | |||||
Affirm=Return | Affirm=Return | ||||
Negate=Backspace | Negate=Backspace | ||||
Action0=A | Action0=A | ||||
@@ -19,3 +19,18 @@ Action6=C | |||||
Action7=V | Action7=V | ||||
Action8=W | Action8=W | ||||
Action9=E | Action9=E | ||||
[Joystick.0.ControlMapping] | |||||
Affirm=11 | |||||
Negate=10 | |||||
Action0=1 | |||||
Action1=0 | |||||
Action2=4 | |||||
Action3=3 | |||||
Action4=6 | |||||
Action5=7 | |||||
Action6=8 | |||||
Action7=9 | |||||
Action8=13 | |||||
Action9=14 | |||||
[Joystick.0] | |||||
AxisThreshold=8000 |
@@ -1,15 +1,19 @@ | |||||
#include "IZ_app.h" | #include "IZ_app.h" | ||||
int IZ_InitializeApp(IZ_App* app) { | int IZ_InitializeApp(IZ_App* app) { | ||||
IZ_LoadConfig(&app->config); | |||||
IZ_SaveConfig(&app->config); | |||||
IZ_LoadVideoConfig(&app->video_config); | |||||
IZ_SaveVideoConfig(&app->video_config); | |||||
app->video_update_at = 0u; | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | for (uint8_t p = 0; p < PLAYERS; p += 1) { | ||||
app->assigned_joysticks[p] = NULL; | |||||
IZ_LoadKeyboardConfig(&app->keyboard_state->config, p); | |||||
IZ_SaveKeyboardConfig(&app->keyboard_state->config, p); | |||||
IZ_LoadJoystickConfig(&app->joystick_state->config, p); | |||||
IZ_SaveJoystickConfig(&app->joystick_state->config, p); | |||||
app->actions[p] = 0; | app->actions[p] = 0; | ||||
} | } | ||||
app->video_update_at = 0u; | |||||
return 0; | return 0; | ||||
} | } |
@@ -1,17 +1,17 @@ | |||||
#ifndef IZ_APP_H | #ifndef IZ_APP_H | ||||
#define IZ_APP_H | #define IZ_APP_H | ||||
#include <SDL_joystick.h> | |||||
#include "config/IZ_config.h" | |||||
#include "input/IZ_keyboard.h" | |||||
#include "input/IZ_joystick.h" | |||||
#include "output/IZ_video.h" | |||||
#include "IZ_action.h" | #include "IZ_action.h" | ||||
typedef struct { | typedef struct { | ||||
IZ_Config config; | |||||
IZ_VideoConfig video_config; | |||||
IZ_Action actions[PLAYERS]; | IZ_Action actions[PLAYERS]; | ||||
SDL_Joystick* assigned_joysticks[PLAYERS]; | |||||
IZ_KeyboardState keyboard_state[PLAYERS]; | |||||
IZ_JoystickState joystick_state[PLAYERS]; | |||||
uint64_t video_update_at; | uint64_t video_update_at; | ||||
} IZ_App; | } IZ_App; | ||||
@@ -8,4 +8,6 @@ | |||||
static const char* APP_NAME = "SDL2"; | static const char* APP_NAME = "SDL2"; | ||||
typedef uint8_t IZ_ProcedureResult; | |||||
#endif | #endif |
@@ -0,0 +1,8 @@ | |||||
#include "IZ_config.h" | |||||
void IZ_GetConfigPath(char* config_path) { | |||||
//const char* config_path_dir = SDL_GetPrefPath("Modal Studios", APP_NAME); | |||||
const char* config_path_dir = SDL_GetBasePath(); | |||||
memcpy_s(config_path, 128, config_path_dir, 128); | |||||
strcat_s(config_path, 128, "config.ini"); | |||||
} |
@@ -0,0 +1,9 @@ | |||||
#ifndef IZ_CONFIG_H | |||||
#define IZ_CONFIG_H | |||||
#include <SDL_filesystem.h> | |||||
#include <string.h> | |||||
void IZ_GetConfigPath(char* config_path); | |||||
#endif |
@@ -1,65 +0,0 @@ | |||||
#include "IZ_config.h" | |||||
void IZ_GetConfigPath(char* config_path) { | |||||
//const char* config_path_dir = SDL_GetPrefPath("Modal Studios", APP_NAME); | |||||
const char* config_path_dir = SDL_GetBasePath(); | |||||
memcpy_s(config_path, 128, config_path_dir, 128); | |||||
strcat_s(config_path, 128, "config.ini"); | |||||
} | |||||
void IZ_SaveConfig(IZ_Config* config) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
FILE* fp; | |||||
fopen_s(&fp, config_path, "w"); | |||||
fprintf_s(fp, "[Video]\n"); | |||||
fprintf_s(fp, "Width=%u\n", config->video.width); | |||||
fprintf_s(fp, "Height=%u\n", config->video.height); | |||||
fprintf_s(fp, "MaxFps=%u\n", config->video.max_fps); | |||||
fprintf_s(fp, "\n"); | |||||
fprintf_s(fp, "[Input]\n"); | |||||
fprintf_s(fp, "GamepadAxisThreshold=%u\n", config->input.gamepad_axis_threshold); | |||||
fprintf_s(fp, "\n"); | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | |||||
fprintf_s(fp, "[Controls.%u.Keyboard]\n", p); | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
fprintf_s(fp, "%s=%s\n", ACTION_NAMES[i], SDL_GetKeyName(config->controls[p].keyboard[i])); | |||||
} | |||||
fprintf_s(fp, "\n"); | |||||
fprintf_s(fp, "[Controls.%u.Joystick]\n", p); | |||||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||||
fprintf_s(fp, "%s=%d\n", ACTION_NAMES[i], config->controls[p].gamepad[i]); | |||||
} | |||||
} | |||||
} | |||||
void IZ_LoadConfig(IZ_Config* config) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
config->video.width = ini_getl("Video", "Width", 640l, config_path); | |||||
config->video.height = ini_getl("Video", "Height", 480l, config_path); | |||||
config->video.max_fps = ini_getl("Video", "MaxFps", 30, config_path); | |||||
config->input.gamepad_axis_threshold = ini_getl("Input", "GamepadAxisThreshold", 8000, config_path); | |||||
char buffer[128]; | |||||
char keyboard_section_name[20] = "Controls.0.Keyboard"; | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | |||||
keyboard_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
ini_gets(keyboard_section_name, ACTION_NAMES[i], SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_CONTROLS[p][i]), buffer, 128, | |||||
config_path); | |||||
config->controls[p].keyboard[i] = SDL_GetKeyFromName(buffer); | |||||
} | |||||
} | |||||
char joystick_section_name[20] = "Controls.0.Joystick"; | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | |||||
joystick_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||||
config->controls[p].gamepad[i] = ini_getl(joystick_section_name, ACTION_NAMES[i], IZ_DEFAULT_JOYSTICK_CONTROLS[p][i], config_path); | |||||
} | |||||
} | |||||
} |
@@ -1,86 +0,0 @@ | |||||
#ifndef IZ_CONFIG_H | |||||
#define IZ_CONFIG_H | |||||
#include <stdio.h> | |||||
#include <string.h> | |||||
#include <SDL_filesystem.h> | |||||
#include <SDL_keyboard.h> | |||||
#include <minIni.h> | |||||
#include "../IZ_common.h" | |||||
#include "../IZ_action.h" | |||||
typedef struct { | |||||
uint16_t width; | |||||
uint16_t height; | |||||
uint8_t max_fps; | |||||
} IZ_VideoConfig; | |||||
typedef struct { | |||||
uint16_t gamepad_axis_threshold; | |||||
} IZ_InputConfig; | |||||
typedef SDL_KeyCode IZ_KeyCode; | |||||
typedef int IZ_PadButton; | |||||
typedef struct { | |||||
IZ_KeyCode keyboard[CONTROLS]; | |||||
IZ_PadButton gamepad[CONTROLS]; | |||||
} IZ_ControlsConfig; | |||||
typedef struct { | |||||
IZ_VideoConfig video; | |||||
IZ_InputConfig input; | |||||
IZ_ControlsConfig controls[PLAYERS]; | |||||
} IZ_Config; | |||||
static const IZ_KeyCode IZ_DEFAULT_KEYBOARD_CONTROLS[PLAYERS][CONTROLS] = { | |||||
{ | |||||
SDLK_UP, | |||||
SDLK_RIGHT, | |||||
SDLK_DOWN, | |||||
SDLK_LEFT, | |||||
SDLK_RETURN, // yes | |||||
SDLK_BACKSPACE, // no | |||||
SDLK_a, // action0 | |||||
SDLK_s, // action1 | |||||
SDLK_d, // action2 | |||||
SDLK_f, // action3 | |||||
SDLK_z, // action4 | |||||
SDLK_x, // action5 | |||||
SDLK_c, // action6 | |||||
SDLK_v, // action7 | |||||
SDLK_w, // action8 | |||||
SDLK_e, // action9 | |||||
}, | |||||
}; | |||||
static const uint8_t IZ_DEFAULT_JOYSTICK_CONTROLS[PLAYERS][CONTROLS] = { | |||||
{ | |||||
255, | |||||
255, | |||||
255, | |||||
255, | |||||
11, | |||||
10, | |||||
1, | |||||
0, | |||||
4, | |||||
3, | |||||
6, | |||||
7, | |||||
8, | |||||
9, | |||||
13, | |||||
14, | |||||
}, | |||||
}; | |||||
void IZ_GetConfigPath(char* config_path); | |||||
void IZ_SaveConfig(IZ_Config* config); | |||||
void IZ_LoadConfig(IZ_Config* config); | |||||
#endif |
@@ -0,0 +1,103 @@ | |||||
#include "IZ_joystick.h" | |||||
void IZ_HandleJoystickDeviceEvents(SDL_Event e, IZ_JoystickState* state) { | |||||
if (e.type == SDL_JOYDEVICEADDED) { | |||||
if (SDL_NumJoysticks() <= PLAYERS && !state->joystick_instance) { | |||||
state->joystick_instance = SDL_JoystickOpen(e.jdevice.which); | |||||
} | |||||
} | |||||
if (e.type == SDL_JOYDEVICEREMOVED) { | |||||
if ( | |||||
state->joystick_instance | |||||
&& SDL_JoystickInstanceID(state->joystick_instance) == e.jdevice.which | |||||
) { | |||||
state->joystick_instance = NULL; | |||||
} | |||||
} | |||||
} | |||||
void IZ_HandleJoystickAxisEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { | |||||
if (e.type == SDL_JOYAXISMOTION) { | |||||
if (e.jaxis.axis == 0 || e.jaxis.axis == 3) { | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_LEFT); | |||||
if (e.jaxis.value > state->config.axis_threshold) { | |||||
*action |= (0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
} else if (e.jaxis.value <= -state->config.axis_threshold) { | |||||
*action |= (0x1 << IZ_ACTION_INDEX_LEFT); | |||||
} | |||||
} | |||||
if (e.jaxis.axis == 1 || e.jaxis.axis == 4) { | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_UP); | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_DOWN); | |||||
if (e.jaxis.value > -state->config.axis_threshold) { | |||||
*action |= (0x1 << IZ_ACTION_INDEX_DOWN); | |||||
} else if (e.jaxis.value <= -state->config.axis_threshold) { | |||||
*action |= (0x1 << IZ_ACTION_INDEX_UP); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void IZ_HandleJoystickHatEvents(SDL_Event e, IZ_Action* action) { | |||||
if (e.type == SDL_JOYHATMOTION) { | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_UP); | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_DOWN); | |||||
*action &= ~(0x1 << IZ_ACTION_INDEX_LEFT); | |||||
if (e.jhat.value != 0) { | |||||
*action |= e.jhat.value; | |||||
} | |||||
} | |||||
} | |||||
void IZ_HandleJoystickButtonEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { | |||||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||||
if (e.jbutton.button == state->config.control_mapping[i]) { | |||||
const uint16_t bitflag = (0x1 << i); | |||||
if (e.type == SDL_JOYBUTTONDOWN) { | |||||
*action |= bitflag; | |||||
} else if (e.type == SDL_JOYBUTTONUP) { | |||||
*action &= ~bitflag; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void IZ_HandleJoystickEvents(SDL_Event e, IZ_JoystickState* state, IZ_Action* action) { | |||||
IZ_HandleJoystickDeviceEvents(e, state); | |||||
IZ_HandleJoystickAxisEvents(e, state, action); | |||||
IZ_HandleJoystickHatEvents(e, action); | |||||
IZ_HandleJoystickButtonEvents(e, state, action); | |||||
} | |||||
void IZ_LoadJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; | |||||
joystick_control_mapping_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||||
config->control_mapping[i] = ini_getl(joystick_control_mapping_section_name, ACTION_NAMES[i], IZ_DEFAULT_JOYSTICK_CONTROLS[p][i], config_path); | |||||
} | |||||
char joystick_section_name[] = "Joystick.0"; | |||||
joystick_section_name[9] = (char) (48 + p); | |||||
config->axis_threshold = ini_getl(joystick_section_name, "AxisThreshold", 8000, config_path); | |||||
} | |||||
void IZ_SaveJoystickConfig(IZ_JoystickConfig* config, uint8_t p) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
char joystick_control_mapping_section_name[] = "Joystick.0.ControlMapping"; | |||||
joystick_control_mapping_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 4; i < CONTROLS; i += 1) { | |||||
ini_putl(joystick_control_mapping_section_name, ACTION_NAMES[i], config->control_mapping[i], config_path); | |||||
} | |||||
char joystick_section_name[] = "Joystick.0"; | |||||
joystick_section_name[9] = (char) (48 + p); | |||||
ini_putl(joystick_section_name, "AxisThreshold", config->axis_threshold, config_path); | |||||
} |
@@ -0,0 +1,50 @@ | |||||
#ifndef IZ_JOYSTICK_H | |||||
#define IZ_JOYSTICK_H | |||||
#include <SDL_joystick.h> | |||||
#include <SDL_events.h> | |||||
#include <minIni.h> | |||||
#include "../IZ_action.h" | |||||
#include "../IZ_config.h" | |||||
typedef uint8_t IZ_PadButton; | |||||
typedef struct { | |||||
uint16_t axis_threshold; | |||||
IZ_PadButton control_mapping[CONTROLS]; | |||||
} IZ_JoystickConfig; | |||||
typedef struct { | |||||
SDL_Joystick* joystick_instance; | |||||
IZ_JoystickConfig config; | |||||
} IZ_JoystickState; | |||||
static IZ_PadButton IZ_DEFAULT_JOYSTICK_CONTROLS[PLAYERS][CONTROLS] = { | |||||
{ | |||||
255, | |||||
255, | |||||
255, | |||||
255, | |||||
11, | |||||
10, | |||||
1, | |||||
0, | |||||
4, | |||||
3, | |||||
6, | |||||
7, | |||||
8, | |||||
9, | |||||
13, | |||||
14, | |||||
}, | |||||
}; | |||||
void IZ_LoadJoystickConfig(IZ_JoystickConfig*, uint8_t); | |||||
void IZ_SaveJoystickConfig(IZ_JoystickConfig*, uint8_t); | |||||
void IZ_HandleJoystickEvents(SDL_Event, IZ_JoystickState*, IZ_Action*); | |||||
#endif |
@@ -0,0 +1,47 @@ | |||||
#include "IZ_keyboard.h" | |||||
void IZ_HandleKeyboardEvents(SDL_Event e, IZ_KeyboardState* state, IZ_Action* action) { | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
if (e.key.keysym.sym == state->config.control_mapping[i]) { | |||||
const uint16_t bitflag = (0x1 << i); | |||||
if (e.type == SDL_KEYDOWN) { | |||||
*action |= bitflag; | |||||
} else if (e.type == SDL_KEYUP) { | |||||
*action &= ~bitflag; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
void IZ_SaveKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
char keyboard_section_name[] = "Keyboard.0.ControlMapping"; | |||||
keyboard_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
ini_puts(keyboard_section_name, ACTION_NAMES[i], SDL_GetKeyName(config->control_mapping[i]), config_path); | |||||
} | |||||
} | |||||
void IZ_LoadKeyboardConfig(IZ_KeyboardConfig* config, uint8_t p) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
char buffer[128]; | |||||
char keyboard_section_name[] = "Keyboard.0.ControlMapping"; | |||||
keyboard_section_name[9] = (char) (48 + p); | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
ini_gets( | |||||
keyboard_section_name, | |||||
ACTION_NAMES[i], | |||||
SDL_GetKeyName(IZ_DEFAULT_KEYBOARD_CONTROLS[p][i]), | |||||
buffer, | |||||
128, | |||||
config_path | |||||
); | |||||
config->control_mapping[i] = SDL_GetKeyFromName(buffer); | |||||
} | |||||
} |
@@ -0,0 +1,45 @@ | |||||
#ifndef IZ_KEYBOARD_H | |||||
#define IZ_KEYBOARD_H | |||||
#include <SDL_keyboard.h> | |||||
#include <SDL_events.h> | |||||
#include <minIni.h> | |||||
#include "../IZ_action.h" | |||||
#include "../IZ_config.h" | |||||
typedef struct { | |||||
SDL_KeyCode control_mapping[CONTROLS]; | |||||
} IZ_KeyboardConfig; | |||||
typedef struct { | |||||
IZ_KeyboardConfig config; | |||||
} IZ_KeyboardState; | |||||
static const SDL_KeyCode IZ_DEFAULT_KEYBOARD_CONTROLS[PLAYERS][CONTROLS] = { | |||||
{ | |||||
SDLK_UP, | |||||
SDLK_RIGHT, | |||||
SDLK_DOWN, | |||||
SDLK_LEFT, | |||||
SDLK_RETURN, // yes | |||||
SDLK_BACKSPACE, // no | |||||
SDLK_a, // action0 | |||||
SDLK_s, // action1 | |||||
SDLK_d, // action2 | |||||
SDLK_f, // action3 | |||||
SDLK_z, // action4 | |||||
SDLK_x, // action5 | |||||
SDLK_c, // action6 | |||||
SDLK_v, // action7 | |||||
SDLK_w, // action8 | |||||
SDLK_e, // action9 | |||||
}, | |||||
}; | |||||
void IZ_LoadKeyboardConfig(IZ_KeyboardConfig*, uint8_t); | |||||
void IZ_SaveKeyboardConfig(IZ_KeyboardConfig*, uint8_t); | |||||
void IZ_HandleKeyboardEvents(SDL_Event, IZ_KeyboardState*, IZ_Action*); | |||||
#endif |
@@ -11,7 +11,6 @@ int main(int argc, char* args[]) { | |||||
IZ_App app; | IZ_App app; | ||||
IZ_InitializeApp(&app); | IZ_InitializeApp(&app); | ||||
if (SDL_Init( | if (SDL_Init( | ||||
SDL_INIT_VIDEO | SDL_INIT_VIDEO | ||||
| SDL_INIT_GAMECONTROLLER | | SDL_INIT_GAMECONTROLLER | ||||
@@ -25,16 +24,14 @@ int main(int argc, char* args[]) { | |||||
APP_NAME, | APP_NAME, | ||||
SDL_WINDOWPOS_CENTERED, | SDL_WINDOWPOS_CENTERED, | ||||
SDL_WINDOWPOS_CENTERED, | SDL_WINDOWPOS_CENTERED, | ||||
app.config.video.width, | |||||
app.config.video.height, | |||||
app.video_config.width, | |||||
app.video_config.height, | |||||
SDL_WINDOW_SHOWN | SDL_WINDOW_SHOWN | ||||
); | ); | ||||
if (window == NULL) { | if (window == NULL) { | ||||
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); | printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); | ||||
return -2; | return -2; | ||||
} | } | ||||
screen_surface = SDL_GetWindowSurface(window); | screen_surface = SDL_GetWindowSurface(window); | ||||
bool quit = false; | bool quit = false; | ||||
@@ -43,84 +40,20 @@ int main(int argc, char* args[]) { | |||||
while (true) { | while (true) { | ||||
uint64_t ticks = SDL_GetTicks64(); | uint64_t ticks = SDL_GetTicks64(); | ||||
// TODO do audio processing | |||||
// TODO do networking? | |||||
// process events | |||||
while (SDL_PollEvent(&e) != 0) { | while (SDL_PollEvent(&e) != 0) { | ||||
if (e.type == SDL_QUIT) { | if (e.type == SDL_QUIT) { | ||||
quit = true; | quit = true; | ||||
break; | break; | ||||
} | } | ||||
// Handle joystick events | |||||
for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { | |||||
if (e.type == SDL_JOYDEVICEADDED) { | |||||
if (SDL_NumJoysticks() <= PLAYERS && !app.assigned_joysticks[current_player]) { | |||||
app.assigned_joysticks[current_player] = SDL_JoystickOpen(e.jdevice.which); | |||||
} | |||||
} | |||||
if (e.type == SDL_JOYDEVICEREMOVED) { | |||||
if ( | |||||
app.assigned_joysticks[current_player] | |||||
&& SDL_JoystickInstanceID(app.assigned_joysticks[current_player]) == e.jdevice.which | |||||
) { | |||||
app.assigned_joysticks[current_player] = NULL; | |||||
} | |||||
} | |||||
if (e.type == SDL_JOYAXISMOTION) { | |||||
if (e.jaxis.axis == 0 || e.jaxis.axis == 3) { | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_LEFT); | |||||
if (e.jaxis.value > app.config.input.gamepad_axis_threshold) { | |||||
app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
} else if (e.jaxis.value <= -app.config.input.gamepad_axis_threshold) { | |||||
app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_LEFT); | |||||
} | |||||
} | |||||
if (e.jaxis.axis == 1 || e.jaxis.axis == 4) { | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_UP); | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_DOWN); | |||||
if (e.jaxis.value > app.config.input.gamepad_axis_threshold) { | |||||
app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_DOWN); | |||||
} else if (e.jaxis.value <= -app.config.input.gamepad_axis_threshold) { | |||||
app.actions[current_player] |= (0x1 << IZ_ACTION_INDEX_UP); | |||||
} | |||||
} | |||||
} | |||||
if (e.type == SDL_JOYHATMOTION) { | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_UP); | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_RIGHT); | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_DOWN); | |||||
app.actions[current_player] &= ~(0x1 << IZ_ACTION_INDEX_LEFT); | |||||
if (e.jhat.value != 0) { | |||||
app.actions[current_player] |= e.jhat.value; | |||||
} | |||||
} | |||||
} | |||||
// Handle keyboard events | |||||
for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | |||||
if (e.key.keysym.sym == app.config.controls[current_player].keyboard[i]) { | |||||
const uint16_t bitflag = (0x1 << i); | |||||
if (e.type == SDL_KEYDOWN) { | |||||
app.actions[current_player] |= bitflag; | |||||
} else if (e.type == SDL_KEYUP) { | |||||
app.actions[current_player] &= ~bitflag; | |||||
} | |||||
} | |||||
if (i >= 4) { | |||||
if (e.jbutton.button == app.config.controls[current_player].gamepad[i]) { | |||||
const uint16_t bitflag = (0x1 << i); | |||||
if (e.type == SDL_JOYBUTTONDOWN) { | |||||
app.actions[current_player] |= bitflag; | |||||
} else if (e.type == SDL_JOYBUTTONUP) { | |||||
app.actions[current_player] &= ~bitflag; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | |||||
IZ_HandleJoystickEvents(e, &(app.joystick_state[p]), &app.actions[p]); | |||||
IZ_HandleKeyboardEvents(e, &(app.keyboard_state[p]), &app.actions[p]); | |||||
} | } | ||||
} | } | ||||
@@ -128,10 +61,9 @@ int main(int argc, char* args[]) { | |||||
break; | break; | ||||
} | } | ||||
if (ticks - app.video_update_at > 1000 / app.config.video.max_fps) { | |||||
if (ticks - app.video_update_at > 1000 / app.video_config.max_fps) { | |||||
// Update window | // Update window | ||||
SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00)); | SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00)); | ||||
for (uint8_t i = 0; i < 64; i += 1) { | for (uint8_t i = 0; i < 64; i += 1) { | ||||
const uint8_t column = (64 - i) % 32; | const uint8_t column = (64 - i) % 32; | ||||
const uint8_t row = i / 32; | const uint8_t row = i / 32; | ||||
@@ -140,20 +72,20 @@ int main(int argc, char* args[]) { | |||||
if (ticks & bitflag) { | if (ticks & bitflag) { | ||||
SDL_FillRect(screen_surface, &(SDL_Rect) { | SDL_FillRect(screen_surface, &(SDL_Rect) { | ||||
column * size, | column * size, | ||||
app.config.video.height - ((row + 1) * size), | |||||
app.video_config.height - ((row + 1) * size), | |||||
size, | size, | ||||
size | size | ||||
}, SDL_MapRGB(screen_surface->format, 0x00, 0xff, 0xff)); | }, SDL_MapRGB(screen_surface->format, 0x00, 0xff, 0xff)); | ||||
} | } | ||||
} | } | ||||
for (uint8_t current_player = 0; current_player < PLAYERS; current_player += 1) { | |||||
for (uint8_t p = 0; p < PLAYERS; p += 1) { | |||||
for (uint8_t i = 0; i < CONTROLS; i += 1) { | for (uint8_t i = 0; i < CONTROLS; i += 1) { | ||||
const uint8_t column = i % 4; | |||||
const uint8_t column = (i % 4) + (p * 4); | |||||
const uint8_t row = i / 4; | const uint8_t row = i / 4; | ||||
const IZ_Action bitflag = (0x1 << i); | const IZ_Action bitflag = (0x1 << i); | ||||
const uint8_t size = 4; | const uint8_t size = 4; | ||||
if (app.actions[current_player] & bitflag) { | |||||
if (app.actions[p] & bitflag) { | |||||
SDL_FillRect(screen_surface, &(SDL_Rect) { | SDL_FillRect(screen_surface, &(SDL_Rect) { | ||||
column * size, | column * size, | ||||
row * size, | row * size, | ||||
@@ -164,7 +96,6 @@ int main(int argc, char* args[]) { | |||||
} | } | ||||
} | } | ||||
SDL_UpdateWindowSurface(window); | SDL_UpdateWindowSurface(window); | ||||
app.video_update_at = ticks; | app.video_update_at = ticks; | ||||
} | } | ||||
} | } | ||||
@@ -1,15 +1,6 @@ | |||||
#include "bdd-for-c.h" | |||||
#include "../../game/config/IZ_config.h" | |||||
#define mock_call_count_t uint8_t | |||||
#define mock(X) static mock_call_count_t calls_##X = 0; | |||||
#define mock_return(X) calls_##X += 1; return | |||||
#define mock_reset(X) calls_##X = 0 | |||||
#define mock_calls(X) ((mock_call_count_t) (calls_##X)) | |||||
#include <bdd-for-c.h> | |||||
#include "../../test/IZ_mock.h" | |||||
#include "IZ_video.h" | |||||
mock(SDL_GetBasePath) char* SDL_GetBasePath() { | mock(SDL_GetBasePath) char* SDL_GetBasePath() { | ||||
mock_return(SDL_GetBasePath) ""; | mock_return(SDL_GetBasePath) ""; | ||||
@@ -68,7 +59,7 @@ spec("config") { | |||||
} | } | ||||
it("should load default config values") { | it("should load default config values") { | ||||
IZ_LoadConfig(&config); | |||||
IZ_LoadVideoConfig(&config); | |||||
check( | check( | ||||
mock_calls(SDL_GetBasePath) > 0, | mock_calls(SDL_GetBasePath) > 0, | ||||
@@ -100,7 +91,7 @@ spec("config") { | |||||
); | ); | ||||
check( | check( | ||||
config.input.gamepad_axis_threshold == 8000, | |||||
config.input.axis_threshold == 8000, | |||||
"Default value for Input.GamepadAxisThreshold is not loaded." | "Default value for Input.GamepadAxisThreshold is not loaded." | ||||
); | ); | ||||
@@ -0,0 +1,19 @@ | |||||
#include "IZ_video.h" | |||||
void IZ_SaveVideoConfig(IZ_VideoConfig* config) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
ini_putl("Video", "Width", config->width, config_path); | |||||
ini_putl("Video", "Height", config->height, config_path); | |||||
ini_putl("Video", "MaxFps", config->max_fps, config_path); | |||||
} | |||||
void IZ_LoadVideoConfig(IZ_VideoConfig* config) { | |||||
char config_path[128]; | |||||
IZ_GetConfigPath(config_path); | |||||
config->width = ini_getl("Video", "Width", 640l, config_path); | |||||
config->height = ini_getl("Video", "Height", 480l, config_path); | |||||
config->max_fps = ini_getl("Video", "MaxFps", 30, config_path); | |||||
} |
@@ -0,0 +1,18 @@ | |||||
#ifndef IZ_VIDEO_H | |||||
#define IZ_VIDEO_H | |||||
#include <stdio.h> | |||||
#include <minIni.h> | |||||
#include "../IZ_config.h" | |||||
typedef struct { | |||||
uint16_t width; | |||||
uint16_t height; | |||||
uint8_t max_fps; | |||||
} IZ_VideoConfig; | |||||
void IZ_SaveVideoConfig(IZ_VideoConfig* config); | |||||
void IZ_LoadVideoConfig(IZ_VideoConfig* config); | |||||
#endif |
@@ -0,0 +1,14 @@ | |||||
#ifndef IZ_MOCK_H | |||||
#define IZ_MOCK_H | |||||
#define mock_call_count_t uint8_t | |||||
#define mock(X) static mock_call_count_t calls_##X = 0; | |||||
#define mock_return(X) calls_##X += 1; return | |||||
#define mock_reset(X) calls_##X = 0 | |||||
#define mock_calls(X) ((mock_call_count_t) (calls_##X)) | |||||
#endif |