3
\$\begingroup\$

Recently I started creating a game in java to hone my rusty java (I work primarily with cpp) and because I thought it to be a neat idea. To better illustrate the problem, let me explain a part of the game. The details aside, the game is in essence a dungeon builder and the problem pertains to the blocks you place down to create the maze adventurers have to travel through. Each block is a corridor and on each wall/floor/ceiling of a block you can place objects such as traps etc. However, while finishing up the game engine I realized I still lacked a list for blocks/objects that are special. Blocks or items that need a special animation (some extend spikes, some shoot fire, some contain a chest with inventory, etc). They're hard to bring together in one class and as we all know they can't be together in one list with different classes unless we want code-bloating. So my question is, what is the most efficient way to make collection of diversified game objects and how do other games do it?

Presently I have the following methods thought out.

  • I reduce all objects to instances of one class. They all fit in one list. However, to induce special methods I need a long list of methods that each do something else. Frankly, this method is inefficient, unpleasant and unpractical to work with.

  • I reduce all object to instances of one class. They all fit in one list. However, they each have an ID of a special action. If the need arises the ID gets compared with another list that's much shorter in length and uses generics or reflection to store the different effect. If it needs a special action it simply activates the effect (such as fire plume) on the given vector. The problem with this is that it does not allow for direct manipulation of the object such as a block that moves out to squash adventurers. Or if it could, it would be messy code, unnecessary throughput of code etc. I'd rather avoid it.

  • I make a list of the base class/interface and add the different child classes to it. Each child class can thus have a different implementation. However, to access it, I need to know to use reflection and for that I need to know the initial class, which, in many cases, I don't since I want a dynamic system. The result is that I need to store the child class name in the 'block' parent class and then when the need arises, use that name to reflect the new class. Once again, it is inefficient and far too slow.

  • I create a list of the block class and access it every time a generic block needs to be checked. However, if a creature/person walks over a tile it checks if the child class name in the block class is empty. If not, convert it to that class and execute the special function. This seems the best option as it gives the least code-bloating, is the most efficient, etc. However, it still needs to reflect and convert every time a creature goes onto a special block.

  • I create an event driven list in which each block instance has his own special event that links to a certain animation. This is very tedious, very inefficient and because it is so detached it is once again difficult to animate the basic block.

  • I use generics. Sadly, this causes far too much code-bloating and the accessing of the classes themselves gets difficult and messy.

  • I create a huge switch method and each block instance has a number. The number corresponds with the correct animation in the switch it needs to execute. I don't think I need to say why I don't want to do this.

And there are a few more, but each of them is still as inefficient as the next. Furthermore, every time I look around this site or another people say "use a base interface/class in a list" however they never say what the most efficient way is to get the class out of the list again. Am I missing something obvious? How should I tackle this?

\$\endgroup\$
1
  • \$\begingroup\$ I feel as if your question is somewhat vague. Can you provide some visualization or code segment to illustrate the problem you are facing? \$\endgroup\$
    – d3dave
    Jul 28, 2015 at 23:46

1 Answer 1

2
\$\begingroup\$

I will try to help you a litlle bit, in the way I can.
Correct me If I am wrong.
If I got it, then your game is about creating a dungeon, in wich, you can place block's to build it, like floor, ceiling's and such., and not only block's but you have other object's as well, like chest's and spikes.
So If I where to create a game like that, first, I would make an abstract class, wich is a father of all kind's of block's, or "Placeable's", these can be placed on dungeon's to build the stage.
So, the essential part of code wich manage placing thing's on stage, will be in this class.
Everything that you will put on the stage to build it, will be, in essence, for example an "Enviroment" Object., this object should be like an "Actor" as well, because, It's an object that is going to be drawn on screen, and (I least that's what I think) he should know how to draw himself, every Actor should have a Draw method that say's how he behave's when need's to be represented on screen. That said, father class, would be like:

    public abstract class Enviroment extends Actor{}

So a Floor block, Its just floor, and does not need to be animated, you will only need to place it somewhere, and give him a look, (asuming you are making a 2D game), that, would be just drawing a sprite and... done.
Then a floor, a wall, a door should be allright just extending of Enviroment:

    public class Floor extends Enviroment{}

Different It's the case, in wich, you have like a candle or spike kind of Enviroment. Those need to be animated, so, you need more like an "Animated Enviroment". Every thing that's going to be animated, in your world, should have an animation., then you can force any object who's gonna be animated, to actually do it., when you say that many different object's could share a behavior, then, they implement an interface.

    public interface Animable 
    {
      InitializeAnimations(ASpriteSheet);
    }

So, then your AnimatedEnviroment that, is an abstract class, will implement this interface.

    public abstract class AnimatedEnviroment extends Enviroment implements Animable 
    {
    }

Then, the way AnimatedEnviroment draws himself, It's not the same as Enviroment, cause he's an animation., every AnimatedEnviroment Object will draw an animation, cause you will override the Draw function in Enviroment.
Then a candle object will be:

    public class Candle extends AnimatedEnviroment{}

In any case, you will have a Candle, that knows how to animate itself, and not only that, this Candle will know how to place itself, cause It's an Enviroment too.
In case of a chest it will surely implement an interface that would be like a "Lootable", this will asure you that every lootable object will open a window to choose wether you want to pick items from it or not, it will extend AnimatedEnviroment, Cause It's gonna animate Himself when it open's, or maybe you just don't want to animate it at all, and just extend it from Enviroment. Anyway a Chest object, will be an Enviroment, and can be placed in Stages., because he already has all the behavior of an enviroment that he inherited and know's how to do it.
Same with spikes, you want them to harm when you step on them, and they get out and in, they are animable and they are hazardous, so It's HarmfullEnviroment that implements Hazardous and extends from AnimatedEnviroment., It make's you add a behaviour that, when you step on them, they make lose the hp of an aventurer object., and know's how to place himself in stages.

So when you check that an adventurer object step's on an enviroment object, you can ask wich kind of Enviroment he stepped on.
(This is an aproximation of a code that I just thougt, I don't know if this would be cool to implement, but for explanation pruposses, it should be ok)

    public void VerifyEnviroment(Adventurer[] MyAdventurers)
    {
       For (Adventurer CurrentAdventurer : MyAdventurers) <----''this is a list.
       {
          Enviroment = GetEnviromentHeSteppinOn(CurrentAdventurer.getX(),CurrentAdventurer.getY());

            If (Enviroment instanceof HazardousEnviroment)
            {
                CurrentAdventurer.setHp(CurrentAdventurer.getHP() - (HazardousEnviroment)Enviroment.DoHarm());
            }
       }
    }

When you make a list, you are making an Enviroment one, and you are adding Enviroment, you don't really care what kind of Enviroment, you just know that they are going to be placed.
I think that a game is complex enough for not-to-be organized with code, so, this is how I would do it.
Sorry if I extend it too much or If I gave you bad practices, but at least is a point of view; Im curious of what kind of platform you are aiming for, if your objective are smartphones I would start from here and then see what I can do to ease method calls or drawing, for example, floor's, don't necessary need to be a lot of block's, but just a large sprite with a certain pattern that cover's all the screen, different would be the case with other Enviroments that could be smaller.
A solution could be just store in a list where the HazardousEnviroments Are placed, so you just ask if any adventurer I'ts on any of them, and if possible, limit the amount of those according to your adventurer's level, should help you save the amount of check's.
Hugs.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .