Notice how we're using the same pattern as before to handle another kind of event - this time so the "tick" event calls OnTick
with runtime
passed as a parameter again.
Now any code we add in OnTick
will run every tick. We can add some code here to check which arrow keys are down, and move the sprite accordingly.
Handling keyboard input
Notice the Keyboard object has been added to the project. This is necessary to receive keyboard input.
The Keyboard object's properties and methods can be accessed with runtime.objects.Keyboard
, but since keyboard input is commonly used, runtime.keyboard
is also provided as a shortcut.
The Keyboard object is global and has no instances. This means its properties and methods are accessed directly on runtime.keyboard
. There is no need to call getFirstInstance()
.
The Keyboard script interface provides a method isKeyDown()
which we can use to detect if a key is currently pressed at the time of the call. The key is specified with a string. A full list can be found on this MDN page, but the keys we need are the arrow keys, represented by the strings "ArrowLeft"
, "ArrowRight"
, "ArrowUp"
and "ArrowDown"
.
So calling runtime.keyboard.isKeyDown("ArrowLeft")
will return a boolean indicating if the left arrow key is currently held down. If that's the case, then we can move the sprite to the left.
Add the following code to the OnTick
function.
function OnTick(runtime)
{
let inst = runtime.objects.Sprite.getFirstInstance();
if (runtime.keyboard.isKeyDown("ArrowLeft"))
inst.x -= 10;
if (runtime.keyboard.isKeyDown("ArrowRight"))
inst.x += 10;
if (runtime.keyboard.isKeyDown("ArrowUp"))
inst.y -= 10;
if (runtime.keyboard.isKeyDown("ArrowDown"))
inst.y += 10;
}
Notice how there are four 'if' statements that check if each of the four arrow keys is down. If a key is down, the Sprite instance's position is moved in that direction. Preview the project and try pressing the arrow keys. The sprite will move around!
Framerate independence
One problem with moving objects by a fixed number of pixels every tick is that the speed depends on the framerate. For example on a system with a 120Hz display the sprite will move twice as fast as on a system with a 60Hz display, because ticks happen twice as fast on the 120Hz display. This problem is explained in more detail in the tutorial Delta-time and framerate independence.
The solution is to instead move the position by delta-time (the time this frame takes in seconds) multiplied by the speed in pixels per second. In JavaScript runtime.dt
returns the current delta-time, which is the same as the dt
expression in Construct's event sheets. Try the following code for OnTick
.
function OnTick(runtime)
{
let inst = runtime.objects.Sprite.getFirstInstance();
if (runtime.keyboard.isKeyDown("ArrowLeft"))
inst.x -= 400 * runtime.dt;
if (runtime.keyboard.isKeyDown("ArrowRight"))
inst.x += 400 * runtime.dt;
if (runtime.keyboard.isKeyDown("ArrowUp"))
inst.y -= 400 * runtime.dt;
if (runtime.keyboard.isKeyDown("ArrowDown"))
inst.y += 400 * runtime.dt;
}
Now the sprite moves at a regular speed of 400 pixels per second regardless of the framerate, because it is moved by a distance of 400 * runtime.dt
.
As the previously linked tutorial notes, Construct's built-in behaviors like 8 Direction handle delta-time for you automatically. However when making movements using JavaScript code - or event blocks - you'll need to factor in delta-time to ensure the movement works the same across different devices. Using delta-time also enables useful time-based effects like pausing or slow-motion, as these work by modifying the value of dt
.
You can also take a look at the Simple keyboard movement example that comes with Construct, which also handles changing the sprite angle.