3.10 Game: A Simple Platformer

Platform Chaser: Your Very First Game

You’ve learned how to create a loop and how to make decisions using conditional statements. You now can create and index objects in the game world and modify their properties. Let’s exercise your knowledge by creating a simple platformer.

This game consist of two platforms that traverse the map, leapfrogging one after the other in a random direction with some gap in the between. The player’s objective is to jump from platform to platform without falling off.


A computer can only make simple decisions. Breaking down complex problems into something solvable through simple computer operations will be one of the most important skills you will learn as a developer. So let’s break this down.

We first need two parts for the platforms

  • part 1
  • part 2

Only one platform will move at a time and must move in the same direction as the last move or to the left or right or that—so no backwards move. Direction will be constrained to the X or Z axis and the move can only be along one axis at a time.

We end up with three possibilities for a move and among those, one is selected.

This can be represented as an X or Z axis move and a positive or negative direction minus the axis-direction that would move the platform in “reverse.”

  • ±X axis
  • ±Z axis

To do that, we will need to keep track of the last platform to move and the direction of the move.

  • current axis
  • current direction
  • current platform

Each time around the loop, one axis will be randomly selected.

If the selected axis is not the same as the current axis, the next position can take either the positive of negative direction of that axis.

However, if the selected axis is the same as the current axis, the next position can only be in the same direction of that axis.


Let’s begin.

Create a new game using the Baseplate template and add a Script into ServerScriptService.

Lua
local part1 = Instance.new("Part")
local part2 = Instance.new("Part")

local xAxis = 1
local zAxis = 2

local currentPart = part2
local currentAxis = zAxis
local currentDirection = -1

We create the parts for the platforms and assign the X and Z axis to 1 and 2 respectively.

Initially, both parts will be placed on the Z axis in the negative direction and part 2 as the last part that moved.

We also need to decide on the size of the platform and how big the gap will be between the platforms.

Lua
local dimension = 12
local gapDistance = 6 + dimension

The gap is set to 6 studs but half the dimension of each platform needs to be added to compensate for their size. Two half-dimension lengths is the same as one dimension length.

Lua
part1.Position = Vector3.new(spawnLocation.Position.X, spawnLocation.Position.Y, spawnLocation.Position.Z - gapDistance)
part2.Position = Vector3.new(spawnLocation.Position.X, spawnLocation.Position.Y, spawnLocation.Position.Z - gapDistance - gapDistance)

part1.Parent = game.Workspace
part2.Parent = game.Workspace

The parts are moved into position relative to the spawn location and one or two steps in the negative Z direction.

With initialization complete, the loop section begins.

Lua
local nextAxis = math.random(2)
local currentPosition = currentPart.Position
local nextPosition 

Randomly select the next axis. This will return 1 or 2, representing the X and Z axis assigned to 1 and 2 earlier.

The current position is needed in order to know where to place the next position.

Lua
if nextAxis == xAxis then
	nextPosition = Vector3.new(gapDistance, 0, 0)
else
	nextPosition = Vector3.new(0, 0, gapDistance)
end

This creates the Vector3 that will be added to the current position.

If the next axis is the X axis (1), the gap is added to the X vector. Otherwise, its placed in the Z vector (2).

Lua
local nextDirection
if nextAxis == currentAxis then
	nextDirection = currentDirection
else
	nextDirection = math.random(2) == 1 and 1 or -1
end

Now for the direction.

If the movement is on the same axis as the current axis, then travel can only be in that same direction.

Otherwise, decide on a random direction for the new axis. This value is mapped to either -1 or 1.

Lua
nextPosition = nextPosition * nextDirection
	
currentAxis = nextAxis
currentDirection = nextDirection
	
if currentPart == part2 then
	currentPart = part1
else
	currentPart = part2
end

When the number nextDirection is multiplied with the vector nextPosition, the number is multiplied with each axis.

But because two of them are 0, it has no effect. Only the dimension containing a non-zero value is affected and sets the direction.

The current axis and direction are updated for the next time around the loop.

And we don’t want to move the part that was just moved so the if statement alternates between parts.

Lua
currentPart.Position = currentPosition + nextPosition

task.wait(minimumWaitTime)

Finally, the new position is added to the current position and assigned to the part.

At the bottom a wait is inserted to give players some time to hop onto the next platform.


We only touched on the major parts in the previous section. This is the entire script. Once you’ve written it, hit the play button to give it a go.

Lua
local ReplicatedStorage = game:GetService("ReplicatedStorage")

game.Workspace.Baseplate.Parent = ReplicatedStorage

local part1 = Instance.new("Part")
local part2 = Instance.new("Part")

local xAxis = 1
local zAxis = 2

local currentPart = part2
local currentAxis = zAxis
local currentDirection = -1

local dimension = 12
local gapDistance = 6 + dimension

local waitTime = 1.5

part1.Size = Vector3.new(dimension, 1, dimension)
part2.Size = Vector3.new(dimension, 1, dimension)

part1.Anchored = true
part2.Anchored = true

local spawnLocation = game.Workspace.SpawnLocation

part1.Position = Vector3.new(spawnLocation.Position.X, spawnLocation.Position.Y, spawnLocation.Position.Z - gapDistance)
part2.Position = Vector3.new(spawnLocation.Position.X, spawnLocation.Position.Y, spawnLocation.Position.Z - gapDistance - gapDistance)

part1.Parent = game.Workspace
part2.Parent = game.Workspace

local countdown = 10

while countdown > 0 do
	print("Get Ready.....", countdown)
	countdown = countdown - 1
	
	wait(1)
end

while true do
	local nextAxis = math.random(2)
	local currentPosition = currentPart.Position
	local nextPosition 
	
	if nextAxis == xAxis then
		nextPosition = Vector3.new(gapDistance, 0, 0)
		
	else
		nextPosition = Vector3.new(0, 0, gapDistance)
		
	end
	
	local nextDirection
	if nextAxis == currentAxis then
		nextDirection = currentDirection
		
	else
		nextDirection = math.random(2) == 1 and 1 or -1
		
	end
	
	nextPosition = nextPosition * nextDirection
	
	currentAxis = nextAxis
	currentDirection = nextDirection
	
	if currentPart == part2 then
		currentPart = part1
	else
		currentPart = part2
	end
	
	currentPart.Position = currentPosition + nextPosition
	
	print("next")
	task.wait(waitTime)
end

Challenge

In its current state, the wait time for each loop is constant.

As a challenge, see if you can come up with a way to decrease the wait time as the game progresses which in turn increases the difficulty over time.