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

2013/3/3

Animating an object

1
2
Gingervitis Gingervitis

2013/3/3

#
I have an object set to change its image several times, but it keeps resetting to the starting image when it is image10. how can I get it to stay at image 10 when it is image 10? Here is the code
public void switchImage()
    {
     
        setImage(image1);
        if ( getImage() == image1)
        {
            setImage(image2);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image2)
        {
            setImage(image3);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image3)
        {
            setImage(image4);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image4)
        {
            setImage(image5);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image5)
        {
            setImage(image6);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image6)
        {
            setImage(image7);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image7)
        {
            setImage(image8);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image8)
        {
            setImage(image9);
            Greenfoot.delay(10);
        }
        
        if ( getImage() == image9)
        {
            setImage(image10);
        }
                
    }
danpost danpost

2013/3/3

#
The use of 'delay' statements as used here and in the Rock class is not the appropriate way to create animation. What you should have, is a counter that tracks the number of cycles an image is displayed for.
// add this instance field
private int imageTimer;

// in the constructor
setImage(image1);

// then your 'switchImage' method should be something like
private void switchImage()
{
    int span = 10; // cycles between image changes
    int imgCt = 10; // total number of images
    if (imageTimer==(imgCt-1)*span) return; // no need to proceed (no more image changes)
    imageTimer++; // increment timer
    if (imageTimer == span) setImage(image2);
    if (imageTimer == 2*span) setImage(image3);
    if (imageTimer == 3*span) setImage(image4);
    if (imageTimer == 4*span) setImage(image5);
    if (imageTimer == 5*span) setImage(image6);
    if (imageTimer == 6*span) setImage(image7);
    if (imageTimer == 7*span) setImage(image8);
    if (imageTimer == 8*span) setImage(image9);
    if (imageTimer == 9*span) setImage(image10);
}
Just change the initial value of 'span' to change the rate of change of the images.
Gingervitis Gingervitis

2013/3/3

#
What does the 'return' do in this code?
danpost danpost

2013/3/3

#
It causes an immediate exit from the method, skipping any code below it.
Gingervitis Gingervitis

2013/3/3

#
Oh ok.... how can I create a turtle in the center of the animating image really small and scale it to its original size simulating the floor is opening up and turtle is coming out of the floor?
danpost danpost

2013/3/3

#
Let us work one thing at a time. We need to get everything else you have working properly before moving on.
Gingervitis Gingervitis

2013/3/3

#
Ok. Do you give me credit for getting it work like that the way I did, even though it was wrong?
danpost danpost

2013/3/3

#
I can commend you on your effort and results. Besides, there is really no wrong way, if it works. But, it should work the way that you intended it to work; not by settling on whatever way you managed to make it do close to something that you wanted. The following is my Rock class (I renamed some of the image files; but this allows the code to be better understood when looking at it):
import greenfoot.*;

public class Rock extends Actor
{
    private boolean hasLanded; // flag to signify whether it has landed yet
    GreenfootImage image = new GreenfootImage("rock.png");
    
    public Rock()
    {
        setImage(new GreenfootImage(1, 1));
    }
    
    public void act()
    {
        if(hasLanded) return; // no action required if grounded
        move();
        updateImage();
        checkGrounded();
    }
    
    private void move()
    {
        turnTowards(473, 441);
        move(4);
        setRotation(0);
    }
    
    private void updateImage()
    {
        GreenfootImage img = new GreenfootImage(image);
        double factor = (double)getX()/(double)getWorld().getWidth();
        img.scale(20+(int)(100*factor), 20+(int)(100*factor));
        setImage(img);
    }
    
    private void  checkGrounded()
    {
        if(getY()>=441)
        {
            hasLanded=true;
            setImage("rock_grounded.png");
        }        
    }
    
    public boolean isGrounded()
    {
        return hasLanded;
    }
}
I am creating the rock in the world constructor. Its initial image is set in the Rock constructor to a single pixel invisible object. When the scenario is started, the image will start updating. The code for the class should be pretty straight-forward and understandable. Hope it can help you in your coding quality. I will complete the Rock class by adding code to create the FireTail objects. Then I will post that class for you.
Gingervitis Gingervitis

2013/3/3

#
Ok. I just added what you posted. . . I think boolean statements are making a little more sense for me....
danpost danpost

2013/3/3

#
Alright, the adjustments to my Rock class and the code for my Tail class (FireTail) follows:
// In Rock class
// added field
private int counter;
// added in 'act' after 'move();'
createTail();
// added the 'createTail' method
private void createTail()
{
    counter = (counter + 1) % 2; // toggles between 0 and 1
    if (counter == 0) getWorld().addObject(new Tail(getImage().getWidth()), getX(), getY());
}

// the Tail class (FireTail)
import greenfoot.*;

public class Tail extends Actor
{
    private GreenfootImage image = new GreenfootImage("tail.png");
    private int size, fade;
    
    public Tail(int initialSize)
    {
        size = initialSize * 2;
        fade = 3 + Greenfoot.getRandomNumber(4);
    }

    public void act()
    {
        updateImage();
        checkSize();
    }
    
    private void updateImage()
    {
        size -= fade;
        GreenfootImage img = new GreenfootImage(image);
        img.scale(size, size);
        setImage(img);
    }
    
    private void checkSize()
    {
        if (size<10) getWorld().removeObject(this);
    }
}
Gingervitis Gingervitis

2013/3/3

#
I added the all of that . . . is there a way to make it so the tail stays behind the rock? (right now it just covers the rock completely) I also made the TPlatform its own class instead of changing the image of the rocket . . .
danpost danpost

2013/3/3

#
In your Intro world class constructor, right after your 'super(600, 500, 1);' statement, add the following:
setPaintOrder(Rock.class);
If you want your turtle to come from underneaath the rocket then:
setPaintOrder(Rock.class, Rocket.class);
Gingervitis Gingervitis

2013/3/3

#
So that's what setPaintOrder() does? Is there a way to have the turtle really small (almost invisible) and scale it to its original size while the image of the rocket.class is changing?
danpost danpost

2013/3/3

#
OK, now we have the Rock and Tail classes above. The Rocket class is totally empty of code at this point. My Turtle and Skip (Text) classes follows:
// my Turtle class code
import greenfoot.*;

public class Turtle extends Actor
{
    private int timer = 100;
    
    public void act()
    {
        if(timer==0)
        {
            move(2);
            if(getRotation()==0 && getX()>=355) timer = 136;
            if(getRotation()==180 && getX()<=202) Greenfoot.setWorld(new Menu());
        }
        else
        {
            timer--;
            if(getX()>=355 && timer<36) setRotation(getRotation()-5);
        }
    }
}

// my Skip (Text class) code
import greenfoot.*;

public class Skip extends Actor
{
    public void act()
    {
        if(Greenfoot.mouseMoved(this)) getImage().setTransparency(0);
        if(Greenfoot.mouseMoved(null) && !Greenfoot.mouseMoved(this)) getImage().setTransparency(255);
        if (Greenfoot.mouseClicked(this))  Greenfoot.setWorld(new Menu());  
    }
}
danpost danpost

2013/3/3

#
Gingervitis wrote...
So that's what setPaintOrder() does? Is there a way to have the turtle really small (almost invisible) and scale it to its original size while the image of the rocket.class is changing?
Please be more specific as to what you want. At the moment, the image of the rocket is not changing; although, in the MainMenu class you did have the Rocket object doing something else. Is that what you were inquiring about?
There are more replies on the next page.
1
2