Input and movement

Its time to start writing some code to move elements around. 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 mark out and delete all the code in the editor and start over again. Writing these examples over and over just make you a better programmer.

If you want to skip straight to making games you can skip this chapter and move directly to the next chapter.


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.

elem = display.emoji("🤩")

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

Line number one 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 /docs/types/element.

In line number two 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 it 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.

elem = display.emoji("🤩", 200, display.center.y)

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

We create an emoji element and set the x coordiante to 200 and the y coordinate to display.center.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.

elem = display.emoji("🦊", 480, 440)

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

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

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

Example 4: 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.

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.

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

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.

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.

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/slide

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 begin event. The key down in this example is handled with if (!e.began) { return }.

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) { return } make the remaining code be called only when the key event begins. 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) { return } to only handle begin 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) { return } to only handle begin event. And we call shift(x, y) with x being 0 and y being -1. This makes the element shift negative one size up.

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

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

Example 10-1: click point goTo

In this example we will use the input.point(event) library method to move and 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.

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.

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 moved to the top of the display if its clicked or if the element drops below the height of the display.

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.

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.

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()
      box = null
    }
  }
})

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.

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 infront of the element and send it of in that direction.

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.

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.

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.

pl = display.emoji("🤩")

jstck = joystick.init()

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 when we touch the screen.

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.

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.

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 spacebar key on the keyboard.

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

This ends the introduction into the Firebox framework. The next set of chapters will look at how to make games in Firebox and we will create simple games and gradually introduce more complex programming methodologies.