help with seamless tile maps
Monkey Forums/Monkey Programming/help with seamless tile maps
| ||
Hi I'm having issues trying to draw seamless tilemaps and getting tiny gaps due to the floating points. Heres my drawing code (I'm using drawrect instead of drawimage at the mo) Translate -player_x,0 SetColor 255,0,0 gap# = player_x-Floor(player_x) i = player_x/60 j = 0 While j<800 DrawRect i*60+j+gap,150,60,60 j=j+60 Wend can anyone help me and explain why its leaving gaps? many thanks |
| ||
Normally when you get this issue, you move your tiles in floats, but display them at ints:Translate -player_x,0 SetColor 255,0,0 gap# = player_x-Floor(player_x) i = player_x/60 j = 0 While j<800 DrawRect Int(i*60+j+gap),150,60,60 j=j+60 Wend I havent yet tried this with Monkey though, so YMMV. |
| ||
cheers for the tip.. I tried that, but it still leaved gaps, This could be due to the fact I'm also scaling the screen to fit different devices I'll try to fix the int to pixels on screen as well |
| ||
Are you rendering on Android? This is still severely messed up on Android. I have to draw all my tiles to overlap or there are lots of gaps. Seems to not happen on iOS or Flash, but Android and HTML5 always leave gaps. |
| ||
It would help if you posted something that ran that shows the problem. As is it's hard to quite understand what your code is meant to be doing. Are i and j ints? What's gap for? From inspection I'd guess that TheRevills is on the right track but there's one more thing involved. You need to pin the integer starting position of your loop and make the translate input an integer too: Translate( Int(-player_x), 0 ) SetColor 255,0,0 Local x_start:Int = Int(player_x/60) * 60 Local j:Int = 0 While j<800 DrawRect( x_start+j,150,60,60 ) j += 60 End I still don't know what that's meant to do exactly, but it does a thing without gaps in the rectangles. |
| ||
cheers for the pointers everyone OK after playing around a bit more its to with the scale of the display for different devices. Heres some self contained running code Strict Import mojo Function Main:Int() New Test() Return 0 End Function Class Test Extends App Field game_counter:Int Const GAME_WIDTH:=800 Field scale:Float Field player_y:Float Field player_x:Float Method OnCreate:Int() Local i:Int scale = 1.0 'DeviceWidth()/Float(GAME_WIDTH) SetUpdateRate(30) game_counter=0 player_x=0 player_y=0 Return True End Method Method OnUpdate:Int() If KeyHit(KEY_UP) Then scale=scale+0.25 If KeyHit(KEY_DOWN) Then scale=scale-0.25 player_x=player_x+3.0 game_counter = game_counter+1 Return True End Method Method OnRender:Int() Local i:Int,j:Int Local tilex:Float PushMatrix() Scale scale,scale Cls(200,230,230) Translate -player_x,0 SetColor 0,0,0 i = (player_x)/60 j = 0 While j<900 DrawRect i*60 + j,100,60,60 j=j+60 Wend PopMatrix() SetColor 255,255,255 DrawText ("device width = "+DeviceWidth(),10,30) DrawText ("player_x = "+player_x,10,50) DrawText ("scale = "+scale,10,70) Return True End Method End Class USE up and down to change the scale factor. [EDIT] I've been running this in HTML5 (and can also see gaps on Android) For me when the scale is whole (1, 2, 3 etc) there are no gaps But when the scale is a fraction (like most displays will be) there are gaps in the solid bar. Question is that I can't seem to work out how to patch them up and keep it smooth. I have a feeling that if I lock to integers for drawing, its going to be jerkier than using floats |
| ||
From what I can tell, it's something to do with the scaling of DrawRect. I don't know if you've tried this with images yet, but when I use a 60x60 black image instead of DrawRect, I don't have gaps. |
| ||
Try drawing textured tiles instead of rects, those should use sub-pixel accuracy with the help of texture filtering, I don't think non-textured polygons can be drawn between pixels. |
| ||
A slightly ridiculous way to deal with this is to try to ensure that the scaled result is rounded to a known pixel boundary:Local scalePlayerX:Int = Int(-player_x * scale) Translate scalePlayerX / scale, 0 SetColor 0,0,0 i = (player_x) / 60 i *= 60 j = 0 Local scale_start:Int = (i + j) * scale Local scale_width:Int = 60 * scale While j < 900 j += 60 DrawRect scale_start / scale, 100, scale_width / scale, 60 scale_start += scale_width Wend Not sure how robust that is and it's certainly not optimal. |
| ||
Great idea. |
| ||
Many thanks for the many solutions. Weirdly I'm getting a lot different results. (I think it depends on the images too) The solution in the end (for me) is to not bother locking to true ints and use images with a 1 pixel (copied) border. I'm getting nice results now at all screen scales and offset floats Also I'm using DrawImageRect to copy from one image onto the screen and not using individual frames for each tile again, many thanks |
| ||
Did this ever get resolved, or is Rich's workaround still the best approach? Think I'm seeing the same issue with android using v60 |
| ||
ok, well I've used an approach similar to that advocated by Rich, and it seems to work. a) resized my tiles to 33x33 (they were 32x32) b) used DrawImageRect to render, rather than DrawImage with the usual image offset c) DrawImageRect draws them as 33x33 (in terms of their size), but they are still laid out as previously (i.e. they are still positioned on the screen as when they were 32x32). Sorry if this is unclear. What a horrible hack! Quick testing with HTML5 on Opera (which was showing the issue), and things look good. Now, let's see if it is better on Android.. I'll pop into onto my galaxy s2.. Update: did this, and it worked fine.. good stuff! |