Skip to main content

Control Schemes

Cub3D supports three input methods that can be used simultaneously:

Keyboard

WASD movement + Arrow keys for looking

Mouse

Mouse look with FPS-style camera control

Gamepad

Full controller support (Xbox, PlayStation, etc.)

Keyboard Controls

Movement

KeyAction
WMove forward
SMove backward
AStrafe left
DStrafe right
Left ShiftSprint (increases movement speed)
Default walk speed: 4.0 units/sec
Sprint speed: 6.0 units/sec

Camera Control

KeyAction
Left ArrowLook left
Right ArrowLook right
MToggle mouse look on/off
Keyboard look velocity: 180°/sec
Mouse look velocity: 20.0 (sensitivity multiplier)

Actions

KeyAction
EInteract / Open doors
SpaceUse equipped item / Fire weapon
QDrop current item
RCycle inventory (next item)

Mouse Wheel

When mouse look is enabled:
InputAction
Mouse Wheel UpCycle inventory forward
Mouse Wheel DownCycle inventory backward
Inventory scroll has a 0.5-second cooldown to prevent accidental double-scrolling.

HUD & Debug

KeyAction
F1Toggle fullscreen
F2Toggle stats HUD
F3Toggle debug info (FPS, coordinates)
F4Toggle minimap
F5Toggle action prompts
F6Toggle entire HUD
F7Reload/detect gamepads

Minimap Controls

KeyAction
8Zoom out minimap
9Reset minimap zoom (5.0x)
0Zoom in minimap
Each zoom level changes by a factor of 1.2x.

Multiplayer

KeyAction
PActivate additional player
ODeactivate a player
Supports up to 4 simultaneous players (split-screen).

System

KeyAction
ESCReturn to hub map (maps/hub.cub)
KToggle keyboard-only mode (disables mouse/gamepad)

Cheat Codes

These are debug features and may break gameplay:
KeyEffect
IToggle invincibility + restore health
BToggle noclip (walk through walls)
The cheating flag is set when invincibility or noclip is active.

Mouse Controls

Mouse Look

1

Enable mouse look

Press M to toggle mouse control on/off.
2

Camera movement

Move the mouse left/right to rotate the camera.The cursor is automatically centered, and movement delta is calculated:
movement = mouse_x - (window_width / 2)
3

Sensitivity curve

Small movements are dampened for precision:
if (abs(movement) < 10)
    movement = movement * (0.5 + (abs(movement) / 20.0))
Mouse look works best in fullscreen mode (F1).

Mouse Deadzone

Movements within 10 pixels of center are scaled down to reduce jitter.

Gamepad Controls

Supported Controllers

Xbox

Xbox One, Series X/S, 360

PlayStation

DualShock 4, DualSense

Generic

Any SDL2-compatible gamepad

Button Mapping

ButtonAction
Left StickMove (forward/back/strafe)
Right StickLook (rotate camera)
LT (L2)Sprint (when > 80% pressed)
RT (R2)Use item / Fire weapon (when > 80% pressed)
LB (L1)Not mapped
RB (R1)Cycle inventory
A (Cross)Not mapped
B (Circle)Drop item
X (Square)Interact / Open doors
Y (Triangle)Not mapped
Menu/StartActivate (keyboard-only override)
View/BackNot mapped

Analog Stick Behavior

Left Stick (Movement)

The stick is divided into directional zones:
// Y-axis: 0.0 to 0.3 (upper zone)
walking_forward = (stick_y < 0.3)
The center deadzone (0.3 to 0.7) prevents stick drift.

Right Stick (Camera)

Same zone mapping for camera rotation:
  • X < 0.3: Look left
  • X > 0.7: Look right
  • Center (0.3-0.7): No rotation

Trigger Sensitivity

// Triggers are pressure-sensitive
pressure = normalize_pressure(trigger_value)  // 0.0 to 1.0
activated = (pressure > 0.8)  // 80% threshold
Light trigger presses won’t fire weapons. This prevents accidental shots.

Controller Deadzone

Raw analog values are filtered:
#define CONTROLLERS_DEADZONE 8000  // Out of 32767

if (abs(raw_value) < 8000)
    raw_value = 0;
This prevents drift when the stick is released.

Gamepad Detection

1

Automatic detection

Controllers are detected on game startup.
2

Hot-plugging

Press F7 to manually reload and detect newly connected controllers.
3

Multiple controllers

Each player can use a separate gamepad (up to 4 players).

Advanced Configuration

Controller Implementation

The player controller is defined in src/utils/entities/controller/player/player2.c:player2.c:
t_player_keys get_player_gamepad_keys(void)
{
    return ((t_player_keys){
        .walking_forward = {FTM_GAMEPAD_LSTICK, false, 0.0, 1.0,
            true, {0.0, 0.0, 0}, {1.0, 0.3, 0}},
        .walking_backward = {FTM_GAMEPAD_LSTICK, false, 0.0, 1.0,
            true, {0.0, 0.7, 0}, {1.0, 1.0, 0}},
        .looking_left = {FTM_GAMEPAD_RSTICK, false, 0.0, 1.0,
            true, {0.0, 0.0, 0}, {0.3, 1.0, 0}},
        .looking_right = {FTM_GAMEPAD_RSTICK, false, 0.0, 1.0,
            true, {0.7, 0.0, 0}, {1.0, 1.0, 0}},
        .sprinting = {FTM_GAMEPAD_L2, true, 0.8, 1.0, false, {0}, {0}},
        .item_use = {FTM_GAMEPAD_R2, true, 0.8, 1.0, false, {0}, {0}},
        // ...
    });
}

