• Docs
  • Install
  • Follow @cosplayengine
  • v.0.9.5
  • GitHub
  • Watch
  • Examples
  1. Home
  2. Keyboard Input

Keyboard Input

  • Introduction
  • Install
  • ASCII Games
  • Demos
  • Examples
  • Macarena
  • Pong
  • Snake
  • Bird
  • Developer Guide
  • Quick Game 🏃
  • Key Concepts
  • Game Structure
  • Scenes & Objects
  • Log & Debugging
  • Pixels & Colors
  • Images
  • Keyboard Input
  • Sprite Animation
  • Shaders
  • Particle Effects
  • Fonts
  • Canvas Drawing
  • Text Input
  • Camera Tracking
  • Tile Mapping
  • Audio
  • Video
  • UI Toolkit
  • Build & Run

Keyboard Input

In-Game Shortcuts

While in game you can use the following reserved keyboard shortcuts. Note that these keys are NOT available to the game itself as they are intercepted and processed by the game engine itself:

  • Ctrl+Q - to toggle in-game FPS overlay.
  • Ctrl+L - to open GUI-based log viewer & debugger.
  • F12 - to take the screenshot in REXPaint *.xp format saved in the current folder.

Handling keyboard input is one of the areas that significantly differs from traditional game development. Most of the quirks discussed below are specific to the native ASCII games only.

The way that graphics games read player input is very different from the way the ANSI terminal reads its keyboard input. Native ASCII games do not have direct access to the keyboard due to compatibility issues with various ANSI terminals. These games can only rely on standard ANSI sequences to read keyboard input which comes with some limitations.

First of all, only certain combination of keys are detected and returned as ANSI sequences and thus available to the CosPlay. In particular, Option and Alt control keys are universally ignored by the ANSI terminals. Also, many combinations share the same return code: for example, Ctrl+M and Enter return the same ANSI code 0x000D in which case CosPlay makes a unilateral decision to return Enter key ignoring Ctrl+M choice all together. That makes Ctrl+M key press technically unavailable to CosPlay games.

See CPKeyboardKey type for the list of detectable and available keyboard keys.

Remapped Keys

The following keystrokes are automatically re-mapped:

  • Ctrl+H is mapped to Backspace
  • Ctrl+I is mapped to Tab
  • Ctrl+M is mapped to Enter

NOTE: Ctrl+h, Ctrl+i and Ctrl+m will not be detected as-is, and you should use their conversions instead. Note that even-though CPKeyboardKey provides constants these keys they will never be returned to the scene objects since they would always be automatically remapped. This is an inherent limitation of the ANSI terminals.

Secondly, the speed with which the terminal read the keyboard input and makes it available to the CosPlay is dependent on the particular terminal and OS preferences such as repeated keystroke delay, etc. Repeated key presses are also detected differently by different terminals. See CPKeyboardEvent type for API details on how to handle repeated key presses.

Thirdly, and this is probably the most unexpected side effect, is the fact ANSI terminals do not detect more than one key pressed at a time. For example, if the player presses Space and keeps holding it (e.g. shooting enemies) - no other key presses will be detected until the player releases the Space key. What this means is that it is impossible to implement combined actions like moving and shooting in the same time by solely relying on the keyboard events. This is one of the most serious limitations in native ASCII games.

Keyboard event is defined by CPKeyboardEvent trait:

  • Keyboard event can be obtained on each frame update via CPSceneObjectContext.getKbevent() method.
    • Note that there is only one keyboard event per each frame update, if any.
  • Keyboard event contains an instance of CPKeyboardKey defining the keyboard key that was pressed.
  • Keyboard event contains other event properties like frame number, timestamp, etc.

Here's a typical pseudocode to check keyboard input on each frame update that can be used in any scene objects, sprites, etc. Keyboard input handling should happen in CPSceneObject.update(...) callback:

            ...
            override def update(ctx: CPSceneObjectContext): Unit =
                super.update(ctx) // Make sure to always call 'super' in callbacks.
                ctx.getKbEvent match
                    case Some(evt) =>
                        evt.key match
                            case KEY_LO_A | KEY_LEFT => moveLeft(...)
                            case KEY_LO_D | KEY_RIGHT => moveRight(...)
                            case KEY_LO_W | KEY_UP => moveUp(...)
                            case KEY_LO_S | KEY_DOWN => moveDown(...)
                            case _ => ()
        

Keyboard Sprite

It is often desirable to abstract out the keyboard handling into its own component. CPKeyboardSprite provides efficient and convenient scene object adapter to do just that. CPKeyboardSprite class extends CPOffScreenSprite making it invisible on the screen. Here is how our previous example can be written using CPKeyboardSprite:

            // Add this sprite to your scene.
            val kbSpr = CPKeyboardSprite((ctx, key) ⇒ key match
                case KEY_LO_A | KEY_LEFT => moveLeft(...)
                case KEY_LO_D | KEY_RIGHT => moveRight(...)
                case KEY_LO_W | KEY_UP => moveUp(...)
                case KEY_LO_S | KEY_DOWN => moveDown(...)
                case _ => ()
            )
        

You can also use this sprite's companion object to add quick handlers for a specific keyboard key. For example, this technique is used by many built-in examples to exit the game on Q press:

            // Add this sprite to your scene.
            val kbSpr = CPKeyboardSprite(_.exitGame(), KEY_LO_Q) // Exit the game on 'q' press.
        

External Devices

Although ASCII games use keyboard as a primary and often the only input device, CosPlay allows you to add any external devices that would emulate keyboard or would map their input into keyboard events. This support comes in a form of:

  • CPInput trait that defines the external input device.
  • CPInputContext trait that is passed to external device on per-frame polling.
  • Methods CPEngine.addInput(...) and CPEngine.removeInput(...) to register and unregister external devices in the game engine.

If the game engine has one or more external devices registered it will call method CPInput.poll(ctx) on each device on every frame update to poll these devices for input. If more than one external device produces an input event, the precedence of which event will be taken is undefined. Note that an event from external devices will override the event from the built-in keyboard input if happened in the same frame.

  • On This Page
  • Keyboard Input
  • Keyboard Sprite
  • External Devices
  • In-Game Shortcuts
  • Ctrl+Q FPS Overlay
  • Ctrl+L GUI Debugger
  • F12 REXPaint Screenshot
  • Quick Links
  • Discord
  • Stack Overflow
  • GitHub
  • @cosplayengine
  • YouTube
  • API
Copyright © 2023 Rowan Games, Inc. Privacy • Docs release: 0.9.5 Latest: