3

I am working on a 2D platformer game for my, last, HS year project. The game is basically about a player walking back & forward, collecting points and reaching goals... The player can shoot bullets and when bullets hit a block, it is destroyed. Now, I wanted to add an explosion effect using so called "particle" objects. I have written the manager class for it and it seemed to have worked the first time but after shooting a few times, i noticed that the particles stopped getting deleted, they just continue and travel out of screen. The life-time limit is 500ns.

I have also noticed that if i shoot bullets as soon as the game starts, the effect finishes as it is supposed to. but after waiting for a few more seconds and then shooting bullets, the effect particles do not behave as they should.

Here is what it looks like when i shoot bullets as soon as i start the game (What it's supposed to look like):
enter image description here

and here is what it looks like, after waiting a few seconds before shooting the bullets. enter image description here

ParticleManager.java

public class ParticleManager {


    private ArrayList<Particle> particles;
    private ArrayList<Particle> removeParticles;

    public ParticleManager() {
        particles = new ArrayList<Particle>();
        removeParticles = new ArrayList<Particle>();
    }


    public int getListSize() {
        return particles.size();
    }

    /*
            Generate particles
     */
    public void genParticle(int x, int y, int amount) {
        for(int i = 0; i < amount; i++) {
            particles.add(new Particle("explosion" , x,y, i));
        }
    }

    public void update() {

         // Iterate trough particle objects
        // update them & check for lifeTime
        for(Particle p: particles) {

            // Updating particle object before 
            // checking for time lapse
            p.update();

            // Append outdated particles to removeParticles
            // if time limit has passed
            if(System.nanoTime() - p.timePassed >= Config.particleLife) {
                removeParticles.add(p);
            }
        }

        // finally, delete all "remove-marked" objects
        particles.removeAll(removeParticles);
    }

    public void render(Graphics2D g) {
        for(Particle p: particles) {
            p.render(g);
        }
    }

}

Particle.java

class Particle {

    private double px, py, x, y; 
    private int radius, angle;
    public long timePassed;
    String type;

    public Particle(String type, double x, double y, int angle) {
        this.x = x;
        this.y = y;
        this.radius = 0;
        this.angle = angle; 
        this.timePassed = 0;
        this.type = type; // explosion, tail

    }

    public void update() {
        px  =   x + radius * Math.cos(angle);
        py  =   y + radius * Math.sin(angle);
        radius += 2;

        this.timePassed = System.nanoTime();
    }

    public void render(Graphics2D g) {
        g.setColor(Color.WHITE);
        g.fillOval((int)px, (int)py, 5, 5); 
    }
}

I haven't figured out what I am doing wrong here, I've googled about some stuff and at one point i came across an answer mentioning that some references don't get deleted directly for some reason...

and my question is "How can I make these particles vanish after a certain amount of time has passed? - as shown in the first GIF"

Bobulous
  • 12,967
  • 4
  • 37
  • 68
Feelsbadman
  • 1,163
  • 4
  • 17
  • 37
  • Should `this.timePassed = System.nanoTime();` be in the `update()` method? It seems perhaps better placed in the constructor, no? – DontKnowMuchBut Getting Better Sep 08 '18 at 20:27
  • I have tried assigning `this.timePassed` in constructor, but then the particles were not painted at all. – Feelsbadman Sep 08 '18 at 20:29
  • 1
    Is the value of `Config.particleLife` immutable? Any chance that something is changing its value several seconds into gameplay? – Bobulous Sep 08 '18 at 20:30
  • Or better, creation time created in constructor, and time passed updated as difference – DontKnowMuchBut Getting Better Sep 08 '18 at 20:30
  • Also, if all particles need to vanish at the same time, why not simplify your design by moving the `timePassed` value into `ParticleManager` so that you only need to keep track of this value in one place for each burst of particles? (I'm guessing maybe your "tail" burst gives each particle its own lifespan, so my suggestion would not work if that's the case.) – Bobulous Sep 08 '18 at 20:31
  • I have tried assigning it in the constructor as you (@DontKnowMuchButGettingBetter) suggested but when i did that, particles were removed immediately. EDIT: also I tried to re-assign timePassed in the update method by subtracting time from constructor. But same result, they vanished immediately, before being drawn and i double checked that Config.particleLife was not modified anywhere in the game. – Feelsbadman Sep 08 '18 at 20:33
  • Then we probably need a decent [mcve] code post to test – DontKnowMuchBut Getting Better Sep 08 '18 at 20:41

1 Answers1

3

I think the problem is that you are constantly overwriting timePassed.

// Updating particle object before 
// checking for time lapse
p.update();

// Append outdated particles to removeParticles
// if time limit has passed
if(System.nanoTime() - p.timePassed >= Config.particleLife) {
    removeParticles.add(p);
}

p.update() sets timePassed to now and then the if check checks if time passed is far from now (it will never be since it was just set).

I think you do want to set timePassed in the constructor (maybe it would be better named timeCreated).

Additionally, just a heads up, you never clear removeParticles so that list is going to grow forever until it causes the process to run out of memory.

dolan
  • 1,716
  • 11
  • 22
  • When i only assign `timePassed` in the constructor, the particle is never drawn and immediately deleted. – Feelsbadman Sep 08 '18 at 20:38
  • 1
    My first guess would be that `particleLife` is too short (potentially zero)? Are you converting it to nanos correctly and setting it? – dolan Sep 08 '18 at 20:42
  • @IdontReallywolf that's probably because you're querying nanoseconds. What's your configured lifetime value? Try increasing it by some orders of magnitude. – daniu Sep 08 '18 at 20:43
  • not sure if i have to convert it, but it is set to 500, i tried setting it to 500000 but that didn't help either. particles not drawn, but immediately deleted – Feelsbadman Sep 08 '18 at 20:44
  • nano means billionth, so if you want half a second you need to set it to a value of `500000000`. – Bobulous Sep 08 '18 at 20:48
  • 500000 nanoseconds is 0.0005 seconds so your eye wouldn't be able to detect if it were drawn (for maybe a single frame). You probably need a few orders of magnitude more. – dolan Sep 08 '18 at 20:49
  • Interesting and relevant video: https://www.youtube.com/watch?v=JEpsKnWZrJ8 – dolan Sep 08 '18 at 20:53
  • :D can't believe that was the issue, It works now. Thank you a lot for all the help :D – Feelsbadman Sep 08 '18 at 20:55