This site requires JavaScript, please enable it in your browser!
Greenfoot back
KCee
KCee wrote ...

2023/4/6

I wanna play an explosion animation using 14 images i have of the explosion

KCee KCee

2023/4/6

#
I have a landmine class that when touched explodes and I want the explosion to be an animation. I have all the images needed for my animation named tile(frame number).png but i dont know how to cycle through the images to make an animation Explosion code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Explosion here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Explosion extends Actor
{
    /**
     * Act - do whatever the Explosion wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    GreenfootImage[] explosionAni;
    GreenfootImage[] currAnim;
    int animTimer;
    public Explosion()
    {
        //this.getImage().setTransparency(250);
        GreenfootImage image = getImage();
        for (int i = 0; i < 14; i++)
        {
            explosionAni[i] = new GreenfootImage("images/tile00" + i + ".png");
            explosionAni[i].scale (400, 350);
        }
    }
    
    public void act()
    {
        this.getImage().setTransparency(getImage().getTransparency() - 3); //slowly becomes transparent
        Hunter hunter = (Hunter)getOneIntersectingObject(Hunter.class);
        if (hunter != null)
        {
            getWorld().removeObject(hunter);
        }
        
        /*if (this.getImage().getTransparency() < 5)
        {
            getWorld().removeObject(this);
        }*/
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() //sets image to the current iamge for a certain amount of time
    {
        animTimer = (animTimer+1)%(10*currAnim.length);
        if(animTimer%10 == 0) 
        {
            setImage(currAnim[animTimer/10]);
        }
    }
}
Landmine code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.util.ArrayList;

/**
 * Write a description of class Landmine here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Landmine extends Actor
{
    /**
     * Act - do whatever the Landmine wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public Landmine()
    {
        GreenfootImage image = getImage();
        image.scale(image.getWidth() - 150, image.getHeight() - 120);
        setImage(image);
    }
    
    public void checkHitHunter()
    {
        ArrayList<Hunter> h = (ArrayList<Hunter>)getObjectsAtOffset(0,0, Hunter.class);
        if (h.size() > 0)
        {
            getWorld().addObject (new Explosion(), this.getX(), this.getY());
            getWorld().removeObject(this);
        }
    }
    
    public void act()
    {
        checkHitHunter();        
    }
}
When the hunter touches the landmine it gives me a NullPointerException Here is the exact error message: java.lang.NullPointerException at Explosion.<init>(Explosion.java:24) at Landmine.checkHitHunter(Landmine.java:28) at Landmine.act(Landmine.java:35) at greenfoot.core.Simulation.actActor(Simulation.java:567) at greenfoot.core.Simulation.runOneLoop(Simulation.java:530) at greenfoot.core.Simulation.runContent(Simulation.java:193) at greenfoot.core.Simulation.run(Simulation.java:183)
danpost danpost

2023/4/7

#
KCee wrote...
When the hunter touches the landmine it gives me a NullPointerException Here is the exact error message: << Error Trace Omitted >>
You never initialize your GreenfootImage array:
explosionAni = new GreenfootImage[14];
Replace line 21, before the for loop, in your Explosion class code with this. Code on that line was not really doing anything. After the for loop, you will need to add the following line:
setAnimation(explosionAni);
That should be all you need to get things going (I hope).
KCee wrote...
I have a landmine class that when touched explodes and I want the explosion to be an animation. I have all the images needed for my animation named tile(frame number).png but i dont know how to cycle through the images to make an animation << Code Omitted >>
Looks like all the key ingredients are there.
KCee KCee

2023/4/7

#
The first explosion frame plays but then it just stays on the first frame and doesnt cycle through the images New explosion code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Explosion here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Explosion extends Actor
{
    /**
     * Act - do whatever the Explosion wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    GreenfootImage[] explosionAni;
    GreenfootImage[] currAnim;
    int animTimer;
    public Explosion()
    {
        //this.getImage().setTransparency(250);
        GreenfootImage image = getImage();
        explosionAni = new GreenfootImage[14];
        for (int i = 0; i < 14; i++)
        {
            explosionAni[i] = new GreenfootImage("images/tile" + i + ".png");
            explosionAni[i].scale (100, 100);
            setAnimation(explosionAni);
        }
    }
    
    public void act()
    {
        //this.getImage().setTransparency(getImage().getTransparency() - 3); //slowly becomes transparent
        Hunter hunter = (Hunter)getOneIntersectingObject(Hunter.class);
        if (hunter != null)
        {
            getWorld().removeObject(hunter);
        }
        
        /*if (this.getImage().getTransparency() < 5)
        {
            getWorld().removeObject(this);
        }*/
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() //sets image to the current iamge for a certain amount of time
    {
        animTimer = (animTimer+1)%(10*currAnim.length);
        if(animTimer%10 == 0) 
        {
            setImage(currAnim[animTimer/10]);
        }
    }
}
danpost danpost

