My pixel by pixel 2D scrolling example with layers

Blitz3D Forums/Blitz3D Beginners Area/My pixel by pixel 2D scrolling example with layers

puredave(Posted 2006) [#1]
Hey all!

Well i have been coding with darkbasic and darkbasic pro for a cpl of years. to be honest havent used it for quite a while due to the horrid bugs + stability issues.

Anyway i just bought Blitz3d to see what it is like, so i guessed the first thing to do would be to convert some darkbasic pro code! (so far very impressed with Blitz)

you can grab my example from here:

http://users.tpg.com.au/puredave/code/PxP_Tile_Engine.zip

This is my version of a 2D scrolling play area. It features the folowing:

Pixel based rather than tile based movement
3 layers for the scenery (ground level, leg level, above level) (walk behind a tree to see this)
animated tiles (check out the water to see this)
collision detection (walk into a tree, bush or rock to see this)
can be controlled by cursor keys.

note i cant draw so i grabbed some scenery gfx and the character gfx from the internet (was so long ago cant remeber where i got them, so i take no credit at all for the gfx!)

please grab the zip file extract and compile and check it out, i would be interested to hear what some more experienced coders could do better or ways to optimise etc

note there is no delta timing etc in this example its just the bare bones for my scrolling tile engine, everything not essential was stripped out (well except for the ability to scroll around of course)

thanx!


Sir Gak(Posted 2006) [#2]
One way to speed up your drawing, is to use the LockBuffer and Unlockbuffer commands, just before and after your image drawing loops. Here is an example I made. Commenting out the commands the first time through, I measured around 2476 milliseconds. Putting in the lock commands, I measured about 385 millseconds.
Graphics 800,600

tile=CreateImage (32,32)
SetBuffer ImageBuffer(tile)

Rect 0,0,32,32,True
SetBuffer BackBuffer()

start=MilliSecs()
LockBuffer BackBuffer()
For loop=0 To 100000
	DrawImage tile,100,100
	Flip False
Next
UnlockBuffer BackBuffer()

SetBuffer FrontBuffer()
Print MilliSecs()-start
MouseWait()
End

So, if you want a significant speed boost, try the lock/unlock buffer commands. Cheers!

(Oh, BTW, the hero looks very much like the McDohl character from Suikoden I.)


Buggy(Posted 2006) [#3]
Does this lockbuffer thing work for RenderWorld too?


big10p(Posted 2006) [#4]
Sir Gak: Using commands like DrawImage on locked buffers is not recommended. It may work on your machine but there's a chance it could cause other machines to crash. From the docs:

After you use LockBuffer on a buffer, the only graphics commands you can use are the read/write pixel commands ReadPixel, WritePixel, ReadPixelFast, WritePixelFast, CopyPixelFast, and CopyPixel. You must UnlockBuffer before using other graphics commands or API calls, and you are advised to only keep the buffer locked for as long as it is needed.




puredave(Posted 2006) [#5]
Hmmm, sounds like it may be a bit iffy to do that Sir Gak, so i think i will avoid it, thanx for the info tho!

Wouldnt be suprised about that hero graphic, i went to an anime gfx site that had alot of character animations, they prolly ripped all of them from old games :)

So anybody else got some tips on better ways of handling the tile engine? or at least some comments on the way i have done mine?

thanx


big10p(Posted 2006) [#6]
I had a quick look at your code, Dave. The way you're doing things seems fine to me - it works well. I noticed you're setting all your type fields/arrays to zero at the start of the code. This isn't strictly necessary as blitz does this automatically. I also think you can make your north,south,east,west variables constants.


Sir Gak(Posted 2006) [#7]
big10p: You are correct in that the command documentation says that, but I have never run into a crash or other problem using Lockbuffer with DrawImage. DrawImage is, after all, a command that changes pixels, just in a group instead of singly.

Has anyone else ever tried the LockBuffer/UnlockBuffer with DrawImage/DrawBlock and experienced any problems?


Ross C(Posted 2006) [#8]
Drawimage doesn't work on this computer when drawing to a locked buffer with anything other than writepixel/fast. Doesn't work on a good few computers i've tried.


Sir Gak(Posted 2006) [#9]
Guess what. I tried it on my PC at work. Doesn't work either. Oh, well, just goes to show you that you can think you're right, and still be very wrong. The docs were correct after all.


Andy(Posted 2006) [#10]
>So anybody else got some tips on better ways of handling
>the tile engine? or at least some comments on the way i
>have done mine?

When I bought B2D, I only had a 200 Mhz Pentium. This meant that I couldn't draw layers upon layers of tiles, without dropping frames left and right.

So after some experimentation, I developed the following technique.

-create a buffer which is larger than your screen in both axii(let's say 12x10 tiles, but atleast the screenres + one extra tile in every direction). Do all of the background drawing on this buffer. before the game begins, draw all tiles from the camera viewpoint on the buffer.

when the game is running and the cameraview reaches the last tile in a direction(let's say you are moving upwards), you copyrect the upper 12x9 rows of data to the lower 12x9 rows, and draw the upper row of tiles. Then you just copyrect to backbuffer and add trees etc. before starting over.

This means that instead of drawing 20x15 tiles plus objects(trees etc.), you make at most two copyrects plus draw 20 tiles.

I also limited the system to only draw in one direction at a time, ie. if the player moved up and to the right, and by chance you need to refresh both down and left, the system would go down,render,go left, render.

I also used a technique where I masked the characters, using a buffer, so that they were drawn on top of, but appeared to be behind a tree or a car etc., which meant that everything was drawn on the buffer and then copyrected to the screen. This saved bundles of time on my P200.

Something to think about. If the tile and object images can reside in memory, then use tilefiles to describe each tile. Use a flat fileformat including data like this...

filename 2334.dat

tilenumber of tile to the north; 4399
tilenumber of tile to the south; 1499
tilenumber of tile to the east; 9999
tilenumber of tile to the west; 6577

Tile background; 244
object foreground; 15


This mean that you can make a world as large as the media the game resides on... ie. hundreds of megabytes or gigabytes if you need it. And these files can be loaded on the fly, one byte at a time, meaning that the player will never have to worry about loading times.

You can see how to emulate threading here:
http://www.blitzbasic.com/codearcs/codearcs.php?code=1531

I am not saying that your demo is slow, but if you can draw more tiles, you can build a richer and more diverse environment for your player. Possibly even one where noone would have guessed it a tileengine which is behind it all.

Andy


Sir Gak(Posted 2006) [#11]
Nice tips, Andy. Thanks! When I checked out the link, then loader took about a minute. At that point, after waiting so (relatively) long, I half expected to see gorgeous graphics, stunning landscapes and lifelike animations. Whew!


Andy(Posted 2006) [#12]
>Nice tips, Andy. Thanks!

You're welcome!

>When I checked out the link, then loader took about a
>minute. At that point, after waiting so (relatively) long,
>I half expected to see gorgeous graphics, stunning
>landscapes and lifelike animations. Whew!

Well, for 15 minutes of work, it's not bad.

The point of course, is that emulating threading will lead to slower loading, but that must be put up against the game completely halting and displaying a load screen.

I hate load screens, and I have yet to encounter a situation where I couldn't load the data fast enough to create the scenario on the fly.

Andy


puredave(Posted 2006) [#13]
Thanx Andy! I will see if i can implement that method :)