BufferStrategy, Fullscreen, and Canvas....arggh!

Hi. I'm working on a 2D tank game that has a GameCanvas that shows the battle action, and a StatusPanel just below the canvas which shows the stats of the tanks. Both of these components are added to a single JPanel through a BorderLayout, which is then added whenever the player clicks the "Play" button at the introduction screen.

I've just recently converted the game to fullscreen with few problems, but it was running especially slow. So I did away with the old double-buffering code for the canvas and tried to implement BufferStrategy, but nothing seems to appear. At the beginning of a game session, I load up graphics by calling loadGraphics(), which is in the GameCanvas class:

publicvoid loadGraphics()

{

createBufferStrategy(2);

strategy = getBufferStrategy();

}

Also, the main game loop calls drawGame(), which is also in GameCanvas, and supposedly shows the graphics. This part is extremely similar to the code snippet on the Fullscreen API site:

publicvoid drawGame()

{

g = (Graphics2D)strategy.getDrawGraphics();

render(g);

strategy.show();

g.dispose();

}

I've pretty much tried everything I know: ignoring repaint, creating the buffer strategy only once in the drawGame() method, removing the status panel, etc. Can anyone please tell me where I went wrong on this? Is it really possible for canvas to have a buffer strategy? If so, how?

Frumple

[1713 byte] By [Frumple] at [2007-9-27 21:03:24]
# 1

I don't claim to be an expert but I've just started working on a full screen game using BufferStrategy and mine works fine. I used a Frame rather than a canvas. Don't know if that makes any difference? I'm also using active rendering like you (i.e. no use of Paint()) but I haven't tried to use AWT or Swing components. I believe you have to call each component's PaintComponent() method when you're using active rendering, or at least PaintComponents() - also I believe there is an issue with using heavyweight (Awt) components and you really need to stick to lightweight (Swing) ones.

How do you expect the panels to be painted - i.e. what do you have in the render() method?

Have you seen the tutorial at... http://java.sun.com/docs/books/tutorial/extra/fullscreen/rendering.html

Good luck,

Tim

TimRyanNZ at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 2

> I don't claim to be an expert but I've just started

> working on a full screen game using BufferStrategy and

> mine works fine. I used a Frame rather than a canvas.

> Don't know if that makes any difference?

Well I'm not exactly sure if a frame can be added to another frame. My game runs as an application that extends JFrame. I would prefer to keep the status panel, since it's separate from the canvas screen.

> I'm also

> using active rendering like you (i.e. no use of

> Paint()) but I haven't tried to use AWT or Swing

> components. I believe you have to call each

> component's PaintComponent() method when you're using

> active rendering, or at least PaintComponents()

Would I have to call paintComponent() in my render method? Actually my status panel shows up as well as any other swing components, but the canvas doesn't show anything.

> also

> I believe there is an issue with using heavyweight

> (Awt) components and you really need to stick to

> lightweight (Swing) ones.

Again, just to clarify, all my components are swing components except for the canvas. Strangely, there's no such thing as a JCanvas.

> How do you expect the panels to be painted - i.e. what

> do you have in the render() method?

Is active rendering something that draw on to the whole screen, or just a component? All my other swing components draw on to the screen. In my render() method, I draw game sprites such as tanks and walls on to the canvas. So would I need to paint the panels and canvas under one whole umbrella, or can i just do active rendering to the canvas and let the panel go on its merry way?

Frumple

Frumple at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 3
I don't know if this helps, but at www.saber-x.com (my site) there is a link to my pong game, which use BufferStrategy on a canvas. The source should be in the jar.
Virum at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 4

> I don't know if this helps, but at www.saber-x.com (my

> site) there is a link to my pong game, which use

> BufferStrategy on a canvas. The source should be in

> the jar.

I never remember source being in the jar file. In fact, I just checked to make sure and still nothing.

Ceranith at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 5
Rats, thatr means I don't have it any more.... >:( Stupid computer crash...
Virum at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 6

I created a full screen slide show application that used a JFrame as the controller, but like the previous poster I extended Frame to get my full screen window. To get this working, I never added the Frame to the JFrame, I simply added the following method to the FullScreenFrame and called it from the controlling JFrame:

public void enterFullScreen(){

setFullScreenWindow(this);

}

Hope this helps.

rgeimer at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 7

Ooops, I forgot that setFullScreenWindow() is also one of my methods. Anyway, here is some more code from my FullScreenFrame class:

private GraphicsDevice gd;

...

private void setFullScreenWindow ( Window w ){

gd.setFullScreenWindow(w);

if ( w != null ){

w.createBufferStrategy(2);

}

}

rgeimer at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 8

Virum, I took the class file from your jar and decompiled it into something readable. However, it's pretty much the same thing that I have: Your pong game creates the buffer strategy in main(), draws to the graphics, and shows the strategy. My game creates the buffer strategy in loadGraphics(), draws stuff in render() and shows the strategy. I don't see much difference there, so I'm guessing it might have something to do with the panels or something else.

rgeimer: I'll try your solution as soon as I have time, but first I'm gonna fiddle with some other things in the game...

Frumple

Frumple at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 9