Custom Key Bindings

To modify key bindings, edit src/utils/entities/controller/player/player2.c:player2.c:
t_player_keys get_player_keyboard_keys(void)
{
    return ((t_player_keys){
        .walking_forward = {FTM_KEY_W, false, 0.0, 1.0, false, {0}, {0}},
        .walking_backward = {FTM_KEY_S, false, 0.0, 1.0, false, {0}, {0}},
        // Change these FTM_KEY_* constants to remap keys
    });
}

Available Key Constants

  • FTM_KEY_W, FTM_KEY_A, FTM_KEY_S, FTM_KEY_D
  • FTM_KEY_SPACE, FTM_KEY_LSHIFT, FTM_KEY_ESC
  • FTM_KEY_E, FTM_KEY_Q, FTM_KEY_R
  • FTM_KEY_LEFT, FTM_KEY_RIGHT, FTM_KEY_UP, FTM_KEY_DOWN
  • FTM_KEY_F1 through FTM_KEY_F12
  • FTM_KEY_0 through FTM_KEY_9
  • FTM_KEY_M, FTM_KEY_K, FTM_KEY_P, FTM_KEY_O
  • FTM_KEY_I, FTM_KEY_B
  • FTM_GAMEPAD_A (Xbox A / PS Cross)
  • FTM_GAMEPAD_B (Xbox B / PS Circle)
  • FTM_GAMEPAD_X (Xbox X / PS Square)
  • FTM_GAMEPAD_Y (Xbox Y / PS Triangle)
  • FTM_GAMEPAD_L1, FTM_GAMEPAD_R1 (Bumpers)
  • FTM_GAMEPAD_L2, FTM_GAMEPAD_R2 (Triggers)
  • FTM_GAMEPAD_MENU (Start/Options)
  • FTM_GAMEPAD_UP, FTM_GAMEPAD_DOWN, FTM_GAMEPAD_LEFT, FTM_GAMEPAD_RIGHT (D-Pad)
  • FTM_GAMEPAD_LSTICK (Left analog stick)
  • FTM_GAMEPAD_RSTICK (Right analog stick)

Player Configuration Constants

Defined in headers/cub3d.h:cub3d.h:
// Player velocities
#define PLAYER_MOUSE_LOOK_VELOCITY 20.0
#define PLAYER_KEY_LOOK_VELOCITY 180.0
#define PLAYER_WALK_VELOCITY 4.0
#define PLAYER_SPRINT_VELOCITY 6.0

// Player camera
#define PLAYER_FOV 66.0  // Field of view in degrees

// Inventory
#define INVENTORY_SIZE 9
#define INVENTORY_SCROLL_DELAY 0.5  // Seconds
Modify these to adjust gameplay feel.

Control Flow

The control system processes input through these layers:
1

SDL Event Capture

SDL2 captures keyboard, mouse, and gamepad events
2

Controller Event Handler

ftm_controller_event_handler() processes gamepad input in src/ft_mlx_utils/controllers/controllers2.c:controllers2.c
3

Key Hook

key_hook() in src/utils/loop/keys.c:keys.c handles keyboard input
4

Mouse Hook

mouse_hook() in src/utils/loop/mouse.c:mouse.c processes mouse movement
5

Entity Controllers

Each entity’s controller struct manages movement and actions
6

Frame Processing

moviment_frame() updates entity positions based on controller state

Troubleshooting

  • Press F7 to reload controllers
  • Ensure controller is connected before starting the game
  • Check if controller is recognized by your OS:
    Linux
    ls /dev/input/js*
    
    macOS
    system_profiler SPUSBDataType | grep -i game
    
  • Verify SDL2 gamepad support:
    ./cub3d maps/hub.cub
    # Look for "Controller 0: <name>" in console output
    
  • Press M to toggle mouse look on/off
  • Check if MOUSE directive in .cub file is set to FALSE
  • Ensure window has focus (click on the game window)
The deadzone is set to 8000/32767 (~24%). If drift persists:
  • Clean or recalibrate your controller
  • Increase CONTROLLERS_DEADZONE in src/ft_mlx_utils/controllers/controllers.h:controllers.h
Adjust velocity constants in headers/cub3d.h:cub3d.h:
#define PLAYER_WALK_VELOCITY 4.0      // Decrease for slower movement
#define PLAYER_MOUSE_LOOK_VELOCITY 20.0  // Decrease for lower sensitivity
Rebuild after changes:
make re
Press K to toggle keyboard-only mode off. This mode disables mouse and gamepad input.

Next Steps

Creating Maps

Design custom levels and configure entities

Building

Compile and test your changes

Build docs developers (and LLMs) love