Please check my approach on cross referencing objects between classes

I want to use physics with images, so I have an object class O which sets up each object. Class O reads an image and creates a body in the usual PhysicsDebugDraw class (which I’ll call P).

When the program runs, Main:draw calls P:draw to update the physics. However, I want to draw my objects in class O. So I want to call O:draw from P:draw, or more specifically, the correct instance of O. The problem is how P knows which instance of O belongs to which body, and which bodies don’t have anything to do with O.

What I’ve done is to set body.info=self when class O adds a body to P. So when P loops through the bodies, it checks if the body.info is nil, and if it isn’t, it calls body.info:draw(), which seems to work fine, but if it isn’t the best way, how do you think I should have done it?

Dermot

I think i do it the same way as you do.

I would do it the other way around. An instance of O sets up P, so O already knows about P. Moreover, the main program knows about O but only indirectly about P. So I would call O:draw which would then call P:draw.

Something like:

class O

function O:init()
    self.physicsobj = P:init()
end

function O:draw()
    self.physicsobj:draw()
end

function setup()
    o = O()
end

function draw()
    o:draw()
end

First you have to realize that PhysicsDebugDraw is a very special implementation, far away from being general. What you are asking for is to keep the existing functions intact as much as possible and just tweak a specific behavior. As long as body.info is unused you can use it for your own purpose, e.g. store a reference to a painter function or object in it.

The PhysicsDebugDraw:draw() loop looks like this:

  • It loops over every body.
  • It says to every body: “I know how to draw you, I set the color by your type and draw your outline by your shape.”

You modified it to:

  • It loops over every body.
  • It says to every body: “If you don’t know how to draw yourself, I will draw a default representation of you, I set the color by your type and draw your outline by your shape.”

Your approach is very legal, but a special override inside a special implementation. If that’s all you want, go for it.

Advantage: Minimal intrusion.

Disadvantage: Still very specific, body.info tied to another object.


There may be other approaches, e.g. you can set a default painter when creating a body. This means essentially that you put the entire code of the inner loop in a function DefaultBodyPainter and upon creating a body you say body.info = DefaultBodyPainter.

Now the PhysicsDebugDraw:draw() loop looks like this:

  • It loops over every body.
  • It says to every body: “Draw yourself.”

Advantage: Now you always know who is responsible for drawing a body, it’s the function (or object) that you placed in body.info.


Thinking further: Do you have a need for “only-bodies”? I mean, do you have bodies that are just these low level bodies that come out of the physics API? I think if it’s not for pure demo purposes, a body should have a meaning, it’s not just a body, it’s for example a rock that is represented by a body or an egg that’s represented by a body but has the property to break easily. In this case you have to implement a more sophisticated solution that goes beyond just drawing. Some ideas:

Every body.info points to a controller object. It knows how to draw the body and how to smash it if it is egg. Everything that it now pure physics goes through the controller object.

Or you can say that the body is a slave object that you need to compute physics. You create a controller object that contains a body. What you now do is to not loop over bodies but over controller objects. And perhaps don’t call them contoller objects like I did, it sounds a bit like I wanted to squeeze a body into a higher level object just because of some misguided object orientation fetish.

Another solution could be a hash table hwre either the body is the key and it provides an associated object as a value. Or the other way round. Hhhhmmmm, I think that’s a queer idea.


I think the most important question is what in your regard is the central piece. Is the body the central piece and there are some properties attached to it? Or is a structure of a higher logic the central piece and you just need the body because of physics requirements. Both ways work, at the moment you have settled for the first one.

The second question is who is responsible for drawing and how to make a setup for a default implementation. PhysicsDebugDraw:draw is not a default implementation, it’s a debug implementation.


While writing this, Andrew explained the second way. Now you have to choose. Do you want bodies that happen to be rocks and eggs or do you want rocks and eggs?

I’m not sure of your question, but here is a small example of what I think you’re asking. 2 of the objects draw a sprite, and 2 just draw a circle. The circles don’t need to be drawn if you just need to keep track of the x,y values.


function setup()
    tab={}
    table.insert(tab,p(200,800,readImage("Cargo Bot:Command Grab")))
    table.insert(tab,p(200,600,readImage("Cargo Bot:Condition Green")))
    table.insert(tab,p(200,400,nil))
    table.insert(tab,p(200,200,nil))    
end

function draw()
    for z=1,#tab do
        tab[z]:draw()
    end
end

p=class()

function p:init(x,y,img)
    self.x=x
    self.y=y
    self.q=img
    if img~=nil then
        self.q=q(img)
    end
end

function p:draw()
    fill(255)
    if self.q ~= nil then
        self.q:draw(self.x,self.y)
    else
        ellipse(self.x,self.y,80)
    end
end


q=class()

function q:init(img)
    self.img=img
end

function q:draw(x,y)
   sprite(self.img,x,y) 
end

Thanks very much to all of you for all the different ideas. I have more than one custom object, so I don’t want each of them calling the physics draw routine, which draws a bunch of other things like walls. So I prefer to call O from P rather than the other way round.

I did want to keep the physics code as unaltered as possible, so I like the idea of encapsulating it in an outer class which manages all the object drawing (thank you CodeSlinger). But in the end the objects in my O class are the core around which I want to build everything else, and the current approach minimises changes to the physics class.

So I’ll keep it as is, but I’m very glad I asked and learned some new stuff. You guys are great.