Restructuring collision code

Started by
12 comments, last by Juliean 11 years ago

So I decided to restructure my collision code to be general and flexible to something like this:

This code restructure single-handily eliminates my original code that had multiple instanceof check inside the for each loop. biggrin.png

Now the only issue I can see is if when I want to add different audio for the monster death upon collision with a projectile. blink.png


// detect collision detection on all monsters on screen
 
public void checkMonsterCollision(ArrayList<GameComponent> gameObjects) {
 
 
// check for Monsters in the ArrayList
for(GameComponent component: gameObjects)
{
if(component instanceof Monster)
{
/* check the intersection of the laser's rectangle and the OneEye monster
*  rectangle. If both rectangles intersects, it is a collision
*/
if(rectangle.intersects(((Monster) component).getRectangle()))
{
 
// uncomment code to play the 
//playDeathSound();
// remove laser upon monster contact
Game.getInstance().remove(this);
// remove the monster upon contact of the laser
Game.getInstance().remove(component);
 
}
}
 
}
}



import java.awt.Rectangle;
 
 
public abstract class Monster extends Sprite{
 
private Rectangle rectangle;
 
public Rectangle getRectangle()
{
return rectangle;
}
}
Advertisement

http://en.wikipedia.org/wiki/Strategy_pattern

The sound of the monster getting hit should be handled within the monster class itself. Essentially, when a laser collides with a monster it will tell that monster it got hit. The monster will then proceed to carry out its "getting hit" logic, which would include playing it's own sound effect for getting hit, among other things.

The sound of the monster getting hit should be handled within the monster class itself. Essentially, when a laser collides with a monster it will tell that monster it got hit. The monster will then proceed to carry out its "getting hit" logic, which would include playing it's own sound effect for getting hit, among other things.

I forgot to mention the monster class is an abstract class. Is it generally allowed to add logic to an abstract class. The examples I learned for abstract class don't have logic implemented in them. If logic is allowed in the abstract class, then that would be logic per monster. If I add 10 monsters that would be 10 logic in the abstract class.

I forgot to mention the monster class is an abstract class. Is it generally allowed to add logic to an abstract class. The examples I learned for abstract class don't have logic implemented in them. If logic is allowed in the abstract class, then that would be logic per monster. If I add 10 monsters that would be 10 logic in the abstract class.

Yeah, you probably don't want to do that. As a general rule of thumb, you should inherit interfaces, not implementations. Of course, the logic doesn't have to be actually in the monster class - rather you could have abstract 'OnHit()' functions which can be implemented for each monster separately.

That said, you probably don't want to be inheriting each monster from a 'monster' base class either. You'll end up with a whole load of separate monster classes which will likely end up containing a lot of copypaste code with small differences which will be a maintenance nightmare. It will be difficult to add new monsters since they are all hardcoded into the inheritance hierarchy. You also run the risk of creating for yourself a whole bunch of horribly convoluted inheritance trees. Does a Centaur inherit from the Horse monster, or the Human monster? Or both? (erk) And then what happens when you add a Pegasus and an Angel (Winged Human)? And Flying Centaurs? And do they all additionally inherit from the Bird?

It would be better to make your monster class concrete, keep it very generic, and use data & composition to differentiate between the different monster behaviours.

I forgot to mention the monster class is an abstract class. Is it generally allowed to add logic to an abstract class. The examples I learned for abstract class don't have logic implemented in them. If logic is allowed in the abstract class, then that would be logic per monster. If I add 10 monsters that would be 10 logic in the abstract class.

Yeah, you probably don't want to do that. As a general rule of thumb, you should inherit interfaces, not implementations. Of course, the logic doesn't have to be actually in the monster class - rather you could have abstract 'OnHit()' functions which can be implemented for each monster separately.

That said, you probably don't want to be inheriting each monster from a 'monster' base class either. You'll end up with a whole load of separate monster classes which will likely end up containing a lot of copypaste code with small differences which will be a maintenance nightmare. It will be difficult to add new monsters since they are all hardcoded into the inheritance hierarchy. You also run the risk of creating for yourself a whole bunch of horribly convoluted inheritance trees. Does a Centaur inherit from the Horse monster, or the Human monster? Or both? (erk) And then what happens when you add a Pegasus and an Angel (Winged Human)? And Flying Centaurs? And do they all additionally inherit from the Bird?

It would be better to make your monster class concrete, keep it very generic, and use data & composition to differentiate between the different monster behaviours.

