Input
We will now explain how to access user input (mouse or keyboard), and how to use it in your project easily.
Gamepad support is scheduled for a future release, and is not made available by batFramework. However it is possible to use the pygame events for gamepad (as any other pygame event).
What is an action
Actions are a structure used to represent an 'action' that can be triggered by any user input. It is then possible to assign one or more mouse and/or keyboard events as triggers for any specific action.
Each action holds a value (in a majority of cases a boolean) that represents if the action is active.
We might want the player to jump by pressing the <UP> directional key, but also the <W> key on the keyboard.
bf.Action("jump").add_key_control(pygame.K_UP, pygame.K_w)
Why not use events
It is indeed possible to manage input directly with if statements, however this can cause issues in larger projects, as well as hinder code readability.
keys = pygame.key.get_pressed()
if keys[pygame.K_w] or keys[pygame.K_UP]:
jump()
By referring to what you want the player to do with an action like 'jump', it is far more legible and easier to manage than pygame.K_SPACE or pygame.K_w. It also makes remapping easy.
jump_action = bf.Action("jump").add_key_control(pygame.K_UP, pygame.K_w)
if jump_action: # or jump_action.active
jump()
How to use Actions
Create an action with:
bf.Action("name")
Assigning controls
You can assign input methods using add_<type>_control() where <type> can be key, mouse, or event.
You can combine different input methods on a single action.
Keyboard
bf.Action("test").add_key_control(pygame.K_UP, pygame.K_w)
Mouse
bf.Action("test").add_mouse_control(1)
When the argument for add_mouse_control is an integer, it refers to the mouse button mappings from pygame-ce.
Events
It is possible to use event types directly as triggers for an action. In pygame-ce all event types are integers.
bf.Action("quit").add_event_control(pygame.QUIT)
Trigger type
Instantaneous
Default. Active for one frame when the key/button is pressed, then cleared on reset().
bf.Action("confirm").set_instantaneous()
Holding
Stays active while the key/button is held down, and deactivates on release.
bf.Action("run").set_holding()
Continuous
Similar to holding for sustained input; use when you need continuous activation semantics.
bf.Action("move").set_continuous()
Lifecycle
When an action is created it has to be managed, either manually or automatically. Each frame:
- Call
process_event(event)for incoming events - Read the action's active state (
action.active, oractions.is_active("name")) between process and reset - Call
reset()to clear instantaneous state
Scenes already do this for self.actions and self.early_actions.
Example
Here's a scene using actions to change the background color:
import batFramework as bf
import pygame
class MyScene(bf.Scene):
def do_when_added(self):
self.add_actions(
bf.Action("change_color").add_key_control(pygame.K_SPACE)
)
self.set_clear_color("black")
def do_update(self, dt):
if self.actions.is_active("change_color"):
self.set_clear_color(bf.utils.random_color())
bf.init((640, 480))
bf.Manager(MyScene("main")).run()
Prefer scene.add_actions(...) / scene.add_early_actions(...) so the scene processes and resets them for you.