Responding to collisions with other characters

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.

Getting ready

Save any other files and reopen categories.lua.

Getting on with it

Enemies shouldn't be concerned about colliding with each other, but collisions between enemies and the character are important.

Defining categories for enemies and the player

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,

Applying categories to bodies

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;
  };

Reacting to collision events

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.

What did we do?

By adding sensor components to the various character bodies, we can now trigger responses, such as reversing direction or reacting with damage.

What else do I need to know?

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.150.163