Framer for Games: Arcade Joystick

Part 7 of Framer for Games series

Core mechanic: Mapping layer positions with Utils.Modulate

Upcoming games and/or game mechanics in this series

Tune in Thursday mornings for a new entry in this series. I’d love to read your suggestions in the comments.

  1. Raid HQ Character Selection [Thursday, June 23]
  2. Endless Runner [Thursday, June 30]
  3. Guitar Hero [Thursday, July 7]
  4. Card Match [Thursday, July 14]
  5. Snake [Thursday, July 21]
  6. Dropping Ball Catcher [Thursday, July 28]
  7. Arcade Joystick [Thursday, August 4]
  8. Sliding Blocks [Thursday, August 11]
  9. Vertical Platformer [Thursday, August 18]
  10. Pong [Thursday, August 25]
  11. Tempest [Thursday, September 1]

Link to Framer Prototype

This prototype is not so much of a game, but rather a simulation of a physical game controller: the arcade joystick. Grabbing it by its handle and dragging in any direction controls an element on the screen.

A simulation of the arcade joystick prototype

Game elements

  • Joystick component
  • Object controlled by the player object
  • [Optional] button to toggle right- and left-handedness

Joystick component

# Joystick Components
# Area at large to encompass both positions for joystick
joystickArea = new Layer
x: Screen.width / 2
y: 901
width: 300, height: 300
backgroundColor: "transparent"
borderColor: "maroon"
borderWidth: 10
borderRadius: "50%"
joystickArea.states.animationOptions = time: 0.2
joystickArea.states.add
right:
x: Screen.width / 2
left:
maxX: Screen.width / 2
# Layer acting as visual joint for joystick handle [Grey shape under joystick]
joystickHandle = new Layer
parent: joystickArea
x: Align.center
y: Align.center
width: 150, height: 150
borderRadius: "50%"
# Draggable joystick object
joystick = new Layer
parent: joystickArea
width: 200, height: 200
x: Align.center
y: Align.center
borderRadius: 100
backgroundColor: "red"
joystick.draggable.enabled = yes
joystick.draggable.overdrag = no
joystick.draggable.constraints =
x: 0, y: 0
width: joystickArea.width
height: joystickArea.height

Switch Hands button

# Switch Hands Button
handToggle = new Layer
y: Align.bottom
width: 750
height: 100
Utils.labelLayer(handToggle, "Switch Hands")
handToggle.style = fontSize: "48px"
# When button is clicked, it toggles state on joystickArea
handToggle.on Events.Click, ->
joystickArea.states.next "left", "right"

Object controlled by joystick

# Joystick-controlled Object
player = new Layer
x: Align.center
y: Align.center(-200)
rotation: 45
borderRadius: "25%"
# Using color to denote whether object is activated by joystick
player.states.add
moving:
backgroundColor: "white"
notMoving:
backgroundColor: "gray"

Where the magic happens

# Joystick Mapping Logic
# Whenever the joystick is being dragged [i.e. it's position changes]
joystick.on "change:point", ->
player.states.switch "moving"
# Update x and y position of game object by amount between 0 and 4 units
# depending on how far from the center the joystick is dragged
player.x = player.x + Utils.modulate(joystick.x, [0,100], [-4,4])
player.y = player.y + Utils.modulate(joystick.y, [0,100], [-4,4])

# Restrict boundary for player object so it never goes beyond screen
if player.x < 0
player.x = 0
if player.maxX > Screen.width
player.maxX = Screen.width
if player.y < rules.height
player.y = rules.height
if player.maxY > Screen.height - handToggle.height
player.maxY = Screen.height - handToggle.height
# When joystick is no longer activated, return it to its original position
joystick.on Events.DragEnd, ->
joystick.center()
player.states.switch "notMoving"

Framer/CoffeeScript mechanics highlighted here

  • Event listeners
  • Layer states
  • Utility methods
  • Control flow