Input and movement

In this section we will look at many different ways to move the elements. The
following code examples will be simple to write, debug and get working. Its
important to type them out to get the habit of writing code into the fingers.
If we copy / paste the code we don’t practice writing which is important to get
good at when programming.
Do not hesitate to select and delete all the code in the editor and start over
again. Writing these examples over and over just make you a better programmer.


Example 1: Follow input

In this example we will move an emoji around the display. There are many ways to
move Firebox elements around the display and this example demonstrates a simple
way of following the input around.

1
2
3
4
5
6
elem = display.emoji("🤩")

update(() => {
  elem.pointTo(input)
  elem.move(2)
})



Line number 1 of this simple script elem = display.emoji("🤩") creates a
Firebox element of the type emoji using the “starstruck” emoji. elem is a
variable which holds the reference to the element object. The element object can
be updated to change its properties. You can read more about the available
methods in the documentation at Element.

In line number 3 we use an update
block to repeat method calls on the element.

  • First we call the pointTo(other)
    method which sets the angle of the element to point to another object with a
    position in the same coordinate space. And in this case its the input which
    is the mouse input on a computer and the touch input on a touch enabled
    device.
  • Second we call the move(distance)
    method which moves the element a given distance in the direction the element
    is facing.

Run the script and move the mouse/touch around the Firebox display.


Example 2: Input up/down (paddle/dodge/collect)

In this example we will use the input coordinates from the input library to move
an element up and down. This type of navigation can be used to control a paddle
in the classic game Pong.

1
2
3
4
5
elem = display.emoji("🤩", 200, display.y)

update(() => {
  elem.y = input.y
})

We create an emoji element and set the x coordinate to 200 and the y
coordinate to display.y.
We then call the update with a code
block that is called continuously on every update loop.

  • Inside the code block we set the elem.y coordinate to be the same as the
    input.y coordinate which moves the element up and down.

Example 3: Follow input left/right (paddle/dodge/collect)

In this example we will use the input coordinates from the input library to move
an element left and right.

1
2
3
4
5
elem = display.emoji("🦊", 480, 540)

update(() => {
  elem.x = input.x
})

We create a fox emoji element and set the x coordinate to 480 and y coordinate
to 540.
We then call the update with a code
block the is called on every update loop.

  • Inside the code block set the elem.x coordinate to be the same as the
    input.x coordinate which moves the element left and right.

Example 4: Input aim air defense

In this example we will create a rotating line controlled by the mouse location.
This type of navigation can be used to create an air defense type game where
flying object can be stopped by aiming and firing at them.

1
2
3
4
5
6
7
8
player = display.line(
  display.center.x, 630,
  display.center.x, 530
)

update(() => {
  player.pointTo(input)
})

First we create a line in the middle of the display with a length of 100 points.
This line is what we will be updating when we handle the mouse input.

We then call the update(callback: function)
code block which will update on every update loop.

  • Inside the update code block we call the pointTo(other)
    so that it will point to the mouse input as the mouse move around.

Example 5: Arrow up/down (paddle/dodge/collect)

In this example we will use the arrow keys to move an element up and down. This
type of navigation can be used to create games like the classic Pong. It can
also be used to dodge elements moving towards the player or it can be used to
collect elements moving towards the player or both.

1
2
3
4
5
6
7
8
elem = display.emoji("🤩", 200, display.center.y)

input.up(() => {
  elem.y -= 5
})
input.down(() => {
  elem.y += 5
})

We create an emoji element and set its coordinates. Then we call the input
library input.up() which handles the up keyboard key.

  • Inside the input up code block we subtract the emoji elements y coordinate
    with -5 which will continuously move our element upwards while holding the
    up keyboard key.

We then call the input library input.down() which
handles the down keyboard key.

  • Inside the input down code block we add the emoji elements y coordinate by 5
    which will continuously move our element downwards while holding the down
    keyboard key.

