Touch Develop retirement postponed until June 22, 2019. Sign-in and access to cloud assets to be removed on May 23, 2018.Learn More..


game board

The game board is a 2D game engine to create simple sprite-based games. The API includes a primitive physics engine to move objects according to gravity and friction values. Game board elements can be orchestrated using events based on touch and regular timing intervals.

what is a sprite?

Sprites are 2D bitmaps that are drawn directly to the screen. Sprites are commonly used to display information such as health bars, number of lives, or text such as scores. Some games, especially older games, are composed entirely of sprites. The game board lets you create and use of several types of sprites, such as ellipse, rectangle, text and picture.

coordinates and units

Positions in the game board API are based on pixels. The origin of the grid is the top left corner when holding the phone upright (the x-axis is horizontal, the y-axis is vertical). Sprite positions refer to the center of the sprite, i.e., the halfway point of its width and height before any rotation is applied. The reasoning behind this choice is so that sprites can rotate around their center. Future versions of TouchDevelop may provide more control for offsetting sprites from their position. Speed and acceleration are measured in pixels/second and pixels/second^2.

program structure

The following example code shows the underlying structure for a typical game:
data board : Board
function
main initial
()
 board := media → create landscape board(800, 480)
… create sprites, add color and features to the board
 board → post to wall
end function
event
gameloop
()
apply physics
 board → evolve
refresh display
 board → update on wall
end event
The gameloop event is triggered approximately every 50 milliseconds, i.e. about 20 times per second.

the board kind

creating and displaying

When creating a board, you need to decide whether your game will be played in landscape or portait orientation. You also decide the width and height in pixels. The board is scaled based on the screen dimensions of the user's device.
  • creating a landscape board
 board := media → create landscape board(800, 480)
  • creating a portrait board with a thinner form factor
 board := media → create portrait board(768, 1360)
A board remains invisible until it is posted to the wall. Once posted, it goes full screen.
 board → post to wall
Once posted, updates to the board state and the sprites on the board become visible only when calling board→update on the wall (typically from the gameloop).
 board → update on wall

board appearance

The board has a background color and a background picture that can be set separately. The default background color is transparent, and no background picture is provided by default. Only one of these background possibilities can be active at a time.
  • setting a random background color
 board → set background(colors → random)
  • setting a background picture
 board → set background picture( pic)
  • getting the width and height of the board
var width :=  board → width
var height :=  board → height

creating sprites

There are four kinds of sprite that display different kinds of visual content: ellipse, rectangle, text and picture.
  • ellipse and rectangle are drawn as solid figures.
  • the value of text sprites can be updated.
There is a fifth kind of sprite known as an anchor sprite. It is invisible and has a special purpose, which is explained below under the heading springs and anchors. Sprites are associated with one or more specific game boards and are created by using methods of the Board type.
  • create an ellipse with 20 pixels wide and 40 pixels high.
var sprite :=  board → create ellipse(20, 40)
  • create a rectangle with 20 pixels wide and 40 pixels high.
sprite :=  board → create rectangle(20, 40)
  • create a text with 100 pixels width, 20 pixels height and font size 40. The width and height are used for the bounding box but the text might over spill this dimension.
sprite :=  board → create text(100, 20, 40, "boom")
Sprites have initial positions centered on the board and no speed or angular rotation. These properties can be set for each sprite using the methods of the Sprite datatype.
  • re-positioning the sprite to (10, 20)
sprite → set pos(10, 20)
  • set the sprite moving right
sprite → set speed x(100)
  • give a little rotation rate of 15 degrees per second.
sprite → set angular speed(15)

enumerating sprites

The board acts as a collection of sprites.
  • get the number of sprites
var sprite count :=  board → count
  • get the sprite at a particular index
sprite :=  board → at(1)
  • enumerate all sprites using a for each loop
for each sp in  board do
access the sprite
end for each
  • appearance actions
  • creating and accessing sprites actions

sprite sets

During games it is very useful to have several collections of sprites. For example, one collection contains spacecraft, another holds asteroids, and so on. A sprite collection can be created as an instance of the Sprite Set datatype. The method create sprite set creates a new set which can hold sprites associated with the board.
  • creating a sprite set
var sprites :=  board → create sprite set
  • adding a sprite to a sprite set. Returns true if sprite was not previously in the set.
var added := sprites → add(sprite)
  • removing a sprite from a sprite set. Returns true if sprite was found and removed.
var removed := sprites → remove(sprite)

obstacles

