Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (539)
Games in Android Showcase (132)
games submitted by our members
Games in WIP (603)
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  
  painting and animating in Jpanel  (Read 1370 times)
0 Members and 1 Guest are viewing this topic.
Offline Muteking

Senior Newbie





« Posted 2013-07-31 07:26:33 »

I drew an Oval and that is supposed to move right, when infact it doesn't. I'm also a little confused about when invoking a BufferedImage.
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  
public class GamePanel extends JPanel implements Runnable {
   
   public static int WIDTH = 1024;
   public static int HEIGHT = WIDTH / 16 * 9;
   private Thread t1;
   boolean running;
   private int FPS = 60;
   private long optimalTime = 1000 / FPS;
   private int heroX = 200;
   private int heroY = 200;
   
   
   public void addNotify(){
      Dimension size = new Dimension(WIDTH,HEIGHT);
      setPreferredSize(size);
      setFocusable(true);
      requestFocus();
      running = true;
      t1 = new Thread(this);
      t1.start();
   }
   

   
   public void paintComponent (Graphics g){
      super.paintComponent(g);
      Graphics2D g2 = (Graphics2D) g;
      g2.setColor(Color.WHITE);
      g2.fillRect(0, 0, WIDTH, HEIGHT);
      g2.setColor(Color.BLACK);
       g2.fillOval(heroX, heroY, 50, 50);
       g2.dispose();
   }

   
   public void run() {
      long startTime;
      long passedTime;
      long waitTime;
      while (running){
         startTime = System.nanoTime();
         System.out.println("Runs");
         update();
         repaint();
         passedTime = System.nanoTime() - startTime;
         waitTime = optimalTime - passedTime / 1000000;
         try {
            if (waitTime <= 0){
               waitTime = 2;
            }
            Thread.sleep(waitTime);
         } catch (InterruptedException e) {
            e.printStackTrace();
         }
      }
     
   }


   private void update() {
     
      heroX += 2;
     
   }

}
Offline Troncoso

JGO Coder


Medals: 20



« Reply #1 - Posted 2013-07-31 07:31:35 »

Typically, you draw first, then update. Not that this should make a difference. Can you confirm that your game loop is indeed looping?

And I don't understand your question about BufferedImages...
Offline Muteking

Senior Newbie





« Reply #2 - Posted 2013-07-31 07:59:52 »

The loop is looping, yes, the debugger says.
About BufferedImage. Do I need it along with paintComponent? Or paintComponent is enough to draw bitmaps?
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Herjan
« Reply #3 - Posted 2013-07-31 08:13:48 »

Im actually very very sure paintComponent doesn't get called (only in the beginning).

Offline Muteking

Senior Newbie





« Reply #4 - Posted 2013-07-31 08:27:44 »

Yes, it's true. But I still don't understand what I'm doing wrong.
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #5 - Posted 2013-07-31 10:14:43 »

You should use Canvas + DoubleBuffering. It is much more accelerated than drawing on a JPanel. Also you can avoid nasty screen flickering when using DoubleBuffering.

paintComponent(Graphics g) is pretty uncontrolable... It is invoked by the JVM when needed and should not be used for rendering. Try to minimize your game window when the loop is running, you will see that the circle moves to the right. So the problem lies withing the repaint() call. Instead use DoubleBuffering to get your Graphics-Object to draw with:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public class GamePanel extends Canvas {
        BufferStrategy bufferStrategy;
        public void addNotify() {
                ....
                this.createBufferStrategy(2) // 2 for DoubleBuffering :)
                bufferStrategy = this.getBufferStrategy(); // gets the current BufferStrategy
        }

        public void render() {
                // Now you can get the Graphics Object from the bufferStrategy and use it to draw on the Canvas
                Graphics2D g2d = (Graphics2D)bufferStrategy.getDrawGraphics();
                // Draw your stuff here
                bufferStrategy.show(); // Important because it makes everything you drew visible on the Canvas/Screen.
        }
}


Here is an excelent tutorial on DoubleBuffering with Java2D and Canvas: DoubleBuffering
Offline Muteking

Senior Newbie





« Reply #6 - Posted 2013-07-31 10:22:41 »

