From: Ed Wegner on
Aaron J. M. wrote:
> I'm designing a game, and I've come across a problem that's similar to
> the one
> listed here (Google Groups):
> http://groups.google.ca/group/comp.object/browse_thread/thread/4a5c70e3560388c8
>
> I have a World, and in this world are Creatures and Projectiles. Both
> of these
> have a location, are able to move around somehow, and can collide with
> each
> other. Creatures also create Projectiles which get added to the
> World.
>
> For that reason I thought about having both of them be subclasses of a
> class
> Mobile. In addition to sharing behavior, Mobile is convenient because
> the
> World only has to keep one big list of Mobiles instead of a list of
> Creatures
> and a list of Projectiles.
>
> 1 N 1
> World --------> Mobile <----\
> has A 1| | collides with
> | \------/
> |
> /----------^----------\
> | |
> | 1 N |
> Creature -----------> Projectile
> shoots
> (Did Google Groups take away the fixed width font option?)
>
> The problem is when Mobiles try to collide with each other. Two
> Projectiles
> colliding doesn't do anything (they pass over each other) and neither
> does two
> Creatures colliding (they don't move). It's only when a Creature and
> a
> Projectile collide that something interesting happens (the Creature is
> hit).
> I couldn't really do that with Mobile without either double dispatch
> or the
> Visitor pattern.
>
> To avoid that problem I can just have World hold two lists: one of
> Creatures and
> one of Projectile. But...then I'd need two lists. That might not be
> a bad
> thing, but it is something extra the World has to take into account
> and I'm also
> lazy.
>
> What do people here think about this?

I think your model above matches your description. In particular,
Creatures and Projectiles being generalisations of Mobile. This appears
to be a complete subset - that is you can view the "list" of Mobiles as
being composed of exactly the "list" of Creatures plus the "list" of
Projectiles. So, you have one list, but each member of the list must
indicate whether it's a Creature or a Projectile (each must be exactly
one or the other).

To address the collision logic you describe, I'd add an Association
class off the "collides with" reflexive relationship between instances
of Mobiles. Let's call it "Collision". When a Collision occurs, the
first thing it checks is whether the colliding Mobiles are one of each.
If so, execute the "Projectile hits Creature" logic. It could also be
the locus of future logic that supported Creature-to-Creature collision
interactions and Projectile-to-Projectile collision interactions....

Good luck with the game.

>
> Thanks,
>
> Aaron J. M.
>

Ed Wegner
From: H. S. Lahman on
Responding to M....

> I'm designing a game, and I've come across a problem that's similar
> to the one listed here (Google Groups):
> http://groups.google.ca/group/comp.object/browse_thread/thread/4a5c70e3560388c8
>
>
> I have a World, and in this world are Creatures and Projectiles.
> Both of these have a location, are able to move around somehow, and
> can collide with each other. Creatures also create Projectiles which
> get added to the World.
>
> For that reason I thought about having both of them be subclasses of
> a class Mobile. In addition to sharing behavior, Mobile is
> convenient because the World only has to keep one big list of Mobiles
> instead of a list of Creatures and a list of Projectiles.
> 1 N 1
> World --------> Mobile <----\
> has A 1| | collides with
> | \------/
> |
> /----------^----------\
> | |
> | 1 N |
> Creature -----------> Projectile
> shoots

> (Did Google Groups take away the fixed width font option?)

I don't use Google Groups, but probably so. Most such services use HTML
now and they default to variable font for rendering. You can get around
that by inserting <pre> ... </pre> around the text drawing.