Obstacles are walls that can be added to the board. Walls cannot be moved once created. Moving sprites which encounter an obstacle will bounce back with a speed determined by the product of the obstacle’s elasticity and the sprite’s elasticity. Elasticities of 1 for both the obstacle and the sprite means the sprite will maintain its full speed, albeit in a different direction. If one or both elasticities are 0, there will be full absorption of the impulse; the sprite will stick to the wall. By default, all elasticities are 1.
 board → create obstacle(x, y, dx, dy, 1)

boundaries

By default, the board is open, meaning it has no boundary. Sprites moving off the visual part of the board will simply continue moving away. Since it is common to need reflecting walls around the board, the create boundary(distance) method can be used to create a reflective set of walls around the board at the given distance from the board’s edges. The elasticity of these reflective walls is 1, i.e. the sprite’s speed is not reduced. If the distance of the boundary from the board’s edge is larger than the sprite’s size, a sprite can disappear off the screen before bouncing back and re-appearing. If the distance is set as a negative number, the boundaries are located inside the board area.
 board → create boundary(0)

gravity

A uniform force can be applied to all sprites on the board. For instance, there could be a force which pulls all objects towards the bottom of the screen, mimicking the force of gravity. However this gravitational force need not remain constant. The script can repeatedly use the phone’s orientation or its accelerometer readings to vary the force and direction of gravity that is experienced by objects in the game.
  • using the accelerometer to apply forces on the board. We scale the acceleration to make the sprite move faster.
var p := senses → acceleration quick
p := p → scale(600)
 board → set gravity(p → x, p → y)
Once sprites are given speeds or if gravity has been made non-zero, the board engine can update a sprite's position. To update all sprite positions for one time step, the board→evolve method should be invoked. The duration of the time step is simply the time since the last call to board→evolve or since the creation of the board.

friction

By default, a sprite keeps on moving without slowing down. It can lose speed only if it moves in an opposite direction to gravity or if it loses energy in a collision with an obstacle whose elasticity is less than 1. If it is desirable to make sprites slow down by themselves, a friction can be provided for each sprite individually.
A friction is defined as the fraction of the forward speed that is experienced as a backwards force. A friction of 0 corresponds to no friction, and a friction of 1 means the sprite will not move at all.
  • adding enough friction so that the sprite eventually stops without forces
sprite → set friction(0.01)
Each sprite can have its own friction setting but, if not set, each sprite experiences the default friction from the board.
 board → set friction(0.001)

springs and anchors

An anchor is a invisible sprite that does not move, even with forces applied to it. You can also fix any other sprite by setting their friction to 1.
var anchor :=  board → create anchor(20, 20)
A spring can be added between two sprites to make them accelerate towards each other.
 board → create spring(sprite, anchor, 100)
The force of the spring is proportional to the distance between the two sprites. The further they are apart, the stronger the force. The constant of proportionality is determined by the stiffness parameter of create spring. The larger its value, the stronger the attractive force.
Without friction to dissipate energy over time, sprites linked by a spring will oscillate indefinitely. With friction, they will eventually converge on the same point. A common scenario is to fix one of the two spring-linked sprites on the board (make it unmovable).
If a sprite linked to an anchor via a spring therefore oscillates around the anchor. Giving the sprite an initial velocity vector perpendicular to the direction of the spring causes the sprite to circle around the anchor. With multiple anchors and springs, some interesting oscillation paths can be produced.

sprite kind

Sprites are movable objects that are used to visually represent parts of a game, such as a space ship and an asteroid, etc. New sprites are created by using methods of the Board datatype. Once a sprite has been created, its attributes such as position, speed, mass, color, etc., can be set by using methods of the Sprite datatype.

visual attributes

The appearance of a sprite can be modified in many ways.
  • get or set the color
var c := sprite → color
sprite → set color(c)
  • hide or show
sprite → hide
sprite → show
  • make transparent using the opacity
sprite → set opacity(0.5)
  • change the picture for Picture Sprite
sprite → set picture( another pic)
  • change the z-index which controls the order in which sprites are rendered on the screen. The sprites are rendered in order of their z-indexes, from smallest to largest.
sprite → set z index(5)
function (Sprite) → color returns Color
Returns the sprite color.
function (Sprite) → height returns Number
Gets the height in pixels
function (Sprite) → hide
Hide sprite.
function (Sprite) → is visible returns Boolean
Returns true if sprite is not hidden
no such topic: Sprite_move clip
function (Sprite) → opacity returns Number
Gets the opacity (between 0 transparent and 1 opaque)
function (Sprite) → picture returns Picture
The picture on a picture sprite (if it is a picture sprite)
function (Sprite) → set clip(left : Number, top : Number, width : Number, height : Number)
Sets the clipping area for an image sprite (if it is an image sprite)
function (Sprite) → set color(color : Color)
Sets the sprite color.
function (Sprite) → set height(height : Number)
Sets the height in pixels
function (Sprite) → set opacity(opacity : Number)
Sets the sprite opacity (between 0 transparent and 1 opaque).
function (Sprite) → set picture(pic : Picture)
Updates picture on a picture sprite (if it is a picture sprite)
function (Sprite) → set text(text : String)
Updates text on a text sprite (if it is a text sprite)
function (Sprite) → set width(width : Number)
Sets the width in pixels
function (Sprite) → set z index(zindex : Number)
Sets the z-index of the sprite
function (Sprite) → show
Show sprite.
function (Sprite) → text returns String
The text on a text sprite (if it is a text sprite)
function (Sprite) → width returns Number
Gets the width in pixels
function (Sprite) → z index returns Number
Gets the z-index of the sprite

