Skip to main content

Random Numbers

One way to make games interesting is to add an element of randomness. Easel contains a number of functions that can be used to generate randomness:

  • Random generates a Number between 0 (inclusive) and 1 (exclusive)
  • RandomVector generates a random 2D Vector with a random angle and a length of 1
  • PickRandom can be used to pick a random element from a collection
  • Shuffle can be used to shuffle the contents of an array
  • The surprise block randomly executes one of its subblocks

Random number generator streams

Generating random numbers in a multiplayer game can cause some cosmetic issues sometimes.

When you generate a random number, Easel takes the next number from a stream of random numbers. In a multiplayer game, it is possible we have not yet received all inputs from the other players. When the inputs finally are received, the timeline must rollback to correct itself. The new timeline may draw random numbers from the stream in a different order than the old timeline. This can sometimes be visible to the player.

For example, if you are making apples appear on the screen at random positions, an apple may suddenly jump to a different side of the screen when the timeline is corrected.

Easel has a number of methods to avoid this.

First, in Easel, every entity has its own random number generator, so they will not interfere with each other. The Random function (and all other random functions) take a this parameter, which is the entity that is generating the random number. You do not normally have to provide this most of the time, just call Random and it will find this from context:

Spawn projectile {
use damage = 10 + Random * 15 // same as calling `projectile.Random`
// ...
}

Second, if this is not enough, you can provide an ID to the Random function in order to separate the random number streams even further.

let applePos = RandomVector<apple>

Giving <apple> to RandomVector as its ID will make sure that the random number stream for the apples is separate from the random number stream for other things.

All random functions, and the surprise block support an ID parameter.

let appleX = Random<apple>
let applePos = RandomVector<apple>
Shuffle<apple>(apples)

surprise<apple> {
{ Smitten },
{ Poisoned },
}

Random seed

If you want to have the same random numbers generated every time, you can provide a seed to the random number generator:

RandomSeed(123)
let applePos = RandomVector

You can also provide an ID to the RandomSeed function to initialize a particular random number generator's stream:

RandomSeed<apple>(123)
let applePos = RandomVector<apple>