> The problem is when Mobiles try to collide with each other. Two
> Projectiles colliding doesn't do anything (they pass over each other)
> and neither does two Creatures colliding (they don't move). It's
> only when a Creature and a Projectile collide that something
> interesting happens (the Creature is hit). I couldn't really do that
> with Mobile without either double dispatch or the Visitor pattern.

The only "interesting" collision collaboration seems to be Projectiles
hitting Creatures since all other combinations seem to the no-ops. IOW,
the "collides with" relationship is symmetric with the "shoots"
relationship:

populates 1 1 populates
+-------------- [World] ------------------+
| R1 R2 |
| |
| * 1 R3 fired * | *
[Creature] ----------------------------- [Projectile]
| 0..1 | 0..*
| impacts |
| R4 |
+-----------------------------------------+

> To avoid that problem I can just have World hold two lists: one of
> Creatures and one of Projectile. But...then I'd need two lists.
> That might not be a bad thing, but it is something extra the World
> has to take into account and I'm also lazy.

I think you would need that anyway. What is the problem space
commonality of Mobile that justifies generalization? It only seems to
exist to support the reflexive "collides with" relationship, but that
relationship doesn't seem to capture what you are really interested in
the problem solution (Projectiles hitting Creatures).

There is also a semantic inconsistency since you said that
Creature/Creature collisions don't count because they don't move. That
makes it kind of tough to rationalize them as a subset of things that
move. B-)

As far as your concerns with lists are concerned, I don't see that as
very relevant. We're talking about collection classes to implement *
relationships during OOP. The relationships and their multiplicity are
supposed to be abstracted from the problem space, so if that is the way
the problem space works, that's how you have to abstract it in the OOA/D.

Note that you already had two * multiplicities in your model. If one
regards R3 and R4 relationships above as instantiated on a "current"
basis like your "collides with", then they will be 1:1 and you would
have the same number of lists.

In addition, for the "collides with" relationship to be 1:1 it needs to
be dynamically instantiated and de-instantitated as different objects
are involved. That is probably going to be significant trouble (e.g.,
what happens when multiple Projectiles are in the air between several
Creatures?) and it will need to be conditional when no Projectiles are
in the air. Managing that for all combinations is likely to be a lot
more trouble than managing the R4 relationship in the model above.


*************
There is nothing wrong with me that could
not be cured by a capful of Drano.

H. S. Lahman
hsl(a)pathfindermda.com
Pathfinder Solutions
http://www.pathfindermda.com
blog: http://pathfinderpeople.blogs.com/hslahman
"Model-Based Translation: The Next Step in Agile Development". Email
info(a)pathfindermda.com for your copy.
Pathfinder is hiring:
http://www.pathfindermda.com/about_us/careers_pos3.php.
(888)OOA-PATH



From: Ed Kirwan on
Aaron J. M. wrote:

>
> But how would a Collision check whether the colliding Mobiles are one
> of each
> without downcasting, double dispatch, or the Visitor pattern?
>
> I might end up doing the Visitor pattern, but I want to put it off for
> now to
> see if I can find an easier solution.
>

It appears OO has a problems when comparing classes, and RTTI in
general. I know of no good solution to your problem, just the visitor;
indeed I experienced it myself when I wrote some interactive fiction.

I had a Verb class and a Thing class. Liquid and Solid were subclasses
of Thing; Take was a subclass of Verb.

When someone took something, I needed the visitor pattern to see what to
do. I don't know how else to do it (without instanceof and other such
unpronouncibles):

Thing extends Visitor {
void execute(Thing thing) {
thing.visit(this);

void accept(Liquid liquid) {
System.out.println("The " + liquid + " seeps through your fingers.");
}

void accept(Solid solid) {
System.out.println("You take the " + solid);
}
}

class Solid extends Thing {
void visit(Verb verb) {
verb.accept(this);
}
}

etc.

I'm trying to get my head around the good Mister Lahman's suggestion
from your link that, "If some types of active
tokens are limited in what they can do with some types of inanimate
objects, that has to be expressed in the relationships properly. "

I'd love if that line held the answer for me ...

(OT: I can never remember which takes the accept() and which takes the
visit(); must dust off GOF again.)

..ed

--
www.EdmundKirwan.com - Home of The Fractal Class Composition.

Download Fractality, free Java code analyzer:
www.EdmundKirwan.com/servlet/fractal/frac-page130.html