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

Text 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

Text 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.

Accepting a text input from the user is rather tricky in ASCII games - this is one of those quirks that needs to be worked out. The obvious problem here is the fact that we render the game on the same terminal from which we have to read the keyboard user input. When you work in the terminal - most of the time you work via command line shells (like sh, ws, fish, zsh, etc.) which provides such functionality for cursor movements, Backspace and Del key handling, Tab focus movements, etc.

In CosPlay one could implement all this support in a special sprite as well. To make the handling of the user input easy out-of-the-box, CosPlay comes with built-in CPTextInputSprite sprite that implements a comprehensive functionality for accepting user keyboard input.

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.

CPTextInputSprite

The CPTextInputSprite sprite acts as a classic input field: user can input text using keyboard and cursor keys. It supports different field and buffer lengths, skinning input (e.g. for the password field) as well as user-defined set of keys for submission and cancellation. You can also chain multiple text inputs together to create an auto-navigable forms. Note that this sprite works only with system font - you can't use FIGLeft fonts with this sprite.

CPTextInputSprite sprite works only with system font.

To understand the API of CPTextInputSprite sprite let's look at the full example of implementing a standard login dialog that prompts the user to enter the username and password:

            import org.cosplay.*
            import CPColor.*
            import CPPixel.*
            import CPFIGLetFont.*
            import CPKeyboardKey.*
            import CPStyledString.styleStr
            import examples.utils.*
            import prefabs.shaders.*

            object LoginDialog:
                def main(args: Array[String]): Unit =
                    val termDim = CPDim(100, 40)

                    def mkSkin(active: Boolean, passwd: Boolean): (Char, Int, Boolean) => CPPixel =
                        (ch: Char, pos: Int, isCur: Boolean) => {
                            val ch2 = if passwd && !ch.isWhitespace then '*' else ch
                            if active then
                                if isCur then ch2&&(C_WHITE, C_SLATE_BLUE3)
                                else ch2&&(C_BLACK, C_WHITE)
                            else ch2&&(C_BLACK, C_WHITE.darker(0.3f))
                        }

                    val userLbl = new CPLabelSprite(6, 4, 1, text = "Username:", C_LIGHT_STEEL_BLUE)
                    val userTin = CPTextInputSprite("user", 6, 5, 1,
                        15, 20,
                        "",
                        mkSkin(true, false),
                        mkSkin(false, false),
                        submitKeys = Seq(KEY_ENTER, KEY_TAB),
                        next = Option("passwd")
                    )
                    val pwdLbl = new CPLabelSprite(6, 7, 1, text = "Password:", C_LIGHT_STEEL_BLUE)
                    val pwdTin = CPTextInputSprite("passwd", 6, 8, 1,
                        15, 20,
                        "",
                        mkSkin(true, true),
                        mkSkin(false, true),
                        submitKeys = Seq(KEY_ENTER, KEY_TAB),
                        next = Option("user")
                    )
                    val panel = CPPanelSprite(2, 2, 24, 11, 0, "Login")
                    val focusAcq = CPOffScreenSprite(ctx ⇒ if ctx.getSceneFrameCount == 0 then ctx.acquireFocus("user"))

                    val bgPx = '.'&&(C_GRAY2, C_GRAY1)
                    val sc = new CPScene("scene", Option(CPDim(27, 13)), bgPx,
                        userLbl, userTin, pwdLbl, pwdTin, panel, focusAcq
                    )

                    // Initialize the engine.
                    CPEngine.init(
                        CPGameInfo(name = "Login Dialog", initDim = Option(termDim)),
                        System.console() == null || args.contains("emuterm")
                    )

                    // Start the game & wait for exit.
                    try CPEngine.startGame(sc)
                    finally CPEngine.dispose()

                    sys.exit(0)
        

NOTE:

  • This example follows the standard game organization: game entry point on the line 11, game engine is initialized on the line 50, game starts on the line 56.
  • CPTextInputSprite sprites are created on the line 24 and 33 for username and password input fields.
  • Both text input sprites are configured similarly with Enter and Tab keys acting as submission keys and default Esc acting as a cancellation key. Apart from the screen positions these two sprites only differ in skinning: password input renders all input as '*'.
  • Notice that both input field sprites are configured in a loop: submitting username moves the keyboard focus to the password field and submitting password moves the keyboard focus to username field. In real life situation this logic will likely be different.
  • On the line 42 we use an off-screen sprite to detect the start of the scene to assign the initial keyboard focus to username field.
  • On lines 23 and 33 we use CPLabelSprite sprite that provides convenient way to create simple text label with system font.
  • Note that we use CPPanelSprite utility sprite on the line 41 that is part of examples. It draws a simple panel with a titled border.

When you run this example (see a similar built-in example) you will get the following output:

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