Coding Hints. Part IV: Game Development
Tags: javascript, codeguppy, codenewbie, beginners
Published: 2020-10-23 03:14:46


Game development is extremely easy and fun with [codeguppy.com](https://codeguppy.com). The system comes with built-in background images, sprites, music and sound effects to allow you to focus on the code rather than searching for assets.

Layers and Background Images

- [Drawing layers](#drawing-layers)
- [Setting Background Images](#setting-background-images)

Sprites

- [Loading built-in sprites](#loading-built-in-sprites)
- [Loading custom sprites](#loading-custom-sprites)
- [Loading animated custom sprites](#animated-custom-sprites)
- [Set sprite position](#set-sprite-position)
- [Moving sprites automatically](#moving-sprites-automatically)
- [Mirroring Sprites](#mirroring-sprites)
- [Sprite rotation](#sprite-rotation)
- [Rotate sprites automatically](#rotate-sprites-automatically)
- [Drawing depth](#drawing-depth)
- [Changing animations](#changing-animations)
- [Mouse events on sprites](#mouse-events-on-sprites)
- [Hiding sprites](#hiding-sprites)
- [Removing sprites](#removing-sprites)
- [Sprite Collisions](#sprite-collisions)
- [Sprite Groups](#sprite-groups)

Music and Sound Effects

- [Background Music](#background-music)
- [Sound Effects](#sound-effects)

Other

- [Collisions between shapes](#collisions-between-shapes)
- [The Game Loop](#the-game-loop)
- [Preloading assets](#preloading-assets)

Multi-scene games

- [Showing a scene](#showing-a-scene)
- [The enter event](#the-enter-event)
- [Passing data to a scene](#passing-data-to-a-scene)

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/47ruzhii50f02c0xp8ar.png)

# Drawing Layers

codeguppy.com has a layered drawing architecture. There are up to 5 drawing layers on top of the canvas at any time as shown in the following diagram:

![Drawing Layers](https://dev-to-uploads.s3.amazonaws.com/i/1lz6rif2e66xgp238kj0.png)

The engine combines automatically all the layers and displays the final image on the screen.

# Setting Background Images

The `background` command was also presented in the "Drawing" section as a way to set the background color of the canvas, like this:

```javascript
background('LightBlue');
```

However, background command can do more than just setting a plain color as a background.

Using the same function, you can set any image from the codeguppy.com library as background:

```javascript
background('Summer');
```

💡 To set the background to an image, open the "Backgrounds" palette, and drag and drop an image in the code area. The system will write the appropriate code for you.

> The `background` commands sets the image in the Background layer as presented in the above diagram. In this way the background image won't be erased or altered by `clear()` instruction or shape drawing instructions or even sprites.

# Sprites

Sprites are small images, often animated, that you can load and manipulate through the code. Sprites are an essential ingredient of a succesful game.

codeguppy.com contains a big library of built-in sprites, and in the same time it offers the user the ability to define custom sprites.

# Loading Built-in Sprites

You can load any sprite from the built-in library using the `sprite` command.

### Loading a sprite

The `sprite` instruction will load the built-in sprite `plane` and place it in the middle of the screen.

```javascript
background('Summer');
sprite('plane');
```

💡 Open the Sprites palette and browse all the included built-in sprites. When you find one that you like, drag and drop it in the code editor and the system will write the code automatically.

### Loading and positioning a sprite

```javascript
background('Summer');
sprite('plane', 400, 200);
```

### Loading and scaling a sprite

In the following code snippet, the sprite `plane` is scalled to `0.5` before being placed in the middle of the screen

```javascript
background('Summer');
sprite('plane', 0.5);
```

### Loading, positioning and scaling of a sprite

In the following code snippet, the sprite `plane` is scalled to `0.5` before being placed in the middle of the screen

```javascript
background('Summer');
sprite('plane', 400, 150, 0.5);
```

### Loading a particular animation of a sprite

For multi-animation sprites, you can specify the default animation at load time by including it in the same string as the sprite name using a `.` symbol (e.g. `plane.shoot`)

💡 You can discover what animations are supported by each sprite, by hovering the mouse over sprites in the "Sprites" palette. Check the information provided in the tooltip.

```javascript
background('Summer');
sprite('plane.shoot', 400, 150, 0.5);
```

> Note: For sprites with multiple animations, you can also change the displayed animation later-on using the sprite `.show()` method.

# Loading custom sprites

For games that required custom graphics, users can define additional custom sprites directly in the code. codeguppy.com uses the Microsoft MakeCode Arcade format for custom sprites with up to 16 colors.

### From text to images

Use `img` in a string template, or as a function, to convert a custom-sprite text to an image

```javascript
let img1 = img`
    . . . . . . . . . . . . . . . .
    . . . . . . . 7 7 7 . . . . . .
    . . . . . . . 7 7 7 . . . . . .
    . . . . . 7 7 7 7 7 7 7 . . . .
    . . . . 2 2 7 7 7 7 7 2 2 . . .
    . . . 2 5 2 2 7 7 7 2 2 5 2 . .
    . . 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    . . 2 5 2 2 5 2 2 2 5 2 2 5 2 .
    . . 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    . . . 2 2 5 2 2 5 2 2 5 2 2 . .
    . . . . 2 2 2 2 2 2 2 2 2 . . .
    . . . . . 2 2 5 2 2 5 2 . . . .
    . . . . . 2 2 2 2 2 2 2 . . . .
    . . . . . . 2 2 5 2 2 . . . . .
    . . . . . . . 2 2 2 . . . . . .
    . . . . . . . . . . . . . . . .
`;

noSmooth();
image(img1, 250, 300, img1.width * 3, img1.height * 3);
```

### From images to sprites

Custom sprites can also be loaded using the `sprite` command. In this way you can manipulate them like the rest of built-in sprites.

```javascript
sprite(img`
    . . . . . . . . . . . . . . . .
    . . . . . . 4 4 5 . . . . . . .
    . 8 8 8 8 8 4 4 4 8 8 8 8 8 . .
    . . . . . . . f . . . . . . . .
    . . . . . 8 8 8 8 8 . . . . . .
    . . . . 8 1 1 8 1 1 8 . . . . .
    . . . . 8 1 f 8 f 1 8 . . . . .
    . . 8 . 8 8 8 2 8 8 8 . 8 . . .
    . . 8 8 8 2 8 8 8 2 8 8 8 . . .
    . . . . 8 8 2 2 2 8 8 . . . . .
    . . . . 8 8 8 8 8 8 8 . . . . .
    . . . . 8 8 8 8 8 8 8 . . . . .
    . . . . 8 . . . . . 8 . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`, 10);
```

### Animated custom sprites

A custom sprite can also be animated. If you need animated sprites, then you need to create multiple frame images for each sprite.

```javascript
// Note: Shark images are from Microsoft MakeCode Arcade
// https://arcade.makecode.com/

var shark1 = img`
    . . . . . . . . . . . . . c c f f f . . . . . . . . . . . . . .
    . . . . . . . . . . . c c d d b c f . . . . . . . . . . . . . .
    . . . . . . . . . . c c d d b b f . . . . . . . . . . . . . . .
    . . . . . . . . . . f c c b b c f . . . . . . . . . . . . . . .
    . . . . . f f f f f c c c c c c f f . . . . . . . . . c c c . .
    . . . f f b b b b b b b c b b b b c f f f . . . . c c b b c . .
    . . f b b b b b b b b c b c b b b b c c c f f . c d b b c . . .
    f f b b b b b b f f b b c b c b b b c c c c c f c d b b f . . .
    f b c b b b 1 1 f f 1 b c b b b b b c c c c c f f b b f . . . .
    f b b b 1 1 1 1 1 1 1 1 b b b b b c c c c c c c b b c f . . . .
    . f b 1 1 1 3 3 c c 1 1 b b b b c c c c c c c c c c c f . . . .
    . . f c c c 3 1 c 1 1 1 b b b c c c c c b d b f f b b c f . . .
    . . . f c 1 3 c 1 1 1 c b b b f c d d d d c c . . f b b f . . .
    . . . . f c c c 1 1 1 f b d b b c c d c c . . . . . f b b f . .
    . . . . . . . . c c c c f c d b b c c . . . . . . . . f f f . .
    . . . . . . . . . . . . . f f f f f . . . . . . . . . . . . . .
`;

var shark2 = img`
    . . . . . . . . . . . . . c c f f f . . . . . . . . . . . . . .
    . . . . . . . . . . . . c d d b b f . . . . . . . . . . . . . .
    . . . . . . . . . . . c d d b b f . . . . . . . . . . . . . . .
    . . . . . . . . . . f c c b b c f . . . . . . . . . . . . c c c
    . . . . f f f f f f c c c c c c f f . . . . . . . . . c c b b c
    . . f f b b b b b b b b b b b b b c f f f . . . . . c d b b c .
    f f b b b b b b b b b c b c b b b b c c c f f . . c d d b b f .
    f b c b b b b b f f b b c b c b b b c c c c c f f f d b b f . .
    f b b b 1 1 1 1 f f 1 b c b c b b b c c c c c c c b b b c f . .
    . f b 1 1 1 1 1 1 1 1 b b b b b b c c c c c c c c c b c c f . .
    . . f c c c 3 3 c c 1 1 b b b b c c c c c c c c f f f b b c f .
    . . . f c 1 3 1 c 1 1 1 b b b c c c c c b d b c . . . f b b f .
    . . . . f 3 3 c 1 1 1 c b b b f d d d d d c c . . . . . f b b f
    . . . . . f f 1 1 1 1 f b d b b f d d c c . . . . . . . . f f f
    . . . . . . . c c c c c f b d b b f c . . . . . . . . . . . . .
    . . . . . . . . . . . . . f f f f f . . . . . . . . . . . . . .
`;

var shark3 = img`
    . . . . . . . . . . . . . . c f f f . . . . . . . . . . . . . .
    . . . . . . . . . . . . c c d d b f . . . . . . . . . . . . . .
    . . . . . . . . . . . c b d d b f f . . . . . . . . . c c c . .
    . . . . . . . . . . f c c b b c f . . . . . . . . . c b b c . .
    . . . f f f f f f f c c c c c c f f . . . . . . . c d b c . . .
    . f f c b b b b b b b b b b b b b c f f f . . . . c d b f . . .
    f c b b b b b b b b b c b b b b b b c c c f f . c d b f . . . .
    f b c b b b b f f b b b c b c b b b c c c c c f f d c f . . . .
    f b b 1 1 1 1 f f b b b c b c b b b c c c c c c b b c f . . . .
    . f b 1 1 1 1 1 1 1 1 b b c b b b c c c c c c c c b b c f . . .
    . . f c c c 3 3 c b 1 1 b b b b c c c c c c c f f f b b f . . .
    . . . f c 1 3 1 c 1 1 1 b b b c c c c c b d b c . . f b b f . .
    . . . . f 3 3 c 1 1 1 c b b c c d d d d d b c . . . . f f f . .
    . . . . . f f 1 1 1 1 f d b b c c d d b c c . . . . . . . . . .
    . . . . . . . c c c c c f d b b b f c c . . . . . . . . . . . .
    . . . . . . . . . . . . . f f f f f . . . . . . . . . . . . . .
`;

var shark4 = img`
    . . . . . . . . . . . . . c c f f f . . . . . . . . . . . . . .
    . . . . . . . . . . . . c d d b b f . . . . . . . . . . . . . .
    . . . . . . . . . . . c d d b b f . . . . . . . . . . . . . . .
    . . . . . . . . . . f c c b b c f . . . . . . . . . . . . c c c
    . . . . f f f f f f c c c c c c f f . . . . . . . . . c c b b c
    . . f f b b b b b b b b b b b b b c f f f . . . . . c d b b c .
    f f b b b b b b b b b c b c b b b b c c c f f . . c d d b b f .
    f b c b b b b b f f b b c b c b b b c c c c c f f f d b b f . .
    f b b b 1 1 1 1 f f 1 b c b c b b b c c c c c c c b b b c f . .
    . f b 1 1 1 1 1 1 1 1 b b b b b b c c c c c c c c c b c c f . .
    . . f c c c 3 3 c c 1 1 b b b b c c c c c c c c f f f b b c f .
    . . . f c 1 3 1 c 1 1 1 b b b c c c c c b d b c . . . f b b f .
    . . . . f 3 3 c 1 1 1 c b b b f d d d d d c c . . . . . f b b f
    . . . . . f f 1 1 1 1 f b d b b f d d c c . . . . . . . . f f f
    . . . . . . . c c c c c f b d b b f c . . . . . . . . . . . . .
    . . . . . . . . . . . . . f f f f f . . . . . . . . . . . . . .
`;

sprite([shark1, shark2, shark3, shark4], 400, 300, 2);
```

### Custom sprites with multiple animations

You can even pack multiple animations in a custom sprite. This help you change later on the animations using the sprite `.show()` method.

```javascript
let ship1 = img`
    . . . . . . . . . . . . . . . .
    8 8 1 . . . . . . . . . . . . .
    2 2 2 2 . . . . . . . . . . . .
    2 2 2 2 . . 9 9 9 9 . . . . . .
    8 8 8 8 8 9 9 9 9 9 9 . . . . .
    8 8 8 8 8 9 9 9 9 9 9 9 . . . .
    2 2 2 2 2 9 9 9 9 9 9 9 2 . . .
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    . 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    4 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2
    4 4 4 4 2 2 8 8 8 8 8 8 8 2 2 .
    4 4 . . . 8 8 8 8 8 8 8 . . . .
    . . . . 8 8 8 8 8 8 8 . . . . .
    . . . 8 8 8 8 8 8 8 . . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`;

let ship2 = img`
    . . . . . . . . . . . . . . . .
    8 8 1 . . . . . . . . . . . . .
    2 2 2 2 . . . . . . . . . . . .
    2 2 2 2 . . 9 9 9 9 . . . . . .
    8 8 8 8 8 9 9 9 9 9 9 . . . . .
    8 8 8 8 8 9 9 9 9 9 9 9 . . . .
    2 2 2 2 2 9 9 9 9 9 9 9 2 . . .
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    4 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    . 4 4 2 2 2 2 2 2 2 2 2 2 2 2 2
    4 4 4 4 2 2 8 8 8 8 8 8 8 2 2 .
    . 4 4 . . 8 8 8 8 8 8 8 . . . .
    4 4 . . 8 8 8 8 8 8 8 . . . . .
    . . . 8 8 8 8 8 8 8 . . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
`;

let shipLand1 = img`
    . . . . . . . 8 8 1 . . . . . .
    . . . . . . . 8 2 2 . . . . . .
    . . . . . . . 8 . . . . . . . .
    . . . . . 9 9 9 9 9 . . . . . .
    . . . . 9 9 9 9 9 9 9 . . . . .
    . . . 9 9 9 9 9 9 9 9 9 . . . .
    . . 2 9 9 9 9 9 9 9 9 9 2 . . .
    . 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    . 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    . . 8 8 . . . . . . . . 8 8 . .
    . . 8 8 . . . . . . . . 8 8 . .
    . . 8 8 . . . . . . . . 8 8 . .
    . 8 8 8 8 . . . . . . 8 8 8 8 .
    . 8 8 8 8 . . . . . . 8 8 8 8 .
`;

let shipLand2 = img`
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . . . . . . . . . . . .
    . . . . . 9 9 9 9 9 . . . . . .
    . . . . 9 9 9 9 9 9 9 . . . . .
    . . . 9 9 9 9 9 9 9 9 9 . . . .
    . . 2 9 9 9 9 9 9 9 9 9 2 . . .
    . 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
    . 2 2 2 2 2 2 2 2 2 2 2 2 2 2 .
    . . 8 8 . 4 4 4 4 4 4 . 8 8 . .
    . . 8 8 . . 4 4 4 4 . . 8 8 . .
    . . 8 8 . . . 4 4 . . . 8 8 . .
    . 8 8 8 8 . . . . . . 8 8 8 8 .
    . 8 8 8 8 . . . . . . 8 8 8 8 .
`;

let oShip = { 
    Flying : [ship1, ship2],
    LandingDown : [shipLand1],
    LandingUp : [shipLand2] 
};

sprite(oShip, 40, 100, 3);
```

### Custom palette for custom sprites

If your program required different colors, you can define a custom palette using `setPalette`.

```javascript
// Define a monochrome palette
setPalette(["", "Brown"]);

let pattern = `
1 1 1 1 1 1 1 1
. . . . . 1 . .
. . . . . 1 . .
. . . . . 1 . .
1 1 1 1 1 1 1 1
. . 1 . . . . .
. . 1 . . . . .
. . 1 . . . . .
`;

let imgBrick = img(pattern);

noSmooth();

for(var row = 0; row < 50; row++)
{
    for(var col = 0; col < 30; col++)
    {
        image(imgBrick, 300 + row * 8, 10 + col * 8);
    }
}
```

Note: You can obtain the current palette at any time using the `getPalette()` function.

# Manipulating sprite properties

At runtime, the custom sprites are indistinguishable from the built-in sprites. No matter how you loaded / created the sprite, you can manipulate it in the same way through the code.

The `sprite` command is returning a reference to an object on which you can invoke methods and properties.


### Set sprite position

The `sprite` command is returning a reference to a sprite object. Use the `.x` and `.y` properties to update the sprite position on the screen.

```javascript
let player = sprite('adventure_girl.idle', 400, 300, 0.5);

player.x = 100;
player.y = 100;
```

### Moving sprites automatically

Instead of changing the `.x` and `.y` coordinates yourself, you can let the engine move the sprite automatically on x or y axes by specifying a value for the appropriate `.velocity`. 

```javascript
let plane = sprite('plane.fly', 0, 100, 0.5);
plane.velocity.x = 1;
```

### Mirroring Sprites

Sometimes you need to flip a sprite on either `.x` axis or `.y` axis. 

To mirror a sprite use the `.mirror` method with `-1` as argument. To mirror it to the original direction use `1` as argument.

```javascript
plane.mirrorX(-1);
```

### Sprite rotation

In certain games and programs, you may want to rotate your sprites at an arbitrary angle. You can do this using the `.rotation` property which allow you to specify a rotation angle.


### Rotate sprites automatically

If you want the sprite to rotate automatically for an indefinite time, you can put it on autorotate by giving a greater than zero value to `.rotationSpeed` property.

```javascript
background('Summer');

for(let i = 0; i < 10; i++)
{
    let flower = sprite(img`
    . . . . . . . . . . . . . . . .
        . . . . . . . 5 5 . . . . . . .
        . . . . 5 5 . 5 5 . 5 5 . . . .
        . . . . 5 5 5 5 5 5 5 5 . . . .
        . . 5 5 . 5 f e f e 5 . 5 5 . .
        . . 5 5 5 f e f e f e 5 5 5 . .
        . . . 5 f e f e f e f e 5 . . .
        . 5 5 5 e f e f e f e f 5 5 5 .
        . 5 5 5 f e f e f e f e 5 5 5 .
        . . . 5 e f e f e f e f 5 . . .
        . . 5 5 5 e f e f e f 5 5 5 . .
        . . 5 5 . 5 e f e f 5 . 5 5 . .
        . . . . 5 5 5 5 5 5 5 5 . . . .
        . . . . 5 5 . 5 5 . 5 5 . . . .
        . . . . . . . 5 5 . . . . . . .
        . . . . . . . . . . . . . . . .
    `, random(width), random(-height, 0), 3);
    
    flower.velocity.y = random(1, 3);
    
    flower.rotationSpeed = 2;
}
```

### Drawing depth

Normally, newly added sprites are drawn on top of the previous ones.

To control which sprite is drawn on top, and which one is drawn behind, you can make use of the `.depth` property. Sprites with lower depth are drawn behind the ones with higher depth.

You can also combine sprites with classical shaped drawn using graphical APIs (`circle`, `rect`, etc.).  

If you want sprites to appear behind the graphical plane, make sure you give sprites a negative depth, otherwise they will be drawn on top of the graphical plane.

### Changing animations

If the sprite you selected contains multiple animations, you can specify what animation you want to display initially by adding the animation name with a `.` in the string of the first parameter:

```javascript
let player = sprite('adventure_girl.idle', 400, 300, 0.5);
```

However, later one, you can change the animation of that sprite using the `.show` method:

```javascript
player.show('run');
```

💡 Please check carefully the animations supported by a sprite by hovering over the sprite thumbnail in the Sprites palette.


### Mouse events on sprites

You can detect mouse clicks on sprites by assigning an event handler (e.g. function) to the following sprite properties:

- `.onMousePressed`
- `.onMouseReleased`
- `.onMouseOver`
- `.onMouseOut`

```javascript
let btnTrophy = sprite('CandyTrophy', 400, 300, 1);

btnTrophy.onMousePressed = btnTrophy_onMousePressed;
btnTrophy.onMouseOver = btn_onMouseOver;
btnTrophy.onMouseOut = btn_onMouseOut;

function btnTrophy_onMousePressed(sender)
{
    sound('female_congratulations');    
}

function btn_onMouseOver(sender)
{
    sender.scale = 1.1;
}

function btn_onMouseOut(sender)
{
    sender.scale = 1;
}
```

### Hiding sprites

You can hide a sprite in two ways:

-	Setting the `.visible` property to false
-	Setting the `.x` and / or `.y` coordinates outside of the visible canvas

```javascript
let p = sprite('adventure_girl.idle', 400, 300, 0.5);

function mouseClicked()
{
    p.visible = !p.visible;
}
```

### Removing sprites

To permanently remove a sprite from the program, use the `.remove()` method on the sprite. This is useful for sprites just as destroyed enemies, collected items, etc.

You can also make a sprite auto-remove after a certain number of frames using the `.life` property. This is useful for objects such as bullets, rockets, etc. that you shoot and forget about them. Collectibles can make use of this property. By default this property has value `-1` (disabled).

```javascript
let score = 0;

for(let i = 0; i < 10; i++)
{
    let coin = sprite('coin.bronze', random(100, 700), random(50, 550), 0.5);
	
	// Make the coin autoremove itself
    coin.life = randomInt(100, 300);
	
    coin.onMousePressed = coin_onMousePressed;
}

function coin_onMousePressed(sender)
{
    sender.remove();
    score++;
}
```

### Sprite Collisions

There are 4 different methods to verify if sprites are colliding:

- `sprite.collide(target, callback);`
- `sprite.displace(target, callback);`
- `sprite.overlap(target, callback);`
- `sprite.bounce(target, callback);`

When called, some of these methods are automatically displacing the sprites, others are impacting their trajectories. They all return a Boolean indicating if the collision happened.

Experiment with these methods to discover their behaviors!

Parameters:

- `target` – this is a reference to the other sprite or group of sprites (more about groups later)
- `callback` – this is optional, but useful in some cases. Callback is a function with the following signature, that gets called automatically in case of collision:

```javascript
function onCollide(spr, target)
{
    score++;
}
```

> Note: Another way to check collisions between sprites, or between sprites and other shapes is by using the following [shape collision](#collisionsbetweenshapes) functions.

### Sprite groups

In games with multiple sprites of the same kind, it is sometimes useful to group various sprites in a single group created with `new Group()`

Main methods of a group are:

- `.add(sprite)` - Add a sprite to the group
- `.remove(sprite)` – Removes a sprite from the group
- `.clear()` - Removes sprites from group. Does not remove sprites from program.
- `.contains(sprite)` - Check if the specified sprite is in the group

```javascript
let player = sprite('game.happy', 400, 300, 0.5);
let coins = new Group();

for(let i = 0; i < 10; i++)
{
    let coin = sprite('coin', random(100, 700), random(50, 550), 0.5);
    
    // add coin to the group
    coins.add(coin);
}

function loop()
{
    player.x = mouseX;
    player.y = mouseY;
    
    // check collision against the group
    player.collide(coins, onCollision)
}

function onCollision(player, coin)
{
    // remove coin from the group
    coins.remove(coin);

    coin.velocity.y = -10;
    coin.life = 100;
}
```

Note: Certain methods, such as sprite collision methods can operate on an entire group of sprites, rather than on a single sprite (as explained on the previous page).


# Background Music

### Play music named Rainbow

```javascript
music('Rainbow');
```

Note: If any music was playing before, the `music` instruction interrupts that before playing the new music.

### Play music named "Fun Background" at volume 0.1

```javascript
music('Fun Background', 0.1);
```

💡 Use the "Music and Sounds" palette to discover music. When you find something that you like, drag and drop the song in the code area. The system will write the appropriate code for you.

# Sound Effects

### Play sound `zap1`

```javascript
sound('zap1');
```

Note: The system plays in parallel all sounds triggered with the `sound` command.

💡 Use the "Music and Sounds" palette to discover sound effects. When you find something that you like, drag and drop the song in the code area. The system will write the appropriate code for you.

# Collisions between shapes

💡 If your game is using only sprites, then we recommend you to use [sprite collision](#spritecollisions) methods.

However, if you are not using sprites, or if you use sprites in combination with regular shapes, you can use the following methods to detect collisions. They take as arguments the parameters of the two shapes and return `true` if the two shapes collide.

> Note: For convenience, some instructions are define twice, with the arguments describing the shaped inversed.

### Detect collision between point and circle

Use any of these instructions to detect the collision between a point and a circle:

collisionPointCircle(pointX, pointY, circleX, circleY, circleR)
collisionCirclePoint(circleX, circleY, circleR, pointX, pointY)


```javascript
let circleX = 400;
let circleY = 300;
let circleR = 200;

function loop()
{
    clear();
    
    let collide = collisionPointCircle(mouseX, mouseY, circleX, circleY, circleR);
    stroke(collide ? "red" : "black");
    
    circle(circleX, circleY, circleR);
}
```


### Detect collision between point and line

Use any of these two instructions to detect the collision between a point and a line:

collisionPointLine(pointX, pointY, lineX1, lineY1, lineX2, lineY2)
collisionLinePoint(lineX1, lineY1, lineX2, lineY2, pointX, pointY)

```javascript
let lineX1 = 300;
let lineY1 = 400;
let lineX2 = 500;
let lineY2 = 200;

function loop()
{
    clear();

    let collide = collisionPointLine(mouseX, mouseY, lineX1, lineY1, lineX2, lineY2);
    stroke(collide ? "red" : "black");

    line(lineX1, lineY1, lineX2, lineY2);
}
```

### Detect collision between a point and a rectangle

Use any of the following two instructions to detect collisions between a point and a rectangle:

collisionPointRect(pointX, pointY, rectX, rectY, rectWidth, rectHeight)
collisionRectPoint(rectX, rectY, rectWidth, rectHeight, pointX, pointY)

```javascript
let rectX = 250;
let rectY = 200;
let rectWidth = 300;
let rectHeight = 200;

function loop()
{
    clear();

    let collide = collisionPointRect(mouseX, mouseY, rectX, rectY, rectWidth, rectHeight);
    stroke(collide ? "red" : "black");

    rect(rectX, rectY, rectWidth, rectHeight);
}
```


### Detect collision between two circles

Use the following instruction to detect collisions between two circles:

collisionCircleCircle(circle1X, circle1Y, circle1R, circle2X, circle2Y, circle2R)

```javascript
let circle1R = 50;
let circle2X = 400;
let circle2Y = 300; 
let circle2R = 100;

function loop()
{
    clear();

    let circle1X = mouseX;
    let circle1Y = mouseY;

    let collide = collisionCircleCircle(circle1X, circle1Y, circle1R, circle2X, circle2Y, circle2R)
    stroke(collide ? "red" : "black");

    circle(circle1X, circle1Y, circle1R);
    circle(circle2X, circle2Y, circle2R);
}
```

### Detect collision between a circle and a rectangle

Use any of the following two instructions to detect collisions between a circle and a rectangle:

collisionCircleRect(circleX, circleY, circleR, rectX, rectY, rectWidth, rectHeight)
collisionRectCircle(rectX, rectY, rectWidth, rectHeight, circleX, circleY, circleR)

```javascript
let circleR = 50;
let rectX = 250;
let rectY = 200;
let rectWidth = 300;
let rectHeight = 200;

function loop()
{
    clear();

    let circleX = mouseX;
    let circleY = mouseY;

    let collide = collisionCircleRect(circleX, circleY, circleR, rectX, rectY, rectWidth, rectHeight);
    stroke(collide ? "red" : "black");

    circle(circleX, circleY, circleR);
    rect(rectX, rectY, rectWidth, rectHeight);
}
```

### Detect collision between two rectangles

Use the following instruction to detect collision between two rectangles:

collisionRectRect(rect1X, rect1Y, rect1Width, rect1Height, rect2X, rect2Y, rect2Width, rect2Height)

```javascript
let rect1X = 0;
let rect1Y = 0;
let rect1Width = 100;
let rect1Height = 50;

let rect2X = 250;
let rect2Y = 200;
let rect2Width = 300;
let rect2Height = 200;

function loop()
{
    clear();

    rect1X = mouseX;
    rect1Y = mouseY;

    let collide = collisionRectRect(rect1X, rect1Y, rect1Width, rect1Height, rect2X, rect2Y, rect2Width, rect2Height);
    stroke(collide ? "red" : "black");

    rect(rect1X, rect1Y, rect1Width, rect1Height);
    rect(rect2X, rect2Y, rect2Width, rect2Height);
}
```

### Detect collision between two lines

Use this instruction to detect collisions between two lines:

collisionLineLine(x1, y1, x2, y2, x3, y3, x4, y4)

```javascript
let x1 = 400;
let y1 = 300;
let x2 = 0;
let y2 = 0;

let x3 = 300;
let y3 = 400;
let x4 = 500;
let y4 = 200;

function loop()
{
    clear();
    
    x2 = mouseX;
    y2 = mouseY;
    
    let collide = collisionLineLine(x1, y1, x2, y2, x3, y3, x4, y4);
    stroke(collide ? "Red" : "Black");
    
    line(x1, y1, x2, y2);
    line(x3, y3, x4, y4);
}

function mouseClicked()
{
    x1 = mouseX;
    y1 = mouseY;
}
```

### Detect collision between a line and a rectangle

Use any of the following two instructions to detect collisions between a line and a rectangle:

collisionLineRect(x1, y1, x2, y2, x3, y3, w, h)
collisionRectLine(x3, y3, w, h, x1, y1, x2, y2)

```javascript
let x1 = 400;
let y1 = 300;

let x3 = 350;
let y3 = 250;
let w = 300;
let h = 100;

function loop()
{
    clear();
    
    let x2 = mouseX;
    let y2 = mouseY;
    
    let v = collisionLineRect(x1, y1, x2, y2, x3, y3, w, h);
    stroke(v ? "Red" : "Black");
    
    line(x1, y1, x2, y2);
    rect(x3, y3, w, h);
}

function mouseClicked()
{
    x1 = mouseX;
    y1 = mouseY;
}

```

# The Game Loop

In virtually all games, you have to define a "game loop" - a special function that continously gets the user input, updates the game state and renders the game graphics.

In codeguppy.com you can easily implement the "game loop" using the `loop()` function. This is the same function described on the "Drawings" page in the "Animations" section. All you have to do is to define this function in your code, and the codeguppy.com engine will run it for you up to 60 times per second! There is no need to call it yourself.

### If your game is using only sprites

To make your character move on the screen, read the keyboard and update character state (e.g. position) inside the `loop()`

```javascript
background('Road');

let p = sprite('adventure_girl.idle', 400, 400, 0.5);

function loop()
{
    p.show("idle");
    
    if (keyIsDown(LEFT_ARROW)) 
    { 
        p.mirrorX(-1);
        p.x -= 10;
        p.show("run");
    }
    else if (keyIsDown(RIGHT_ARROW)) 
    { 
        p.mirrorX(1);
        p.x += 10;
        p.show("run");
    }
}
```

### If your games is using sprites and shapes

If your game uses also classical shapes, then you need to re-render those inside the `loop` function. Sprites are rendered automatically when you change their properties.

```javascript
background('Field');
textSize(40);

let plane = sprite('plane.fly', 50, 100, 0.3);
let textX = -280;

function loop()
{
    textX++;
    displayBanner();
    
    plane.x++;
}

function displayBanner()
{
    clear();
	fill("White");
	rect(textX - 10, 80, 250, 50);
	fill("Black");
    text("Hello, World!", textX, 120);
}
```

Think of your games as a series of frames! Start by drawing the first frame, then erase it and draw the second frame in a slightly different position, and so on!

# Preloading Assets

codeguppy.com engine automatically scans your code prior to execution to identify what assets (e.g. background, sprites, music, sound effects) need to be loaded. The engine identify these by looking into the corrsponding `background`, `sprite`, `music` and `sound` commands you used.

If these commands don't specify the asset as a constant, then you need to preload the required assets using the `preload` function. Just list all required assets comma separated:

```javascript
preload("adventure_girl", "knight", 'Fun Background');

myMusic = "Fun" + " " + "Background";
music(myMusic);

createPlayer("adventure_girl");
createPlayer("knight");

function createPlayer(spriteName)
{
    return sprite(spriteName, random(width), 300, 0.5);
}
```

# Multi-Scene Games

Support for building multi-scene games is one of the main highlight of codeguppy.com environment! 

By adding more scenes to a game, you're game will appear more polished. In the typical game, you may want to create an "Intro" scene to explain how to play the game, the actual "Game" scene and the "Congrats" scene that shows the congratulations / score after you finish the game.

Each scene is created in a new code page. Make sure you name the code pages appropriately since we need to refer to them later.

### Showing a scene

When the program starts it will always run the first scene you define. To show other scene you need to use the `showScene` method:

```javascript
function mouseClicked()
{
    showScene("Game");
}
```

### The enter event

If your scene contains a function named `enter`, then the engine will automatically run this function when a scene is entered / shown. In a typical game a scene may be shown more than once during the game. For instance the "Game" scene will be shown each time the user restarts the game from the "Intro" scene. 

This gives you the ability to set the scene state appropriately.

> Note: The loose code outside functions is executed just once per scene. Successive displays of the scene won't trigger that code anymore.

```javascript
background("Red");

let score;

function enter()
{
    score = 0;
}
```

### Passing data to a scene

In certain cases, it is useful to pass data to a scene via the `showScene` method. For instance you can pass the game options from the "Intro" scene to the "Game" scene, or the player score from the "Game" scene to the "Congrats" scene.

### Passing a number (e.g. score) to "Congrats" scene

```javascript
showScene("Congrats", 1000);
```

Inside the "Congrats" scene, you can retrieve this passed data in the following way:

```javascript
function enter()
{
    let score = sceneArgs;
    text(score, 400, 300);
}
```

### Passing a complex structure to "Congrats" scene

```javascript
let data = {
    score : 1000,
    time : 10,
    bonusPoints : 100
}

showScene("Congrats", data);
```

Inside the "Congrats" scene, you can retrieve this passed data in the following way:

```javascript
function enter()
{
    let data = sceneArgs;
    
    text("Score: " + data.score, 400, 300);
    text("Time: " + data.time, 400, 320);
    text("Bonus Points: " + data.bonusPoints, 400, 340);
}
```

# Further reading

For a deeper understanding on how to work with sprites in codeguppy.com, please consult these tutorials:

- [Working with built-in sprites](https://codeguppy.com/code.html?t=_sprites_builtin&list=coding)
- [Working with custom sprites](https://codeguppy.com/code.html?t=_sprites_custom&list=coding)

---

codeguppy.com is using the [p5.play](https://molleindustria.github.io/p5.play/) library as the main game engine. Advanded users can consult directly this library for further details. Custom sprites are based on the Microsoft MakeCode Arcade format.

---

This article is part of a series of mini-articles containing JavaScript coding hints applicable to [codeguppy.com](https://codeguppy.com) environment.

- [Coding Hints. Part I: JavaScript syntax](https://dev.to/codeguppy/coding-hints-part-i-javascript-syntax-264m)

- [Coding Hints. Part II: Drawing]
(https://dev.to/codeguppy/coding-hints-part-ii-drawing-2ok9)

- [Coding Hints. Part III: User Input]
(https://dev.to/codeguppy/coding-hints-part-ii-user-input-13ec)

- [Coding Hints. Part IV: Game Development]
(https://dev.to/codeguppy/coding-hints-part-iv-game-development-42l2)

- [Coding Hints. Part V: Other hints]
(https://dev.to/codeguppy/coding-hints-part-v-other-hints-3amb)