Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (497)
Games in Android Showcase (114)
games submitted by our members
Games in WIP (563)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  problems with animation  (Read 1153 times)
0 Members and 1 Guest are viewing this topic.
Offline asphaltgalaxy

Junior Member


Medals: 1



« Posted 2012-01-24 20:20:29 »

Hello,

Probably this question is too easy to most of you, but I feel like stuck.

I've got everything ok with moving the image, but when I draw different images (from array), I see some flashing.

You can try the applet here:
http://asphaltgalaxy.com/test2/animtest.html

Press space to see that unwanted effect or press left or right to move.

Shortly about my animation loop:

I've got JPanel:
1  
public class Board extends JPanel implements ActionListener, Runnable {


and there is I think pretty standard run method in it:
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 run () {

        long beforeTime, timeDiff, sleep;

        beforeTime = System.currentTimeMillis();

        while (true) {

            UpdateGame();
            repaint();

            timeDiff = System.currentTimeMillis() - beforeTime;
            sleep = DELAY - timeDiff;

            if (sleep < 0) sleep = 2;
            try {
                Thread.sleep(sleep);
            }
            catch (InterruptedException e) {
                System.out.println("interrupted");
            }

            beforeTime = System.currentTimeMillis();
        }
    }


My paint method is like this:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
    public void paint(Graphics g) {
        super.paint(g);
        switch (gamestate) {
            case RUNNING: {
                DrawRunning (g);
             }
        }
        Toolkit.getDefaultToolkit().sync();
        g.dispose();
    }


And finally DrawRunning runs this method of Paddle class:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
    public void Draw (Graphics g, JPanel p) {
       
        switch (state) {
            case GET_NARROWER:
                g.drawImage(narrower[narrowerframe], x, y, p);
                break;
            case GET_WIDER:
                g.drawImage(wider[widerframe], x, y, p);
                 break;
            default:
                g.drawImage(paddle, x, y, p);
                break;
        }
    }


where wider and narrower arrays of images:
1  
2  
    Image[] wider = new Image[WIDER_FRAMES];
    Image[] narrower = new Image[NARROWER_FRAMES];


And arrays are filled in Paddle class when you press space (I've got one image which I resize frame by frame):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
    public void Wider () {
        if (state == State.NORMAL) {
            state = State.GET_WIDER;
            sizechange = WIDER_SIZE / WIDER_FRAMES;
            widerframe = 0;
             for (int i = 0; i < WIDER_FRAMES; i++) {
                wider[i] = iid.getImage().getScaledInstance(w + sizechange * (i + 1), H, 0);
            }
            effectdelay = EFFECT_DELAY;
        }
    }


Any help needed, what and where I am doing wrong?

If I didnt provided some important code, please, let me know... Just didnt want to paste a lot of it to make main logic as clear as possible.
Offline Waterwolf

Junior Member


Medals: 3



« Reply #1 - Posted 2012-01-24 20:49:07 »

Unable to check the applet but I'm fairly sure the problem is that you're not using double buffering. Luckily its fairly easy to implement
Offline ra4king

JGO Kernel


Medals: 345
Projects: 3
Exp: 5 years


I'm the King!


« Reply #2 - Posted 2012-01-25 00:31:15 »

I don't see any flickering in the test applet Smiley

Oh I hit space again and I noticed the flashing. It doesn't always happen, most of the time it works fine. If it was flashing all the time then that would be a problem with either your animation or with how you resize, but since it works sometimes, the only place there might be a problem is how you do the animation.

EDIT: Could you post the entire class, I think I have a hunch onto why this is happening.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #3 - Posted 2012-01-25 16:02:48 »

Thanks for answering!

Yeah, I forgot to mention that I do use doublebuffering provided by JPanel:

1  
setDoubleBuffered(true);

Maybe these are roots of evil? Smiley

For me it almost always flashes (those few times I think I saw that it didn't flash I can address to my imagination Smiley )

Anyway, here is full Paddle class listing:

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  
123  
124  
125  
126  
127  
128  
129  
130  
131  
132  
133  
134  
public class Paddle {
   
    enum State {NORMAL, WIDE, GET_WIDER, GET_NARROWER};
    State state = State.NORMAL;
   
    public enum Direction {LEFT, RIGHT, NONE};
    int dm = 0, w;
    Direction direction = Direction.NONE;
   
    Image paddle;
   
    ImageIcon iid = new ImageIcon(this.getClass().getResource("paddle.png"));
   
    final int STARTX = 200, STARTY = Board.BOARD_Y_TO - 40, SPEED = 15, SPEEDD = 7, W = 80, H = 15;
    final int XLEFT = BrickBoard.X, XRIGHT = BrickBoard.X + BrickBoard.W;
    final int EFFECT_DELAY = 50, WIDER_SIZE = 40, WIDER_FRAMES = 10, NARROWER_FRAMES = 10;
    int widerframe, narrowerframe, sizechange;
    int x, xprev, y, speed, effectdelay;
   
    Image[] wider = new Image[WIDER_FRAMES];
    Image[] narrower = new Image[NARROWER_FRAMES];
   
    public Paddle () {
        x = STARTX;
        y = STARTY;
        speed = 0;
        w = W;
       
        paddle = iid.getImage().getScaledInstance(W, H, 0);

    }
   
    public void Move (Direction d) {
        direction = d;
        speed = SPEED;
        switch (direction) {
            case LEFT: {
                dm = -1;
                break;
            }
            case RIGHT: {
                dm = 1;
                break;
            }    
        }
    }
    public void Stop () {
        direction = Direction.NONE;
    }
    public void Wider () {
        if (state == State.NORMAL) {
            state = State.GET_WIDER;
            sizechange = WIDER_SIZE / WIDER_FRAMES;
            widerframe = 0;
            xprev = x;
            for (int i = 0; i < WIDER_FRAMES; i++) {
                wider[i] = iid.getImage().getScaledInstance(w + sizechange * (i + 1), H, 0);
            }
            effectdelay = EFFECT_DELAY;
        }
    }
   
    public void Update () {
       
        switch (state) {
            case WIDE:
                if (--effectdelay == 0) {
                    state = State.GET_NARROWER;
                    sizechange = WIDER_SIZE / NARROWER_FRAMES;
                    narrowerframe = 0;
                   
                    for (int i = 0; i < NARROWER_FRAMES; i++) {
                        narrower[i] = iid.getImage().getScaledInstance(w - sizechange * (i + 1), H, 0);
                    }
                }
                break;
            case GET_WIDER:

                    w = W + sizechange * (widerframe + 1);
                    xprev = x;
                    x -= sizechange / 2;
                    widerframe++;
                    if (widerframe == WIDER_FRAMES) {
                        paddle = iid.getImage().getScaledInstance(W + WIDER_SIZE, H, 0);
                        state = State.WIDE;
                    }
                break;
               
            case GET_NARROWER:
                w = W - sizechange * (widerframe + 1);
                x += sizechange / 2;
                narrowerframe++;
                if (narrowerframe == NARROWER_FRAMES) {
                    paddle = iid.getImage().getScaledInstance(W, H, 0);
                    state = State.NORMAL;
                }                
                break;
        }
       
        if (direction == Direction.NONE) {
            speed -= SPEEDD;
            if (speed < 0) {
                speed = 0;
            }            
        }
     
        int dx = x + speed * dm;
        if (dx + w > XRIGHT) {
            x = XRIGHT - w;
        }
        else if (dx < XLEFT) {
            x = XLEFT;
        }
        else {
            x = dx;
        }    
               
    }
   
    public void Draw (Graphics g, JPanel p) {
       
        switch (state) {
            case GET_NARROWER:
                g.drawImage(narrower[narrowerframe], x, y, p);
                break;
            case GET_WIDER:
                g.drawImage(wider[widerframe], x, y, p);
                 break;
            default:
                g.drawImage(paddle, x, y, p);
                break;
        }
    }
}


When you hit Space Wider is called, and Update and Draw according to main game loop are executed.

Waiting for any info Smiley
Offline AurelienRibon

Senior Newbie


Medals: 3


Toolmaker, yeah.


« Reply #4 - Posted 2012-01-25 16:37:04 »

I can't really comment on the update method, but I know one thing: what you're trying to do is interpolating the scale of your paddle from a narrow size to a wider size, and vice-versa.

Instead of playing with state-machines and frames, I would recommend you to have a look to this library (it's not self-advertising, the lib is free, it's just that it could be a nice use-case Grin).

For instance, your Wider() method would be as follows:
1  
2  
3  
4  
5  
    public void Wider () {
        myManager.killTarget(this, SCALE_X);
        Tween.to(this, SCALE_X, 500).target(2).ease(Quart.INOUT).start(myManager);
        Tween.to(this, SCALE_X, 500).target(1).ease(Quart.INOUT).delay(EFFECT_DELAY).start(myManager);
    }


line 1: Stops any running animation affecting the scale of our paddle,
line 2: Animates the scale of the paddle from its current value to twice its size (with a nice "quart" easing) during 500ms,
line 3: Wait for EFFECT_DELAY milliseconds, then animates the scale of the paddle from its current value to its original size (with a nice "quart" easing) during 500ms.

Moreover, your update() method would be heavily trimmed, since you wouldn't need your state machine anymore.
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  
public void Update () {
        // ------------------------------------------------
       // Your whole state machine would be replaced by:

        int deltaMillis = <compute_delta_here>;
        tweenManager.update(deltaMillis);

        // ------------------------------------------------
       
        if (direction == Direction.NONE) {
            speed -= SPEEDD;
            if (speed < 0) {
                speed = 0;
            }            
        }
     
        int dx = x + speed * dm;
        if (dx + w > XRIGHT) {
            x = XRIGHT - w;
        }
        else if (dx < XLEFT) {
            x = XLEFT;
        }
        else {
            x = dx;
        }    
               
    }


Simple enough?

Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #5 - Posted 2012-01-25 16:56:12 »

I can't really comment on the update method, but I know one thing: what you're trying to do is interpolating the scale of your paddle from a narrow size to a wider size, and vice-versa.

Instead of playing with state-machines and frames, I would recommend you to have a look to this library (it's not self-advertising, the lib is free, it's just that it could be a nice use-case Grin).

For instance, your Wider() method would be as follows:
1  
2  
3  
4  
5  
    public void Wider () {
        myManager.killTarget(this, SCALE_X);
        Tween.to(this, SCALE_X, 500).target(2).ease(Quart.INOUT).start(myManager);
        Tween.to(this, SCALE_X, 500).target(1).ease(Quart.INOUT).delay(EFFECT_DELAY).start(myManager);
    }


line 1: Stops any running animation affecting the scale of our paddle,
line 2: Animates the scale of the paddle from its current value to twice its size (with a nice "quart" easing) during 500ms,
line 3: Wait for EFFECT_DELAY milliseconds, then animates the scale of the paddle from its current value to its original size (with a nice "quart" easing) during 500ms.

....


Simple enough?

Yep, you're right. And thanks for link. When using library code is simplier, thats true. Library seems really useful. But I've got some goals here:
1. Learn Java actually Smiley
2. Learn and feel (that it is more important for me) graphics programming and it's concepts and capabilities
3. Understand actually what went wrong here, cause till now everything went quite smooth. Smiley
Online Damocles
« Reply #6 - Posted 2012-01-25 17:00:42 »

To add more knowthebetter suggestions Wink

Try not to write the code "propperly" as learned in programming class.
Messie, linear code can help to get things done, and keep motivation up.

So dont structure your code too much yet.

Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #7 - Posted 2012-01-25 17:10:22 »

To add more knowthebetter suggestions Wink

Try not to write the code "propperly" as learned in programming class.
Messie, linear code can help to get things done, and keep motivation up.

So dont structure your code too much yet.

Aha thanks Smiley You think this will help me to solve paddle flashing on resize problem? Wink
Online Damocles
« Reply #8 - Posted 2012-01-25 17:21:36 »

First, try to extend the paddle very slowly, and check if it still flickers.
So you know if its related to missing double buffering.


Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #9 - Posted 2012-01-25 19:03:20 »

Delayed game loop to 2 FPS and removed background - paddle still flickers on resize but not every frame (randomly actually). When moving paddle - everything ok, like before.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline ra4king

JGO Kernel


Medals: 345
Projects: 3
Exp: 5 years


I'm the King!


« Reply #10 - Posted 2012-01-25 19:43:06 »

I see that you regenerate the animation array every single time you call Wider(). It is best to generate these arrays when the class is first initialized, so then all you have to do is modify the "currentFrame" variables.

Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #11 - Posted 2012-01-26 15:03:50 »

I see that you regenerate the animation array every single time you call Wider(). It is best to generate these arrays when the class is first initialized, so then all you have to do is modify the "currentFrame" variables.

Actually moving this image generation to constructor didnt help. And as I understand shouldnt keeping in mind 2 FPS game speed for generation 10 images of size 80x15 pixels Smiley

Started to debug and noticed, that my Draw method was called more often than game loop. Passing null as image observer stopped that.

Also I noticed, that image is not drawn for the first time! That probably caused flickering! So when I in my Draw method at the beginnig drew all images from array, images from this array were drawn correctly without flashing (when paddle was getting wider).
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
    public void Draw (Graphics g, JPanel p) {
        for (int i = 0; i < WIDER_FRAMES; i++) {
           g.drawImage(wider[i], 60, STARTY - 20 * (i + 2), null);
        }
        switch (state) {

            case GET_NARROWER:
                g.drawImage(narrower[narrowerframe], x, y, null);
                break;
            case GET_WIDER:
                g.drawImage(wider[widerframe], x, y, null);
                 break;
            default:
                g.drawImage(paddle, x, y, null);
                break;
        }
    }


Without this loop in the beginning and passing null as image observer I saw no paddle image at all when paddle was getting wider. Also putting same drawImage twice was not helping:

1  
2  
3  
4  
            case GET_WIDER:
                g.drawImage(wider[widerframe], x, y, null);
                g.drawImage(wider[widerframe], x, y, null);
                break;


I see, that I dont understand what happening Smiley But maybe somebody could explain me?

My thoughts are like:
1. I am using wrong game loop (posted in first message).
2. I do not handle image drawing correctly.

Which one, or maybe both? Or something else? Where is truth? Smiley
Offline asphaltgalaxy

Junior Member


Medals: 1



« Reply #12 - Posted 2012-01-27 15:02:07 »

It seems I figured it out.

As found in getScaledInstance documentation: "...The new Image object may be loaded asynchronously even if the original source image has already been loaded completely..."

So I should use ImageIcon again when scaling my paddle. And code may look like that:

1  
2  
3  
4  
                    for (int i = 0; i < NARROWER_FRAMES; i++) {
                        ImageIcon ii = new ImageIcon (iid.getImage().getScaledInstance(w - sizechange * (i + 1), H, 0));
                        narrower[i] = ii.getImage();
                    }


Now it's smooth like before Smiley
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

BurntPizza (16 views)
2014-09-19 03:14:18

Dwinin (34 views)
2014-09-12 09:08:26

Norakomi (61 views)
2014-09-10 13:57:51

TehJavaDev (84 views)
2014-09-10 06:39:09

Tekkerue (42 views)
2014-09-09 02:24:56

mitcheeb (64 views)
2014-09-08 06:06:29

BurntPizza (47 views)
2014-09-07 01:13:42

Longarmx (35 views)
2014-09-07 01:12:14

Longarmx (39 views)
2014-09-07 01:11:22

Longarmx (36 views)
2014-09-07 01:10:19
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!