How to handle playfield larger than screen?

BlitzMax Forums/BlitzMax Programming/How to handle playfield larger than screen?

Sokurah(Posted 2007) [#1]
I've been experimenting with this but can't seem to find a good way to do it.

Imagine a playfield 2000*2000 pixels in size, but with a window onto that playfield being only the size of the screen - eg. 640*480 pixels in size - but not by using tiles or scrolling.

Is there some easy way to handle the complete 2000*2000 playfield as a kind of backbuffer, redraw it all each frame (would be wasteful but this is just an example) and then flip only a 640*480 section of it to the screen - something like (pseudocode);
"FlipRect backbuffer,500,500,640,480"?

This would be for a game so the framerate should be 60fps which makes speedy code essential.


ImaginaryHuman(Posted 2007) [#2]
If the graphics hardware is fairly recent it will support textures up to 2048x2048 so you could have a single large image. But it may not be backward compatible with some older cards.


Sokurah(Posted 2007) [#3]
Yeeees...that may very well be, but it didn't really answer the question. ;)


smilertoo(Posted 2007) [#4]
The answer is yes and no, you can easily create a 2048x2048 as mentioned above...but you cant just flip part of it, and with 3d acceleration theres no need to.


Qube(Posted 2007) [#5]
Split it into tiles of 32x32 and just draw the ones you need :) - Best not to mess with one massive image alone.


Big&(Posted 2007) [#6]
Like Qube said, cut it up into tiles and just draw the ones you need.

You should really make your playfield out of a tileset with something like Mappy as having one big texture in memory is truly wasteful.


Who was John Galt?(Posted 2007) [#7]
There's a drawrect command. Just draw the part of the image that is on screen.


Bremer(Posted 2007) [#8]
Couldn't you just load the image and draw it at offsets. I have tried loading a 1680x1050 pixel image and draw it to a 640x480 pixel window and on my gfx card it does it almost 1700 times per second, so its not slow at all. But as ImaginaryHuman points out, some old gfx cards might not support images that large, so if you plan on supporting old hardware, you might be better off just doing it as tiles.

When doing it as a big image, you don't have to use the CLS to clear the screen since the image will cover it all anyways.

Here is a quick test code:

Graphics 640,480

tmp:TImage = LoadImage("test.png")
MidHandleImage tmp

sinus:Int = 0
fps:Int = 0
fps_cnt:Int = 0
updateSinus:Int = MilliSecs()
updateFps:Int = MilliSecs()

While Not KeyHit(KEY_ESCAPE)

DrawImage tmp,320+Sin(sinus)*520,240
DrawText "FPS: "+fps,8,8
Flip 0
fps_cnt :+ 1

If MilliSecs() > updateSinus+25 Then
	updateSinus = MilliSecs()
	sinus :+ 1
	If sinus > 359 Then sinus :- 360
End If

If MilliSecs() > updateFps+1000 Then
	updateFps = MilliSecs()
	fps = fps_cnt
	fps_cnt = 0
End If

Wend
End



smilertoo(Posted 2007) [#9]
He specifically said he didn't want to use tiles.


Qube(Posted 2007) [#10]

He specifically said he didn't want to use tiles.


Well tough!, lol. There is no better way to handle large maps. No point in hoping there is :)


ImaginaryHuman(Posted 2007) [#11]
If you don't want tiles then you really can only do it with a single image/texture. Either you break up the image or you don't.

Drawing the entire image at the appropriate location and letting the graphics hardware clip the parts that are offscreen is probably not too bad for performance.


Leon Drake(Posted 2007) [#12]
cant you just take an image shot of the entire playfield, then shrink it to the appropriate size, then take a shot of the shrunk version and draw the final smaller version?


Leon Drake(Posted 2007) [#13]
maybe i misunderstood was the entire playfield suppose to fit into the screen or are parts suppose to be offscreen?

if thats the case i would take a snapshot of the entire playfield as cache. then simply copy a section of the image as needed and display it.


Sokurah(Posted 2007) [#14]
Thanks all.

>ImaginaryHuman
>Drawing the entire image at the appropriate location and letting the graphics hardware clip the parts that are offscreen is probably not too bad for performance.

This is actually what I'm after, but I have no idea how to draw directly to a large image as if it's a "backbuffer"

Actually, the entire playfield would be about 800x600 (just under actually) in size and the screenmode 640x480, so it's not like I would actually have a single 2048x2048 texture - that was just an example.

So, since there's not that much overhead, it wouldn't be much of a performance hit to just draw everything to a backbuffer and just show the part of it that's needed.

It would simplify the calculations needed a lot.

Perhaps I'll have to redo the code I've already done - I don't know yet...I'll need to think about that.


altitudems(Posted 2007) [#15]
Hmm... I have some thoughts, but what kind of game is it going to be?
And why don't you want tiles?
What about non-uniform tiles?
Search the forums for Render to Texture if you want some kind of backbuffer functionality.

If your trying to avoid a blocky look, just create an array/list of scenery objects or images and draw them at there individual world positions.

I like the flexability of having "tile" images any size or position, but I use a grid that they can snap to as well.

Maybe use some kind of a camera or viewport system to determine what gets rendered.

I run several cameras here for hot seat games with many scenery/game entities in the world, only drawing them if they are visible to each camera. With even 8 cameras its almost the same FPS as just 1.

And most definatly seperate logic from rendering.


ImaginaryHuman(Posted 2007) [#16]
So what you're asking for is an image buffer like blitz3d where you can draw to an area larger than the screen.


Sokurah(Posted 2007) [#17]
>So what you're asking for is an image buffer like blitz3d where you can draw to an area larger than the screen.

Exactly!

It's going to be for a 2D arena-shooter type game.

I've solved the initial problem, so I have something that works, but the way I'm doing it is not as easy to handle as a B3D imagebuffer type solution, and the more simple the code, the less chance there is that the code will become an unreadable mess when I get further along with the project.

...so I'm still interersted if anyone has an idea. :)


Gabriel(Posted 2007) [#18]
Drawing the entire image at the appropriate location and letting the graphics hardware clip the parts that are offscreen is probably not too bad for performance.

With a 2048x2048 texture? It probably will be bad for performance. Just because most videocards support 4096x4096 textures doesn't mean that they handle them speedily. A lot of onboard cards and probably even a few others will make you pay a high price for anything over 1024x1024.


Scaremonger(Posted 2007) [#19]
I did one with a large 2000x2000 image that is used as the "world" in the background.

I redraw the image each frame using TileImage(). This automatically wraps your image at the screen/window edges.

All you need to do is draw it at X,Y calculated from the location of the player.


Dreamora(Posted 2007) [#20]
One thing to keep in mind is that a 2000x2000 = 2048x2048 = 20 MB of VRAM with mipmapping.

while subimages would only waste as much VRAM as needed to fill the screen.

And this kind of images are far slower to handle on low bandwidth cards (ie casual user systems!)