Coding hints IV: JavaScript Game Development with codeguppy.com

Game development is extremely easy and fun with 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

Sprites

Music and Sound Effects

Other

Multi-scene games

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

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:

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:

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.

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

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

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

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.

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:

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:

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:

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:

Custom palette for custom sprites

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

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.

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.

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.

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:

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:

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:

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

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
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).

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:
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 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

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

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

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

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 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)

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)

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)

Detect collision between two circles

Use the following instruction to detect collisions between two circles:

collisionCircleCircle(circle1X, circle1Y, circle1R, 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)

Detect collision between two rectangles

Use the following instruction to detect collision between two rectangles:

collisionRectRect(rect1X, rect1Y, rect1Width, rect1Height, 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)

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)

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()

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.

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:

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:

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.

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

showScene("Congrats", 1000);

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

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

Passing a complex structure to "Congrats" scene

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:

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:


This article is part of a series of mini-articles containing JavaScript coding hints applicable to codeguppy.com environment:

Read more blog articles Browse JavaScript projects

About codeguppy

CodeGuppy is a FREE coding platform for schools and intependent learners. If you don't have yet an account with codeguppy.com, you can start by visiting the registration page and sign-up for a free account. Registered users can access tons of fun projects!


Follow @codeguppy on Twitter for coding tips and news about codeguppy platform. For more information, please feel free to contact us.