2023/4/7

#
KCee wrote...
The first explosion frame plays but then it just stays on the first frame and doesnt cycle through the images New explosion code: << Code Omitted >>
I said after the for loop, not at the end of it:
public Explosion()
{
    explosionAni = new GreenfootImage[14];
    for (int i=0; i<14; i++)
    {
        explosionAni[i] = new GreenfootImage("tile" + i + ".png");
        explosionAni[i].scale (100, 100);
    }
    setAnimation(explosionAni);
}
Although, the end result will be the same. There is one thing missing in the class. The animation is not running because the act method does not call that code that runs it:
public void act()
{
    removeTouching(Hunter.class); // should suffice for this action
    setImage(); // runs animation
}
Also, line 15 could be moved to the beginning of the constructor:
import greenfoot.*;

public class Explosion extends Actor
{
    GreenfootImage[] currAnim;
    int animTimer;
    
    public Explosion()
    {
        GreenfootImage[] explosionAni = new GreenfootImage[14];
        for (int i=0; i<14; i++)
        {
            explosionAni[i] = new GreenfootImage("tile"+i+".png");
            explosionAni[i].scale(100, 100);
        }
        setAnimation(explosionAni);
    }
    // etc.
Again, this will not change anything as far as how it runs. It is just not necessary to retain something that is not going to be used later and it makes the code a slight bit cleaner.
KCee KCee

2023/4/9

#
The animation plays fine but it keeps looping. How would i make it so it just plays once
danpost danpost

2023/4/9

#
KCee wrote...
The animation plays fine but it keeps looping. How would i make it so it just plays once
Inside the setImage method in the Explosion class, in the if block, right before
setImage(currAnim[animTimer/10]);
insert the following:
if (currAnim[currAnim.length-1].equals(getImage())) getWorld().removeObject(this);
In fact, I think this might even work:
if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
KCee KCee

2023/4/9

#
How do i make the animations play out faster? I tried manipulating the numbers in setImage but its giving me errors like java.lang.ArrayIndexOutOfBoundsException: Index 14 out of bounds for length 14 at Explosion.setImage(Explosion.java:53) at Explosion.act(Explosion.java:28) current code:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Explosion here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Explosion extends Actor
{
    GreenfootImage[] currAnim;
    int animTimer;
    public Explosion()
    {
        GreenfootImage[] explosionAni = new GreenfootImage[14];
        for (int i=0; i<14; i++)
        {
            explosionAni[i] = new GreenfootImage("tile" + i + ".png");
            explosionAni[i].scale (100, 100);
        }
        setAnimation(explosionAni);
    }
    
    public void act()
    {
        //this.getImage().setTransparency(getImage().getTransparency() - 3); //slowly becomes transparent
        removeTouching(Hunter.class);
        setImage();
        /*if (hunter != null)
        {
            getWorld().removeObject(hunter);
        }
        
        if (this.getImage().getTransparency() < 5)
        {
            getWorld().removeObject(this);
        }*/
    }
    
    private void setAnimation(GreenfootImage[] anim)
    {
        currAnim = anim;
        animTimer = -1;
        setImage();
    }

    private void setImage() //sets image to the current iamge for a certain amount of time
    {
        animTimer = (animTimer+1)%(10*currAnim.length);
        if(animTimer%10 == 0) 
        {
            if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
            setImage(currAnim[animTimer/10]);
        }
    }
}
danpost danpost

2023/4/9

#
KCee wrote...
How do i make the animations play out faster? I tried manipulating the numbers in setImage but its giving me errors like << Error Trace Omitted >> << Code Omitted >>
The number that needs changed appears several times in the setImage method. Also, it should probably be a constant for the Explosion class:
private static final int frameDuration = 10;
Your setImage method can then be modified to this:
private void setImage() {
    animTimer = (animTimer+1)%(frameDuration*currAnim.length);
    if (animTimer%frameDuration == 0) {
        if (currAnim[currAnim.length-1] == getImage()) getWorld().removeObject(this);
        setImage(currAnim[animTimer/frameDuration]);
    }
}
Now, you can adjust the value of the constant field to a smaller value to shorten the duration of the frames.
You need to login to post a reply.