position and motion

A sprite has a current position and a current angular orientation. Both of these change at rates determined by the sprite’s speed and its angular velocity.

accelerations, forces and bounces

In the absence of gravity, springs and friction, a sprite will keep moving across the board at a constant velocity until it hits a barrier of some kind. However, in the presence of these effects, the sprite’s velocity does change.
Springs are created using the create spring method of the board. They have been covered already. The acceleration induced on a sprite by a spring’s force is inversely proportional to the sprite’s mass. The heavier the sprite, the longer it will take for a spring to have its full effect. Each sprite has a default mass which is simply the product of the sprite’s width and height. However, that default can be overridden by the sprite’s set mass method. A mass cannot be made zero or negative.
A gravitational force can be specified for the board and this applies a force to every sprite, excluding any anchor sprites. The size of the force is proportional to the sprite’s mass. However, the effect of the force on a sprite’s speed is inversely proportional to the mass, so the acceleration induced by gravity is independent of the sprite’s mass.
An additional force which works to slow down a moving sprite is friction. A friction value can be specified for the board using its set friction method. This becomes the default friction value for all sprites on the board. However, friction can also be set for individual sprites using the set friction method of the Sprite instance.
All these forces listed above combine to produce the net force on a sprite and cause a sprite to move. If the combined forces do not produce the desired effect, there is one more adjustment which can be made. This adjustment is produced by the set acceleration method, covered in the next subsection of this chapter.
When a sprite hits an obstacle, the sprite rebounds with a new velocity in a new direction. The magnitude of that new velocity is determined by the product of the elasticities of the sprite and the obstacle. If both elasticities are 1, it is a perfect bounce which loses no energy. The sprite loses no speed. If the product is 0, the sprite loses all its speed and stays stuck to the obstacle.
The current implementation of the game board in TouchDevelop does not detect collisions between sprites. This would require too much computation, especially if there are many sprites. One sprite will simply appear to pass through another sprite.

managing sprites

Implementing a game will usually require some extra programming which is not provided by the features of boards and sprites covered so far.
For collision detection, the overlap with and overlaps with methods should help. Provided that the sprites are not moving so fast or the sprites are not so small that one sprite completely passes through another sprite during one time step, the colliding sprites will overlap when drawn on the board. The two methods allow such the collision to be detected, and then the directions of motion of the two sprites can be overridden to simulate the two sprites bouncing off each other.
If, for example, the sprites represent planets revolving around a star, a spring force between a planet and the star is a long way from being a proper implementation of gravitational attraction. In this situation, a good approach would be to avoid using springs altogether and to calculate the force induced on a planet by gravitational attraction. Combining that force with the planet’s current velocity and its mass allows the acceleration induced by gravitational attraction to be calculated. And that acceleration can be explicitly given to the planet by the set acceleration method. When an acceleration is specified, the effect of the acceleration is in addition to any accelerations induced by springs and gravity. The acceleration value remains in effect until changed by a new call to set acceleration.
Another possibility is that a sprite needs to be destroyed and removed from the board. In this case, the delete method should be invoked. The sprite instance is automatically removed from the board and from all sprite collections. Any references to the instance become invalid.

Sprite Set Datatype

When writing simple games with multiple objects of the same kind (e.g. multiple shots, missiles, etc.), it quickly becomes necessary to group related sprites into collections. The Board datatype provides the method board→create sprite set which creates a new empty collection of sprites.
Sprite Set provides most of the methods common to the mutable collection types. These are the methods add, add many, at, count, is invalid, and post to wall. However, there is a major difference. All the other collection types are lists of values. It implies that the same value can appear in the list several times. A Sprite Set is, in contrast, an ordered set. A value can appear at most once in the set. The elements of the set are ordered by their index positions.

touch and board events

The board has six specific kinds of events which are covered in the subsections below. All but one of these events are triggered when the user touches the screen and taps, swipes or drags a finger across the board.

touching actions

