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

2012/12/6

Movement and animation?

Johnathon Johnathon

2012/12/6

#
Hey, so im having an issue with having something both run an animation and move from a key being down. Either alone run, but together it cant. Any help will be greatly appreciated. It's a rather long code so i'm only going to post the relevant parts.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void checkKeys()
{
    if (Greenfoot.isKeyDown("left"))
    {
        setImage("TeemoLeft.png");
        moveLeft();
    }
    if (Greenfoot.isKeyDown("right")) 
    {
        moveRight();
        animateRight();
    }
    if (Greenfoot.isKeyDown("up") )
    {
        if (onGround()) {jump();}
    }
   }
public void moveRight() { setLocation ( getX() + speed, getY() ); } public void animateRight() { int atime = 0; while (atime < 18) { atime++; setImage("TeemoRight.png"); setLocation ( getX() + speed, getY() ); if (atime == 6){ setImage("TeemoRunRight.png"); } if (atime == 12){ setImage("TeemoRunRight2.png"); } if (atime == 18){ atime = 0; } } }
danpost danpost

2012/12/7

#
The problem is in the way you coded the animation. You are trying to put all the animation into one act cycle (the act method calls the checkKeys method, which calls the animateRight method when the right key is pressed). While the act cycle cannot move on to another object or the world, everything stops during the processing of the animation (even the animated actor, which will not be refreshed until after the act cycle completes). Solution: make 'atime' an instance object variable and use it to control the animation, incrementing and checking its value each act cycle.
Johnathon Johnathon

2012/12/7

#
Sorry but I don't really understand. I looked up instance object variables and the best I could get would be to do something such as make a method to run it like I have and then instead of using animateRight() I would do like moveRight().animateRight() which doesn't work. Im a first year student trying to use this for my final.
danpost danpost

2012/12/7

#
An instance object variable is any non-static field that is declared within an Object class (world or actor) but not within a method. Each instance of that type class will have its own variable (with its own value) with that name. So if you add an instance object variable to an actor class, each actor created from within that class will have a variable with that name and the value of each one is independent of the others. Normally, the general layout of a class will be
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// imports
import greenfoot.*;
 
// class declaration
public class Teemo extends Actor
{
    // static class variables and non-static instance object variables
    // (static variables will have the 'static' keyword)
    private int atime=0;
    private boolean facingLeft=false;
 
    // constructors (if any)
    public Teemo()
    {
        // some code
    }
 
    // methods (if any)
    public void act()
    {
        // some code, like the following
        atime=atime+1;
        if (atime==18) atime=0;
        if (atime==0) setImage("TeemoRight.png");
        if (atime==6) setImage("TeemoRunRight.png");
        if (atime==12) setImage("TeemoRunRight2.png");
        if (facingLeft) getImage().mirrorHorizontally();
    }
}
The code in the 'act' method above should create a simple continuous 'running-right' animation. You can move the code out of the act method and into one with a name like 'animate' (since it controls both left and right). And for moving the actor, use 'if(facingLeft) move(-speed); else move(speed);'. When you check keys you could, if no keys are pressed, set 'atime' to negative one (-1), set the image to appropriate one for standing and facing current direction, and qualify the call to 'animate' with 'if(atime!=-1)animate();'.
Johnathon Johnathon

2012/12/9

#
Still can't seem to get it to work. That seemed to definately put it in the right direction though. The error seems to be on the mirroring, as right key 'kind of; works and the left key makes him flips back and forth like crazy. Heres the code now.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void act()
    {
        super.act();
        if(Greenfoot.isKeyDown("p"))
        {
            pause();
        }
         
        if(Greenfoot.isKeyDown("r"))
        {
            resume();
        }
        animate();
        checkKeys();       
        checkFall();
    }