Thanks, Sirkarpfen. But I've already accomplished to use Canvas. Then I stumbled upon this article, which basically says that is a bad idea to mix lightweight(JFrame)components with heavyweight(Canvas) ones.
http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html
As matter of fact, Canvas was superseded many years ago by Swing, even though it is still popular among some programmers.

So, maybe I'm thinking that I don't have to use paintComponent at all (since I cannot use it outside the EDT), but just a graphic object. Still looking for a solution.
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #7 - Posted 2013-07-31 13:18:04 »

Thanks, Sirkarpfen. But I've already accomplished to use Canvas. Then I stumbled upon this article, which basically says that is a bad idea to mix lightweight(JFrame)components with heavyweight(Canvas) ones.
http://www.oracle.com/technetwork/articles/java/mixing-components-433992.html
As matter of fact, Canvas was superseded many years ago by Swing, even though it is still popular among some programmers.

So, maybe I'm thinking that I don't have to use paintComponent at all (since I cannot use it outside the EDT), but just a graphic object. Still looking for a solution.

As by the article you postet, there are nearly no problems when mixing lightweight and heavyweight components (since JDK 6 update 12). Also i never encountered any problems using a JFrame with Canvas.

I tried to write games using a JPanel too and found out that Canvas (and BufferStrategy) is just the better solution for massive drawing in short intervalls.
Of course you can draw on JPanel, unfortunatly you won't be able to use accelerated java2D with it, so you have to find another way to prevent flickering Smiley.
Offline Herjan
« Reply #8 - Posted 2013-07-31 13:28:33 »

Thanks, Sirkarpfen. But I've already accomplished to use Canvas. Then I stumbled upon this article, which basically says that is a bad idea to mix lightweight(JFrame)components with heavyweight(Canvas) ones.

Blabla, lol... all these bad ideas, Canvas works well...
Even Notch uses canvas... (In his herping the derp Team Fortress 2 Game).

However, if you want to do it another way, (for double buffering and stuff) I recommend to draw everything to an image and then draw the image to the screen, thats the way I do it always in normal Java.

Offline Andre Lopes
« Reply #9 - Posted 2013-07-31 14:24:52 »

Thanks, Sirkarpfen. But I've already accomplished to use Canvas. Then I stumbled upon this article, which basically says that is a bad idea to mix lightweight(JFrame)components with heavyweight(Canvas) ones.

Blabla, lol... all these bad ideas, Canvas works well...
Even Notch uses canvas... (In his herping the derp Team Fortress 2 Game).

However, if you want to do it another way, (for double buffering and stuff) I recommend to draw everything to an image and then draw the image to the screen, thats the way I do it always in normal Java.

When i was messing with java2D , i did exactly like that. I draw in a separated image and then i put in jPanel.

But this book here will help you guys out :

http://fivedots.coe.psu.ac.th/~ad/jg/

Its a little old but it explains Canvas/Java2D for games.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Muteking

Senior Newbie





« Reply #10 - Posted 2013-07-31 14:32:21 »

Herjan how can you say they are bad ideas when they come from Oracle? And even when I was posting to other forums with Canvas examples everybody said to me to use JPanel.
 Huh
Offline gouessej
« Reply #11 - Posted 2013-07-31 14:59:58 »

Herjan how can you say they are bad ideas when they come from Oracle? And even when I was posting to other forums with Canvas examples everybody said to me to use JPanel.
 Huh
At first, some Oracle tutorials aren't fully up-to-date, some of them are contradictory, especially about mixing heavyweight and lightweight components which was a bad practice before Java 1.6 update 10. Moreover, if you put a single AWT canvas into a JPanel, you will get a very simple solution that wouldn't be problematic even with Java 1.5. You're on Javagaming.org, there are lots of people who already created more or less "finished" games. Some advises obtained on more general Java forums might be valid in typical Swing clients but not in games. Finally, Oracle can make bad decisions, it's just a corporation composed of human beings and some of its orientations are questionable. In my humble opinion, if you really need better performance, you shouldn't even use Java2D, you should switch to LibGDX or raw OpenGL with the binding of your choice.

Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #12 - Posted 2013-07-31 17:05:09 »

