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:
*.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:
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:
CPSceneObjectContext.getKbevent()
method.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 _ => ()
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.
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:
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.