ソースを参照

Isolate input/output handling

Make device handling opt-in.
feature/data-structs
コミット
656bcf0260
19個のファイルの変更379行の追加271行の削除
  1. +10
    -8
      CMakeLists.txt
  2. +1
    -0
      dependencies.txt
  3. +18
    -3
      docs/reference/files/config.ini
  4. +9
    -5
      src/packages/game/IZ_app.c
  5. +6
    -6
      src/packages/game/IZ_app.h
  6. +2
    -0
      src/packages/game/IZ_common.h
  7. +8
    -0
      src/packages/game/IZ_config.c
  8. +9
    -0
      src/packages/game/IZ_config.h
  9. +0
    -65
      src/packages/game/config/IZ_config.c
  10. +0
    -86
      src/packages/game/config/IZ_config.h
  11. +103
    -0
      src/packages/game/input/IZ_joystick.c
  12. +50
    -0
      src/packages/game/input/IZ_joystick.h
  13. +47
    -0
      src/packages/game/input/IZ_keyboard.c
  14. +45
    -0
      src/packages/game/input/IZ_keyboard.h
  15. +15
    -84
      src/packages/game/main.c
  16. +5
    -14
      src/packages/game/output/IZ_config.test.c
  17. +19
    -0
      src/packages/game/output/IZ_video.c
  18. +18
    -0
      src/packages/game/output/IZ_video.h
  19. +14
    -0
      src/packages/test/IZ_mock.h

+ 10
- 8
CMakeLists.txt ファイルの表示

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.20)
cmake_minimum_required(VERSION 3.21)

# Set your project name here
project(izanagi C)
@@ -9,6 +9,7 @@ include_directories(
"${PROJECT_SOURCE_DIR}/dependencies/SDL2/include"
"${PROJECT_SOURCE_DIR}/dependencies/minIni/dev"
"${PROJECT_SOURCE_DIR}/dependencies/bdd-for-c"
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/pm_common"
)

if (WIN32)
@@ -21,20 +22,21 @@ endif ()

link_directories(
"${PROJECT_SOURCE_DIR}/dependencies/SDL2/lib/${PROJECT_ARCH}"
"${PROJECT_SOURCE_DIR}/dependencies/portmidi/Release"
)

add_executable(
game
dependencies/minIni/dev/minIni.h
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_action.h
src/packages/game/IZ_app.h
src/packages/game/IZ_app.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(
game
SDL2main
@@ -43,11 +45,11 @@ target_link_libraries(

add_executable(
game-test
src/packages/game/config/IZ_config.h
src/packages/game/config/IZ_config.c
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)
add_custom_command(TARGET game POST_BUILD


+ 1
- 0
dependencies.txt ファイルの表示

@@ -1,2 +1,3 @@
https://github.com/compuphase/minIni
https://github.com/grassator/bdd-for-c
https://github.com/PortMidi/portmidi

+ 18
- 3
docs/reference/files/config.ini ファイルの表示

@@ -1,12 +1,12 @@
[Video]
Width=640
Height=480
[Controls.0.Keyboard]
MaxFps=30
[Keyboard.0.ControlMapping]
Up=Up
Right=Right
Down=Down
Left=Left
Up=Up
Affirm=Return
Negate=Backspace
Action0=A
@@ -19,3 +19,18 @@ Action6=C
Action7=V
Action8=W
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

+ 9
- 5
src/packages/game/IZ_app.c ファイルの表示

@@ -1,15 +1,19 @@
#include "IZ_app.h"

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) {
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->video_update_at = 0u;

return 0;
}

+ 6
- 6
src/packages/game/IZ_app.h ファイルの表示

@@ -1,17 +1,17 @@
#ifndef 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"

typedef struct {
IZ_Config config;
IZ_VideoConfig video_config;

IZ_Action actions[PLAYERS];
SDL_Joystick* assigned_joysticks[PLAYERS];
IZ_KeyboardState keyboard_state[PLAYERS];
IZ_JoystickState joystick_state[PLAYERS];

uint64_t video_update_at;
} IZ_App;


+ 2
- 0
src/packages/game/IZ_common.h ファイルの表示

@@ -8,4 +8,6 @@

static const char* APP_NAME = "SDL2";

typedef uint8_t IZ_ProcedureResult;

#endif

+ 8
- 0
src/packages/game/IZ_config.c ファイルの表示

@@ -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");
}

+ 9
- 0
src/packages/game/IZ_config.h ファイルの表示

@@ -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

+ 0
- 65
src/packages/game/config/IZ_config.c ファイルの表示

@@ -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);
}
}
}