Herjan how can you say they are bad ideas when they come from Oracle? And even when I was posting to other forums with Canvas examples everybody said to me to use JPanel.
 Huh
At first, some Oracle tutorials aren't fully up-to-date, some of them are contradictory, especially about mixing heavyweight and lightweight components which was a bad practice before Java 1.6 update 10. Moreover, if you put a single AWT canvas into a JPanel, you will get a very simple solution that wouldn't be problematic even with Java 1.5. You're on Javagaming.org, there are lots of people who already created more or less "finished" games. Some advises obtained on more general Java forums might be valid in typical Swing clients but not in games. Finally, Oracle can make bad decisions, it's just a corporation composed of human beings and some of its orientations are questionable. In my humble opinion, if you really need better performance, you shouldn't even use Java2D, you should switch to LibGDX or raw OpenGL with the binding of your choice.

It seems like Muteking hasn't much experience in java game developing, so it would be wiser to choose java2d before getting into the "hard-to-learn" stuff like OpenGL and their respective bindings. Java2D is much easier to learn and is more suited for beginners. After that i would recommend LibGDX or Slick2D to dive deeper into 2D Game-Developing. Raw OpenGL makes sense when starting to create 3D-Games (2D Games can be written in OpenGL too but it seems a little over-the-top for me xD).
Offline philfrei
« Reply #13 - Posted 2013-07-31 19:36:16 »

I put the code that is in addNotify() into a normal constructor and it works fine.

I've never used addNotify(). What is that about?

And what is it with all this cruft about the different graphics methods, folks? The OP was just trying to get a simple animation to work.

"It's after the end of the world! Don't you know that yet?"
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #14 - Posted 2013-07-31 19:40:55 »

I put the code that is in addNotify() into a normal constructor and it works fine.

I've never used addNotify(). What is that about?

And what is it with all this cruft about the different graphics methods, folks? The OP was just trying to get a simple animation to work.

I was just trying to give some advice on how to use a better and smoother rendering method. I started out the same way and soon encountered the problem with flickering animations, so i tried to point the OP into a "better" way of rendering stuff. Thought it would be helpfull Smiley.
Offline philfrei
« Reply #15 - Posted 2013-07-31 21:00:17 »

My apologies for the grumpiness.

I know that there are a lot of disputations and controversies about how to "best" handle graphics, what does or doesn't cause flicker, lightweight vs heavyweight, JPanel vs JComponent, use of this library or that. And, it is very tempting to answer with what one knows about rather than solve the question itself (insert old joke about drunk looking for keys near lamppost).

I am genuinely curious about the addNotify() method and why it was used instead of wrapping the same code in a Constructor. What benefits are gained by this?

From api:
>>Creates the Panel's peer. The peer allows you to modify the appearance of the panel without changing its functionality. <<

Apparently it is included in a text on animation (according to one link I found) but the book name is not mentioned.

"It's after the end of the world! Don't you know that yet?"
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #16 - Posted 2013-07-31 21:17:32 »

My apologies for the grumpiness.

I know that there are a lot of disputations and controversies about how to "best" handle graphics, what does or doesn't cause flicker, lightweight vs heavyweight, JPanel vs JComponent, use of this library or that. And, it is very tempting to answer with what one knows about rather than solve the question itself (insert old joke about drunk looking for keys near lamppost).

I am genuinely curious about the addNotify() method and why it was used instead of wrapping the same code in a Constructor. What benefits are gained by this?

From api:
>>Creates the Panel's peer. The peer allows you to modify the appearance of the panel without changing its functionality. <<

Apparently it is included in a text on animation (according to one link I found) but the book name is not mentioned.

no harm done Smiley. The addNotify() method doesn't make any sense. Why would someone want to change the native peer of the JPanel in that case? Some clarification would be appreciated Smiley.
Offline gouessej
« Reply #17 - Posted 2013-07-31 21:46:53 »