1
2
3
4
5
6
7
private void checkKeys()
{
    if (Greenfoot.isKeyDown("up") )
    {
        if (onGround()) {jump();}
    }
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void animate()
    {
        if (Greenfoot.isKeyDown("left")) facingLeft = true;
        if (Greenfoot.isKeyDown("right")) facingLeft = false;
        if (Greenfoot.isKeyDown("right") || Greenfoot.isKeyDown("left")) atime = atime + 1;
        if (atime == 12) atime = 0;
        if (atime == 0)  setImage("TeemoRight.png");
        if (atime == 4)  setImage("TeemoRunRight.png");
        if (atime == 8) setImage("TeemoRunRight2.png");
        if (Greenfoot.isKeyDown("left") || Greenfoot.isKeyDown("right")){   
        if (facingLeft) setLocation (getX() - speed, getY());
        if (!facingLeft) setLocation (getX() + speed, getY());
        if (facingLeft) getImage().mirrorHorizontally();}
    }
vonmeth vonmeth

2012/12/9

#
The image only gets set at 3 different intervals, but is flipped every time animate is called while it is facing left and the left button is being pressed. This is what is causing that behaviour.
danpost danpost

2012/12/10

#
The problem is that 'facingLeft' is supposed to keep track of which way the character is currently facing; not which way we are going to want it to face. Line 13 should only be done immediately after setting a new image to the object (that was my fault -- sorry). That means you will have to change lines 7 through 9 to
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (atime==0)
{
    setImage("TeemoRight.png");
    if (facingLeft) getImage().mirrorHorizontally();
}
if (atime==4)
{
    setImage("TeemoRunRight.png");
    if (facingLeft) getImage().mirrorHorizontally();
}
if (atime==8)
{
    setImage("TeemoRunRight2.png");
    if (facingLeft) getImage().mirrorHorizontally();
}
Of course, I would code it as follows
1
2
3
4
5
6
String[] images = { "TeemoRight.png", "TeemoRunRight.png", "TeemoRunRight2.png" };
if (atime%4==0)
{
    setImage(images[atime/4]);
    if (facingLeft) getImage().mirrorHorizontally();
}
Johnathon Johnathon

2012/12/10

#
So I tried to change out what you told me to there, and I am not suppose to use arrays for the project so I can't use the second bit. A problem still seems to exist with this code. I'm trying to have it so that when the keys are let up, Teemo will look the direction he is moving, but in his "Stance" image which is TeemoRight.png. When I let go of the key about 75% of the time he seems to do that, but it doesn't always succeed. Also, the left animation is still rather off. Letting go of the left key results in both left and right facing teemo and in all three positions of the animation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public void animate()
{
    if (Greenfoot.isKeyDown("left")) facingLeft = true;
    if (Greenfoot.isKeyDown("right")) facingLeft = false;
    if (Greenfoot.isKeyDown("right") || Greenfoot.isKeyDown("left")) atime = atime + 1;
    if (atime == 12) atime = 0;
    if (atime==0
    
        setImage("TeemoRight.png"); 
        if (facingLeft) getImage().mirrorHorizontally(); 
    
    if (atime==4
    
        setImage("TeemoRunRight.png"); 
        if (facingLeft) getImage().mirrorHorizontally(); 
    
    if (atime==8
    
        setImage("TeemoRunRight2.png"); 
        if (facingLeft) getImage().mirrorHorizontally(); 
    }
    if (Greenfoot.isKeyDown("left") || Greenfoot.isKeyDown("right")){   
    if (facingLeft) setLocation (getX() - speed, getY());
    if (!facingLeft) setLocation (getX() + speed, getY());}
}
danpost danpost

2012/12/10

#
This would be a slight improvement on the 15-line code above:
1
2
3
4
5
6
7
8
9
String image="";
if(atime==0)image="TeemoRight.png";
if(atime==4)image="TeemoRunRight.png";
if(atime==8)image="TeemoRunRight2.png";
if(!"".equals(image))
{
    setImage(image);
    if(facingLeft)getImage().mirrorHorizontally();
}
Johnathon Johnathon

2012/12/10

#
Haha... I have no idea whats going wrong... I can't figure out the timings at all but I think its because somethings still wrong with it. I replace
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
if (atime==0)   
 {   
     setImage("TeemoRight.png");   
     if (facingLeft) getImage().mirrorHorizontally();   
 }   
 if (atime==4)   
 {   
     setImage("TeemoRunRight.png");   
     if (facingLeft) getImage().mirrorHorizontally();   
 }   
 if (atime==8)   
 {   
     setImage("TeemoRunRight2.png");   
     if (facingLeft) getImage().mirrorHorizontally();   
 }
with:
1
2
3
4
5
6
7
8
9
10
11
if (Greenfoot.isKeyDown("right") || Greenfoot.isKeyDown("left")) atime = atime + 1;
        if (atime == 12) atime = 0;
        String image=""
        if(atime==0)image="TeemoRight.png"
        if(atime==4)image="TeemoRunRight.png"
        if(atime==8)image="TeemoRunRight2.png"
        if(!"".equals(image)) 
        
            setImage(image); 
            if(facingLeft)getImage().mirrorHorizontally(); 
        }
The results are rather poor. For some reason he seems to take forever with getting to "TeemoRunRight.png" and then "TeemoRunRight2.png" seems to come instantly. I've tried timing like
1
2
3
if(atime==0)image="TeemoRight.png";
if(atime==100)image="TeemoRunRight.png";
if(atime==200)image="TeemoRunRight2.png";
but the image kind of just sputters. It his the first one then instantly returns to the stand. The left is still horribly wrong lol. The overall code again
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
import greenfoot.*;  // (World, Actor, GreenfootImage, and Greenfoot)
import java.lang.*;
import java.util.*;
 
/**
 *
 * @author Johnathon Posemato
 * @version 0.01
 */
public class Teemo extends Characters
{
    public void addedToWorld(World world)
    {
        setImage("Default.gif");
    }
     
    private static final int acceleration = 1;      // down (gravity)
    private static final int speed = 3;             // running speed (sideways)
    private static final int jumpStrength = 16;
     
    private int vSpeed = 0;                       
    private long time, pastTime;
    private static final long DELAYY = 6500;
    private static final long DELAY2 = 1000;
     
    int anim;
    int atime;
    private boolean facingLeft=false;
    public void act()
    {
        super.act();
        if(Greenfoot.isKeyDown("p"))
        {
            pause();
        }
         
        if(Greenfoot.isKeyDown("r"))
        {
            resume();
        }
        animate();
        checkKeys();       
        checkFall();
    }
     
    private void checkKeys()
    {
        if (Greenfoot.isKeyDown("up") )
        {
            if (onGround()) {jump();}
        }
       }
    
     
    private void jump()
    {
        setVSpeed(-jumpStrength);
        fall();
    }
     
    private void checkFall()
    {
        if (onGround()) {
            setVSpeed(0);
        }
        else {
            fall();
        }
    }
     
    public void animate()
    {
        if (Greenfoot.isKeyDown("left")) facingLeft = true;
        if (Greenfoot.isKeyDown("right")) facingLeft = false;
        if (Greenfoot.isKeyDown("right") || Greenfoot.isKeyDown("left")) atime = atime + 1;
        if (atime == 12) atime = 0;
        String image=""
        if(atime==0)image="TeemoRight.png"
        if(atime==4)image="TeemoRunRight.png"
        if(atime==8)image="TeemoRunRight2.png"
        if(!"".equals(image)) 
        
            setImage(image); 
            if(facingLeft)getImage().mirrorHorizontally(); 
        
        /*if (atime==0) 
        
            setImage("TeemoRight.png"); 
            if (facingLeft) getImage().mirrorHorizontally(); 
        
        if (atime==4) 
        
            setImage("TeemoRunRight.png"); 
            if (facingLeft) getImage().mirrorHorizontally(); 
        
        if (atime==8) 
        
            setImage("TeemoRunRight2.png"); 
            if (facingLeft) getImage().mirrorHorizontally(); 
        } */
        if (Greenfoot.isKeyDown("left") || Greenfoot.isKeyDown("right")){   
        if (facingLeft) setLocation (getX() - speed, getY());
        if (!facingLeft) setLocation (getX() + speed, getY());}
    }
     
    public boolean onGround()
    {
        Object under = getOneObjectAtOffset(0, getImage().getHeight()/2-8 , null);
        return under != null;
    }
 
    public void setVSpeed(int speed)
    {
        vSpeed = speed;
    }
     
    public void fall()
    {
        setLocation ( getX(), getY() + vSpeed);
        vSpeed = vSpeed + acceleration;
    }
}
A lot of useless variables exist because of past attempts at the animation. Thanks again for trying. If you have any other ideas please and thankyou on them.
danpost danpost

2012/12/10

#
I copied what you posted last (Haha post) as far as overall into a new actor subclass in a new scenario. I (for my sake) made it a subclass of Actor and removed anything dealing with its 'old' superclass (Characters). Since I did not have your images, I used three different colors instead of your String filenames. I created another subclass of Actor for the Ground object (just a continuous platform across the bottom of the screen). Nothing appeared out of sorts when I ran it. I slowed it down and the colors were changing regularly. This tells me that it might have something to do with some of the code I had removed (code dealing with calls to the superclass 'Characters'.
Johnathon Johnathon

2012/12/10

#
Oh my! That was probably a big part of my issues the whole time. I originally tried making all of this work with a code that involved using gif animated images already and never deleted it. Thank you so much!
pengtroll23 pengtroll23

2015/6/13

#
public void fall() { setLocation ( getX(), getY() + vSpeed); vSpeed = vSpeed + acceleration; }
You need to login to post a reply.