Taking licks¶
It’s time to make kobolds a little dangerous! In this chapter we’re going to give the player health and have the kobolds attack them!
Giving the player HP¶
The first thing we’re going to do is give the player a Health
component.
prism.components.Health(10),
Creating the attack component¶
We need a component to hold information about attackers. For now, it will just hold how much damage they deal.
--- @class Attacker : Component
--- @field damage integer
--- @overload fun(damage: integer)
local Attacker = prism.Component:extend("Attacker")
--- @param damage integer
function Attacker:__new(damage)
self.damage = damage
end
return Attacker
In kobold.lua
, add our new Attacker
component to the list.
prism.components.Attacker(1)
The attack action¶
Now let’s make an attack action that the kobolds can use on the player. This is
pretty straightforward. Anything with health is attackable, and we apply our Damage
action
based on the Attacker
component.
local AttackTarget = prism.Target()
:isPrototype(prism.Actor)
:with(prism.components.Health)
---@class Attack : Action
---@overload fun(owner: Actor, attacked: Actor): Attack
local Attack = prism.Action:extend "Attack"
Attack.name = "Attack"
Attack.targets = { AttackTarget }
Attack.requiredComponents = { prism.components.Attacker }
--- @param level Level
--- @param attacked Actor
function Attack:perform(level, attacked)
local attacker = self.owner:expect(prism.components.Attacker)
local damage = prism.actions.Damage(attacked, attacker.damage)
if level:canPerform(damage) then
level:perform(damage)
end
end
return Attack
Next we need to make kobolds actually use the attack action. Navigate to modules/MyGame/components/koboldcontroller.lua
and right above the final return we’re going to add the following:
function KoboldController:act(level, actor)
...
local attack = prism.actions.Attack(actor, player)
if level:canPerform(attack) then
level:perform(attack)
end
return prism.actions.Wait(actor)
end
Sending a message¶
If you play the game now and let yourself get beat up by kobolds you’ll find something unfortunate:
the game crashes when you die! To solve this we’ll send a Message
to the user interface with Level:yield()
when the last player controlled actor dies.
Note
You can read more about the game loop and why this happens here.
Create a new folder in
modules/MyGame/
calledmessages
.Create a new file called
lose.lua
--- @class LoseMessage : Message
--- @overload fun(): LoseMessage
local LoseMessage = prism.Object:extend("LoseMessage")
return LoseMessage
This message just indicates that the game is over, so it doesn’t need to hold any data. Next
head back over to the Die action. Let’s change its perform
to the following:
function Die:perform(level)
level:removeActor(self.owner)
if not level:query(prism.components.PlayerController):first() then
level:yield(prism.messages.Lose())
end
end
And finally we’re going to handle this message in the user interface. Head back over to
gamestates/MyGamelevelstate.lua
and let’s modify MyGameLevelState:handleMessage
.
function MyGameLevelState:handleMessage(message)
spectrum.LevelState.handleMessage(self, message)
if prism.messages.Lose:is(message) then
self.manager:pop()
love.event.quit()
end
end
If we receive our LoseMessage
, we simply close the game. We’ll improve on this in the next chapter.
Wrapping up¶
That’s it for this chapter. Kobolds now wield an Attack
action and we’ve handled
a fatal game crash by using a Message
. In the next section we’ll focus on
the user interface with stuff like adding a game over screen and a message log.