Smooth tile scrolling.

BlitzMax Forums/BlitzMax Programming/Smooth tile scrolling.

hub(Posted 2009) [#1]
Hi !

Is somebody have a very smooth scrolling 32x32 tile experience with bmax ? i've tested a lot of technic for my shooter game (delta time, fixed rate logic, ...). And have always some pb with this (jerks) ! (no smooth). i Need just to know if it is possible to do !

Thanks !


QuickSilva(Posted 2009) [#2]
Yes it is possible, take a look at Grey Aliens AOTMG demo on his site for a good example. Even thought this is not tile based it will give you a good insight into the smoothness that can be achieved with BMax.

Myself, I have finally grasped fixed rate logic which is giving me great results in my game. One thing that I would point out is that windowed mode always seems a little jittery when Flip is set to true but things are silky smooth without it and in full screen mode.

Hope this helps,

Jason.


hub(Posted 2009) [#3]
i've already this. But grey use floating numbers with the scrolling. i prefer an integer approach and fix the fps for example at 60 fps.


Brucey(Posted 2009) [#4]
Why not use Floats? For smooth scrolling it's what I would use too.


QuickSilva(Posted 2009) [#5]
I`ve tried integers and it works for me, good if you are looking for that retro look which I`m guessing you are after in this case.

Jason.


REDi(Posted 2009) [#6]
You could use floats for storing the position and then cast to int for drawing.


hub(Posted 2009) [#7]
inside my project i've always the same problem and never found my error ! Today the program works fine, but my tile scrolling is bad, not smooth !

i can show you exactly the pb. I've the beta here : http://www.zigwigwis.com/beta/telech/zigwigwis_beta.zip but archive is 30 Mo. (If you try it, lauch zigwigwi.exe, during the game press 'g' to pass to 'god mode'.

after using floats without success, now i use integers.

	Local FPS_fps:Float = 60
	Local FPS_time:Float = 1000 / FPS_fps
	Local FPS_timer:Float = MilliSecs() + FPS_time	
	Local FPS_ms:Float				
	
	While ()
		
		 FPS_ms = MilliSecs()
		    
			If (FPS_ms >= FPS_timer) Then
	
		    	FPS_timer = FPS_ms + FPS_time					
			
				Cls
				
				delta = 1.0

				Compute_logic()
				
				If MilliSecs() > FPScheckTime Then
					FPScheckTime:+ 1000
					curFPS = fpscounter
					fpscounter = 1
				Else
					fpscounter = fpscounter + 1
				End If			

				Display()	
				
				Flip 0 
			
		End If
		    




Thanks for your help !


Difference(Posted 2009) [#8]
Assuming the tiles have a minimum amount of vertical and/or horizontal lines, floats will look terrible.

The way I do my tilemap is with integers and filtering turned off.
I think it's a bad idea to cast from floats, as that will almost surly result in jerkiness.
If you are true to the integer idea, you can get ultra smooth scrolling.

[EDIT]: I just tried you game, and in your case, I would just soften up the horizontal lines (change graphics so that that the tiles are not so square looking), and then stick with float for the tile layer and everything else.

If you really feel you need the square look, you can experiment with an alpha blended border. You can use tiles with and without border, depending how the are placed on the tilemap layer


hub(Posted 2009) [#9]
note that i've an artist who re-design the tiles (not inside the demo). i use a 512x512 image to store the tileset.


hub(Posted 2009) [#10]
when i use float and grey alien method, i've the same problem.


hub(Posted 2009) [#11]
i don't understand why i never have this pb with blitzplus !


GaryV(Posted 2009) [#12]
B+ is 2D (unless using the OpenGL driver) and BMax is 3D. You can't really compare the two.


Nate the Great(Posted 2009) [#13]
a while back I came up with a method for drawing stuff so that you could draw images to a floating point value and it would alpha off the edges. It worked brilliantly so you could draw images to a floating point location. Unfortunately I lost the code and it was a bit slower than the native draw commands for blitz max.

edit: perhaps you could change the bmax source code to draw polygons to floating point variable values. It is 3d after all.


hub(Posted 2009) [#14]
If you really feel you need the square look, you can experiment with an alpha blended border. You can use tiles with and without border, depending how the are placed on the tilemap layer


perhaps a solution should be to have a transparent 1 px border around the tile ? How to do this ? i use a classic 512x512 tileset and use drawimage with the frame parameter to choose the 32x32 tile.

How to automatically add a transparent pixel arround an image (not a pixmap) tile into the code.

himage = loadimage ("test",32,32)
drawimage himage, x#,y#

how to transform himage and add it a transparent pixel arround ? himage2 should be an image not a pixmap. pixmaps are so slow to display !

Thanks !


Difference(Posted 2009) [#15]
A transparent 1 px border will not help. It will just move the flickering 1 pixel in.

If you want relatively slow smooth scrolling, you have to go with floats, and then deal with the flickering that comes from pixels not being mapped 1:1 to your "screen" pixels. (There might already be blur and non 1:1 pixel mapping if your user is running an lcd in non native resolution, but forget about that for now.)

It is up to you to decide what looks good, but in your case it seems you can avoid most issues by designing your graphics without to many vertical lines. If I understand you issue correctly, that leaves the vertical borders to be dealt with.


If I was you, I'd loose the tilemap approach, and make everything sprites with rounder forms.

PS: It looks to me like you have a smooth time problem too, because the big sprites are also jerky.

PPS: There are lots of code for drawing on pixmaps in the archives on on the forum.


hub(Posted 2009) [#16]
If I was you, I'd loose the tilemap approach, and make everything sprites with rounder forms.

i agree, the tile approach was a bad idea. But now i can't change this ! i've designed and work hard on the editor ! An the artist produce a nice tileset ! i always think that i could find a method to fix the problem ;-<


ImaginaryHuman(Posted 2009) [#17]
You said you are getting flickering - I notice you used Flip 0 in your above code - that will probably cause tearing/flickering. Change it to Flip 1?


Grey Alien(Posted 2009) [#18]
Yeah I found that square tiles with hard edges produce an odd effect as the tile moves through floating point coords because the edge gets anti-aliased based on the floating point value so it looks like it fluctuates (but it's correct based on what the graphics card is doing). There's also a problem when you have two tiles right next to each other and they are both anti-aliasing their edges.

Also it's definitely better having a 1 pixel border round anything you are drawing at floating point coords so at least the graphics card anti-alias to transparent and not white or black as I've seen it do before.

A long time ago I was asking if there is a way to make "mesh" or some such where all the tiles are tied together in a big grid so that it is anti-aliased together as one image insead of lots of little images with edges. It seemed to be possible be I never got round to making it work.


hub(Posted 2009) [#19]
Thanks grey so i post this again :

How to automatically add a transparent pixel arround an image (not a pixmap) tile into the code.

himage = loadimage ("test",32,32)
drawimage himage, x#,y#

Thanks !


hub(Posted 2009) [#20]
another question is why there is these problems. Drawimage is not pixel-perfect position (integer) ? Why this works perfectly in true 2d like blitzplus and not with blitzmax ?


Grey Alien(Posted 2009) [#21]
I added the transparent pixel externally to BMax, i.e. in a paint program. DrawImage draws at Integer coords fine. The jerking (even at floating point) is just a fact of life on modern PCs using DX7 or higher. Not sure why it's not there in BPlus, perhaps because it's only DX1 or something.


hub(Posted 2009) [#22]
I added the transparent pixel externally to BMax

perhaps it works too if we had a transparent pixel internally with bmax ?
i use the drawimage frame parameter to choose a tile inside the 512x152 png loaded image. but dont know it is possible to 'extract the tile' from the image tileset. Create the transparent pixel arround into an other 34x34 image and display the final image with drawimage. If somebody here could help me with this step it could be very usefull for me !
Many thanks !


Grey Alien(Posted 2009) [#23]
There is some code here http://www.blitzmax.com/Community/posts.php?topic=82765 that lets you extract a rectangle from a larger image and draw it onto the screen. That may solve the problem, but I'm not sure if you grab from the screen if it contains an alpha channel (it probably doesn't). There's also code on the forum that lets you draw one image on another (it contains for loops because it's done one pixel at a time) that may be possible to adapt for your purposes.


Tommo(Posted 2009) [#24]
Use integer coordinates can avoid the bluring of image edge.
And you have to ensure that the SetOrigin is not working with fraction, because the final coordinate will be transfromed with it.


MGE(Posted 2009) [#25]
Start initial tile at an integer value, draw all other tiles off this initial location at integer values and all is well. ;)


Difference(Posted 2009) [#26]
Here is your smooth, flickefree integer scrolling.




hub(Posted 2009) [#27]
with more tiles !
SuperStrict
Graphics 768,1024


Local img:TImage = CreateImage(32,32,DYNAMICIMAGE) '<- no need for filterimage flag

DrawLine 0,0,32,0
DrawLine 0,0,32,32
DrawLine 32,0,0,32
DrawOval 0,0,32,32

GrabImage img,0,0
 

Local scroll_y:Int = 0

SetClsColor 0,0,0

While Not KeyHit(KEY_ESCAPE)
	Cls
		For Local y : Int =1 To 768 Step 32
			For Local x : Int = 0 To 1024 Step 32
				DrawImage img,x, scroll_y + y
			Next
		Next
	Flip 1
	scroll_y:+1
	If scroll_y > 768 Then scroll_y = 0
	Delay 10

Wend


In my code could you keep the drawimage himage, x#,y# syntax but use and compute only integers values for x# and y# (for example x# = 1). Just to not modify all my code !!!) Or the drawimage himage, x,y is required for tests ?

i ask silly things but with all these technics i begin to loose my code knowledge ! Note than delta timing could not be used now for my main loop as it is floating numbers (delta) technic ! Drawimage himage, x# * Delta#, y * Delta#

To fight this bug, in fact i can modify my main loop to adapt to several technics. Delta timing, fixed rate logic, ... just to send the scroll_y parameter to the tiles and objects position functions (eventually also the delta parameter !)


hub(Posted 2009) [#28]
i've killed the delta system for the y_scroll ! INTEGERS BACK FOR Y.

@Peter : could you try this new exe and level :
dnowload this :

- www.zigwigwis.com/beta/telech/zigwigwi_integer.exe (3.8 Mo)
- www.zigwigwis.com/beta/telech/level5.map

Replace the older zigwigwi.exe with zigwigwi_integer.exe. Next copy the level5.map into the map/classic/ folder

Press 'g' during game. The scroll is set to speed '1 pixel'. The scrolling could be stopped durring some seconds. But it's not a bug.

Thanks !


Grey Alien(Posted 2009) [#29]
But if you remove delta then the timing code is screwed...you are relying on VSync for the timing which is not a good idea.


hub(Posted 2009) [#30]
not exactly. I not use delta timing to scroll the tiles but i use the first code posted here. In my case, i've not find another solution. My game isn't a commercial product.


ImaginaryHuman(Posted 2009) [#31]
I'm not sure how much a `mesh` would help with anything other than drawing lots of `tiles` next to each other. Like, you'd create a triangle strip where vertices are shared between each `quad` and the hardware can then calculate the pixels between quads correctly. Haven't tried it yet though.


Grey Alien(Posted 2009) [#32]
The mesh wouldn't help with the jerkiness it would help with weird anti-aliasing between individually drawn tiles (on their edges) because the mesh would be anti-aliased as a whole afterwards (I think).


ImaginaryHuman(Posted 2009) [#33]
There is also a thing called polygon antialiasing which can antialiase the edges of quads when they are rotated and such, which probably has to be switched on in order to smoothly blend the edge pixels even in unrotated quads. But it has a requirement that a specific blend mode be used which isn't very helpful when you want to do other blend modes like light blend and such at the same time.

Then you also have full screen antialiasing with multisampling, but that requires a lot more rendering horsepower and to be set up when the screen is set up internally.


hub(Posted 2009) [#34]
so no other easy method... i don't see any other blitzmax game with tiles ?


Jesse(Posted 2009) [#35]
how fast is your computer aside from the graphics card?
I noticed the biggest amount of jerkiness is when there are a lot of objects in the screen. Have you put a fps counter it seems with all of the action going on in the background you might be running it down to lower than 60 fps and back to 60fps which explain the jerking.


hub(Posted 2009) [#36]
amd athlon 1.92 Ghz. 1 go Ram. Nvidia 6600;


Jesse(Posted 2009) [#37]
can you produce a demo that displays the fps counter?
your example above shows clearly how you resolve when the logic takes less than 16.6666.. millisecs to execute but it doesn't show how you are resolving when your logic and drawing takes longer than that.
I am curious, are you using the built in "imagescollide" function for your collision detection? or did you make your own collision function?


MGE(Posted 2009) [#38]
"so no other easy method... i don't see any other blitzmax game with tiles ?"

http://jgoware.com/mge/maptest4.zip

I coded that demo last year. It has 3 layers of tile maps. Runs at 60fps on my old crappy system but I think has issues on some newer hardware.


hub(Posted 2009) [#39]
M : display FPS and Garbage collector (gc)
I : display game logic time (ms)

G : God mode
S : sound on/off
D : some debug infos
C : capture screen

i use imagescollide if the ship is near an obstacle for perfect pixel collision test otherwise my own functions.

mge : i always appreciate your work with 'mge engine'. Do you share/publish the maptest4.zip code ?