Appearance
⌨Input System - Moteur Graphique R-Type
L'Input System gère toutes les entrées utilisateur (clavier, souris) et les expose via :
- Actions sémantiques : Booléens persistants (actionPressed, actionJustPressed, actionJustReleased)
- Axes : Valeurs continues (-1, 0, +1) pour les déplacements
- Touches directes : Accès brut aux touches individuelles
- Souris : Position et boutons
- Rebinding dynamique : Modifier les contrôles à l'exécution
- Singleton pattern : Accès global facile
- Abstraction backend : Indépendant du renderer
Architecture
Flux d'Entrée
┌─────────────────────────────────┐
│ Événements SFML/Backend │
│ (Clavier, Souris, Fenêtre) │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ IInputBackend │
│ (Interface abstraction) │
└────────────┬────────────────────�┘
│
┌────────────▼────────────────────┐
│ InputManager (Singleton) │
│ • Mappings actions │
│ • État des touches │
│ • Détection just pressed/rel │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ Votre Code de Jeu │
│ if (inputMgr.isActionPressed) │
└─────────────────────────────────┘
┌─────────────────────────────────┐
│ Événements SFML/Backend │
│ (Clavier, Souris, Fenêtre) │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ IInputBackend │
│ (Interface abstraction) │
└────────────┬────────────────────�┘
│
┌────────────▼────────────────────┐
│ InputManager (Singleton) │
│ • Mappings actions │
│ • État des touches │
│ • Détection just pressed/rel │
└────────────┬────────────────────┘
│
┌────────────▼────────────────────┐
│ Votre Code de Jeu │
│ if (inputMgr.isActionPressed) │
└─────────────────────────────────┘
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Composants
InputManager (Singleton)
cpp
class InputManager {
static InputManager& getInstance();
// Actions (booléens)
void createAction(const std::string& name);
void bindKey(const std::string& action, Key key);
void bindMouseButton(const std::string& action, MouseButton btn);
bool isActionPressed(const std::string& action) const;
bool isActionJustPressed(const std::string& action) const;
bool isActionJustReleased(const std::string& action) const;
// Axes (valeurs -1, 0, +1)
void createAxis(const std::string& name, Key negative, Key positive);
float getAxis(const std::string& name) const;
// Touches directes
bool isKeyPressed(Key key) const;
bool isKeyJustPressed(Key key) const;
bool isKeyJustReleased(Key key) const;
bool isMouseButtonPressed(MouseButton btn) const;
// Souris
void getMousePosition(int& x, int& y) const;
// Cycle de mise à jour
void update();
// Backend
void setBackend(IInputBackend* backend);
};
class InputManager {
static InputManager& getInstance();
// Actions (booléens)
void createAction(const std::string& name);
void bindKey(const std::string& action, Key key);
void bindMouseButton(const std::string& action, MouseButton btn);
bool isActionPressed(const std::string& action) const;
bool isActionJustPressed(const std::string& action) const;
bool isActionJustReleased(const std::string& action) const;
// Axes (valeurs -1, 0, +1)
void createAxis(const std::string& name, Key negative, Key positive);
float getAxis(const std::string& name) const;
// Touches directes
bool isKeyPressed(Key key) const;
bool isKeyJustPressed(Key key) const;
bool isKeyJustReleased(Key key) const;
bool isMouseButtonPressed(MouseButton btn) const;
// Souris
void getMousePosition(int& x, int& y) const;
// Cycle de mise à jour
void update();
// Backend
void setBackend(IInputBackend* backend);
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Énumérations des Touches
cpp
enum class Key {
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
Escape, LControl, LShift, LAlt, LSystem, RControl, RShift, RAlt, RSystem,
Menu, LBracket, RBracket, Semicolon, Comma, Period, Quote, Slash, Backslash,
Tilde, Equal, Hyphen, Space, Return, Backspace, Tab, PageUp, PageDown,
End, Home, Insert, Delete, Add, Subtract, Multiply, Divide,
Left, Right, Up, Down, Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
Pause, ...
};
enum class MouseButton {
Left,
Right,
Middle,
XButton1,
XButton2
};
enum class Key {
A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
Num0, Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9,
Escape, LControl, LShift, LAlt, LSystem, RControl, RShift, RAlt, RSystem,
Menu, LBracket, RBracket, Semicolon, Comma, Period, Quote, Slash, Backslash,
Tilde, Equal, Hyphen, Space, Return, Backspace, Tab, PageUp, PageDown,
End, Home, Insert, Delete, Add, Subtract, Multiply, Divide,
Left, Right, Up, Down, Numpad0, Numpad1, Numpad2, Numpad3, Numpad4,
Numpad5, Numpad6, Numpad7, Numpad8, Numpad9,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15,
Pause, ...
};
enum class MouseButton {
Left,
Right,
Middle,
XButton1,
XButton2
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
Initialisation
1. Charger le Backend d'Entrée
cpp
#include "GameEngine/Graphic/Systems/Input_system.hpp"
#include "GameEngine/Graphic/Systems/InputManager.hpp"
// Charger backend (après avoir créé le backend graphique)
void* backendHandle = dlopen("./LibEngine/Backends/sfml_backend.so", RTLD_NOW);
auto get_input_backend = (input::IInputBackend* (*)(graphics::IGraphicsBackend*))
dlsym(backendHandle, "get_input_backend");
input::IInputBackend* inputBackend = get_input_backend(graphicsBackend);
// Configurer le manager
auto& inputMgr = input::InputManager::getInstance();
inputMgr.setBackend(inputBackend);
#include "GameEngine/Graphic/Systems/Input_system.hpp"
#include "GameEngine/Graphic/Systems/InputManager.hpp"
// Charger backend (après avoir créé le backend graphique)
void* backendHandle = dlopen("./LibEngine/Backends/sfml_backend.so", RTLD_NOW);
auto get_input_backend = (input::IInputBackend* (*)(graphics::IGraphicsBackend*))
dlsym(backendHandle, "get_input_backend");
input::IInputBackend* inputBackend = get_input_backend(graphicsBackend);
// Configurer le manager
auto& inputMgr = input::InputManager::getInstance();
inputMgr.setBackend(inputBackend);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
2. Enregistrer le Système ECS
cpp
void* inputHandle = dlopen("./LibEngine/Systems/input_system.so", RTLD_NOW);
auto register_input = (void(*)(registry&))
dlsym(inputHandle, "register_systems");
register_input(reg);
void* inputHandle = dlopen("./LibEngine/Systems/input_system.so", RTLD_NOW);
auto register_input = (void(*)(registry&))
dlsym(inputHandle, "register_systems");
register_input(reg);
1
2
3
4
5
6
2
3
4
5
6
3. Configurer les Contrôles
cpp
auto& inputMgr = input::InputManager::getInstance();
// ===== ACTIONS =====
// Mouvements
inputMgr.createAction("MoveUp");
inputMgr.bindKey("MoveUp", input::Key::Z);
inputMgr.bindKey("MoveUp", input::Key::Up);
inputMgr.createAction("MoveDown");
inputMgr.bindKey("MoveDown", input::Key::S);
inputMgr.bindKey("MoveDown", input::Key::Down);
inputMgr.createAction("MoveLeft");
inputMgr.bindKey("MoveLeft", input::Key::Q);
inputMgr.bindKey("MoveLeft", input::Key::Left);
inputMgr.createAction("MoveRight");
inputMgr.bindKey("MoveRight", input::Key::D);
inputMgr.bindKey("MoveRight", input::Key::Right);
// Actions
inputMgr.createAction("Shoot");
inputMgr.bindKey("Shoot", input::Key::Space);
inputMgr.bindMouseButton("Shoot", input::MouseButton::Left);
inputMgr.createAction("Pause");
inputMgr.bindKey("Pause", input::Key::Escape);
inputMgr.createAction("Sprint");
inputMgr.bindKey("Sprint", input::Key::LShift);
// ===== AXES =====
// Déplacement horizontal
inputMgr.createAxis("Horizontal", input::Key::Q, input::Key::D);
// Déplacement vertical
inputMgr.createAxis("Vertical", input::Key::S, input::Key::Z);
std::cout << "✓ Contrôles configurés" << std::endl;
auto& inputMgr = input::InputManager::getInstance();
// ===== ACTIONS =====
// Mouvements
inputMgr.createAction("MoveUp");
inputMgr.bindKey("MoveUp", input::Key::Z);
inputMgr.bindKey("MoveUp", input::Key::Up);
inputMgr.createAction("MoveDown");
inputMgr.bindKey("MoveDown", input::Key::S);
inputMgr.bindKey("MoveDown", input::Key::Down);
inputMgr.createAction("MoveLeft");
inputMgr.bindKey("MoveLeft", input::Key::Q);
inputMgr.bindKey("MoveLeft", input::Key::Left);
inputMgr.createAction("MoveRight");
inputMgr.bindKey("MoveRight", input::Key::D);
inputMgr.bindKey("MoveRight", input::Key::Right);
// Actions
inputMgr.createAction("Shoot");
inputMgr.bindKey("Shoot", input::Key::Space);
inputMgr.bindMouseButton("Shoot", input::MouseButton::Left);
inputMgr.createAction("Pause");
inputMgr.bindKey("Pause", input::Key::Escape);
inputMgr.createAction("Sprint");
inputMgr.bindKey("Sprint", input::Key::LShift);
// ===== AXES =====
// Déplacement horizontal
inputMgr.createAxis("Horizontal", input::Key::Q, input::Key::D);
// Déplacement vertical
inputMgr.createAxis("Vertical", input::Key::S, input::Key::Z);
std::cout << "✓ Contrôles configurés" << std::endl;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Utilisation Courante
Actions (Booléens)
Vérifier si une Action est Pressée
cpp
auto& inputMgr = input::InputManager::getInstance();
if (inputMgr.isActionPressed("Shoot")) {
// Tir en continu tant que la touche est maintenue
shootTimer += deltaTime;
if (shootTimer > fireRate) {
spawnBullet();
shootTimer = 0.f;
}
}
auto& inputMgr = input::InputManager::getInstance();
if (inputMgr.isActionPressed("Shoot")) {
// Tir en continu tant que la touche est maintenue
shootTimer += deltaTime;
if (shootTimer > fireRate) {
spawnBullet();
shootTimer = 0.f;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Vérifier si une Action Vient d'être Pressée
cpp
if (inputMgr.isActionJustPressed("Jump")) {
// Déclenché UNE SEULE FOIS au moment du pressage
player.jump();
}
if (inputMgr.isActionJustPressed("Pause")) {
pauseGame();
}
if (inputMgr.isActionJustPressed("Jump")) {
// Déclenché UNE SEULE FOIS au moment du pressage
player.jump();
}
if (inputMgr.isActionJustPressed("Pause")) {
pauseGame();
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Vérifier si une Action Vient d'être Relâchée
cpp
if (inputMgr.isActionJustReleased("Charge")) {
// Le joueur a relâché le bouton après une charge
releaseChargedAttack();
}
if (inputMgr.isActionJustReleased("Charge")) {
// Le joueur a relâché le bouton après une charge
releaseChargedAttack();
}
1
2
3
4
2
3
4
Axes (Valeurs Continues)
Axe Simple (Déplacement)
cpp
// Retourne -1 (négatif appuyé), 0 (rien), ou +1 (positif appuyé)
float horizontalAxis = inputMgr.getAxis("Horizontal");
float verticalAxis = inputMgr.getAxis("Vertical");
// Appliquer le mouvement
auto& transforms = reg.get_components<component::transform>();
auto* playerT = transforms.get_ptr(playerEntity);
if (playerT) {
playerT->_x += horizontalAxis * moveSpeed * deltaTime;
playerT->_y += verticalAxis * moveSpeed * deltaTime;
}
// Retourne -1 (négatif appuyé), 0 (rien), ou +1 (positif appuyé)
float horizontalAxis = inputMgr.getAxis("Horizontal");
float verticalAxis = inputMgr.getAxis("Vertical");
// Appliquer le mouvement
auto& transforms = reg.get_components<component::transform>();
auto* playerT = transforms.get_ptr(playerEntity);
if (playerT) {
playerT->_x += horizontalAxis * moveSpeed * deltaTime;
playerT->_y += verticalAxis * moveSpeed * deltaTime;
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Normaliser la Diagonale
cpp
float h = inputMgr.getAxis("Horizontal");
float v = inputMgr.getAxis("Vertical");
// Éviter le boost diagonal
if (h != 0.f && v != 0.f) {
float magnitude = std::sqrt(h*h + v*v);
h /= magnitude;
v /= magnitude;
}
velocity.x = h * moveSpeed;
velocity.y = v * moveSpeed;
float h = inputMgr.getAxis("Horizontal");
float v = inputMgr.getAxis("Vertical");
// Éviter le boost diagonal
if (h != 0.f && v != 0.f) {
float magnitude = std::sqrt(h*h + v*v);
h /= magnitude;
v /= magnitude;
}
velocity.x = h * moveSpeed;
velocity.y = v * moveSpeed;
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Touches Directes (Sans Actions)
cpp
// Vérifier une touche individuelle
if (inputMgr.isKeyPressed(input::Key::F1)) {
toggleDebugMode();
}
if (inputMgr.isKeyJustPressed(input::Key::Escape)) {
openPauseMenu();
}
if (inputMgr.isKeyJustReleased(input::Key::Return)) {
submitMenuOption();
}
// Vérifier une touche individuelle
if (inputMgr.isKeyPressed(input::Key::F1)) {
toggleDebugMode();
}
if (inputMgr.isKeyJustPressed(input::Key::Escape)) {
openPauseMenu();
}
if (inputMgr.isKeyJustReleased(input::Key::Return)) {
submitMenuOption();
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Souris
cpp
// Position souris
int mouseX, mouseY;
inputMgr.getMousePosition(mouseX, mouseY);
// Boutons souris
if (inputMgr.isMouseButtonPressed(input::MouseButton::Left)) {
fireAtMousePosition(mouseX, mouseY);
}
if (inputMgr.isMouseButtonJustPressed(input::MouseButton::Right)) {
openContextMenu(mouseX, mouseY);
}
// Position souris
int mouseX, mouseY;
inputMgr.getMousePosition(mouseX, mouseY);
// Boutons souris
if (inputMgr.isMouseButtonPressed(input::MouseButton::Left)) {
fireAtMousePosition(mouseX, mouseY);
}
if (inputMgr.isMouseButtonJustPressed(input::MouseButton::Right)) {
openContextMenu(mouseX, mouseY);
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Cycle de Mise à Jour
Où Appeler update() ?
L'InputSystem appelle automatiquement inputMgr.update() à chaque frame via le registre ECS :
cpp
while (backend->isOpen()) {
// Votre logique de jeu
// Le système ECS s'exécute (Input System inclus)
reg.run_systems(); // ← update() appelé ici
}
while (backend->isOpen()) {
// Votre logique de jeu
// Le système ECS s'exécute (Input System inclus)
reg.run_systems(); // ← update() appelé ici
}
1
2
3
4
5
6
2
3
4
5
6
Ou manuellement si vous n'utilisez pas run_systems() :
cpp
while (backend->isOpen()) {
// Événements
backend->pollEvents();
// Mise à jour input
inputMgr.update(); // ← Important pour just pressed/released
// Logique
updateGame();
// Rendu
render();
}
while (backend->isOpen()) {
// Événements
backend->pollEvents();
// Mise à jour input
inputMgr.update(); // ← Important pour just pressed/released
// Logique
updateGame();
// Rendu
render();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Configuration Avancée
Rebinding Dynamique
cpp
// Permettre au joueur de reconfigurer ses contrôles
void rebindKey(const std::string& action, input::Key newKey) {
auto& inputMgr = input::InputManager::getInstance();
// Enlever tous les anciens bindings
// (Note: API complète dépend de l'implémentation)
// Ajouter le nouveau
inputMgr.bindKey(action, newKey);
}
// Utilisation
if (userSelectsRebindMenu) {
rebindKey("Shoot", input::Key::W);
}
// Permettre au joueur de reconfigurer ses contrôles
void rebindKey(const std::string& action, input::Key newKey) {
auto& inputMgr = input::InputManager::getInstance();
// Enlever tous les anciens bindings
// (Note: API complète dépend de l'implémentation)
// Ajouter le nouveau
inputMgr.bindKey(action, newKey);
}
// Utilisation
if (userSelectsRebindMenu) {
rebindKey("Shoot", input::Key::W);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Gamepads (Future Extension)
Actuellement supporté :
- Clavier
- Souris
Extensible pour :
- Gamepads/Manettes
- Joysticks
- Manettes Xbox/PlayStation
cpp
// Futur
inputMgr.createAxis("StickHorizontal", GamepadAxis::LeftX);
inputMgr.createAction("ButtonA");
inputMgr.bindGamepadButton("ButtonA", GamepadButton::A);
// Futur
inputMgr.createAxis("StickHorizontal", GamepadAxis::LeftX);
inputMgr.createAction("ButtonA");
inputMgr.bindGamepadButton("ButtonA", GamepadButton::A);
1
2
3
4
2
3
4
Combos (Entrées Multiples)
cpp
struct InputCombo {
std::string name;
std::vector<std::string> sequence;
float timeWindow;
float timeSinceLastInput;
};
// Système de combo personnalisé
if (inputMgr.isActionJustPressed("Punch")) {
// Ajouter à la séquence
comboSequence.push_back("Punch");
comboTimer = timeWindow;
}
if (inputMgr.isActionJustPressed("Kick")) {
comboSequence.push_back("Kick");
comboTimer = timeWindow;
}
// Vérifier pattern
if (comboSequence.size() >= 3 &&
comboSequence[0] == "Punch" &&
comboSequence[1] == "Punch" &&
comboSequence[2] == "Kick") {
executeSpecialMove();
comboSequence.clear();
}
struct InputCombo {
std::string name;
std::vector<std::string> sequence;
float timeWindow;
float timeSinceLastInput;
};
// Système de combo personnalisé
if (inputMgr.isActionJustPressed("Punch")) {
// Ajouter à la séquence
comboSequence.push_back("Punch");
comboTimer = timeWindow;
}
if (inputMgr.isActionJustPressed("Kick")) {
comboSequence.push_back("Kick");
comboTimer = timeWindow;
}
// Vérifier pattern
if (comboSequence.size() >= 3 &&
comboSequence[0] == "Punch" &&
comboSequence[1] == "Punch" &&
comboSequence[2] == "Kick") {
executeSpecialMove();
comboSequence.clear();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Exemples Pratiques
Jeu de Type Shoot'em Up (R-Type)
cpp
auto& inputMgr = input::InputManager::getInstance();
// Configuration
inputMgr.createAction("MoveUp");
inputMgr.createAction("MoveDown");
inputMgr.createAction("MoveLeft");
inputMgr.createAction("MoveRight");
inputMgr.createAction("Shoot");
// Bindage
inputMgr.bindKey("MoveUp", input::Key::Z);
inputMgr.bindKey("MoveDown", input::Key::S);
inputMgr.bindKey("MoveLeft", input::Key::Q);
inputMgr.bindKey("MoveRight", input::Key::D);
inputMgr.bindKey("Shoot", input::Key::Space);
// Dans la boucle de jeu
while (backend->isOpen()) {
auto& transforms = reg.get_components<component::transform>();
auto* playerT = transforms.get_ptr(playerEntity);
if (playerT) {
// Déplacement
const float speed = 300.f;
if (inputMgr.isActionPressed("MoveUp")) {
playerT->_y -= speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveDown")) {
playerT->_y += speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveLeft")) {
playerT->_x -= speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveRight")) {
playerT->_x += speed * deltaTime;
}
// Tir automatique
if (inputMgr.isActionPressed("Shoot")) {
shootTimer += deltaTime;
if (shootTimer >= shootInterval) {
spawnBullet(reg, playerT->_x, playerT->_y);
shootTimer = 0.f;
}
}
}
reg.run_systems();
}
auto& inputMgr = input::InputManager::getInstance();
// Configuration
inputMgr.createAction("MoveUp");
inputMgr.createAction("MoveDown");
inputMgr.createAction("MoveLeft");
inputMgr.createAction("MoveRight");
inputMgr.createAction("Shoot");
// Bindage
inputMgr.bindKey("MoveUp", input::Key::Z);
inputMgr.bindKey("MoveDown", input::Key::S);
inputMgr.bindKey("MoveLeft", input::Key::Q);
inputMgr.bindKey("MoveRight", input::Key::D);
inputMgr.bindKey("Shoot", input::Key::Space);
// Dans la boucle de jeu
while (backend->isOpen()) {
auto& transforms = reg.get_components<component::transform>();
auto* playerT = transforms.get_ptr(playerEntity);
if (playerT) {
// Déplacement
const float speed = 300.f;
if (inputMgr.isActionPressed("MoveUp")) {
playerT->_y -= speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveDown")) {
playerT->_y += speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveLeft")) {
playerT->_x -= speed * deltaTime;
}
if (inputMgr.isActionPressed("MoveRight")) {
playerT->_x += speed * deltaTime;
}
// Tir automatique
if (inputMgr.isActionPressed("Shoot")) {
shootTimer += deltaTime;
if (shootTimer >= shootInterval) {
spawnBullet(reg, playerT->_x, playerT->_y);
shootTimer = 0.f;
}
}
}
reg.run_systems();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
Jeu Puzzle avec Axes
cpp
auto& inputMgr = input::InputManager::getInstance();
inputMgr.createAxis("Horizontal", input::Key::Left, input::Key::Right);
inputMgr.createAxis("Vertical", input::Key::Down, input::Key::Up);
inputMgr.createAction("Interact");
inputMgr.bindKey("Interact", input::Key::Return);
while (backend->isOpen()) {
float h = inputMgr.getAxis("Horizontal");
float v = inputMgr.getAxis("Vertical");
// Déplacer le curseur/sélection
if (h != 0.f || v != 0.f) {
gridX += (int)h;
gridY += (int)v;
gridX = std::clamp(gridX, 0, 9);
gridY = std::clamp(gridY, 0, 9);
}
// Interagir
if (inputMgr.isActionJustPressed("Interact")) {
selectTile(gridX, gridY);
}
reg.run_systems();
}
auto& inputMgr = input::InputManager::getInstance();
inputMgr.createAxis("Horizontal", input::Key::Left, input::Key::Right);
inputMgr.createAxis("Vertical", input::Key::Down, input::Key::Up);
inputMgr.createAction("Interact");
inputMgr.bindKey("Interact", input::Key::Return);
while (backend->isOpen()) {
float h = inputMgr.getAxis("Horizontal");
float v = inputMgr.getAxis("Vertical");
// Déplacer le curseur/sélection
if (h != 0.f || v != 0.f) {
gridX += (int)h;
gridY += (int)v;
gridX = std::clamp(gridX, 0, 9);
gridY = std::clamp(gridY, 0, 9);
}
// Interagir
if (inputMgr.isActionJustPressed("Interact")) {
selectTile(gridX, gridY);
}
reg.run_systems();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Menu de Jeu
cpp
enum MenuOption { PLAY, SETTINGS, QUIT };
MenuOption currentOption = PLAY;
while (backend->isOpen()) {
if (inputMgr.isActionJustPressed("MoveUp")) {
currentOption = (MenuOption)((currentOption - 1 + 3) % 3);
}
if (inputMgr.isActionJustPressed("MoveDown")) {
currentOption = (MenuOption)((currentOption + 1) % 3);
}
if (inputMgr.isActionJustPressed("Shoot")) { // Select
switch (currentOption) {
case PLAY:
startGame();
break;
case SETTINGS:
openSettings();
break;
case QUIT:
backend->close();
break;
}
}
renderMenu(currentOption);
reg.run_systems();
}
enum MenuOption { PLAY, SETTINGS, QUIT };
MenuOption currentOption = PLAY;
while (backend->isOpen()) {
if (inputMgr.isActionJustPressed("MoveUp")) {
currentOption = (MenuOption)((currentOption - 1 + 3) % 3);
}
if (inputMgr.isActionJustPressed("MoveDown")) {
currentOption = (MenuOption)((currentOption + 1) % 3);
}
if (inputMgr.isActionJustPressed("Shoot")) { // Select
switch (currentOption) {
case PLAY:
startGame();
break;
case SETTINGS:
openSettings();
break;
case QUIT:
backend->close();
break;
}
}
renderMenu(currentOption);
reg.run_systems();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
État des Touches
État Complet d'une Touche
Avant : [Relâché]
|
↓
[Espace] Pressé → [isKeyJustPressed = true]
|
↓
Pendant : [Appuyé] → [isKeyPressed = true]
(frames suivantes)
|
↓
[Espace] Relâché → [isKeyJustReleased = true]
|
↓
Après : [Relâché] → [isKeyPressed = false]
Avant : [Relâché]
|
↓
[Espace] Pressé → [isKeyJustPressed = true]
|
↓
Pendant : [Appuyé] → [isKeyPressed = true]
(frames suivantes)
|
↓
[Espace] Relâché → [isKeyJustReleased = true]
|
↓
Après : [Relâché] → [isKeyPressed = false]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Exemple Temporel
Frame 1 : Utilisateur appuie
- isKeyJustPressed() → TRUE
- isKeyPressed() → TRUE
Frame 2 : Utilisateur maintient
- isKeyJustPressed() → FALSE
- isKeyPressed() → TRUE
Frame 3 : Utilisateur maintient
- isKeyJustPressed() → FALSE
- isKeyPressed() → TRUE
Frame 4 : Utilisateur relâche
- isKeyJustReleased() → TRUE
- isKeyPressed() → FALSE
Frame 5 : Touche relâchée
- isKeyJustReleased() → FALSE
- isKeyPressed() → FALSE
Frame 1 : Utilisateur appuie
- isKeyJustPressed() → TRUE
- isKeyPressed() → TRUE
Frame 2 : Utilisateur maintient
- isKeyJustPressed() → FALSE
- isKeyPressed() → TRUE
Frame 3 : Utilisateur maintient
- isKeyJustPressed() → FALSE
- isKeyPressed() → TRUE
Frame 4 : Utilisateur relâche
- isKeyJustReleased() → TRUE
- isKeyPressed() → FALSE
Frame 5 : Touche relâchée
- isKeyJustReleased() → FALSE
- isKeyPressed() → FALSE
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
🔧 Debugging
Afficher l'État des Entrées
cpp
// En développement
if (inputMgr.isKeyPressed(input::Key::F1)) {
std::cout << "=== INPUT DEBUG ===" << std::endl;
std::cout << "MoveUp: " << inputMgr.isActionPressed("MoveUp") << std::endl;
std::cout << "Shoot: " << inputMgr.isActionPressed("Shoot") << std::endl;
std::cout << "Horizontal: " << inputMgr.getAxis("Horizontal") << std::endl;
int mx, my;
inputMgr.getMousePosition(mx, my);
std::cout << "Mouse: (" << mx << ", " << my << ")" << std::endl;
}
// En développement
if (inputMgr.isKeyPressed(input::Key::F1)) {
std::cout << "=== INPUT DEBUG ===" << std::endl;
std::cout << "MoveUp: " << inputMgr.isActionPressed("MoveUp") << std::endl;
std::cout << "Shoot: " << inputMgr.isActionPressed("Shoot") << std::endl;
std::cout << "Horizontal: " << inputMgr.getAxis("Horizontal") << std::endl;
int mx, my;
inputMgr.getMousePosition(mx, my);
std::cout << "Mouse: (" << mx << ", " << my << ")" << std::endl;
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Logger les Événements
cpp
void logInputEvent(const std::string& eventType, const std::string& key) {
std::cout << "[INPUT] " << eventType << ": " << key << std::endl;
}
if (inputMgr.isActionJustPressed("Shoot")) {
logInputEvent("PRESSED", "Shoot");
}
if (inputMgr.isActionJustReleased("Charge")) {
logInputEvent("RELEASED", "Charge");
}
void logInputEvent(const std::string& eventType, const std::string& key) {
std::cout << "[INPUT] " << eventType << ": " << key << std::endl;
}
if (inputMgr.isActionJustPressed("Shoot")) {
logInputEvent("PRESSED", "Shoot");
}
if (inputMgr.isActionJustReleased("Charge")) {
logInputEvent("RELEASED", "Charge");
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
Référence Complète
Méthodes Actions
| Méthode | Retour | Description |
|---|---|---|
createAction(name) | void | Créer une nouvelle action |
bindKey(action, key) | void | Lier une touche à une action |
bindMouseButton(action, btn) | void | Lier un bouton souris |
isActionPressed(name) | bool | Action maintenue ? |
isActionJustPressed(name) | bool | Action vient d'être pressée ? |
isActionJustReleased(name) | bool | Action vient d'être relâchée ? |
Méthodes Axes
| Méthode | Retour | Description |
|---|---|---|
createAxis(name, neg, pos) | void | Créer un axe |
getAxis(name) | float | Obtenir valeur (-1, 0, +1) |
Touches Directes
| Méthode | Retour | Description |
|---|---|---|
isKeyPressed(key) | bool | Touche maintenue ? |
isKeyJustPressed(key) | bool | Touche vient d'être pressée ? |
isKeyJustReleased(key) | bool | Touche vient d'être relâchée ? |
isMouseButtonPressed(btn) | bool | Bouton souris appuyé ? |
Souris
| Méthode | Retour | Description |
|---|---|---|
getMousePosition(x, y) | void | Obtenir position |
Bonnes Pratiques
- Créer des actions sémantiques : Utiliser des noms logiques ("Shoot" plutôt que "Space")
- Multi-binding : Permettre plusieurs touches pour une action (ZQSD + Flèches)
- Appeler update() : Ne pas oublier à chaque frame
- Just vs Pressed : Utiliser
JustPressedpour les événements,Pressedpour l'effet continu - Normaliser les diagonales : Pour les axes en 2D
- Rebinding : Offrir la possibilité aux joueurs de modifier les contrôles
- Feedback : Vibrations/son pour confirmer les entrées