+ 0
- 86
src/packages/game/config/IZ_config.h ファイルの表示

@@ -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

+ 103
- 0
src/packages/game/input/IZ_joystick.c ファイルの表示

@@ -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);
}

+ 50
- 0
src/packages/game/input/IZ_joystick.h ファイルの表示

@@ -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

+ 47
- 0
src/packages/game/input/IZ_keyboard.c ファイルの表示

@@ -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);
}
}

+ 45
- 0
src/packages/game/input/IZ_keyboard.h ファイルの表示

@@ -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

+ 15
- 84
src/packages/game/main.c ファイルの表示

@@ -11,7 +11,6 @@ int main(int argc, char* args[]) {
IZ_App app;

IZ_InitializeApp(&app);

if (SDL_Init(
SDL_INIT_VIDEO
| SDL_INIT_GAMECONTROLLER
@@ -25,16 +24,14 @@ int main(int argc, char* args[]) {
APP_NAME,
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
);

if (window == NULL) {
printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
return -2;
}

screen_surface = SDL_GetWindowSurface(window);

bool quit = false;
@@ -43,84 +40,20 @@ int main(int argc, char* args[]) {
while (true) {
uint64_t ticks = SDL_GetTicks64();

// TODO do audio processing

// TODO do networking?

// process events
while (SDL_PollEvent(&e) != 0) {
if (e.type == SDL_QUIT) {
quit = true;
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;
}

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
SDL_FillRect(screen_surface, NULL, SDL_MapRGB(screen_surface->format, 0x00, 0x00, 0x00));

for (uint8_t i = 0; i < 64; i += 1) {
const uint8_t column = (64 - i) % 32;
const uint8_t row = i / 32;
@@ -140,20 +72,20 @@ int main(int argc, char* args[]) {
if (ticks & bitflag) {
SDL_FillRect(screen_surface, &(SDL_Rect) {
column * size,
app.config.video.height - ((row + 1) * size),
app.video_config.height - ((row + 1) * size),
size,
size
}, 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) {
const uint8_t column = i % 4;
const uint8_t column = (i % 4) + (p * 4);
const uint8_t row = i / 4;
const IZ_Action bitflag = (0x1 << i);
const uint8_t size = 4;
if (app.actions[current_player] & bitflag) {
if (app.actions[p] & bitflag) {
SDL_FillRect(screen_surface, &(SDL_Rect) {
column * size,
row * size,
@@ -164,7 +96,6 @@ int main(int argc, char* args[]) {
}
}
SDL_UpdateWindowSurface(window);

app.video_update_at = ticks;
}
}


src/packages/game-test/config/IZ_config.c → src/packages/game/output/IZ_config.test.c ファイルの表示

@@ -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_return(SDL_GetBasePath) "";
@@ -68,7 +59,7 @@ spec("config") {
}

it("should load default config values") {
IZ_LoadConfig(&config);
IZ_LoadVideoConfig(&config);

check(
mock_calls(SDL_GetBasePath) > 0,
@@ -100,7 +91,7 @@ spec("config") {
);

check(
config.input.gamepad_axis_threshold == 8000,
config.input.axis_threshold == 8000,
"Default value for Input.GamepadAxisThreshold is not loaded."
);


+ 19
- 0
src/packages/game/output/IZ_video.c ファイルの表示

@@ -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);
}

+ 18
- 0
src/packages/game/output/IZ_video.h ファイルの表示

@@ -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

+ 14
- 0
src/packages/test/IZ_mock.h ファイルの表示

@@ -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

読み込み中…
キャンセル
保存