Bales, Missiles and Triggers, Oh My!

turtleSpaces is great for creating 3D models and animations, but we also want it to be great for games. Unfortunately, the interpreter is not the fastest thing around — but that’s okay! We can compensate by creating new commands that work ‘under the hood’ to take care of certain game elements.

Bales are groups of turtles that all execute the same code, for example alien attackers in a space battle game. They are declared similarly to turtles, using a NEWBALE declaration.

When each member of a bale is initialized, it executes the code in the bale’s INIT procedure. Then, it repeatedly executes the code in the MAIN procedure in sequence with the other members of the bale, that is each member of the bale executes the code in succession using the same thread. At the end of each cycle, when all bale members have executed, their ‘turtle tracks’ are rendered. This makes it seem like they’ve all moved at the same time.

Take for example this code from a Space Invaders-inspired game (you can try it out here: https://turtlespaces.org/weblogo/?pub=81)

NEWBALE "ships

TO init
  ;bales are groups of turtles that execute the same code in sequence,
  ;one after the other. They are useful for things like groups of
  ;enemies, to keep them in lock step, where hatchlings can end up
  ;executing at different rates of speed and fall out of sequence
  ;with each other.
  
  ;new bale members always execute the init procedure, after which
  ;they repeatedly execute the main procedure until they are
  ;removed or the entire bale is stopped.
  
  penup
  noaudiowait
  newmodel "bullet [setfillcolor 15 icosphere 1.5]
  setmodelscale 1.5
  setposition {
    (-150 + 30 * (remainder baleindex - 1 5))
    100 - (20 * (int ((baleindex - 1) / 5)))
    5
  }
  ;based on the number (index) of the bale member, place
  ;it in the attacking wave
  
  if 1 = remainder int (baleindex - 1) / 5 2 [setx xpos + 10]
  ;let's offset the turtles in alternating rows
  
  right 180
  ;turn to face down
  
  showturtle
  ;show the turtle
  
  rollright baleindex * 10
  ;set the default roll rotation
  
  output [dir 1]
  ;the pairs provided by output become variables in main
  ;in this case we're setting the default move direction, which
  ;is the same for all members in this bale
END

Each member of the bale is placed based upon its index number in the bale. Once we position the bale member, it moves on to the main execution loop:

TO main
  dosleep 10 [
    ;take at least 10 milliseconds to do the following:
    
    rollright 10
    ;roll right ten degrees
    
    if and xpos < 150 :dir = 1 [drift 5 [1 0 0] drift 1 [0 -1 0]] if and xpos = 150 :dir = 1 [make "dir 0 drift 10 [0 0 -1] drift 10 [0 -1 0]] if and xpos > -150 :dir = 0 [drift 5 [-1 0 0] drift 1 [0 -1 0]]
    if and xpos = -150 :dir = 0 [make "dir 1 drift 10 [0 0 1] drift 10 [0 -1 0]]
    ;we use drift to move the ships because we're rolling them for effect
    
    if 1 = random 20 [
      newmissile "missile "bullet [0 -1 0] 20 + random 20 [200]
      playsound "zap3
    ]
    ;fire a missile randomly
    
    if or ypos < -100 containsp "myrtle near position 20 [ make "hit true ] ;if an alien reaches the bottom of the screen it's over if baleindex = last balemembers balename [ if :delay > 0 [dec "delay]
      ;this increases the speed of the invaders 'music'
      ;once each time all the bale turtles have executed
      ;(each loop)
    ]
  ]
END

Each bale member moves across the screen, randomly firing missiles, until they are destroyed or reach the bottom of the screen, triggering a ‘game over’ condition.

newmissile "missile "bullet [0 -1 0] 20 + random 20 [200]

Missiles are simple elements that are controlled by the game engine. They move through 3D space, and are detected by primitives such as NEARMISSILEP and NEARMISSILES. They can also be detected by the nearmissile trigger. They are much more efficient than using turtles as projectiles.

Similarly, triggers are blocks of code that are executed when a certain condition occurs. These conditions are monitored by the underlying game engine, and are ‘triggered’ when these conditions are detected to be true. Once again, this is much more efficient then having a turtle constantly execute Logo code waiting for the condition to occur!

The following trigger belongs to the previously mentioned alien ships bale:

ON boom nearmissile block [missile2 10]
  hideturtle
  playsound "explosion
  inc "score
  show :score
  stopmissile flat list :boom :boomanim
  die
  ;this turtle is no more
END

This trigger increments the player’s score, disposes of the missile that triggered it, and then ends the turtle to whom the trigger belongs, in this case a member of the alien ship bale.

As you can see, bales, missiles and triggers all contribute to empowering turtleSpaces coders to create faster-paced, more engaging games.