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

2012/12/22

Problems with Movement Animation

1
2
JimmyFake JimmyFake

2012/12/22

#
Hi everyone :) Im trying to code the animation for the movement of the hero in my game. The movement itself was working flawlessly and wasn't hard to do, but I'm having difficulties with the animation. I already looked into some discussions here, and learned a few things and could improve my code, but it still isnt working properly. Ok, I have 7 pictures that represent the standing and moving of my hero in the right direction.
    GreenfootImage sr = new GreenfootImage("sr.png");
    GreenfootImage wr1 = new GreenfootImage("wr1.png");
    GreenfootImage wr2 = new GreenfootImage("wr2.png");
    GreenfootImage wr3 = new GreenfootImage("wr3.png");
    GreenfootImage wr4 = new GreenfootImage("wr4.png");
    GreenfootImage wr5 = new GreenfootImage("wr5.png");
    GreenfootImage wr6 = new GreenfootImage("wr6.png");
    GreenfootImage[] images = {wr1, wr2, wr3, wr4, wr5, wr6};
That's the movement method:
public void movement() // Hero's movement
    {
        if(Greenfoot.isKeyDown("up")) // up
        {
            setLocation(getX(),getY()- mspeed/2);
            moveIndex++;
        } 
        if(Greenfoot.isKeyDown("down")) // down
        {
            setLocation(getX(),getY()+ mspeed/2);
            moveIndex++;
        } 
        if(Greenfoot.isKeyDown("left")) // left
        {
            setLocation(getX()- mspeed,getY());
            moveIndex++;
            facingLeft = true;
        }
        if(Greenfoot.isKeyDown("right")) // right
        {
            setLocation(getX()+ mspeed,getY());
            moveIndex++;
            facingLeft = false;
        }
        if(!Greenfoot.isKeyDown("right") && !Greenfoot.isKeyDown("left") && !Greenfoot.isKeyDown("up") && !Greenfoot.isKeyDown("down")) 
        {
            moveIndex = -1;
        }
        moveAnimation();
    }
And thats the Animation method:
    public void moveAnimation()
    {
        if (moveIndex == 60) moveIndex=0;
        if (moveIndex % 10==0)
        {  
            setImage(images[moveIndex/10]);  
        }
        if (moveIndex== -1) 
        {
            setImage(sr);
        }
        if (facingLeft) 
        {
            getImage().mirrorHorizontally(); 
        }
    }
I've got two problems: the first one is that sometimes, I get an java.lang.ArrayIndexOutOfBoundsException- Error, but I can't pinpoint what triggers that. the second one is, that the image is being mirrowed uncontrolled, that's probably because I somehow wrongy implemented the part with the boolean facingLeft, but I'm not sure whats wrong. I would be thankful for any help. Greetings Jimmy
danpost danpost

2012/12/22

#
One thing you could try is change your first line in 'moveAnimation' to
if (moveIndex >= 60) moveIndex=0;
(using 'greater than or equal to' instead of just 'equal to'). Holding down two keys as the value of 'moveIndex' goes from 59 to 61 would skip 60 and therefore allow the value to go up to 70 where the next image to change to is not present.
vonmeth vonmeth

2012/12/22

#
Erm, the Array error is odd. It should just go 0 through 5 based on the code you gave, which is within range of your image array as far as I can see. Edit: Looks like danpost got this. =) Your facingLeft code is getting called continuously, unless you change direction. I *believe* it should work if you nest it in with your other 'ifs' where the image is set. Like so:
public void moveAnimation()  
{  
    if (moveIndex == 60) moveIndex=0;  
    if (moveIndex % 10==0)  
    {    
        setImage(images[moveIndex/10]);
		if (facingLeft) getImage().mirrorHorizontally();  
    }  
    if (moveIndex== -1)   
    {  
        setImage(sr);
		if (facingLeft) getImage().mirrorHorizontally(); // not sure if you want to mirror this as well?
    }  
}  
Minion1 Minion1

2012/12/22

#
I don't know if I can help, but your code is fairly different from my movement code. What kind of animation style are we talking about here? Is it a platformer game (super mario bros)? A bird's eye view game (like the original zelda for instance)? Or a first person style game (dungeon crawler style)? I can show you the code for the scenario I'm working on for my zelda style game. The hero animates between just four images, but it works without flaw. Let me know if you'd like to see it.
JimmyFake JimmyFake

2012/12/23

#
@ danpost: got that, but isn't the same problem present at if (moveIndex % 10==0), the pictures are only changed if the moveIndex ist 0,10,20,30,40 or 50. Getting the Index to an odd number and then holding down two buttons would result in a movement with the no changing picture, wouldn't it? @vonmeth: tried that out, but it still now working properly :( The same as before, only difference is, I don't seem to get any out of Bounds errors anymore ( probably, because of danpost's fix tip). And yes, i want to mirror sr (standingRight), too ;) @Minion1: I don't actually know, how the type of game is called that uses the same movement animation as my game, but I could give you an example : TEKKEN Force Mode. It's a flowing animation when walking to the right or to the left, and if you press up or down, the hero simply walks up or down while being animated with the pictures for the last direction he was facing too. I would be interested in seeing your code, if you mean that your animation uses four images in each direction. If it's one image in each direction, then I appreciatively refuse.( I was able to do that, myself :) ) Thank you all for your fast replies, even though its just before christmas ^^ Wish you a cheerful Christmas Eve ^^
danpost danpost

2012/12/24