Example 6: Arrow left/right (paddle/dodge/collect)

The next example will use the keyboards left and right arrow keys to move a
firebox element left and right. This type of navigation can be used to create
paddle type games like the classic Breakout. It can also be used to dodge
elements moving towards the player or it can be used to collect elements moving
towards the player or both.

1
2
3
4
5
6
7
8
elem = display.emoji("🤩", display.center.x, 540)

input.left(() => {
  elem.move(-5) // elem.x -= 5
})
input.right(() => {
  elem.move(5)  // elem.x += 5
})

First we create a firebox element which we will use as the player. We set the
initial x position of the element to be display.center.x which is in the
center horizontally. We set the initial y position of the element to be 540
which is 100 points up from the bottom.

We then call the input.left() with a code block that will be called on all the
keyboard left key input events.

  • Inside the code block we call the element.move(distance)
    method. The distance to move is -5 and the effect of continuously calling
    move is that the element will continuously move to the left.

We then call the input.right() with a code block that will be called on all
the keyboard right key input events.

  • Inside the code block we call the element.move(distance)
    method. The distance to move is 5 so the element will continuously move in
    the right direction.

Example 7: Arrows turn and move

In this example you will create a script that controls an element with the
arrow keys on a keyboard. Clear out the previous example and start over with
this example. Type out every character on the keyboard and do not
copy / paste this either. Its important to get used to the keystrokes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
elem = display.emoji("🤩")

input.left(() => {
  elem.rotate(-4)
})
input.right(() => {
  elem.rotate(4)
})
input.up(() => {
  elem.move(4)
})
input.down(() => {
  elem.move(-4)
})

We first create en emoji element elem = display.emoji("🤩"). Then we create 4
similar types of blocks. We use input and call the left, right, up and
down methods. You can read about the methods in the input documentation.

The first call to input is input.left()
which handles the left key on the keyboard.

  • We call rotate(value) which
    rotates an element by a given value. In our example we rotate by negative 4
    (-4) which will rotate our element counter-clockwise.

The second call to input is input.right()
which handles the right key on the keyboard.

  • Like in the left key code block we call the rotate(value)
    method on our element but this time with a positive value which rotates our
    element in a clockwise direction.

The third call to input is input.up() which handles
the up keyboard key.

  • Inside the code block we call the move(distance) which
    we also used in the previous example and this method moves the element a given
    distance in the direction it is facing.

The fourth and last code block calls the input.down()
which handles the down key on the keyboard

  • Inside this code block we also call the move(distance) but
    with a negative value which moves the element in the opposite direction, or
    backwards, of the current angle which the element is facing.

Example 8: Arrow key aim air defence

In this example we will create a rotating line controlled with the left and
right arrow keys on the keyboard. This type of navigation can be used to create
an air defense type game where flying object can be stopped by aiming and firing
at them.

1
2
3
4
5
6
7
8
9
10
11
12
player = display.line(
  display.center.x, 630,
  display.center.x, 530
)

input.left(() => {
  player.rotate(-5)
})

input.right(() => {
  player.rotate(5)
})

First we create a line in the middle of the display with a length of 100 points.
This line is what we will be updating when we handle the keyboard input.

Next we make a call to input.left()
method which handles the left arrow key on the keyboard.

  • Inside the code block we call the rotate(value)
    which rotates the line by a given value. In this example we rotate by negative
    5 (-5) which will rotate the line counter-clockwise.

Next we make a call to the input.right()
method which handles the right arrow key on the keyboard.

  • Inside the code block we call the rotate(value)
    which rotates the line by a given value. In this example we rotate with
    positive 5 (5) which will rotate the line in the clockwise direction.

Example 9: Arrow block shift

In the next example we will move an element by shifting its position by its own
size. We we will also only shift on arrow key began event. The key
down in this example is handled with if (e.began) { ... }.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
elem = display.emoji("🤩")

