Windowed bufferstrategy demo (similar to ball.jar)

lots of people ask about using bufferstrategy in a window. i did too, so i made this app tonight to get to understand it better. it’s a basic demo, does a similar thing to Abuse’s demo, but in a window.
Download: http://members.austarmetro.com.au/~juddman/java/BufferStrat.jar

thanks JavaNoob for doing a great framework demo of a windowed/fullscreen app which uses bufferstrategy. posted at http://www.java-gaming.org/cgi-bin/JGOForums/YaBB.cgi?board=share;action=display;num=1036791657

i used that, and took out the stuff that wasn’t necessary for windowed mode.

thanks abuse for your demo. posted at
http://www.java-gaming.org/cgi-bin/JGOForums/YaBB.cgi?board=2D;action=display;num=1043770995

The FPS is limited at the moment to 50. it doesn’t use accurate timers. you can max the fps to 100 by changing SPEED=20 to 10, but it’s not really useful.

i can get about 1000 objects bouncing around the window in double or triple buffering mode without the FPS dropping from 50. If you try this and get diferent results, plz post your system specs.

my specs:
Dell Inspiron 1 ghz
GeForce 2 Go (32 mb)
Flat panel LCD (60 hz max)

Edit: Abuse: Hope you dont mind me using that pinball gif!

zparticle:
1.2Ghz
Geforce4 Ti 4600 (128meg)
I can get around 1500 objects before it slows down at all and can go much much further before if gets down to around 45 FPS.

Laptop, Toshiba Satellite 2800-400
750MHz PIII
8MB S3 Savage/IX
128MB RAM

Buffers=2:
0 objects: 19fps
1000 objects: 18fps
1500 objects: 12fps
2000 objects: 10fps

Buffers=3:
Exactly the same results as with two buffers!

With 1000 objects, fps drops below 10 with more than six buffers.

[quote]With 1000 objects, fps drops below 10 with more than six buffers.
[/quote]
that’d be cause you’d run out of video memory for the buffers. i get about 14 buffers before it slows down, and 15 is really slow, 16 too, 19 is just as fast as 3, 20 slow 21 fast… till 25 when it all bogs down.

but it’s not really an issue since who would ever use more than 3 buffers. it just introduces time lag.

i did get better speed on abuses demo with 3 buffers instead of 2, but with this app it doesnt seem to make a diference.

2 extremes…

http://members.austarmetro.com.au/~juddman/images/anotherExtreme.gif

http://members.austarmetro.com.au/~juddman/images/oneExtreme.gif

Well, I’m glad you did this. I know at least know that is works some of the time. I doesn’t help me understand why some of my projects like F15 Strike gets acceloration in full screen but not in windowed.

EDIT: BTW, you can remove:


autoImage = gc.createCompatibleImage(32,32,Transparency.BITMASK);
Graphics2D mautoG = (Graphics2D)autoImage.getGraphics();
mautoG.setComposite(AlphaComposite.Src);
mautoG.drawImage(tileImage,0,0,null);
mautoG.dispose();

From the ImageBank class. You get an automatic image from the ImageIcon classes getImage method.

thx!!!

i cant seem to manage to load an image from the jar file if it’s not in the root of that jar… do you know an alternate way to do this other than putting the images into the jar’s root? URL didn’t seem to work.

edit: just noticed you already posted to the other subject.

[quote]Well, I’m glad you did this. I know at least know that is works some of the time. I doesn’t help me understand why some of my projects like F15 Strike gets acceloration in full screen but not in windowed.

EDIT: BTW, you can remove:


autoImage = gc.createCompatibleImage(32,32,Transparency.BITMASK);
Graphics2D mautoG = (Graphics2D)autoImage.getGraphics();
mautoG.setComposite(AlphaComposite.Src);
mautoG.drawImage(tileImage,0,0,null);
mautoG.dispose();

From the ImageBank class. You get an automatic image from the ImageIcon classes getImage method.
[/quote]
you can do that - but I wouldn’t recommend it :stuck_out_tongue:

although both images are ‘automatic’ images, they can still behave differently.

if you use Image.createScaledInstance on an offscreen image (such as the 1 you get from createCompatibleImage) it will work just fine.

if you do the same on a fully loaded Image obtained from toolkit.createImage(somefile), the resultant scaled image will be partially corrupt :S

I’m fairly sure its an ImageProducer related bug, (as the same problem appears when using the ImageFilter classes as well)

p.s.
JuddMan, can you remove the fps capping?
atm the benchmark is pretty useless to me, cos im using Win98 (so I get a fixed 19-20fps all the time [1000/(50-55)])
oh yeah… I don’t mind you stealing my balls! :smiley:

actually, I spose I should add windowed mode to my Balls.jar :stuck_out_tongue:

EDIT:

at the risk of hijacking your thread…
i’ve updated Balls.jar so it now supports windowed mode :smiley:

http://www.pkl.net/~rsc/Balls.jar

So basically do it if you’re scaling your images but don’t worry about it if you aren’t because it is just overhead. Good to know.

Excellent.

ballls.jar at 640x480 windowed gives about 1200 objects @ 50 fps.

i didnt know about that FPS capping…? does the swing timer run at a diferent speed on the win 98 system?

