Do you like my tutorials?

Then consider supporting me on Ko-fi

Talking about Stairs game, 3D, Game development, Godot Engine and HTML5.

Here we go with the 3rd step of the development of a “Stairs” HTML5 prototype using Godot.

In first step, we saw how to build an endless staircase, in second step we added spikes and assigned materials to the meshes. Now it’s time to add the bouncing ball.

We need to add another child node to the scene, so right click on Spatial in Scene panel and select Add Child Node.

As usual, select MeshInstance.

We want to give the node a better name, so let’s right click on it, select Rename and call it Ball.

This is how your Scene panel should look now:

Now let’s give our mesh instance an actual mesh: select Ball and in the Inspector panel in Mesh selector choose New SphereMesh.

Now click on the white sphere picture and you should see the sphere has Radius = 1 and Height = 2. If you followed the tutorial using my values for step and spike sizes, you don’t need to change these values.

Anyway, if you need a bigger or smaller sphere, just remember to set Height to 2 * Radius.

Don’t worry about positioning the mesh, because we’ll do it at runtime by code. But we want to change the material, so in Material selector choose New SpatialMaterial.

Then click on the white sphere and choose Albedo -> Color, then change the color.

I painted my sphere blue.

Now we are ready to write some code, so let’s select Ball in Scene Panel, right click on it and choose Attach Script.

No need to change anything, so click on Create.

This is what you should see in the main window: the new default script and Ball.gd highlighted.

Let’s start with this simple script:

extends MeshInstance

# ball starting step. 0: first step, 1: second step, and so on
var ballStartingStep = 1

# Called when the node enters the scene tree for the first time.
func _ready() :
	
	# get Step reference
	var step = get_node('/root/Spatial/Step')
	
	# determine ball y position according to step size and starting step
	translation.y = step.mesh.size.y * ballStartingStep + step.mesh.size.y / 2 + mesh.radius
	
	# determine ball z position according to step size and starting step
	translation.z = -step.mesh.size.z * ballStartingStep

I wanted to add room for customization to the game, so I will let players decide the step to place the ball over.

First step is step zero, second step is step one, an so on.

This is what you get if you run the game with ballStartingStep = 1:

And this is what you’d get if you run the game with ballStartingStep = 3:

I am going to stick to ballStartingStep = 1, but you are free to experiment how the game feels with various ballStartingStep values.

Now let’s make the ball bounce. As explained in the Phaser tutorial, we aren’t looking for a complex physics simulation, but for a quick and easy hyper casual game, so a sine movement will be more than enough.

The only thing we need to know is the amount of time required for the ball to jump, that is the time needed for a step to move one step down.

We can determine such time this way: Jump Time = Step Height / Step Speed.

So let’s change Ball.gd script this way:

extends MeshInstance

# ball starting step. 0: first step, 1: second step, and so on
var ballStartingStep = 1

# jump height, should be higher than step height
var jumpHeight = 5

# here we'll store the jump time, that is the time required for a step to take the place of another
var jumpTime

# here we'll store the amount of time the ball is in play
var ballTime

# we need to store ball starting y position to determine its y position when it's jumping
var ballY

# Called when the node enters the scene tree for the first time.
func _ready() :
	
	# get Step reference
	var step = get_node('/root/Spatial/Step')
	
	# jump time, in seconds, is step height divided by step speed
	jumpTime = step.mesh.size.y / step.get('speed') * 1000
	
	# ballTime starts at zero
	ballTime = 0
	
	# determine ball y position according to step size and starting step
	ballY = step.mesh.size.y * ballStartingStep + step.mesh.size.y / 2 + mesh.radius
	
	# move the ball to ballY position
	translation.y = ballY
	
	# determine ball z position according to step size and starting step
	translation.z = -step.mesh.size.z * ballStartingStep
	
# called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta) :
	
	# increase ballTime assing delta to it
	ballTime += delta * 1000
	
	# if ballTime is greater or equal than jump time...
	if (ballTime >= jumpTime) :
		
		# subtract jumpTime to ballTime
		ballTime -= jumpTime
	
	# ratio ranges from 0 (ball at the beginning of jump time) to 1 (ball at the end of jump time)
	var ratio = ballTime / jumpTime
	
	# move the ball to y position equal to sin of ratio * PI multiplied by jump height
	translation.y = ballY + sin(ratio * PI) * jumpHeight

And now we can have our ball performing fake jumps along the staircase just using trigonometry.

This is where this step ends, next time we’ll see how to control ball movement. Meanwhile, download the Godot project and have fun with it.

Never miss an update! Subscribe, and I will bother you by email only when a new game or full source code comes out.