It seems like Muteking hasn't much experience in java game developing, so it would be wiser to choose java2d before getting into the "hard-to-learn" stuff like OpenGL and their respective bindings. Java2D is much easier to learn and is more suited for beginners. After that i would recommend LibGDX or Slick2D to dive deeper into 2D Game-Developing. Raw OpenGL makes sense when starting to create 3D-Games (2D Games can be written in OpenGL too but it seems a little over-the-top for me xD).
Yes, I tried to learn how to use the standard APIs before tinkering the third party APIs and that's a good advice. It allows to understand some concepts and the language itself before using APIs that introduce more complicated notions. LibGDX uses some OpenGL bindings, it's interesting to understand how it works under the hood, that's why raw OpenGL is still interesting for 2D at least for pedagogical purposes.

Offline Muteking

Senior Newbie





« Reply #18 - Posted 2013-08-01 06:39:56 »

I'm new here but I really like this forum! Thanks for the answers, so far. I think I'll have to try everything before finding which method works best for me.
Anyway, concurrency docs say that swing painting operations must reside in the EDT, aka run Thread.

I cannot call paint component directly, so I'm using a BufferedImage painted by a (g) graphic object. It moves but the problem now is that it flickers like crazy.
Jpanel is double buffered by default so I must be offroad, somehow.

Now I get this (add notify let you draw the Panel and when it's ready it will show up, and most of all, it saves me a line of code since I don't have to call the class, it starts automatically):
I've modified the game loop just to be sure that it has not the culprit.

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  
public class GamePanel extends JPanel implements Runnable {
   
   public static int WIDTH = 1024;
   public static int HEIGHT = WIDTH / 16 * 9;
   private Thread t1;
   boolean running;
   private int FPS = 60;
   private long optimalTime = 1000 / FPS;
   private int heroX = 200;
   private int heroY = 200;
   private BufferedImage Base;
   public Graphics g;
   
   
   public void addNotify() {
      super.addNotify();
      Dimension size = new Dimension(WIDTH,HEIGHT);
      setPreferredSize(size);
      setFocusable(true);
      requestFocus();
      running = true;
      t1 = new Thread(this);
      t1.start();
   }

   public void init() {
      Base = new BufferedImage(20, 20, BufferedImage.TYPE_INT_RGB);
      g = (Graphics) Base.getGraphics();
   }
   
   
   public void run() {
      init();
      long startTime;
      long passedTime;
      long waitTime;
      while (running){
      //   startTime = System.nanoTime();
      //   System.out.println("Runs");
         update();
         draw();
         repaint();
      //   passedTime = System.nanoTime() - startTime;
      //   waitTime = optimalTime - passedTime / 1000000;
         try {
         Thread.sleep(17);
         } catch (InterruptedException e) {
           e.printStackTrace();
         }
      }
     
   }



   public void draw() {
     
      g.setColor(Color.WHITE);
      g.fillRect(0, 0, WIDTH, HEIGHT);
      g.setColor(Color.BLACK);
      g.fillOval(heroX,heroY,30,30);
      g = this.getGraphics();
      g.drawImage(Base,0,0,null);
   }



   private void update() {
     
      heroX += 2;
     
   }

}
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #19 - Posted 2013-08-01 07:01:28 »

The problem is that you rely on the JVM to do your painting. You only use BufferedImages to buffer the loading process, the drawing with the Graphics object is still unbuffered and therefore flickers like hell Smiley.

Even the paintComponent(Graphics g) call would produce less flickering...
If you call repaint() you just give the JVM the "hint" to repaint as soon as possible, so you can never truly know when repaint() will be done Smiley. It is true that JPanel is marked as "Double Buffered". Even if it is, you can never gain full access at when a new frame will be drawn...

Also addNotify() should not be called inside a program:

"Makes this Component displayable by connecting it to a native screen resource. This method is called internally by the toolkit and should not be called directly by programs. "

I still don't understand why you use this method... The stuff you do inside is initialising the program, so just put it into a constructor and everything should be fine Smiley.
Offline Muteking

Senior Newbie





« Reply #20 - Posted 2013-08-01 07:18:57 »

Ok, very weird things happening. First of all, I've changed this line
1  
repaint();


to this

1  
paint(this.getGraphics());


And the flickering is gone.