> Well I'm not exactly sure if a frame can be added to

> another frame. My game runs as an application that

> extends JFrame. I would prefer to keep the status

> panel, since it's separate from the canvas screen.

No you're right it cannot. All I meant was I used a Frame as the owner of the screen and buffer strategy. I can see no reason why you couldn't use a JFrame to do the same thing.

> Would I have to call paintComponent() in my render

> method? Actually my status panel shows up as well as

> any other swing components, but the canvas doesn't

> show anything.

Sounds like you are using a combination of passive (paint()/repaint()) and active (render()) rendering. I believe Sun's documentation discourages that. Again I urge you to check that link I gave above.

> Is active rendering something that draw on to the

> whole screen, or just a component? All my other swing

> components draw on to the screen. In my render()

> method, I draw game sprites such as tanks and walls on

> to the canvas. So would I need to paint the panels and

> canvas under one whole umbrella, or can i just do

> active rendering to the canvas and let the panel go on

> its merry way?

In active rendering you actually turn off the Swing repaint hierachy completely using setIgnoreRepaint() on the parent frame (JFrame in your case). When you do this it means you have to do ALL the painting in your own render method - including the Swing components (using paintComponent() or similar). An alternative technique, which sounds closer to what you are ACTUALLY doing is to use the standard (passive) repaint technique that all "normal" windows use. When using that technique you can have normal JPanels, JLabels etc, and then put all your own drawing logic in your canvas's paint() method and call repaint() on the canvas whenever you want that part of the screen updated.

Hope that makes sense and helps in some way.

Tim

TimRyanNZ at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 10
Wait, this is a fullscreen prog right?Well, when I tried to put my pong game in full-screen I had a lot of problems...it still painted, but not correctly. I don't know hwo to do the full screen stuff when you are using canvas, I always use frame now.
Virum at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 11

> In active rendering you actually turn off the Swing

> repaint hierachy completely using setIgnoreRepaint()

> on the parent frame (JFrame in your case). When you do

> this it means you have to do ALL the painting in your

> own render method - including the Swing components

> (using paintComponent() or similar). An alternative

> technique, which sounds closer to what you are

> ACTUALLY doing is to use the standard (passive)

> repaint technique that all "normal" windows use. When

> using that technique you can have normal JPanels,

> JLabels etc, and then put all your own drawing logic

> in your canvas's paint() method and call repaint() on

> the canvas whenever you want that part of the screen

> updated.

Okay, just the only thing I don't get is: how do I implement active rendering? Here's a little diagram to help you see which of the components of my game go where:

TankBattle (JFrame)

|

--> GameEngine (JPanel, also where the game loop resides)

|

--> GameCanvas (Canvas)

|

--> StatusPanel (JPanel)

Before, I had the buffer strategy created in the GameCanvas class and that class also did all the rendering and such. I was hoping to have the strategy only apply to the canvas itself, but since that involves mixing passive and active rendering, this is impossible, right?

Now, I've created a buffer strategy in the TankBattle frame instead of the canvas. However, from here I become stuck. I tried calling paintComponents() and put the graphics from the strategy into its parameters but no frame appears. I also tried passing the strategy up to the game engine and painting components from there but I think that was a bad move.

Remember, I would still like to keep the GameCanvas and StatusPanel. I want to be able to put the actual "game" part of this program (in the form of the GameEngine) separate from the application (TankBattle) itself.

Thanks,

Frumple

Frumple at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 12

> Before, I had the buffer strategy created in the

> GameCanvas class and that class also did all the

> rendering and such. I was hoping to have the strategy

> only apply to the canvas itself, but since that

> involves mixing passive and active rendering, this is

> impossible, right?

The way I understand it is that for any given component of the display you can choose to call setIgnoreRepaint() and from then on you must draw everything visible on that component - i.e. perform active rendering. So you should be able to perform active rendering (optionally using a BufferStrategy) just on your canvas, and have the JPanel repainted by the underlying Swing logic (i.e. passive rendering) fine.

The only time you shouldn't mix active and passive rendering is on the same component and that doesn't appear to be what you wanted to do.

As to how you do active rendering, you simply call your render code within your main game processing loop...

while ( ! exit )

{

doGamePlayLogic();

render();

doTimingWaitIfRequired();

show();// If you're using BufferStrategy

}

or something similar.

Regards,

Tim

TimRyanNZ at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 13

