Skip to content

Tutorials · Crypt Knight · Chapter 5

The knight

30 minutes Uses: CharacterBody, Shape, direction, pressed, held, set_number, set_flag, jump, cut_jump

By the end

  • An input map of three actions: move on WASD and the arrow keys, jump on Space, and down on S and Down
  • The knight in the room, a crimson box until chapter 7 gives it its art, as a Character Body its script drives
  • A first script, knight.rgs, that runs it at 110 units a second, jumps it, jumps it lower when Space is let go early, and drops it through a ledge
  • The jump’s feel: how high, how forgiving, and why
On this page

Name the controls

A script never asks whether D is down. It asks about an action, a name such as move or jump, and the project’s input map says which keys run it. A player could then run with the arrows instead of WASD, and no script would change. Input has the whole of it.

  1. Choose View → Input map…. With no input map saved yet, the window starts on six actions of its own: left, right, up, down, jump and action. Select each of the six in turn and press Remove: your own replace them.
  2. Type move into New action and press Add.
  3. With move selected, press Add composite and choose WASD, then press Add composite again and choose Arrow keys. The list shows two Vector2 rows: W, S, A and D, and Up, Down, Left and Right.
  4. Add an action called jump, press Record a control, and press Space.
  5. Add an action called down, press Record a control, and press S. Press Record a control again, and press Down.
  6. Press Save. The window writes input.ron into the project, and you can close it.
The Input window with three actions, move, jump and down, and move selected: two Vector2 composites, one of W, S, A and D and one of the arrow keys Up, Down, Left and Right

A composite stands in for a stick: four keys read as one direction, which a script gets as a vector. With two composites on move, either set of keys runs the knight.

The Input window with down selected, bound to S and to Down, each as a Press, and the window’s warnings that move and down share S and Down

A body in the room

The knight is a node with a Character Body: a box that falls under gravity, stands on solid ground, is stopped by walls, and jumps. Its Shape, a coloured rectangle, shows where it is until it has art. Both come from one preset.

  1. Select Gate, press + Add node, and choose Character. Rename it knight.
  2. Set its Position to 72 and 160: a little way in from the left wall, standing on the start floor, whose top is at y 160. A body’s position is where its feet are.
  3. In its CharacterBody, set Size to 12 and 30, and Driven By to Script. Leave Motion Mode on Grounded.
  4. Set Gravity to 900, Terminal Velocity to 400 and Jump Speed to 295. Leave Speed at 220: a body driven by a script is never run at it.
  5. In its Jumping fold, set Coyote Time to 0.1, Jump Buffer to 0.1 and Jump Cut to 0.5, and leave Air Jumps at 0.
  6. In its Shape, keep Kind on Rectangle, set Size to 12 and 30, Anchor to 0.5 and 1, and Outline to 0, so the box stands on the node’s position with its feet.
  7. Set the Shape’s Color to a crimson, 0.6, 0.01, 0.04, alpha 1, and its Sort Layer to 5, so it draws over the ground, which is at 0.
The knight selected, its Inspector narrowed to its CharacterBody: Size 12 by 30, Motion Mode Grounded, Driven By Script, Gravity 900, Terminal Velocity 400, Speed 220, Jump Speed 295, and in the Jumping fold Coyote Time 0.10, Jump Buffer 0.10, Jump Cut 0.50 and Air Jumps 0; in the Viewport the crimson Shape stands on the start floor inside the body’s pale green box, with a small square grab on each of the box’s top corners
The knight’s Inspector narrowed to its Shape: Kind Rectangle, Size 12 by 30, Anchor 0.5 and 1, a crimson Color, Outline 0 and Sort Layer Custom, 5
Driven By
Keys is the controller the engine ships: A and D or the arrows walk the body and Space jumps it. Script leaves all of that to the body’s own script, which sets its sideways speed and asks for its jumps. The knight is driven by its script, and so, later, are the enemies and the boss.
Size
The body’s box, 12 by 30 world units, and smaller than the 38 by 48 art it gets in chapter 7: the box is what walls and floors see, so a cape may brush a wall.
Gravity, Terminal Velocity and Jump Speed
How hard the world pulls the knight down, in units a second each second, how fast it may fall, and how fast a jump throws it up. Together they make a held jump rise about 48 units, three cells, in theory, and about 46 in the game, which steps in sixtieths of a second.
Coyote Time
Seconds after running off a ledge in which a jump still counts, as if from the ground. Without it, the jump that comes a hair late is the one the player blames.
Jump Buffer
Seconds a jump asked for just before landing waits to happen on landing: a press a moment early is still a jump.
Jump Cut
How much of the upward speed is kept when the jump is let go early. At 1 all of it, so Space only starts a jump; at 0.5, half, so a tap rises about a quarter as high as a held jump.

