Bouncing off enemies as appropriate

Like any good platformer, our character will bounce off of enemies when he/she lands on top of them, but not when he/she hits them from the side. We'll accomplish this by checking the position of the collision on the main character.

Getting on with it

We've already created the basic behavior for when the character collides with an enemy, by taking damage and flinching back.

Checking for foot-head contact

Although there are a number of tests to determine whether a body has landed on top of another body, such as checking direction or comparing positions for horizontal overlap and vertical separation, we're going to create another sensor fixture. This one is intended to detect collisions with walls, rather than other sprites. Open character/init.lua and calculate the width of the new body in the main function:

local spirit = setmetatable({isSensor = true, filter = kind.Group}, {__index = kind.Form})
  local width, height = calculateBaseWidth(body)
  width, height = width or (sprite.width / 2 - 2), height or (sprite.height / 2)
    return function(world)

Use this base width to create an outline along the bottom of the sprite:

  width, height = width or (sprite.width / 2 - 2), height or (sprite.height / 2)
  local feet = {isSensor = true, filter = categories.body; shape = {width, height; width, height + 2; -width, height + 2; -width, height} }
    return function(world)

Include this fixture as the third component of each character body:

  local feet = {isSensor = true, filter = categories.body; shape = {width, height; width, height + 2; -width, height + 2; -width, height} }
  physics.addBody(sprite, 'dynamic', body, spirit, feet)

Modify the contact function so that its collision recognition checks for this specific overlap. This can be used to distinguish between landing on the ground or running into a wall:

    if other.Name == 'Ground' then
      if event.selfElement == 3 then
        self:dispatchEvent{name = 'Land'}
        self.Standing = other
      elseif self.Standing and self.Standing ~= other then
        self:dispatchEvent{name = 'Bump'}
      end
    elseif self.Allegiance == categories.player then

It can be used to distinguish whether the player character has landed on top of an enemy or bumped into it from the side:

    elseif self.Allegiance == categories.player then
      if other.Allegiance == categories.enemy and event.selfElement ~= 3 then
        self:dispatchEvent{name = 'Hurt'}
      end
    elseif self.Allegiance == categories.enemy then

It can also be used by the enemy to act more bouncy when the layer jumps on them. The player bouncing off the tops of enemies is part of their physics, not their control.

    elseif self.Allegiance == categories.enemy then
      if other.Allegiance == categories.player and event.otherElement == 3 then
        local dX, dY = other:getLinearVelocity()
        other:setLinearVelocity(dX, -dY)
        self:dispatchEvent{name = 'Stomp'}
        timer.performWithDelay(350, function() self:removeSelf() end)
      end
    end

What did we do?

We distinguished between two different sorts of collision between the same pair of bodies, by using multiple sensors within a single body.

What else do I need to know?

Collision events also include x and y fields, which specify the point where the colliding bodies made contact. These also offer a way to check the particulars of a collision; however, at the time of this writing, there was a Corona bug affecting the coordinates reported in this event. If this seems like a simpler way to process your collision events, check the Corona update logs to see if this is now reporting reliably.

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

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