input.left((e) => {
  if (e.began) {
    elem.shift(-1, 0)
  }
})
input.right((e) => {
  if (e.began) {
    elem.shift(1, 0)
  }
})
input.up((e) => {
  if (e.began) {
    elem.shift(0, -1)
  }
})
input.down((e) => {
  if (e.began) {
    elem.shift(0, 1)
  }
})

We create an emoji with elem = display.emoji("🤩") and handle the arrow input
keys by calling the left, right, up and down methods in the input
library. Inside the input arrow key blocks we call the shift(x, y)
method.

The first call to input is input.left()
which handles the left key on the keyboard.

  • Calling if (e.began) { ... } make the code be called only when
    the key event began. We call the shift(x, y)
    on the element with x being -1 and y being 0 which will place the element
    1 size to the left.

The second call to input is input.right()
which handles the right key on the keyboard.

  • Again we call if (e.began) { ... } to only handle the began event. Next we
    call shift(x, y) with
    x being 1 and y being 0. The element shifts 1 size to the right.

The third call to input is input.up()
which handles the up keyboard key.

  • Again we call if (e.began) { ... } to only handle the began event. And we
    call shift(x, y) with
    x being 0 and y being -1. This makes the element shift negative one size
    upwards.

The fourth and last code block calls the input.down()
which handles the down key on the keyboard.

  • Again we call if (e.began) { ... } to only handle the began event. And we
    call shift(x, y) with
    x being 0 and y being 1. This makes the element shift one size downwards.

Example 10-1: click point goTo

In this example we will use the input.point(event) library method to move an
element around. The input.point(event)
method is triggered by the mouse on a computer and on a phone / tablet it will
be triggered by touch input.

1
2
3
4
5
6
7
elem = display.emoji("🤩")

input.point((e) => {
  if (e.ended) {
    elem.goTo(e.position)
  }
})

First we create a firebox emoji element elem = display.emoji("🤩"). Next we
call the input.point(event) with a code
block that we can use the given event inside.
We check if the event ended with if (e.ended) which occurs when the mouse
button is released from a click or finger is released from the touch.

  • We then call the element.goTo(point)
    method and set the location of the current input event location.

Example 10-2: click point moveTo

In this example we will move an element around by calling the element.moveTo(point)
method.

1
2
3
4
5
6
7
elem = display.emoji("🤩")

input.point((e) => {
  if (e.ended) {
    elem.moveTo(e.position)
  }
})

First we create a firebox element elem = display.emoji("🤩"). Then we
call the input.point(event) with a code
block that we can use the given event inside.

  • We check if the event ended with if (e.ended) which occurs when the mouse
    button is released from a click or finger is released from the touch.

    • We then call the element.moveTo(point)
      method and set the location of the current input event location. Instead of
      teleporting to the new position the element slides to the new position.

Example 11: Element falling, then click

In this example we will create a simple app where an element is falling down and
is moved to the top of the display if its clicked or if the element drops below the
height of the display.

1
2
3
4
5
6
7
8
9
10
11
12
13
elem = display.emoji("🤩")

update(() => {
  elem.y += 5

  if (elem.y > 680) {
    elem.y = -40
  }
})

elem.click(() => {
  elem.goTo(random.num(0, 960), -40)
})

First we call the display library and create an element with
elem = display.emoji("🤩"). We then call the update(callback)
with a code block that will repeatedly be called.

  • Inside the code block we add 5 to the elements y position which will move it
    down on the display. If the element drops below the display height the element
    will be moved to -40.

Next we call the element.click()
method which will be triggered when the element is clicked.

  • Inside the code block of the click method we call the elem.goTo(x, y)
    which will move the element to the top of the screen and give it a random x
    coordinate position.

Example 12: If on edge bounce

In this example we create an element and continuously move it around in the
display and if it touches the edge of the display it will bounce and continue
moving.

1
2
3
4
5
6
7
elem = display.circle(100, 100, 20)
elem.rotate(45)

