1

So I am making a game for Android and I have this singleton class called ParticleEmitter that has a function for adding particles to a CopyOnWriteArrayList. What gets added to the list is an abstract Particle, it can either be a Laser particle or a Meteor particle. I also have a MainThread class which acts as the game engine and it handles the drawing and updating of frames.

So this ParticleEmitter class has an update() function which handles the updating of all the particles in the list. But what it also does is tell when the particles are going to go offscreen, so they can be removed from the list. The update() function, in the middle of iterating through all the particles, can also call the checkCollisions(Particle laser) function to test a laser parameter, to see if it collides with any of the meteors, so they can both be removed from the list.

private Particle checkCollisions(Particle laser) {

    Iterator<Particle> iter = particles.iterator();
    Particle p;
    while (iter.hasNext()) { // looping through all particles
        p = iter.next();
        if (p instanceof Meteor) { // if particle is a meteor, then see if it collides with the passed in laser
            if (p.intersect(laser)) {
                setChanged();
                notifyObservers(GameController.Event.METEOR_DESTROYED);
                return p;
            }
        }
    }

    return null;

}

public void update(int screenWidth, int screenHeight) {

    // function called by game loop (many times a second)

    List<Particle> particlesToRemove = new LinkedList<>();

    int meteors = 0;

    Iterator<Particle> iter = particles.iterator();
    Particle p;
    while (iter.hasNext()) {
        p = iter.next();
        p.update();
        if (p instanceof Laser) {
            Particle m = checkCollisions(p); // returns the collided with meteor if there was a collision, null if not
            if (m != null) {
                particlesToRemove.add(p);
                particlesToRemove.add(m);
            } else if (p.offscreen(screenWidth, screenHeight)) { // no collision with any meteors... still need to check if offscreen
                particlesToRemove.add(p);
            }
        } else {
            meteors++;
            if (p.offscreen(screenWidth, screenHeight)) { // if meteor went off screen, it meant it hit the earth, so need to alert GameController
                setChanged();
                notifyObservers(GameController.Event.METEOR_HIT_EARTH);
                particlesToRemove.add(p);
            }
        }
    }

    particles.removeAll(particlesToRemove);

    if (meteors == 0) {
        setChanged();
        notifyObservers(GameController.Event.NO_METEORS_ON_SCREEN);
    }

}

Is this code single-thread safe? I have already tested some and it seems to work good. I just want to make sure I'm not going to run into any exceptions (I've tried many solutions before this; just want to make sure I've stumbled upon the right one). And if you can think of a better way to implement what I'm doing here, I would appreciate that also :). Thanks.

Jacob
  • 439
  • 6
  • 19
  • 2
    Looks good to me since `update` is `private` and you are removing the elements in one go. That said, not sure why you would need a `CopyOnWriteArrayList` based on the code you have shown. – Chetan Kinger Nov 12 '17 at 05:08
  • Yup. `CopyOnWriteArrayList` can be used for performance tuning (on the micro level, not really applicable to games) when reads far outweigh the writes. You could just use a regular `Collections.synchronizedList(new ArrayList<>());`. – Kayaman Nov 12 '17 at 05:47
  • 1
    "is this code single-thread safe" what exactly do you mean here? – Andy Turner Nov 12 '17 at 07:45
  • Correction in my comment.. I meant to say since `checkCollisions` is `private`.. – Chetan Kinger Nov 12 '17 at 08:07

0 Answers0