1
votes

I am making a Shooting game in flash actionscript 3 and have some questions about the flow of logic and how to smartly use the OOPs concepts.

There are mainly 3 classes:

  1. Main Class: Initializes the objects on the screen.
  2. Enemy Class: For moving the enemies around on the screen.
  3. Bullet Class: For shooting.

What I want to do is find out if the Enemy has been hit by a bullet and do things which must be done as a result ...

What I am doing right now is that I have a ENTER_FRAME event in which i check collision detection of each enemy unit (saved in an array) with the bullet instance created, and if it collides then perform all the necessary actions in the Main class .. clogging the Main class in the process ..

Is this the right technique ? or are there better solutions possible ?

2

2 Answers

4
votes

Try to think more OOP, what is every object responsible for?

We have the enemies wich we can hit:

class Enemy : extends NPC implements IHittable {
    . . .

    function update(delta) {
        // move, shoot, etc.
    }

    function handleHit(bullet) {
        // die
    }
}

A hittable object:

interface IHittable {
    function handleHit(bullet);
}

The bullet is suppose to move and hit things:

class Bullet : {
    function update(delta) {
        // update position
    }

    function checkHits(world:World) {
        for each(var hittable:IHittable in world.objects) { // might want to cluster objects by location if you're handling lots of objects / bullets)
            if (isColidingWith(hittable))
                o.handleHit(bullet);
        }
    }
}

And then we have the world with everything inside:

class World {
    var npcs: Array ...
    var bullets: Array ...
    var hittables: Array ...

    function update(delta) {
        foreach(var c:NPC in npcs)
            c.update(delta);

        foreach(var b:Bullet in bullets) {
            b.update(delta);
            b.checkCollisions(world);
        }
    }
}

And your main loop is just simple as that:

var lastTime:int;

function onEnterFrame(...) {
    var now:int = getTimer(); // FlashPlayer utility function to get the time since start (in ms)

    world.update(now - lastTime);
    lastTime = now;
}

A few other notes:

  • try to do all the computation based on a delta of time, otherwise the game's speed will vary with the framefrate.

  • what happens when a character dies? bullet disappear? Well, you could do it several ways:

    • fire an event, like EnemyDied and remove it from the world
    • implement an interface CanDie that has a (get dead():Boolean property) and use that to cleanup the world at every update.
    • but don't write the code to remove the enemy in the Enemy class, because then you will be polluting the class with code that should be handled by the World, and that will be hard to maintain later.

Sorry for the long answer, but I couldn't help myself :)

0
votes

Was clogging the Main class the problem, or finding out what bullet hit what enemy the problem? If it was the bullet, you need to describe the bullet behavior - can it hit multiple enemies, how fast does it move (is it possible that when testing using "enterFrame" the bullet will first appear in front of the enemy, and, on the second frame, it will appear behind the enemy?). May enemy be simplified to some basic geometrical shape like circle or rectangle, or do you need pixel-perfect precision? Finally, how many bullets and how many enemies are you planning to have at any one time? It could be too expensive to have a display object per bullet, if you are going to have hundreds of them, and then it could make more sense to draw them into single shape / bitmapdata.

If the problem is that the Main class is too long, there are several possibilities here.

  1. A nobrainer answer to this problem - use inheritance to simply put parts of the code in separate files. Not the best way, but a lot of people do it.
  2. If you did the first, then you'd realize that there are certain groups of functions you put into superclass and subclasses - this will help you split the "clogged" class into several smaller independent pieces that have more particular specialization.
  3. After you did the second, you may find out that there is certain dependency between how you split the big class into smaller classes, so you can try generating those smaller classes by a certain pattern.
  4. And then you write the clogged code that generalizes those parts you just managed to split.

Above is basically the cycle from more concrete to more generic code. In the process of perfecting the last step, you'll write some concrete code again. And that will move you to the step 1. Lather, rinse, repeat :) In fact, you don't want to write OO code, or procedure code or anything that fashion of the day tells you to do. You want to write good code :) And you do it by moving from more generic to more specific and back to more generic, until it's perfect :P

Probably not the best answer, but you must admit, you didn't give much info to give you more precise answer.