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