And in the main class

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
public class Game {

   
   public static void main(String[] args) {
   JFrame frame = new JFrame();
   frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   frame.setContentPane(new GamePanel());
   frame.setResizable(false);
   frame.pack();
   frame.setLocationRelativeTo(null);
   frame.setVisible(true);
   
   }

}


Changing the setResizable from a line to another determines the flickering too. Wow, I've found this by trial and error, am I supposed to find documentation about that?
The problem is that you rely on the JVM to do your painting. You only use BufferedImages to buffer the loading process, the drawing with the Graphics object is still unbuffered and therefore flickers like hell Smiley.
@sirkarpfen: How do you buffer the graphic object?
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #21 - Posted 2013-08-01 07:47:10 »

calling paint(Graphics g) or paintComponent(Graphics g) directly is not recommended. Instead you should use repaint(). If you want a nice and smooth rendering you should definetely use Canvas + accelerated Graphics and double buffering (as i allready posted before^^).

Also this:

1  
frame.setContentPane(new GamePanel());


Is useless, instead just add the GamePanel to the frame:

1  
frame.add(new GamePanel);


It seems like you have to learn a bit more about Swing and AWT Components and the painting Mechanism so you could take a look here:
http://www.oracle.com/technetwork/java/painting-140037.html

EDIT: As Oracle confirmes JPanel has a double buffered Graphics Object by default, but it still seems that it is much slower than using the Graphics Object from a Canvas with a double buffered strategy. Is it because AWT is much more low-level? Can someone maybe explain that to us? xD
Offline Muteking

Senior Newbie





« Reply #22 - Posted 2013-08-01 09:13:29 »

And while I'm reading Oracle, I'm submitting to you this.
Quote
Swing starts with AWT's basic painting model and extends it further in order to maximize performance and improve extensibility
Offline gouessej
« Reply #23 - Posted 2013-08-01 09:39:02 »

And while I'm reading Oracle, I'm submitting to you this.
Quote
Swing starts with AWT's basic painting model and extends it further in order to maximize performance and improve extensibility
which is interesting and efficient for 2D GUIs but not for games in which you use custom painting.

Offline Muteking

Senior Newbie





« Reply #24 - Posted 2013-08-01 15:52:24 »

Ok, after testing and studying I am at a conclusion. Correct me if I'm wrong.
You can mix awt and Swing, especially if it's a Canvas inside a JFrame, so you won't deal with other components like JButton and stuff. Canvas let you bypass the JVM (so you won't be overriding paint) with the bufferstrategy inside EDT.
Once you did that, you can draw anything you like with g object.
Jpanel can bypass too the JVM with a BufferedImage to avoid the overwritten PaintComponent and thus putting everything into the EDT.
Offline sirkarpfen

Junior Devvie


Medals: 2
Exp: 2 years



« Reply #25 - Posted 2013-08-01 16:40:24 »

Basically you can mix as many AWT and Swing Components as you like. This was only a problem before Java 6 Update 10. It was fixed and there are no more problems when mixing components. If it's usefull is another story Smiley.

What you wrote about the buffered Graphics object is correct. But with Canvas you get a new Graphics object when creating a bufferstrategy. This object is for your use only and is normally not touched by drawing operations triggered by the JVM. The JPanels Graphics Object is used in every paintComponent(Graphics g) call.

Well now i am curious about why you allways talk about the EDT? Every drawing Method is normally done within the EDT, except when you draw with a graphics object inside a thread that was created by you 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.

rwatson462 (32 views)
2014-12-15 09:26:44

Mr.CodeIt (23 views)
2014-12-14 19:50:38

BurntPizza (51 views)
2014-12-09 22:41:13

BurntPizza (84 views)
2014-12-08 04:46:31

JscottyBieshaar (45 views)
2014-12-05 12:39:02

SHC (59 views)
2014-12-03 16:27:13

CopyableCougar4 (58 views)
2014-11-29 21:32:03

toopeicgaming1999 (123 views)
2014-11-26 15:22:04

toopeicgaming1999 (114 views)
2014-11-26 15:20:36

toopeicgaming1999 (32 views)
2014-11-26 15:20:08
Resources for WIP games
by kpars
2014-12-18 10:26:14

Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

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
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!