.....which all pretty much brings me back to square one. :(

This is practically the same sort of thing I was having trouble with at the beginning. I had my panels and other swing components use passive rendering, while the canvas created its own buffer strategy and used the main loop for rendering. Now I have the same thing I had back then. When I run my game, the status panel is visible, but none of the sprites that were supposed to be painted on the canvas can be seen. There's just nothing painting on the canvas.

Well, it's seems BufferStrategy doesn't truly work with canvas then. I think I'll go look into other solutions like VolatileImage or something or even go back to manual double buffering.

Thanks anyways,

Frumple

Frumple at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 14

Sorry we went round in circles Frumple - I'm learning too! :(

The only thing I can suggest is that you check some of the flags available from BufferStrategy - maybe it is not allowing the Buffering for some reason.

If you use the method strategy.getBufferCapabilities() you get a BufferCapabilities object. This has the method isFullScreenRequired() which might help explain why it doesn't work on the canvas.

Regards,

Tim

TimRyanNZ at 2007-7-7 2:45:21 > top of Java-index,Other Topics,Java Game Development...
# 15

Nah, it's okay. :)

Long before I tried using BufferStrategy I was using double buffering with a BufferedImage. Yeesh, that method was really slow, especially on full screen. :( So now, I've tried double buffering with just VolatileImage and my frame rate became so much better! ^_^

Blah, enough with BufferStrategy. Right now, I need to actually work on the "game" part of my game, instead of fiddling with graphical annoyances. :P

Frumple

Frumplea at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 16

The short version is, I'm stuck with a similar problem... I tried getting Canvas to work with a BufferStrategy, and it just won't display. Obviously either I'm doing something wrong, or there's something wrong with the way things are set up. I just don't believe that you an use a Canvas with full screen... Any chance this is a bug we should report to the sun team?

PS... I checked isFullScreenRequired() and got false... So that ain't it.

cbisbeea at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 17

I don't understand the advatanges of canvar instead of drawing on just the frame. Obviously if you are going to use fullscreen mode, you are not going to use the basic buttons and jbuttons are you? Then why not just forget the canvas and handle everything with 2d api, since thats what you are going to do anyway.

It definately is more work, but it gives you the personal view and you are in the charge of the code, which is what I like.

OlliPekkaa at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 18

In my case, what I'm trying to do is have mutliple Panel-type entities inside my frame. Based on what's going on in the game, I want a different "Panel" displayed. So for instance, I want a Main Menu Panel, a World Map Canvas, a In-A-Town Panel, etc. To me, it seems like much better design to have the Full Screen Frame display whichever Panel/Canvas should be showing... But I can't get a Canvas to display in the full screen mode, so I can't do it this way.

So, can I get the Frame's BufferStrategy graphics and pass it to whichever object I want to do the painting? Well, yes, but I think that's a pretty ugly way to go about things. I'd rather do it my way, and the Java API sez I should be able to do it my way... But it doesn't work.

cbisbeea at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 19

In my case, what I'm trying to do is have mutliple Panel-type entities inside my frame. Based on what's going on in the game, I want a different "Panel" displayed. So for instance, I want a Main Menu Panel, a World Map Canvas, a In-A-Town Panel, etc. To me, it seems like much better design to have the Full Screen Frame display whichever Panel/Canvas should be showing... But I can't get a Canvas to display in the full screen mode, so I can't do it this way.

So, can I get the Frame's BufferStrategy graphics and pass it to whichever object I want to do the painting? Well, yes, but I think that's a pretty ugly way to go about things. I'd rather do it my way, and the Java API sez I should be able to do it my way... But it doesn't work.

cbisbeea at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 20

> So now, I've tried double buffering with just

> VolatileImage and my frame rate became so much better!

> ^_^

Frumple, I'm interested by this because my machine is pretty low spec and I've found using full screen BufferStrategy pretty slow - I also followed a thread on this site where someone was complaining about the same thing.

How do you blit from the VolatileImage to the screen?

Regards,

Tim

TimRyanNZa at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...
# 21

> I don't understand the advatanges of canvar instead of

> drawing on just the frame. Obviously if you are going

> to use fullscreen mode, you are not going to use the

> basic buttons and jbuttons are you? Then why not just

> forget the canvas and handle everything with 2d api,

> since thats what you are going to do anyway.

It's actually much easier for me to split my game into a canvas (where I do the 2D graphics on to and draw tanks, projectiles, walls, etc.) and a status panel. (which shows statistics in JLabels, JProgressBars, and JButtons in case the player wants to pause or quit.) In this situation, drawing to the frame directly is simply something I don't want because I won't be able to show anything from the status panel. Maybe if you read my previous messages, you'd understand first instead of jumping to conclusions. :P

> Frumple, I'm interested by this because my machine is

> pretty low spec and I've found using full screen

> BufferStrategy pretty slow - I also followed a thread

> on this site where someone was complaining about the

> same thing.

>

> How do you blit from the VolatileImage to the screen?

Um? Actually I've just starting fiddling with VolatileImage and not exactly sure how it works. All I really did was create the VolatileImage like any other image, do some manual double buffering, and suddenly it became faster. :P I don't know if it'll do blitting...

> So, can I get the Frame's BufferStrategy graphics and

> pass it to whichever object I want to do the painting?

> Well, yes, but I think that's a pretty ugly way to go

> about things. I'd rather do it my way, and the Java

> API sez I should be able to do it my way... But it

> doesn't work.

I tried something like this just before I gave up and went to VolatileImages. I don't think you should try this, because of course, it's messy, and it's likely you'll run into IllegalStateExceptions or other annoying things along the way.

If canvas really doesn't work in full-screen mode with a BufferStrategy, then maybe a bug might be in order. Though the divine Sun gods take a while to get around to it...

Frumple

Frumplea at 2007-7-18 15:59:19 > top of Java-index,Other Topics,Java Game Development...