painting and animating in Jpanel

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.

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;
		
	}

}

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…

The loop is looping, yes, the debugger says.
About BufferedImage. Do I need it along with paintComponent? Or paintComponent is enough to draw bitmaps?

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

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

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:


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

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 :).

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.

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.
???

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).

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 :).

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 :). 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 :).

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.

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.


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;
		
	}

}

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 :).

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 :). 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 :).