update(() => {
  elem.move(10)
  elem.ifOnEdgeBounce()
})

First we create and element of the type circle. We then rotate its angle by
45 degrees. Then we create an update(callback)
code block.

  • Inside the update loop we move the element by 10. Then we call the
    ifOnEdgeBounce() method
    which will rotate the element to the angle that mirrors its direction.

Example 13: Drag / drop, build / cut

In the next example we will take a look at pick up, drag and drop. We will pick
up a box and drag it over another, then merge them together.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
box = display.rect(display.center, 50, 50)

box2 = display.rect(100, 100, 50, 50)

box2.point((e) => {
  if (e.updated) {
    box2.position = e.position
  }
  if (e.ended) {
    if (box2.collide(box)) {
      box2.height += box.height
      box.destroy()
    }
  }
})

We start with creating a rectangle we call box which we place in the center
of the display (display.center).

Then we create a new rectangle we call box2 and place it in the upper left
corner.

Then we call the element.point(callback)
method which handles pointer input from mouse and touch screen touches triggered
if the input event is in the elements coordinate space.

  • Inside the point code block we first check if the event is in the updated
    state. If it is then we update the box2 position. Then the box is moved
    around.
  • The next event phase we check is if the event is ended. If the event is
    ended we check if the boxes collide by calling the element.collide(other)
    and if they do we add box height to box2s height and then destroy box.

Example 13-2: Drag / drop, build / cut

In this example we continue with drag and drop but this time we will create a
new box to collide with each time we pick up another element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
box = display.rect(860, 540, 50, 50)

box2 = display.rect(100, 100, 50, 50)

box2.point((e) => {
  if (e.updated) {
    box2.position = e.position
  }
  if (e.ended) {
    if (box2.collide(box)) {
      box2.height += box.height
      box.destroy()

      box = display.rect(random.pos(), 50, 50)
    }
  }
})

First we create a box in the lower right corner and give it a size of 50 points.

Then we create a box we call box2, this box is placed in the top left corner.

We then call element.point()
on box2. When this box is clicked we handle the mouse input or touches on a
touch screen.

  • Inside the point code block we check if the event is updated which is when
    we move the element around. We then update box2s position.
  • Then we check if the event is ended. And we check if the boxes in the
    display collide by calling the element.collide(other).
    If they collide we increase box2s height by boxs height, destroy box and
    create a new box at a random position.

These steps then repeat for every box we pickup.


Example 14: Stretch front release

In this example we will move an element by dragging an angle in front of the
element and send it of in that direction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
elem = display.circle(100, 540, 30)
elem.speed = 0

elem.point((e) => {
  if (e.began) {
    lin = display.line(elem.position, e.position)
    lin.style = LineStyle.dots
  }
  if (e.updated) {
    lin.to(e.position)
  }
  if (e.ended) {
    elem.angle = lin.angle
    elem.speed = 10
    lin.destroy()
  }
})

update(() => {
  elem.move(elem.speed)
})

First we create an element of type circle and set position and size. We also set
the speed of the element to 0.

Next we call the element.point(callback)
and pass in a code block where we will draw the line and set the direction for
the element.

  • When the point event begin (if (e.began)) we create a new line by calling
    display.line() and set the position from the circle element position to the
    point event start position. And we set the line style to LineStyle.dots.

  • Then we check if the point event updated (if (e.updated)) and update the
    line to position (lin.to(e.position)) and set it to the current event position.

  • Then we check if the point event is ended (if (e.ended)) and set the circle
    element angle to the line angle and update the elements speed. We then destroy
    the line.

To get the circle element moving we create an update(callback)
code block which is called repeatedly on every update loop call.

  • Inside the update code block we move the circle element by its speed which
    will continuously move the element forward.

Example 15: Stretch front release physics

In this example we will create a circle and give it physics properties. Then
interact with it inside the display.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
world.frame()

elem = display.circle(100, 540, 30)
physics.add(elem)

