Skip to content

Commit a2a22e5

Browse files
ADDED: example: core_input_actions (#5211)
* adding core_input_actions action based input API vs direct input, allows remapping of buttons or keys to an action. * adjusted formatting. * updates for struct name and fixed a typo
1 parent 4767841 commit a2a22e5

File tree

2 files changed

+175
-0
lines changed

2 files changed

+175
-0
lines changed

examples/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ CORE = \
524524
core/core_input_mouse_wheel \
525525
core/core_input_multitouch \
526526
core/core_input_virtual_controls \
527+
core/core_input_actions \
527528
core/core_random_sequence \
528529
core/core_random_values \
529530
core/core_render_texture \

examples/core/core_input_actions.c

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
2+
/*******************************************************************************************
3+
*
4+
* raylib [core_inputactionInputs] example - presents a simple API for remapping input to actions
5+
*
6+
* Example complexity rating: [★☆☆☆] 1/4
7+
*
8+
* Example originally created with raylib 5.5, last time updated with raylib 5.6
9+
*
10+
* Example contributed by MonstersGoBoom and reviewed by Ramon Santamaria (@raysan5)
11+
*
12+
* Example licensed under an unmodified zlib/libpng license, which is an OSI-certified,
13+
* BSD-like license that allows static linking with closed source software
14+
*
15+
* Copyright (c) 2025 MonstersGoBoom
16+
*
17+
********************************************************************************************/
18+
19+
/*
20+
Simple example for decoding input as actions, allowing remapping of input to different keys or gamepad buttons.
21+
for example instead of
22+
IsKeyDown(KEY_LEFT)
23+
you'd use
24+
IsActionDown(ACTION_LEFT)
25+
which can be reassigned to e.g. KEY_A and also assigned to a gamepad button. the action will trigger with either gamepad or keys
26+
*/
27+
28+
29+
#include <stdio.h>
30+
#include <stdlib.h>
31+
#include <stdbool.h>
32+
#include "raylib.h"
33+
34+
// add your own action types here
35+
36+
typedef enum ActionType
37+
{
38+
NO_ACTION,
39+
ACTION_UP,
40+
ACTION_DOWN,
41+
ACTION_LEFT,
42+
ACTION_RIGHT,
43+
ACTION_FIRE,
44+
MAX_ACTION
45+
} ActionType;
46+
47+
// struct for key and button inputs
48+
typedef struct ActionInput
49+
{
50+
int key;
51+
int button;
52+
} ActionInput;
53+
54+
// gamepad index, change this if you have multiple gamepads.
55+
int gamepadIndex = 0;
56+
static ActionInput actionInputs[MAX_ACTION] = {0};
57+
58+
// combines IsKeyPressed and IsGameButtonPressed to one action
59+
bool isActionPressed(int action)
60+
{
61+
if (action<MAX_ACTION)
62+
return (IsKeyPressed(actionInputs[action].key) || IsGamepadButtonPressed(gamepadIndex, actionInputs[action].button));
63+
return (false);
64+
}
65+
66+
// combines IsKeyReleased and IsGameButtonReleased to one action
67+
bool isActionReleased(int action)
68+
{
69+
if (action<MAX_ACTION)
70+
return (IsKeyReleased(actionInputs[action].key) || IsGamepadButtonReleased(gamepadIndex, actionInputs[action].button));
71+
return (false);
72+
}
73+
74+
// combines IsKeyDown and IsGameButtonDown to one action
75+
bool isActionDown(int action)
76+
{
77+
if (action<MAX_ACTION)
78+
return (IsKeyDown(actionInputs[action].key) || IsGamepadButtonDown(gamepadIndex, actionInputs[action].button));
79+
return (false);
80+
}
81+
// define the "default" keyset. here WASD and gamepad buttons on the left side for movement
82+
void DefaultActions()
83+
{
84+
actionInputs[ACTION_UP].key = KEY_W;
85+
actionInputs[ACTION_DOWN].key = KEY_S;
86+
actionInputs[ACTION_LEFT].key = KEY_A;
87+
actionInputs[ACTION_RIGHT].key = KEY_D;
88+
actionInputs[ACTION_FIRE].key = KEY_SPACE;
89+
90+
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_LEFT_FACE_UP;
91+
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
92+
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_LEFT_FACE_LEFT;
93+
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_LEFT_FACE_RIGHT;
94+
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
95+
}
96+
97+
// define the "alternate" keyset. here Cursor Keys and gamepad buttons on the right side for movement
98+
void CursorActions()
99+
{
100+
actionInputs[ACTION_UP].key = KEY_UP;
101+
actionInputs[ACTION_DOWN].key = KEY_DOWN;
102+
actionInputs[ACTION_LEFT].key = KEY_LEFT;
103+
actionInputs[ACTION_RIGHT].key = KEY_RIGHT;
104+
actionInputs[ACTION_FIRE].key = KEY_SPACE;
105+
106+
actionInputs[ACTION_UP].button = GAMEPAD_BUTTON_RIGHT_FACE_UP;
107+
actionInputs[ACTION_DOWN].button = GAMEPAD_BUTTON_RIGHT_FACE_DOWN;
108+
actionInputs[ACTION_LEFT].button = GAMEPAD_BUTTON_RIGHT_FACE_LEFT;
109+
actionInputs[ACTION_RIGHT].button = GAMEPAD_BUTTON_RIGHT_FACE_RIGHT;
110+
actionInputs[ACTION_FIRE].button = GAMEPAD_BUTTON_LEFT_FACE_DOWN;
111+
}
112+
113+
//------------------------------------------------------------------------------------
114+
// Program main entry point
115+
//------------------------------------------------------------------------------------
116+
117+
int main(int argc, char **argv)
118+
{
119+
const int screenWidth = 800;
120+
const int screenHeight = 450;
121+
122+
InitWindow(screenWidth, screenHeight, "raylib [core] example - input via actions");
123+
SetWindowState(FLAG_WINDOW_RESIZABLE);
124+
SetTargetFPS(60);
125+
126+
// set default actions
127+
char actionSet = 0;
128+
DefaultActions();
129+
130+
Vector2 position = (Vector2){100, 100};
131+
Vector2 size = (Vector2){32, 32};
132+
133+
while (!WindowShouldClose()) // Detect window close button or ESC key
134+
{
135+
//----------------------------------------------------------------------------------
136+
BeginDrawing();
137+
ClearBackground(DARKGRAY);
138+
DrawText(actionSet == 0 ? "WASD Default Set" : "Cursor Set", 0, 0, 18, WHITE);
139+
DrawText("Tab key toggles keyset", 0, 18, 18, WHITE);
140+
DrawRectangleV(position, size, RED);
141+
EndDrawing();
142+
143+
gamepadIndex = 0; // set this to gamepad being checked
144+
if (isActionDown(ACTION_UP))
145+
position.y -= 2;
146+
if (isActionDown(ACTION_DOWN))
147+
position.y += 2;
148+
if (isActionDown(ACTION_LEFT))
149+
position.x -= 2;
150+
if (isActionDown(ACTION_RIGHT))
151+
position.x += 2;
152+
if (isActionPressed(ACTION_FIRE))
153+
{
154+
position.x = (screenWidth-size.x)/2;
155+
position.y = (screenHeight-size.y)/2;
156+
}
157+
158+
// switch control scheme by pressing TAB
159+
if (IsKeyPressed(KEY_TAB))
160+
{
161+
actionSet = !actionSet;
162+
if (actionSet == 0)
163+
DefaultActions();
164+
else
165+
CursorActions();
166+
}
167+
//----------------------------------------------------------------------------------
168+
}
169+
170+
// De-Initialization
171+
//--------------------------------------------------------------------------------------
172+
CloseWindow(); // Close window and OpenGL context
173+
return 0;
174+
}

0 commit comments

Comments
 (0)