DirtyTalk: Decouple your entities through messages

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
User avatar
MarekkPie
Inner party member
Posts: 587
Joined: Wed Dec 28, 2011 4:48 pm
Contact:

DirtyTalk: Decouple your entities through messages

Post by MarekkPie »

DirtyTalk Messaging System
Based on the messaging system from Programming Game AI by Example by Mat Buckland

Github page

Included with the repository is a demo showing off the system. It doesn't require LOVE to use.

Why should I care about this?

Suppose you have this situation:

Code: Select all

function Enemy:new(...)
  -- ...
  self.name = "Enemy"
  self.x, self.y = 0, 0
  self.damage = 10
  self.removable = false
  -- ....
end

function Player:collide(o)
  if o.name == "Enemy" then
    if o.y > self.y + self.height then
      o.removable = true
    else
      self.hp = self.hp - o.damage
    end
  end
end
A pretty typical example to handle a Mario-like platformer. You check to see if you are coming from above the enemy, and if so, destroy it; otherwise, take damage from it.

But what happens if you change in the Enemy class where the damage variable is located. Or instead of calling the y-coordinate y, you call it top? It means you also need to change the Player class, even though that information doesn't really have much to do with that class.

Code: Select all

function Enemy:new(...)
  -- ...
  self.left, self.top = 0, 0
  self.attributes = {
    -- ...
    name = "Enemy",
    damage = 10,
    removable = false,
    -- ...
  }
  -- ...
end

function Player:collide(o)
  if o.attributes.name == "Enemy" then -- change
    if o.top > self.top + self.height then -- change
      o.attributes.removable = true -- change
    else
      self.hp = self.hp - o.attributes.damage -- change
    end
  end
end
While this contrived example doesn't look like it's that big of a deal, imagine how it could pile up for a central class like Player. Tiles, enemies, doors, controls, etc. all must communicate with Player, and anytime you make a change to those objects, you have to change the Player class.

With a message system, you only pass the necessary information between entities, and you choose how that information is passed. So the only thing that would need to change is how you pass that information.

Code: Select all

function Enemy:collide(o)
  DirtyTalk:dispatch(0, "COLLISION", o, { name = self.name, y = self.y, damage = self.damage, sender = self })
end

function Player:handleMessage(msg)
  if msg.message == "COLLISION" then
    if msg.extra.name == "Enemy" then
      if msg.extra.y > self.y + self.height then
        DirtyTalk:dispatch(0, "REMOVE", msg.extra.sender)
      else
        self.hp = self.hp - msg.extra.damage
      end
    end
  end
end

Code: Select all

function Enemy:collide(o)
  DirtyTalk:dispatch(0, "COLLISION", o, { name = self.attributes.name, y = self.top, damage = self.attributes.damage, sender = self })
end

-- And nothing changes in Player!
EDIT: Fixed some typos and errors
Post Reply

Who is online

Users browsing this forum: No registered users and 56 guests