In addition to events, the Board datatype provides five methods which can be used to gather information about how the screen has been touched. However the tap, swipe and drag events explained later in this section are easier to program and their use is recommended.
  • touch current: returns the coordinates of the current touch point on the board; the z component is 0.
  • touch end: returns the coordinates of the last touch point on the board; the z component is 0
  • touch start: returns the coordinates of the latest start point for a touch gesture on the board; the z component is 0
  • touch velocity: returns the final swiping velocity after a touch has gesture; the z component is 0
  • touched: returns true if the board has been touched

gameloop Event

The gameloop event contains code that needs to be run regularly and frequently. The event is triggered about every 50ms. It is a natural location to contain collision detection code, or to monitor the passage of time.
event
gameloop
()
apply physics
 board → evolve
refresh display
 board → update on wall
end event
The gameloop event code should be efficient. If it takes too long to execute, the display may stutter and collisions may go undetected.

tap board Event

The tap board event fires if there is tap anywhere on the board except on a position where a sprite is located. Tapping means that one’s finger leaves the screen at approximately the same position as where it first touched. Otherwise, the application will report a swipe event instead. The event fires once the finger is lifted.
As an example, the code below creates a new ball wherever there is a tap.
event
tap board: board
(
x : Number,
y : Number)
do
var sprite :=  board → create ellipse(20, 20)
sprite → set pos(x, y)
end event
The tap board event has two parameters x and y which give the position where the tap occurred.

swipe board Event

The swipe board event is similar, except that the event code is passed four parameters. The first two show where the swipe started and the second two show the extent of the swipe in the x and y dimensions.
As an example, the code below creates a new sprite and gives it an initial speed which corresponds to the extent of the swipe.
event
swipe board: board
(
x : Number,
y : Number,
delta x : Number,
delta y : Number)
do
var sprite :=  board → create ellipse(20, 20)
sprite → set pos(x, y)
sprite → set speed(delta x, delta y)
end event

tap sprite in YYY Event

Tap events can be provided for sprites held in different sprite sets. This makes it easier to program one kind of action for a spaceship, say, and a different kind of action when tapping an asteroid, say.
If, for example, there is a global data variable named spaceships with the type Sprite Set, then an event named tap sprite in asteroids can be provided. The event is passed four parameters. These are the sprite which was tapped, the index of the sprite in the sprite set, and the coordinates of the sprite on the board.
function
main sprite sets
()
… create board
 asteroids :=  board → create sprite set
populate board and asteroids with sprites
...
end function
A sample of code which uses the event is as follows:
event
tap sprite in asteroids
(
sprite : Sprite,
index in set : Number,
x : Number,
y : Number)
do
change the asteroid color
sprite → set color(colors → random)
end event

swipe sprite in YYY Event

The swipe sprite event is similar to the tap sprite event, except that one’s finger is swiped across the screen and the extent of the swipe is passed as two additional parameters.
For example, the following code will cause the sprite which is swiped to start moving in the direction of the swipe.
event
swipe sprite in asteroids
(
sprite : Sprite,
index in set : Number,
x : Number,
y : Number,
delta x : Number,
delta y : Number)
do
sprite → set speed(delta x, delta y)
end event

drag sprite in YYY Event

A drag event does not wait for the finger to be lifted from the screen, as with the tap and swipe events. It fires while one’s finger is still on the screen. It will repeatedly fire while the finger is in motion across the screen. The event is passed very similar parameters to the swipe sprite event, except that the last two parameters provide the extent of the dragging motion (so far).
The event can be used to temporarily set the speed of a dragged sprite to 0 and to display it at the current drag position. In this way, it will appear that the sprite is being held at the finger’s position.
Here is example coding with the asteroids:
event
drag sprite in asteroids
(
sprite : Sprite,
index in set : Number,
x : Number,
y : Number,
delta x : Number,
delta y : Number)
do
sprite → set pos(x, y)
sprite → set speed(delta x, delta y)
end event
When the finger is lifted at the end of the motion, a swipe sprite event is triggered (if event code for that action has been provided).

tap sprite YYY, swipe sprite YYY, drag sprite YY

Instead of having events associated with sprite sets, it is possible to have events associated with an individual sprite. To do this, the sprite must be promoted to be a global data variable (in the data section of a script).
If the data variable is named asteroid, then the corresponding event names are tap sprite: asteroid, swipe sprite: asteroid and drag sprite: asteroid.

debugging Games

To make it a bit simpler to debug sprite position and speed related problems in scripts, the debug mode for the board can be enabled.
 board → set debug mode(true)
If debug mode is on, the board will display the position and speed of a sprite next to the sprite content. Additionally, the width and height is displayed as a box around the sprite. Also, in debug mode, even invisible sprites are displayed. This can be useful for finding forgotten sprites or where anchors are placed.