|
From: Ed Wegner on 29 Mar 2007 01:00 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 29 Mar 2007 14:48 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 30 Mar 2007 06:55 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
|
Pages: 1 Prev: Double Dispatch Problem: Mobile Creatures and Projectiles in a Game World Next: Use Cases |