Build a 3D HTML5 game like “Stairs” using Godot – Step 3: adding the bouncing ball using only trigonometry

Read all posts about "" game

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.

Get the most popular Phaser 3 book

Through 202 pages, 32 source code examples and an Android Studio project you will learn how to build cross platform HTML5 games and create a complete game along the way.

Get the book

215 GAME PROTOTYPES EXPLAINED WITH SOURCE CODE
// 1+2=3
// 100 rounds
// 10000000
// 2 Cars
// 2048
// A Blocky Christmas
// A Jumping Block
// A Life of Logic
// Angry Birds
// Angry Birds Space
// Artillery
// Astro-PANIC!
// Avoider
// Back to Square One
// Ball Game
// Ball vs Ball
// Ball: Revamped
// Balloon Invasion
// BallPusher
// Ballz
// Bar Balance
// Bejeweled
// Biggification
// Block it
// Blockage
// Bloons
// Boids
// Bombuzal
// Boom Dots
// Bouncing Ball
// Bouncing Ball 2
// Bouncy Light
// BoxHead
// Breakout
// Bricks
// Bubble Chaos
// Bubbles 2
// Card Game
// Castle Ramble
// Chronotron
// Circle Chain
// Circle Path
// Circle Race
// Circular endless runner
// Cirplosion
// CLOCKS - The Game
// Color Hit
// Color Jump
// ColorFill
// Columns
// Concentration
// Crossy Road
// Crush the Castle
// Cube Jump
// CubesOut
// Dash N Blast
// Dashy Panda
// Deflection
// Diamond Digger Saga
// Don't touch the spikes
// Dots
// Down The Mountain
// Drag and Match
// Draw Game
// Drop Wizard
// DROP'd
// Dudeski
// Dungeon Raid
// Educational Game
// Elasticity
// Endless Runner
// Erase Box
// Eskiv
// Farm Heroes Saga
// Filler
// Flappy Bird
// Fling
// Flipping Legend
// Floaty Light
// Fuse Ballz
// GearTaker
// Gem Sweeper
// Globe
// Goat Rider
// Gold Miner
// Grindstone
// GuessNext
// Helicopter
// Hero Emblems
// Hero Slide
// Hexagonal Tiles
// HookPod
// Hop Hop Hop Underwater
// Horizontal Endless Runner
// Hundreds
// Hungry Hero
// Hurry it's Christmas
// InkTd
// Iromeku
// Jet Set Willy
// Jigsaw Game
// Knife Hit
// Knightfall
// Legends of Runeterra
// Lep's World
// Line Rider
// Lumines
// Magick
// MagOrMin
// Mass Attack
// Math Game
// Maze
// Meeblings
// Memdot
// Metro Siberia Underground
// Mike Dangers
// Mikey Hooks
// Nano War
// Nodes
// o:anquan
// One Button Game
// One Tap RPG
// Ononmin
// Pacco
// Perfect Square!
// Perfectionism
// Phyballs
// Pixel Purge
// PixelField
// Planet Revenge
// Plants Vs Zombies
// Platform
// Platform game
// Plus+Plus
// Pocket Snap
// Poker
// Pool
// Pop the Lock
// Pop to Save
// Poux
// Pudi
// Pumpkin Story
// Puppet Bird
// Pyramids of Ra
// qomp
// Quick Switch
// Racing
// Radical
// Rebuild Chile
// Renju
// Rise Above
// Risky Road
// Roguelike
// Roly Poly
// Run Around
// Rush Hour
// SameGame
// SamePhysics
// Save the Totem
// Security
// Serious Scramblers
// Shrink it
// Sling
// Slingy
// Snowflakes
// Sokoban
// Space Checkers
// Space is Key
// Spellfall
// Spinny Gun
// Splitter
// Spring Ninja
// Sproing
// Stabilize!
// Stack
// Stairs
// Stick Hero
// String Avoider
// Stringy
// Sudoku
// Super Mario Bros
// Surfingers
// Survival Horror
// Talesworth Adventure
// Tetris
// The Impossible Line
// The Moops - Combos of Joy
// The Next Arrow
// Threes
// Tic Tac Toe
// Timberman
// Tiny Wings
// Tipsy Tower
// Toony
// Totem Destroyer
// Tower Defense
// Trick Shot
// Tunnelball
// Turn
// Turnellio
// TwinSpin
// vvvvvv
// Warp Shift
// Way of an Idea
// Whack a Creep
// Wheel of Fortune
// Where's my Water
// Wish Upon a Star
// Word Game
// Wordle
// Worms
// Yanga
// Yeah Bunny
// Zhed
// zNumbers