Even though we don't want characters colliding violently with each other, we still want them interacting when they come into contact. We'll deal with this by adding sensor elements (what Box2D calls fixtures ) to our existing objects, with the same shapes as their solid portions; these sensors won't generate dynamic collisions, but they will trip collision events so that we can detect when they happen.
Enemies shouldn't be concerned about colliding with each other, but collisions between enemies and the character are important.
The player and enemy objects are very similar in their overall requirements; they collide with the same sorts of things, but they have different requirements as to what they need to ignore.
maskBits = ID.wall; }, player = { categoryBits = ID.spirit, maskBits = ID.spirit + ID.ladder; }, enemy = { categoryBits = ID.spirit, maskBits = ID.spirit + ID.ladder; }, }
Each one belongs to a different group in order to control collisions, though.
player = { groupIndex = ID.player; categoryBits = ID.spirit, maskBits = ID.spirit + ID.ladder; }, enemy = { groupIndex = ID.enemy; categoryBits = ID.spirit,
Save any open files and open character/init.lua
. Find the module function, which accepts a character description and generates a character constructor function. This function is currently generating a solid body only for a new character:
Add a new body to the constructor function, based on the same template as the first one.
local body = setmetatable({isSensor = false, filter = categories.body}, {__index = kind.Form})
local spirit = setmetatable({isSensor = true, filter = kind.Group}, {__index = kind.Form})
return function(world)
Add this extra fixture to the physics body creation.
self.Mind = require "plan" (self.Brain, self, world, kind.Personality(self))
physics.addBody(self, 'dynamic', body, spirit)
self.isFixedRotation = true
Now that we have code to make use of the Group
field of a character description, switch to character/person.lua
and add this field to the character descriptions there. This file is already requiring the categories
module.
humanoid{ Name = "Hero"; Appearance = "ranger_f"; Personality = require "player"; Group = categories.player; Speed = 64; }; humanoid{ Name = "Mummy"; Appearance = "mummy"; Personality = require "monster"; Group = categories.enemy; Speed = 32; };
Now that each character has both a solid fixture to collide with walls, and a sensor fixture to detect collisions with each other, it's time to link some of that processing together.
Now that player and monster characters can collide with each other, we can resolve collisions based on what character is involved. Add some new options to the contact function in character/init.lua
.
if other.Name == 'Ground' then self:dispatchEvent{name = 'Land'} self.Standing = other elseif self.Allegiance == categories.player then elseif self.Allegiance == categories.enemy then end
If the player collides with something that is not ground, it's currently reasonable to assume that it must be an enemy, which hurts the player.
elseif self.Allegiance == categories.player then
self:dispatchEvent{name = 'Hurt'}
elseif self.Allegiance == categories.enemy then
Make sure that collisions will trigger the contact
function to process them, and the character's mind will be apprised of the fact that he or she has been hurt, in the body of the constructor.
self.isFixedRotation = true self:addEventListener('collision', contact) self:addEventListener('Hurt', self.Mind) self:addEventListener('Fall', self.Mind)
We also need to specify that being hurt will pre-empt anything else the character is doing, and block their control for a moment. There is already a function to handle this, but we need to let this event interrupt other functions. Add a couple entries to the precedence table at the top of character/init.lua
.
local precedence = {
fall = {
Land = 'idle',
Hurt = 'flinch',
Steer = 'fall',
Add the same line, Hurt = 'flinch'
, to the walk and idle subtables.
By adding sensor components to the various character bodies, we can now trigger responses, such as reversing direction or reacting with damage.
Sensor components are slightly limited compared to solid components, because there are no reactive collisions to disable or modify. The biggest indication of this is that they don't receive preCollision
or postCollision
events, only the collision event with both began
and ended
phases. This also means that their contact points can't be disabled, or have bounce or friction modified, because they don't generate any.
3.17.150.163