TileMap Array and only drawing whats on screen?

BlitzMax Forums/BlitzMax Beginners Area/TileMap Array and only drawing whats on screen?

Amon(Posted 2008) [#1]
How do I only draw what's on screen in a tilemap array to save me from drawing every tile in the array?


Dreamora(Posted 2008) [#2]
calculate the edge tiles (top left, bottom right) that are visible (you will need to have a function / method that calculates tile grid position from screen x,y anyway if you ever want to interact with it) and only draw between the indices of those.


Czar Flavius(Posted 2008) [#3]
Hmm.. you're going to need to know the current viewing coordinates, the size of each array tile and use some maths to work out which array[x][y] are visable on screen.

If pixel = index * tilesize, then index = pixel / tilesize.

So if each tile is 10x10
and the screen is at coordinates (100,100)
and is of size (200, 200)
(numbers for convenience)

Then the minimum index is 100/10 = 10 and the maximum index is 300/10 = 30. Same for both x and y in this case.

So draw array[10][10] to array[30][30].

I hope this helps.


Amon(Posted 2008) [#4]
Can someone post a code example using this bit of code here?



It would be better for me to see the actual code. I learn better that way. :)

Thanks. :)


tonyg(Posted 2008) [#5]
I wouldn't code it like this but it's what you asked for

and I am sure there'll be bugs in it.
You should check Blitz2D Newbies: Basic Map File Loading & Scrolling which will still help for BlitzMax especially as you're not using OOP.
The Orientation tutorial here might help as well.


Amon(Posted 2008) [#6]
Thanks. :)


Amon(Posted 2008) [#7]
Hi, looking at the code it seems to work but how would I convert the following code to work like say in a tilemap game?

e.g The map scrolls and as it scrolls it only draws whats on screen at that time.

SuperStrict




Graphics 800, 600

Global MapWidth:Int = 2400 / 25
Global MapHeight:Int = 2400 / 25

Global MapStartX:Int = 0
Global MapSTartY:Int = 0

Global MapXOffset:Int, MapYOffset:Int

Global array:Int[MapWidth, MapHeight] 


For Local x:Int = 0 Until MapWidth
	For Local y:Int = 0 Until MapHeight
		array[x, y] = Rand(0, 5) 
	Next
Next



While Not KeyHit(KEY_ESCAPE) 
	Cls
		
		DrawMap() 
		MoveMap() 
		
	Flip
Wend

Function MoveMap() 
	If KeyDown(KEY_LEFT) 
		'MapStartX:-3
		MapXOffset:+1
	ElseIf KeyDown(KEY_RIGHT) 
		'MapStartX:+3
		MapXOffset:-1
	End If
	
	If KeyDown(KEY_UP) 
		'MapSTartY:+3
		MapYOffset:-1
	ElseIf KeyDown(KEY_DOWN) 
		'MapSTartY:-3
		MapYOffset:-1
	End If
	
End Function


Function DrawMap() 
	Local endmapx:Int, endmapy:Int
	If MapXOffset + 25 > MapWidth
		endmapx=mapwidth
	Else
		endmapx = MapXOffset + 25
	EndIf
	If MapYOffset + 18 > MapHeight
		endmapy=mapheight
	Else
		endmapy = mapyoffset + 25
	EndIf
	
	
	For Local x:Int = 0 Until endmapx
		For Local y:Int = 0 Until endmapy
			Select array[x, y] 
				Case 0
					SetColor 255, 255, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 1
					SetColor 0, 255, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 2
					SetColor 255, 0, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 3
					SetColor 255, 255, 0
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 4
					SetColor 0, 0, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
			End Select
		Next
	Next
End Function


I have a MapStartX/Y which moves the map but am confused on howe to synchronise it with only drawing whats on screen.

Thanks for any help you guys can offer. :)


tonyg(Posted 2008) [#8]
Hi Amon,
You might to read the Orientation tutorial here .
This might also help.
I would love to write some code showing map scrolling but have little enougn spare time of my own. It's also very difficult to change your own code as it is the 'I wouldn't start from there' syndrome.
How about checking some of the Tilemap Engine Bmax source that has been released. There might be some specific formatting commands but the movex/movey code will all be very similar.

<edit> P.S. ... and the best tutorials I have found for different tilemap moving is Krylar's Learn to Program 2D Games in BlitzBasic.


Jesse(Posted 2008) [#9]
this is what I used for my tank game I hope it can help you
it generates a random map of specified size it may be used with many different graphics modes.
I made it flexible enough to be used with different size tiles but I have never tried it with tiles other than 32x32 so it might and it might not work with bigger or smaller tiles.
name this "maze.bmx"

test with this:
SuperStrict

Include "maze.bmx"
Graphics 800,600,32

Local map:tmap = tmap.Create(30,40) 'mapsize  create(width ,height) in tiles all tiles are 32 X 32

Repeat
	Cls
	map.MouseMove()
	map.display()
	Flip()
Until KeyDown(key_escape)

use this images:
"grass.png"

and "mazetiles.png"

note: I have not tried to use the map with anything other than 32 x 32 tiles


Amon(Posted 2008) [#10]
I came up with my own noob way of doing it thanks to understanding what tonyg was doing.

Code here if anyone wants it.

SuperStrict

Graphics 800, 600

Global MapWidth:Int = 1600 / 25
Global MapHeight:Int = 1600 / 25

Global MapStartX:Int = 50
Global MapSTartY:Int = 50

Global MapXOffset:Int, MapYOffset:Int

Global array:Int[MapWidth, MapHeight] 

Print MapWidth

For Local x:Int = 0 Until MapWidth
	For Local y:Int = 0 Until MapHeight
		array[x, y] = Rand(0, 5) 
	Next
Next

Global startmapx:Int = 0, startmapy:Int = 0

While Not KeyHit(KEY_ESCAPE) 
	Cls
		
		DrawMap() 
		MoveMap() 
		
	Flip
Wend

Function MoveMap() 
	If KeyHit(KEY_LEFT) 
		If startmapx <= 0
			startmapx = 0
			MapStartX = 50
		Else
			MapXOffset:-1
			startmapx:-1
			MapStartX:+25
		EndIf
	ElseIf KeyHit(KEY_RIGHT) 
		If startmapx < MapWidth - 28
			MapXOffset:+1
			startmapx:+1
			MapStartX:-25
		Else
			startmapx = MapWidth - 28
		End If
	End If
	
	If KeyHit(KEY_UP) 
		If startmapy <= 0
			startmapy = 0
			MapSTartY = 50
		Else
			MapYOffset:-1
			startmapy:-1
			MapSTartY:+25
		EndIf
	ElseIf KeyHit(KEY_DOWN) 
		If startmapy < MapHeight - 20
			MapYOffset:+1
			startmapy:+1
			MapSTartY:-25
		Else
			startmapy = MapHeight - 20
		EndIf
	End If
	
End Function


Function DrawMap() 
	Local endmapx:Int, endmapy:Int
		
	If MapXOffset + 25 > MapWidth
		endmapx=mapwidth
	Else
		endmapx = MapXOffset + 28
	EndIf
	If MapYOffset + 20 > MapHeight
		endmapy=mapheight
	Else
		endmapy = MapYOffset + 20
	EndIf
	
	
	For Local x:Int = startmapx Until endmapx
		For Local y:Int = startmapy Until endmapy
			Select array[x, y] 
				Case 0
					SetColor 255, 255, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 1
					SetColor 0, 255, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 2
					SetColor 255, 0, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 3
					SetColor 255, 255, 0
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
				Case 4
					SetColor 0, 0, 255
					DrawRect MapStartX + x * 25, MapSTartY + y * 25, 25, 25
			End Select
		Next
	Next
End Function



Brucey(Posted 2008) [#11]
Here's something I knocked together in half an hour or so...



I think the important thing when you are scrolling is doing it smoothly, unless your character moves in whole-tile-steps ;-)

I've made the actual scroll area such that you can see how it is drawing the tiles across the viewable area in order to have those new tiles appear smoothly.

Note that it is always drawing width/length +1 row/column number of tiles.

Hope it helps... :-)


Amon(Posted 2008) [#12]
Ahh! Thanks. Will study it. Da Codezz r teh always g00d. :)


Jesse(Posted 2008) [#13]
I updated the map I posted above. A little bit more documented and slightly more flexible. Let me know what you think. Let me know what you don't understand and I'll try to explain it to the best of my ability.