elem.point((e) => {
  if (e.began) {
    physics.stop(elem)
    lin = display.line(elem.position, e.position)
    lin.style = LineStyle.dots
  }
  if (e.updated) {
    lin.to(e.position)
  }
  if (e.ended) {
    elem.applyImpulse(
      (e.position.x - elem.position.x) / 5,
      (e.position.y - elem.position.y) / 5
    )
    lin.destroy()
  }
})

We first create a world frame by calling world.frame().

Then we create an element and give it physics properties by calling the
physics.add(elem) method with the element.

Next we call the element.point(callback)
and pass in a code block where we will draw the line and set the direction for
the element.

  • When the point event begin (if (e.began)) we stop the physics and we create a
    new line by calling display.line() and set the position from the circle
    element position to the point event start position. And we set the line style
    to LineStyle.dots.

  • Then we check if the point event updated (if (e.updated)) and update the
    line to position (lin.to(e.position)) and set it to the current event position.

  • Then we check if the point event is ended (if (e.ended)) and call the elem.applyImpulse()
    method on the element with the delta of the event position and the circle
    elements position divided by 5. We then destroy the line.

The result is that the element flies of in the direction of the angle of the
line.


Example 16: Stretch back release

In this example we will create an element and use pull back release to apply
physics so the element flies of in opposite direction.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
world.frame()

elem = display.emoji("🤩", 200, 520)
physics.add(elem, { radius: elem.size.width/2 })

physics.add(
  display.rect(display.width/2, world.height - 25, display.width, 50)
)

elem.point((e) => {
  if (e.began) {
    physics.stop(elem)
    lin = display.line(elem.position, e.position)
    lin.style = LineStyle.dots
  }
  if (e.updated) {
    lin.to({
      x: elem.position.x + ((elem.position.x - e.position.x) * 2),
      y: elem.position.y + ((elem.position.y - e.position.y) * 2)
    })
  }
  if (e.ended) {
    elem.applyImpulse(
      elem.position.x - e.position.x,
      elem.position.y - e.position.y
    )
    lin.destroy()
  }
})

times(10, () => {
  display.cloud(
    random.pos(),
    random.num(5, 20)
  )
})

We first create a world frame by calling world.frame().

Then we create an element of type emoji and give it physics properties by
calling the physics.add(elem)
method with the element.

Next we create the ground since we need some space to drag the input.
We create a rectangle element and immediately add it to physics. The size of the
rectangle is set to fill the whole display width and the bottom 50 points.

Next we call the element.point(callback)
and pass in a code block where we will draw the line and set the direction for
the element.

  • When the point event begin (if (e.began)) we stop the physics and we create
    a new line by calling display.line() and set the position from the emoji
    element position to the point event start position. And we set the line style
    to LineStyle.dots.

  • Then we check if the point event updated (if (e.updated)) and update the
    line to position which is a negative delta to the current event position.

  • Then we check if the point event is ended (if (e.ended)) and call the elem.applyImpulse()
    method on the element with the negative delta of the event position and the
    emoji elements position, which will apply the impulse in the opposite
    direction of the current input event. We then destroy the line.

The result is that the element flies off in the opposite direction of the angle of
the current input event and in the direction of the line.


Example 17: Joystick

In this example we will create an emoji element and move it around with an on
screen joystick.

1
2
3
4
5
6
7
8
pl = display.emoji("🤩")

jstck = display.joystick()

jstck.update((x, y) => {
  pl.x += 4 * x
  pl.y += 4 * y
})

First we create an element of type emoji.

Then we initialize a joystick which will appear in the lower left corner of the
display.

We then call joystick.update(callback) and pass in a code block were we will
handle the user input.

  • Inside the code block we get the two variables x and y to use. We then
    update the emoji elements x coordinate value by calling pl.x += 4 * x and
    the elements y coordinate value by calling pl.y += 4 * y.