#
You could try changing the way you check the movement:
public void movement() // Hero's movement
{
    if(Greenfoot.isKeyDown("up")) // up
    {
        setLocation(getX(),getY()- mspeed/2);
    } 
    if(Greenfoot.isKeyDown("down")) // down
    {
        setLocation(getX(),getY()+ mspeed/2);
    } 
    if(Greenfoot.isKeyDown("left")) // left
    {
        setLocation(getX()- mspeed,getY());
        facingLeft = true;
    }
    if(Greenfoot.isKeyDown("right")) // right
    {
        setLocation(getX()+ mspeed,getY());
        facingLeft = false;
    }
    if(!Greenfoot.isKeyDown("right") && !Greenfoot.isKeyDown("left") && !Greenfoot.isKeyDown("up") && !Greenfoot.isKeyDown("down")) 
    {
        moveIndex = -1;
    }
    else
    {
        moveIndex++;
    }
    moveAnimation();
}
All I did was remove 'moveIndex++;' from each individual check and placed it in an else on the check for no keys down. Now it will only increment once per act cycle (if at all).
JimmyFake JimmyFake

2012/12/24

#
hmm, that would solve the problem, that it was possible to skip the if (moveIndex % 10==0), - Clause, but still got problems with the animation mirrowing. I noticed that, as long as I am using only the right,up, and down buttons everything works fine. But once is used the left button and the animation mirrowed when not wanted, it also ceases working with the right button ( also mirrows the image uncontrolled).
danpost danpost

2012/12/24

#
Implementing vonmeth's 'moveAnimation' method above should solve that problem as you will only adjust the facing of the image when you reset it.
JimmyFake JimmyFake

2012/12/24

#
I did implement vonmeth's 'moveAnimation' already, the problem is still there. Here's the code:
    public void moveAnimation()
    {
        if (moveIndex >= 60) moveIndex=0;
        if (moveIndex % 10==0)
        {  
            setImage(images[moveIndex/10]);
            if (facingLeft) getImage().mirrorHorizontally();    
        }
        if (moveIndex== -1) 
        {
            setImage(sr);
            if (facingLeft) getImage().mirrorHorizontally(); 
        }
    }
JimmyFake JimmyFake

2012/12/24

#
I can upload the szenario together with the code, if that would help. But sadly I don't really know how to ^^
danpost danpost

2012/12/24

#
Use the 'Share' button on the top left of the Greenfoot frame. Adjust the scenario icon and fill in the appropriate text/input boxes; and be sure to check to 'Publish source code' checkbox before clicking 'Share'.
JimmyFake JimmyFake

2012/12/24

#
Ok, took me some time, but I uploaded it here: http://www.greenfoot.org/scenarios/7126
vonmeth vonmeth

2012/12/24

#
Oooooo. Took me forever to figure out what the heck was going on. If you mirror the current image it is set to, it mirrors the image it references in the array. Whatever the current image is set to is not a copy, but the actual image in the array.
    public void moveAnimation()
    {
        if (moveIndex >= 60) moveIndex=0;
        if (moveIndex % 10==0)
        {  
            setImage(images[moveIndex/10]);
            if (facingLeft){
                GreenfootImage temp = new GreenfootImage(getImage());
                temp.mirrorHorizontally();
                setImage(temp);
            }
        }
        if (moveIndex== -1) 
        {
            setImage(sr);
            if (facingLeft) {
                GreenfootImage temp = new GreenfootImage(getImage());
                temp.mirrorHorizontally();
                setImage(temp);
            }    
        }
    }
Or you could do something like this:
    GreenfootImage[] mirrorImages;
    GreenfootImage srm;
    
    public Hero()
    {
        mirrorImages = new GreenfootImage[images.length];
        for(int i = 0; i < images.length; i++){
            mirrorImages[i] = new GreenfootImage(images[i]);
            mirrorImages[i].mirrorHorizontally();
        }
        srm = new GreenfootImage(sr);
        srm.mirrorHorizontally();
    }

    public void moveAnimation()
    {
        if (moveIndex >= 60) moveIndex=0;
        if (moveIndex % 10==0)
        {  
            if (facingLeft) setImage(mirrorImages[moveIndex/10]);
            else            setImage(images[moveIndex/10]);
        }
        if (moveIndex== -1) 
        {
            if (facingLeft) setImage(srm);
            else            setImage(sr);
        }
    }
danpost danpost

2012/12/24

#
An easier adjustment to your code would be:
public void moveAnimation()
{
    if (moveIndex >= 60) moveIndex=0;
    if (moveIndex % 10==0)
    {  
        setImage(new GreenfootImage(images[moveIndex/10]));
        if (facingLeft) getImage().mirrorHorizontally();    
    }
    if (moveIndex== -1) 
    {
        setImage(new GreenfootImage(sr));
        if (facingLeft) getImage().mirrorHorizontally();
    }
}
JimmyFake JimmyFake

2012/12/24

#
Thank you really much :) Both versions or all three (Vonmeth posted 2) are working. Danpost's is the one with the slightest change in code, so I took that one for now. But I've got a last question: Wouldn't the second version of Vometh be the best, as it doesn't create a new Image every Cycle and therefore would slow the programm the least. As for Vonmeths first or Danpost's version, I would have created millions of GreenfootImage's if running the game for a while. Am I wrong with my assumption? (I hope I was able to express myself correctly, as you probably already noticed I'm not a native one^^ )
There are more replies on the next page.
1
2