Results 1 to 15 of 15
  1. #1
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default Animation randomly changing speed problem - Please Help!

    Hi, Can somebody please explain to me why my java animation of a simple oval bouncing about the screen randomly changes speed? Sometimes it goes normal, sometimes slow. Even though I had a specific speed set. I have tried using a Timer and actionListener and also a Thread with the run method. The same thing happens.

    Is it because the time is never precise so sometimes the code might execute sooner or later than it should?

    Please I need to understand why it just randomly changes speed.

  2. #2
    KevinWorkman's Avatar
    KevinWorkman is offline Crazy Cat Lady
    Join Date
    Oct 2010
    Location
    Washington, DC
    Posts
    4,041
    Rep Power
    10

    Default

    Let's test out my psychic ability- do you have animation logic in your paintComponent() method?

    If you want help with your code, we'll have to see your code.

    Make sure it's in SSCCE form, and don't forget the code tags.

  3. #3
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    Java Code:
    public AnimationWithThreads(){
       
        x=0;
        y=0;
    }
    
     
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.fillRect(x, y, 40, 40);
    
        }
        public void move(){
             if(x<0||x>750){
                dx = -dx;
            }
             if(y<0||y>520){
                dy = -dy;
            }
                x += dx;
                y += dy;
    
        }
    
        public void run() {
        while (true) {
           move();
                repaint();
                try {
                    Thread.sleep(10);
                } catch (InterruptedException ex) {
                    //
                }
            }
            
        }
    
    
    
    }
    Java Code:
    public class Main extends JFrame {
    
       
        public static void main(String[] args){
           Main m = new Main();
            AnimationWithThreads a = new  AnimationWithThreads();
            Thread myThread = new Thread(a);
           m.add(a);
           myThread.start();
            m.setSize(800,600);
            m.setTitle("HEllo");
            m.setDefaultCloseOperation(EXIT_ON_CLOSE);
            m.setVisible(true);
        }
    
    
    }
    I have no idea why it's happening, but the funny thing is, sometimes it will work perfectly for a couple of minutes, No matter how many times I run it. I was thinking it may be something to do with NetBeans but then I tried it in textpad and it did the same. Sometimes it's perfect, other times it's not.

    This does the same thing even if I use a Timer and actionListener.


    I also did a pong game and the same problem was happening, this is my paint and actionperformed methods from that game
    Java Code:
    public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
    
          drawGame(g2d);
            g.dispose();
            g2d.dispose();
        }
        public void actionPerformed(ActionEvent e) {
            if(inGame){
            checkCollisions();
            players.move();
            ball.move();
            repaint();
            }
    
        }
    I can't see the small bit of logic if(ingame) doing much, but should I just not have any logic at all?
    Last edited by andyman99008; 12-21-2010 at 09:02 PM.

  4. #4
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Please double check the code that you've posted because it doesn't compile and thus isn't a true SSCCE. YOur animation class is missing stuff.

  5. #5
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    Ok, here is the Animation class with imports
    Java Code:
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import javax.swing.JPanel;
    
    public class AnimationWithThreads extends JPanel implements Runnable {
    
    private int x,y,dx=2,dy=2;
    
    public AnimationWithThreads(){
       
        x=0;
        y=0;
    }
    
     
        public void paintComponent(Graphics g){
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g;
            g2d.fillOval(x, y, 40, 40);
    
        }
        public void move(){
             if(x<0||x>750){
                dx = -dx;
            }
             if(y<0||y>520){
                dy = -dy;
            }
                x += dx;
                y += dy;
    
        }
    
        public void run() {
        while (true) {
           move();
                repaint();
                try {
                    Thread.sleep(5);
                } catch (InterruptedException ex) {
                    //
                }
            }
            
        }
    
    
    
    }
    Then the main method I already posted works with this, they are both in separate files.

    The other code I posted was just showing that I didn't have any logic inside the paint method but I still get the problem.(it was part of another program)
    Last edited by andyman99008; 12-21-2010 at 09:18 PM.

  6. #6
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    I have no idea how I can fulfill the last part of the SSCCE, How can I show an example of my problem? I have no idea what is causing it.

  7. #7
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    One problem I see is that your speed is fully dependent on the time period of a Thread.sleep, and the accuracy of this is not guaranteed. I'm no animation expert, but you are probably better off having your speed be dependent on the system clock so that if your sleep period is longer or shorter than usual, your animation will take that into account. Myself I'd use a Swing Timer, but to demo with your threading:

    Java Code:
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    
    import javax.swing.*;
    
    public class HisAnimationMain extends JFrame {
       public static void main(String[] args) {
          HisAnimationMain m = new HisAnimationMain();
          AnimationWithThreads a = new AnimationWithThreads();
          Thread myThread = new Thread(a);
          m.add(a);
          myThread.start();
          m.setSize(800, 600);
          m.setTitle("Hello");
          m.setDefaultCloseOperation(EXIT_ON_CLOSE);
          m.setVisible(true);
       }
    }
    
    class AnimationWithThreads extends JPanel implements Runnable {
       private static final int SIDE = 40;
       private static final long SLEEP_DELAY = 5;
       private static final double SPEED_PER_MILI = 0.2;
       private static final int PAD = 40;
       private double x;
       private double y;
       private double dx = 1;
       private double dy = 1;
       private long latestTime;
    
       public AnimationWithThreads() {
          x = 0;
          y = 0;
          latestTime = System.currentTimeMillis();
       }
    
       public void paintComponent(Graphics g) {
          super.paintComponent(g);
          Graphics2D g2d = (Graphics2D) g;
          g2d.fillRect((int)x, (int)y, SIDE, SIDE);
    
       }
    
       public void move() {
          
          if (x < 0) {
             dx = Math.abs(dx);
          } else if (x + SIDE > getWidth()) {
             dx = -Math.abs(dx);
          }
          if (y < 0) {
             dy = Math.abs(dy);
          } else if (y + SIDE > getHeight()) {
             dy = -Math.abs(dy);
          }
          long newTime = System.currentTimeMillis();
          int deltaTime = (int) (newTime - latestTime);
          latestTime = newTime;
          x += dx * SPEED_PER_MILI * deltaTime;
          y += dy * SPEED_PER_MILI * deltaTime;
    
       }
    
       public void run() {
          while (true) {
             repaint((int)x - PAD, (int)y - PAD, SIDE + 2*PAD, SIDE + 2*PAD);
             move();
             repaint((int)x, (int)y, SIDE, SIDE);
             try {
                Thread.sleep(SLEEP_DELAY);
             } catch (InterruptedException ex) {
                //
             }
          }
    
       }
    }

  8. #8
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    Ok, Couple of questions,
    Java Code:
    long newTime = System.currentTimeMillis();
          int deltaTime = (int) (newTime - latestTime);
          latestTime = newTime;
          x += dx * SPEED_PER_MILI * deltaTime;
          y += dy * SPEED_PER_MILI * deltaTime;
    I don't really understand whats happening here, what is the latestTime? I can see that everytime this runs, latestTime will increase but I don't understand it. When newTIme gets the currentTime in milliseconds what does that mean? Say its, 21:00pm, how does it convert to milliseconds?

    I also don't know what you mean by delta , I have heard it before in maths but I forget what it is.

    Where did you get the SPEED_PER_MILI from? Is it just an arbitrary number less than 1?
    I think the whole time calculations is confusing me the most. Would you be able to right it out in pseudo format? or in logical english or something?


    Another thing I don't understand(Because I have never seen it), is in the run method.
    What do the calculations inside the repaint parentheses do? Also, why do you have 2 repaints()?

    Sorry for all the questions but I think if I can just understand the time thing, it could be much clearer.

    Also, Thanks for taking the time to help me.

  9. #9
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    You can't control how many milliseconds there will be in each time slice, you can only suggest it, either with a Timer time delay or a Thread sleep parameter, and so your animation must take this into account. In your animation above, your time slice is 10 msec, and you're having the sprite move 2 pixels (or whatever the unit is), each 10 msec. I did the division of pixels divided by msecs, and turned this into a double constant of 0.2. So regardless of how many msecs pass, I want my sprite to move 0.2 pixels per mSec. So if 10 mSecs pass, then my sprite will move 2, if 15 pass, it will move 3. I get the time slice amount by calling System.currentTimeMillis() and subtracting the result from the last time that I called it. That's all I'm doing there.

  10. #10
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    Ah I see now about how that code works. But I still don't know why you have 2 repaints() and why they have paramaters?

  11. #11
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by andyman99008 View Post
    Ah I see now about how that code works. But I still don't know why you have 2 repaints() and why they have paramaters?
    Actually, my repaints are wrong. Rather than repaint the whole area, you just need to repaint the rectangle where the sprite was and where the new sprite is. But both repaints need to be done after x and y are changed. Again my code is in error.

  12. #12
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    Oh, so just calling repaint() repaints the entire frame?
    So the paramaters specify the exact position on the screen to repaint?
    So, for testing purposes, if I set 2 of the numbers in the repaint(...) to 0,0(where the square starts) it will only repaint that so I will end up with a black smudge moving down my screen?

    Again, thanks alot for your help

  13. #13
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Here's a better version of the run method, one that stores the old x and y positions, calls move, and then calls two repaints, one to erase the old sprite and the other to draw the new sprite (they'll likely overlap, so a small spot will be drawn twice, but that doesn't matter much):

    Java Code:
       public void run() {
          while (true) {
             int oldX = (int)x;
             int oldY = (int)y;
             move();
             
             // repaint a rectangle somewhat bigger than the previous position of sprite
             // this is to erase old image
             repaint(oldX - PAD, oldY - PAD, SIDE + 2*PAD, SIDE + 2*PAD);
             
             // repaint new position of sprite
             repaint((int)x, (int)y, SIDE, SIDE);
             try {
                Thread.sleep(SLEEP_DELAY);
             } catch (InterruptedException ex) {}
          }
       }

  14. #14
    andyman99008 is offline Member
    Join Date
    Dec 2010
    Posts
    17
    Rep Power
    0

    Default

    wow, I can only say thanks so many times...but seriously, thanks for all your help. I feel like I should be paying you!(But I wont :D)

    There is only 1 last question I need to ask, so I understand everything, and that is:
    If I was working on a game, with different animations happening at the same time, would it be better(faster) to repaint() the whole screen, or have methods to repaint(...) each animation at there specific locations?

    Thanks alot!

  15. #15
    Fubarable's Avatar
    Fubarable is offline Moderator
    Join Date
    Jun 2008
    Posts
    19,315
    Blog Entries
    1
    Rep Power
    26

    Default

    Quote Originally Posted by andyman99008 View Post
    There is only 1 last question I need to ask, so I understand everything, and that is:
    If I was working on a game, with different animations happening at the same time, would it be better(faster) to repaint() the whole screen, or have methods to repaint(...) each animation at there specific locations?
    I'm not an animation pro nor do I make games, so my answers are:
    1) I don't know
    2) If it were me, I'd try both options and see which worked better.
    3) Also, I still would probably use a Swing Timer rather than a background thread.


    Thanks alot!
    You're welcome.

Similar Threads

  1. Replies: 0
    Last Post: 08-14-2010, 11:09 AM
  2. Problem with my animation applet
    By cblue in forum Java 2D
    Replies: 0
    Last Post: 08-24-2009, 05:24 PM
  3. Animation Delay - Thread problem
    By wererabit in forum Advanced Java
    Replies: 3
    Last Post: 04-10-2009, 11:35 PM
  4. Replies: 0
    Last Post: 03-08-2009, 02:52 PM
  5. Replies: 3
    Last Post: 09-16-2008, 12:55 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •