Descending into the depths¶
In this chapter we’re going to add stairs and create a new Level when the player uses the Descend action on the stairs.
Adding a stair component¶
The first thing we’re going to want to do is create a new tag component. This component will be used to indicate that this actor is a staircase.
Navigate to modules/MyGame/components/
and create a new file called stair.lua
. This
will be a simple tag component.
--- @class Stair : Component
local Stair = prism.Component:extend("Stair")
Stair.name = "Stair"
return Stair
This is just a simple tag component like void earlier in the tutorial.
Creating the stairs actor¶
Next we’ll create a stairs actor, again really simple.
prism.registerActor("Stairs", function()
return prism.Actor.fromComponents {
prism.components.Position(),
prism.components.Drawable("<"),
prism.components.Stair(),
prism.components.Remembered(),
}
end)
Placing the stairs on the map¶
Okay we’ve got our stairs created, it’s time to place them on the map. Navigae to
levelgen.lua
and head to the bottom of the function right above return.
--- @type Rectangle[]
local availableRooms = {}
for _, room in pairs(rooms) do
if room ~= startRoom then
table.insert(availableRooms, room)
end
end
local stairRoom = availableRooms[rng:getUniformInt(1, #availableRooms)]
local corners = stairRoom:toCorners()
local randCorner = corners[rng:getUniformInt(1, #corners)]
builder:addActor(prism.actors.Stairs(), randCorner.x, randCorner.y)
We collect all the rooms the player didn’t spawn in into a table, and then choose a random room. We place the stairs in a random corner of that room for now.
So we’ve got stairs now, but we can’t do anything with them. Let’s move on.
The descend message¶
Navigate to moudles/MyGame/messages
and create a new file descend.lua
.
--- @class DescendMessage : Message
--- @overload fun(): DescendMessage
local DescendMessage = prism.Object:extend("DescendMessage")
return DescendMessage
For now we don’t need anything inside of Descend, we’ll get to that later.
The descend action¶
local DescendTarget = prism.Target()
:with(prism.components.Stair)
:range(1)
---@class Descend : Action
---@overload fun(owner: Actor, stairs: Actor): Descend
local Descend = prism.Action:extend("Descend")
Descend.targets = { DescendTarget }
function Descend:perform(level)
level:removeActor(self.owner)
level:yield(prism.messages.Descend())
end
return Descend
First we create a target that targets actors with the stair component within range 1. Then we create our Descend action, which is really similar to Die except we send a different message.
Now let’s add some code to MyGameLevelState:keypressed
. After we figure out which direction the user
just pressed we’ll add the following.
if keybindOffsets[action] then
local destination = owner:getPosition() + keybindOffsets[action]
-- add this
local descendTarget = self.level:query(prism.components.Stairs)
:at(destination:decompose())
:first()
local descend = prism.actions.Descend(owner, descendTarget)
if self.level:canPerform(descend) then
decision:setAction(descend)
return
end
Creating the next floor¶
Now that we’ve got everything set up we need to actually handle the descend message. In
MyGameLevelState:handleMessage
we’ll add the following message handling.
if prism.messages.Descend:is(message) then
self.manager:enter(MyGameLevelState(self.display))
end
Okay and now if we run the game and go find ourselves a staircase we’ll be able to go down to a new floor!
A couple of problems, though. The new level has a completely new player on it and we’re not tracking depth anywhere.
In the next chapter¶
We’ll set up a Game object that tracks what depth we’re on and manages level generation. We’ll pass the player to the new level so that we’re playing the same character all the way down.