The knight’s script

Rengy Script is a small language for what happens in a game. A script is one component: its fields are rows in the Inspector, and its hooks run as the game does. Rengy Script covers the language; this chapter needs only what follows.

  1. In Assets, press Create, choose New script, type knight, and press Enter. The editor writes knight.rgs into the project folder.
  2. Click the Code tab above the Viewport, then knight.rgs in its Scripts list, which shows every script in the project.
  3. Replace everything in it with the script below, and press Ctrl+S. The panel says Up to date once the script checks.
rgs knight.rgs
/// The knight: runs where `move` points, jumps on `jump`, jumps lower when
/// `jump` is let go early, and drops through a ledge when `down` is held as it
/// jumps.
component Knight {
    /// How fast the knight runs.
    #[suffix("u/s")]
    speed: f32 = 110.0,

    fn loop() {
        set_number("CharacterBodyComponent", "velocity.x", direction("move").x * speed);
        let drop = pressed("jump") && held("down");
        set_flag("CharacterBodyComponent", "drop_through", drop);
        if pressed("jump") && !drop {
            jump();
        }
        if !held("jump") {
            cut_jump();
        }
    }
}
The Code panel open on knight.rgs, the Knight component’s twenty lines, with Up to date in its status line, and the Inspector showing the knight’s CharacterBody
component Knight and speed
The script is a component called Knight, and its file is named after it, in lower case: knight.rgs. speed is a field: a row in the Inspector with this default, 110 units a second. The /// line above it is its tooltip.
fn loop()
A hook: it runs on every step of the game, 60 a second. Everything the knight does, it does here.
direction and set_number
direction("move") is where the action points, as a vector with each part from -1 to 1; .x is the sideways half, -1 for A, 1 for D and 0 for neither. set_number writes a number into a field of one of this node’s components, here the Character Body’s sideways velocity, velocity.x. A body driven by a script keeps whatever speed its script last gave it.
pressed and held
pressed("jump") is true on the step Space goes down, once. held("jump") is true on every step it stays down.
jump
Asks the body for a jump. The body honours its Coyote Time and its Jump Buffer, and its Air Jumps: asking in the air after running off a ledge, or just before landing, still jumps.
cut_jump
If the body is rising from a jump that has not been cut, keeps the Jump Cut’s share of its upward speed. The script calls it on every step Space is not held, so letting go in mid-rise cuts the jump short, and on the ground it does nothing.
set_flag and drop_through
The Character Body’s Drop Through says to ignore one-way ledges while leaving one. The script turns it on for the step on which Space goes down with S or Down held, and then does not jump: the knight falls through the ledge instead.

A script’s write lands at the end of the step, as every script write does, so the knight jumps one step, a sixtieth of a second, after the press. That is why the shortest tap, one step long, rises about 14 units, a hair less than the step’s 16: a press of two steps or more climbs it.

Give the knight its script

  1. Click the Viewport tab, select knight, press Add component, and choose Knight. It is listed under a rule, below the built-in components, once its script checks: a script with a mistake in it is not offered.
  2. Leave its Speed at 110, and press Ctrl+S.

Check it works

The game’s window: the crimson box of the knight standing on the Gate’s start floor, with the wall at the left, the town behind it, and the step rising at the right
The knight in the air near the top of a jump, the crimson box well above the start floor, over the town