What do you mean by not inheriting implementations? Give me an example. So you are saying, I think I'm pretty sure this is what you mean. I should create a DeathSound interface that contains a method called "playDeathSound" in which the Monster class inherit from. But override the playDeathSound for each class that extends Monsters. It worked!

What do you mean by not inheriting implementations? Give me an example. So you are saying, I think I'm pretty sure this is what you mean. I should create a DeathSound interface that contains a method called "playDeathSound" in which the Monster class inherit from. But override the playDeathSound for each class that extends Monsters.

No, just like Sandman was saying - having an abstract OnHit() function and overriding this in each of your monster implementations.

But, like Sandman also implied, you might be better of using an entity/compontent based approach, where you have compose your monsters of generic data containers, called components, and have systems to handle the actual behaviour. In your case an entity might have a DeathSound component, containing the name of he sound to play on death.

Have a look at how EntityX works (though its C++11, you might want a somewhat similar "interface"), and for a bit older implementation (but further explaining the basics) http://www.gamasutra.com/blogs/MeganFox/20101208/88590/Game_Engines_101_The_EntityComponent_Model.php

I forgot to mention the monster class is an abstract class. Is it generally allowed to add logic to an abstract class. The examples I learned for abstract class don't have logic implemented in them. If logic is allowed in the abstract class, then that would be logic per monster. If I add 10 monsters that would be 10 logic in the abstract class.

Yeah, you probably don't want to do that. As a general rule of thumb, you should inherit interfaces, not implementations. Of course, the logic doesn't have to be actually in the monster class - rather you could have abstract 'OnHit()' functions which can be implemented for each monster separately.

That said, you probably don't want to be inheriting each monster from a 'monster' base class either. You'll end up with a whole load of separate monster classes which will likely end up containing a lot of copypaste code with small differences which will be a maintenance nightmare. It will be difficult to add new monsters since they are all hardcoded into the inheritance hierarchy. You also run the risk of creating for yourself a whole bunch of horribly convoluted inheritance trees. Does a Centaur inherit from the Horse monster, or the Human monster? Or both? (erk) And then what happens when you add a Pegasus and an Angel (Winged Human)? And Flying Centaurs? And do they all additionally inherit from the Bird?

It would be better to make your monster class concrete, keep it very generic, and use data & composition to differentiate between the different monster behaviours.

I never thought of the hierarchy like that. But thanks for the heads-up. This definitely opens new opportunities to add certain weaknesses given a certain projectile. So far there are only 2 monsters in the arcade shooter. Right now, the instances of the Monsters like Ghost and OneEye are mostly copy and paste code with some small differences examples: one has animation frames and one does not, and overriding deathsound methods.

Given that one is a ghost which on the top of my head I might label as a Spirit Type and OneEye might be a Flying Type(given OneEye is a one-eyed winged monster.

Yes the monster is generic in the sense it is an abstract class. I do not understand what you mean by concrete though. An example would be nice.

Concrete means "non-abstract" i.e. you can create an object of a concrete class type.

I wouldn't use the term "generic" for an abstract class since generic usually means it is a parameterised type (like a List<T> is a generic class).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I never thought of the hierarchy like that. But thanks for the heads-up. This definitely opens new opportunities to add certain weaknesses given a certain projectile. So far there are only 2 monsters in the arcade shooter. Right now, the instances of the Monsters like Ghost and OneEye are mostly copy and paste code with some small differences examples: one has animation frames and one does not, and overriding deathsound methods.

I hope you are well aware that this kind of hierachy you've been "suggested" has really be given as an example of what not to do? Don't like/want to speak for someone else, but I wouldn't want you to go on with the thought "I've been told to make all kind of weird five-parent ten-depth inheritance hierachies to create my entities" and actually belive it to be a good practice. Also sorry if I actually misunderstood an of eighter yours or sandmans saying. It can/will work, but if you care about writing flexible, reusable and halfway decent code, you would never ever want to have things like a "Flying" and "Spirit" class an inherit from both of these. Like you said, they share so much in common, an entity/component system would really fit great here. Given from what I see you might (also) want to have a read at this great article on the topic that good coincidently released today on gamedev:

http://www.gamedev.net/page/resources/_/technical/game-programming/understanding-component-entity-systems-r3013

EDIT: Just imagine the "undead flying one-eyed poisiounous evil man-tree of fire" - while not a quite actual example from a game, just thing about how horrible this would work if you had all those "attributes" as single classes, and needed to inherit from all of this - with components you could compose this quite easily, without having one line of boilerplate-code - and you could just as well compose a thousand other similar or completely differnt entities using those components.

This topic is closed to new replies.

Advertisement