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

2013/6/20

Walking animation

davemib123 davemib123

2013/6/20

#
Hi Guys, in the process of doing a Mario game. I've come to a slight stumbling block. I can get Mario to move left and right, but the animation looks slightly off as the frames change to quickly. How do I slow it down? The scenario is located here: http://www.greenfoot.org/scenarios/8881 The code is as follows:
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)

/**
 * Write a description of class Mario here.
 * 
 * @author (your name) 
 * @version (a version number or a date)
 */
public class Mario extends Actor
{
    private final GreenfootImage RMidle= new GreenfootImage("mario-idle.gif");
    private final GreenfootImage RMjump= new GreenfootImage("mario-jump.gif");
    private final GreenfootImage RMwalk1= new GreenfootImage("mario-walk1.gif");
    private final GreenfootImage RMwalk2= new GreenfootImage("mario-walk2.gif");
    private final GreenfootImage RMwalk3= new GreenfootImage("mario-walk3.gif");

    private final GreenfootImage LMidle = new GreenfootImage(RMidle);
    private final GreenfootImage LMjump = new GreenfootImage(RMjump);
    private final GreenfootImage LMwalk1 = new GreenfootImage(RMwalk1);
    private final GreenfootImage LMwalk2 = new GreenfootImage(RMwalk2);
    private final GreenfootImage LMwalk3 = new GreenfootImage(RMwalk3);

    private int speed = 3;
    private int frame;
    private boolean walking;
    private boolean facingRight;
    private boolean isKeyPressed;

    /**
     * An example of a method - replace this comment with your own
     */
    public Mario()
    {
        setImage(RMidle);
        walking = false;
        facingRight = true;

        RMidle.scale(38,50);
        RMjump.scale(51,50);
        RMwalk1.scale(48,50);
        RMwalk2.scale(36,50);
        RMwalk3.scale(44,50);

        LMidle.scale(38,50);
        LMjump.scale(51,50);
        LMwalk1.scale(48,50);
        LMwalk2.scale(36,50);
        LMwalk3.scale(44,50);

        LMidle.mirrorHorizontally();
        LMjump.mirrorHorizontally();     
        LMwalk1.mirrorHorizontally();     
        LMwalk2.mirrorHorizontally();     
        LMwalk3.mirrorHorizontally();     
    }

    /**
     * Act - do whatever the Mario wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    public void act() 
    {
        checkKeys();
    }

    /**
     * An example of a method - replace this comment with your own
     */
    public void checkKeys()
    {
        isKeyPressed = false;
        if (Greenfoot.isKeyDown("right"))
        {
            walkRight();
            setLocation (getX()+speed, getY());
            isKeyPressed = true;
        }
        if (Greenfoot.isKeyDown("left"))
        {
            walkLeft();
            setLocation (getX()-speed, getY());
            isKeyPressed = true;
        }
        if (!(isKeyPressed))
        {
            stopWalking();
        }
    }

    public void walkRight()
    {
        walking = true;
        facingRight = true;
        frame ++;
        if(frame==1)
        {
            setImage(RMidle);
        }
        else if(frame==2)
        {
            setImage(RMwalk1);
        }
        else if(frame==3)
        {
            setImage(RMwalk2);
        }
        else if (frame==4)
        {
            setImage(RMwalk3);
            frame = 1;
            return;
        }

    }

    public void walkLeft()
    {
        walking = true;
        facingRight = false;
        frame ++;
        if(frame==1)
        {
            setImage(LMidle);
        }
        else if(frame==2)
        {
            setImage(LMwalk1);
        }
        else if(frame==3)
        {
            setImage(LMwalk2);
        }
        else if (frame==4)
        {
            setImage(LMwalk3);
            frame = 1;
            return;
        }

    }

    public void stopWalking()
    {
        walking = false;
        if (facingRight)
            setImage (RMidle);
        else
            setImage (LMidle);
    }
}
Zamoht Zamoht

2013/6/20

#
I downloaded the scenario and this helped, but I'm not sure it's a full fix.
public void walkLeft()
    {
        int delay = 4;
        walking = true;
        facingRight = false;
        frame ++;
        if(frame < 1 * delay)
        {
            setImage(LMidle);
        }
        else if(frame < 2 * delay)
        {
            setImage(LMwalk1);
        }
        else if(frame < 3 * delay)
        {
            setImage(LMwalk2);
        }
        else if (frame < 4 * delay)
        {
            setImage(LMwalk3);
            frame = 1;
            return;
        }

    }
You can test it for yourself by changing the value of delay.
davemib123 davemib123

2013/6/20

#
Zamoht that is a good suggestion. it delays the animation but when I press left and right arrow keys one after another the image sticks to the idle stance
Zamoht Zamoht

2013/6/20

#
Fixed it:
public void checkKeys()
    {
        isKeyPressed = false;
        if (Greenfoot.isKeyDown("right") && Greenfoot.isKeyDown("left"))
        {
            stopWalking();
            isKeyPressed = true;
        }
        else if (Greenfoot.isKeyDown("right"))
        {
            walkRight();
            setLocation (getX()+speed, getY());
            isKeyPressed = true;
        }
        else if (Greenfoot.isKeyDown("left"))
        {
            walkLeft();
            setLocation (getX()-speed, getY());
            isKeyPressed = true;
        }
        if (!(isKeyPressed))
        {
            stopWalking();
        }
    }
You can remove the if statement that checks wether both keys are pressed if you want, but if you do so and both keys are pressed mario will move right. Also change the move method a little:
public void walkLeft()
    {
        int delay = 4;
        walking = true;
        if (facingRight == true)
        {
            frame = 0;
        }
        facingRight = false;
        frame ++;
        if(frame < 1 * delay)
        {
            setImage(LMidle);
        }
        else if(frame < 2 * delay)
        {
            setImage(LMwalk1);
        }
        else if(frame < 3 * delay)
        {
            setImage(LMwalk2);
        }
        else if (frame < 4 * delay)
        {
            setImage(LMwalk3);
            frame = 1;
            return;
        }
    }
Add the same changes to walkRight() though remember to change if (facingRight == true).
davemib123 davemib123

2013/6/21

#
That's great. I've tested it and found if remove this piece of code it works fine moving left and right:
if (facingRight == true)  
        {  
            frame = 0;  
        } 
You need to login to post a reply.