anyway, that’s simple… dl from same location as the new one in the other post (i ripped off someone elses gfx this time. you probably recognise them)

using many diferent gfx seems to slow it down a bit. 1000 objects at 45 fps… (sorry, mine doesnt have a framerate target feature in it.)

http://members.austarmetro.com.au/~juddman/java/MultiGFXBuffer.jar

60 fps = 580 objects…

320 objects at 98 fps. framerate is only capped by the maximum speed of the swing timer.** see edit.

well, if anyone has a timer class that works really well and particularly if it is self containing and just invokes a method of a class passed to in on construction, that’d be useful.

if you have some great timer code and dont mind me converting it to something like the above, that’d be good too. post a link or the code if you can be bothered.

just wondering… is it good to have the timer running on a separate thread to the main class? i get the impression that it’s not and it locks out all the operations that swing uses to maintain the GUI. no problem for fullscreen but in a movable window…

Edit: i modified it to bypass the swing timer alltogether and put the main rendering code into a while(true) loop.

it doesnt have any impact at all on the GUI. in fact the gui seems to be much more responsive now than before. bad sideeffect though is that it does a slight hang at intervals of exactly one second (perhaps a couple of frames during FPS calculation)

edit: it does run faster on the whole though. 800 fps (yeah right) at 1 object,
20: 740 fps
40: 750 fps(?)
100: 400 fps
200: 229 fps
400: 115 fps
600: 80 fps
1000: 50 fps (but the ‘crunches’ are very noticable)
1500: 33 fps
2000: 22
4000: 12 (GUI still responsive. before it was slow. sprite movements very jerky)

In win98, the timer resolution obtainable through Thread.sleep(delay) and System.currentTimeMillis() is somewhere between 50 and 55ms. (on Winnt/2k/xp its somewhere around 10ms; I dunno what it is on mac, linux, or solaris but i’d wager its very small.)

Therefor, any animation loop that uses either of these techniques will never run at more than 20fps on a win98 system ??? (java.util.Timer and javax.swing.Timer both use currentTimeMillis i think)

you can however use this…


synchronized(this)
{
   this.wait(delay);
}

on win98 machines, this gives a much better timer resolution (I get between 5 and 10ms)

you could also opt for a native based timer. Its come up on these boards before now - you basically write a java wrapper for the QueryPerformanceCounter api function.
This gives you a timer resolution of well below <0.1ms :o (I don’t know exactly what I get - but its very small :D)

thanks for the advice, abuse. i’ll have to do that. (havent got the time just now, maybe in 3 hours when i finish work)

anyway, here’s a link to the “game” in it’s early stages with smooth scrolling but no sprites yet.

http://members.austarmetro.com.au/~juddman/java/jariobros/

sorry, but i’ve gone back to the swing timer here, as without any capping it’s way too fast to see the level fly by.

i’ll be implementing a decent timer probably after i have the sprites going. since i’ve done away with all the swing (ecxept the JFrame) it should be much easier to control this.

just wanted to know where that synchronised(this){} goes…

does it go where you’d usually put Thread sleep()?

[quote]does it go where you’d usually put Thread sleep()?
[/quote]
yup.

its just a straight swap for

Thread.sleep(delay);

Abuse: I review some of your code to see if I could improve my own game engine and stumbled across this:

/* fps calculation */
if(System.currentTimeMillis()-lastTime>1000)
{
    lastTime+=1000;

    totalFPS+=paints - previousFPS[fpsIndex];
    averageFPS = totalFPS/FPS_AVERAGING;
    previousFPS[fpsIndex] = paints;
    fpsIndex=(fpsIndex+1)%FPS_AVERAGING;

    fpsString.string = Integer.toString(paints);
    paints = 0;
}
/* end fps calculation */

Is the:

    lastTime+=1000;

line really correct. If I’m not mistaken more than 1000 ms could have passed and thus lastTime would lag behind?

Shouldn’t it read:

timeSinceLast = System.currentTimeMillis() - lastTime;
if (timeSinceLast > 1000)
{
    lastTime += timeSinceLast;
    // Other stuff...
}

It’s a very minor issue but I’m just curious. Perhaps I’m too tired and mistaken…

Best Regards,

Johan Tibell

Well spotted :slight_smile:

That code is indeed technically not correct.

However, its only the fps calculation :smiley:

Also, the difference in the measured fps will be hidden by the rounding to a whole number anyway.

The 1 situation where you might be able to see a difference in the measured value, will be when running at extremely low fps (0-5).

Mac OS X 10.2.5
1GHz G4
Java 1.4.1_01

2 buffers…

drops below 50 fps with the first 20 objects - but it is very close (45-50)… next 20 objects (total 40) and it can’t keep up… sits around 42-48 fps
60 objects = 42 fps
80 objects = 38 fps
100 objects = 32 fps

go to 3 buffers and it starts to crawl (even worse) 40 objects, 3 buffers = 26 fps

I don’t think the Apple 1.4.1 port doesn’t do ‘managed’ images yet as far as I can tell. I’m sure that Apple is aware of graphics performance issues… they just wanted to get a 1.4.1 implementation out (it was taking forever) before they went and optimized everything.