The result is that we are moving the element around the display with the
joystick control.


Extra

Example 18: Input aim air defence

In this example we will create a rotating line controlled by the mouse
location. This type of navigation can be used to create an air defense type game
where flying object can be stopped by aiming and firing at them.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
line = display.line(
  display.center.x, 630,
  display.center.x, 530
)

update(() => {
  line.pointTo(input)
})

input.point((e) => {
  if (e.ended) {
    bu=display.rect(line.end, 10, 5)
    bu.angle = line.angle
  }
})

update(() => {
  display.each("rect", (elem) => {
    elem.move(10)
  })
})

First we create a line in the middle of the display with a length of 100 points.
This line is what we will be updating when we handle the mouse input.

To get the line to point to the mouse input we need to call the pointTo(other: Element)
for a line. We also have to call it repeatedly when the mouse moves around the
display. The update() code block will
call its code repeatedly.

  • Inside the update code block we call the pointTo(other: Element) so that
    it will point to the mouse input as the mouse move around.

Next we handle mouse input by calling the input.point()

  • Inside the input point code block we check if the input event is ending and
    if it is create a new rectangle and set its angle to the same as the line.

To get the rectangles (bullets) to fly we create another update code block

  • Inside the update code block we call the display.each(tag: String, (elem: Element) => ())
    which will repeat for every element with the given tag. Since we pass the
    rect tag which is the default tag for rectangles.
    • Inside the each loop we move the rectangle by 10 points which will move the
      elements one by one 10 points each.

Example 19: Arrow key aim, air defence

In this example we will create a rotating line controlled with the left and
right arrow keys on the keyboard. This type of navigation can be used to create
an air defense type game where flying object can be stopped by aiming and firing
at them. This is a big example with over 20 lines of code. Try not to copy and
paste and type out all of the lines of code one by one.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
line = display.line(
  display.center.x, 630,
  display.center.x, 530
)

input.left(() => {
  line.rotate(-5)
})

input.right(() => {
  line.rotate(5)
})

input.space((e) => {
  if (e.ended) {
    bu=display.rect(line.end, 10, 5)
    bu.angle = line.angle
  }
})

update(() => {
  display.each("rect", (elem) => {
    elem.move(10)
  })
})

First we create a line in the middle of the display with a length of 100 points.
This line is what we will be updating when we handle the keyboard input.

Next we make a call to input.left()
method which handles the left arrow key on the keyboard.

  • Inside the code block we call the rotate(value)
    which rotates the line by a given value. In this example we rotate by negative
    5 (-5) which will rotate the line counter-clockwise.

Next we make a call to the input.right()
method which handles the right arrow key on the keyboard.

  • Inside the code block we call the rotate(value)
    which rotates the line by a given value. In this example we rotate with
    positive 5 (5) which will rotate the line in the clockwise direction.

Next we make a call to input.space() method
which handles the space-bar key on the keyboard.

  • Inside the code block we check if the space-bar key event is ending and if it
    is, create a new rectangle with display.rect(position: Point, width: Number, height: Number)
    at the tip of the line. Then we update the new rectangles angle to match the
    main line angle. This will become a moving bullet.

To get the bullet moving we need to move it over and over again. This is done in
the next code block that we make. This is a call to the update(callback: function)
method and the code inside this block will repeat over and over.

  • Inside the update code block we call the display.each(tag: String, (elem: Element) => ())
    which will repeat for every element with the given tag. Since we pass the
    rect tag which is the default tag for rectangles.
    • Inside the each loop we move the rectangle by 10 points which will move the
      elements one by one 10 points each.

Summary

In this section we looked at many different ways of controlling elements in the
display.

We looked at how to get an element to follow the user input.

We looked at how to move and manipulate an elements coordinates with the arrow
keys.

We looked at how to click/tap around the display to give the elements new
coordinates.

And we looked at how to use mouse/finger input to draw lines and set the
direction for new element coordinates.