Noob in need of tile array help!
BlitzMax Forums/BlitzMax Beginners Area/Noob in need of tile array help!
| ||
Hi, I was wondering if someone could take a look at what I have been working on.... (its supposed to be a basic map) I have a couple of issues/questions a) Is this the best way of doing this sort of tile map b) If you look at the 1s I would say they should be in a diagonal south east - line. However, there is a sort of larger gap along the x-axis. I wondered whether this was the *50 remark however i tried taking this out but that was obviously wrong. Graphics 640, 480 Global map[13,10] #mapoftiles DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 Global tile1 = LoadImage("grass.png") Global tile2 = LoadImage("Path.png") 'MAIN GAME LOOP While Not KeyHit(KEY_ESCAPE) Cls Fdrawtiles() Flip Wend Function Fdrawtiles() RestoreData mapoftiles For y = 0 Until 10 For x = 0 Until 13 ReadData map[x,y] If map(x,y) = 0 Then DrawImage tile1,x*50,y*50 ElseIf map(x,y) = 1 Then DrawImage tile2,x*50,y*50 EndIf Next Next End Function ANY help would be amazing as I dont really know what Im doing lol Tom |
| ||
I don't know how the defdata stuff works as I personally never use it. But it looks like you are re-reading the data into your map array each time. Try to read the whole map in a loadup function before your main game. I like to store my data in files. Make a function to output a map array to a file and a function to read it from a file. Write/read two integers for the sizes of the map at the beginning. Try to use more constants/variables instead of magic numbers. For example, store 10 and 13 in mapsizex and mapsizey variables of some kind. It lets you change the size of your map much easier later on. Is 50 the size of the image? You should also put this in a variable for changing it later. Last edited 2011 |
| ||
your map is not 13 width it's 17 make your array 17x10 also Last edited 2011 |
| ||
@CZar Thank you I will get those consts/vars in. However iM not exactly sure how to write the map array to file and then to load it again after - Im very new to programming and extremely poor at it. LOL @Jesse OMG! These silly mistakes I keep making are a pain!! Thank you Last edited 2011 |
| ||
I tried to structure your code so it would be more logical and clear for you to understand:Strict Graphics 640, 480 '******************* initialization of variables *************************** Const MAP_WIDTH:Int = 17 Const MAP_HEIGHT:Int = 10 Const GRASS_TILE:Int = 0 Const PATH_TILE:Int = 1 Global map[MAP_WIDTH,MAP_HEIGHT] Global tile1:TImage = LoadImage("grass.png") Global tile2:TImage = LoadImage("Path.png") '****************** map data 17 x 10 *************************************** #mapoftiles DefData 1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 DefData 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 '********************* preload map ************************* LoadMap() 'MAIN GAME LOOP While Not KeyHit(KEY_ESCAPE) Cls Fdrawtiles() Flip Wend '****************** 'load map function ********************** Function LoadMap() RestoreData mapoftiles For Local y:Int = 0 Until MAP_HEIGHT For Local x:Int = 0 Until MAP_WIDTH ReadData map[x,y] Next Next End Function '***************** display map funciton ********************* Function Fdrawtiles() For Local y:Int = 0 Until MAP_HEIGHT For Local x:Int = 0 Until MAP_WIDTH If map[x,y] = GRASS_TILE Then DrawImage tile1,x*50,y*50 ElseIf map[x,y] = PATH_TILE Then DrawImage tile2,x*50,y*50 EndIf Next Next End Function a few things to suggest as you are a beginner so that you can learn good programming practice and your experience will be more enjoyable: First and most important use Strict or Superstrict at the beginning of your code. This will make debugging your code 100 easier. second use indentation when writing your code for functions, loops, ifs, whiles etc. this will make your code easier to read and understand for you and anybody that tries to help you in debugging. third limit the number of globals you use as much as possible. One of the best ways of avoiding that is by learning to use "Types". if you get into the habit of doing stuff the right way now you won't have problems in the future developing those habits. finally if you haven't read any tutorials in the tutorial section here are some good ones that might help you: http://www.blitzmax.com/Community/posts.php?topic=42519 http://www.blitzmax.com/Community/posts.php?topic=59509 http://www.blitzmax.com/Community/posts.php?topic=59233 http://www.blitzmax.com/Community/posts.php?topic=48800 http://www.blitzmax.com/Community/posts.php?topic=61157 http://www.blitzmax.com/Community/posts.php?topic=42619 Last edited 2011 Last edited 2011 |
| ||
WOW Jesse I really appreciate the effort you have gone to for me here, thank you |
| ||
If you're really a beginner, there's a risk the following is beyond you.., but alas.. let's mention it anyway! :) * I could suggest procedural map generation over data statements. I personally find such data statements distracting and hard to manage. Think of (your!) functions like: Mapmake(w,h,clearvalue), Mapline(x,y,angle,length,value) and Maprect(x,y,w,h,value). * Put your graphics into an array rather than in unique variables, or put 'm all in one image and load it with LoadAnimimage so that you can use the image frame as array position. That way you don't need these endless If map[x,y] = GRASS_TILE checks, you simply draw the image that corresponds to the map value for a given x,y coordinate. No checks, no nothing! * Even though you may be a beginner, using types would already be rewarding, and you really don't have to go with scary inheriting 'n stuff. Just having a data container with its own methods is already a great way to bring peace to your brain. |
| ||
E.g. you could do this:SuperStrict Type TTilemap ' ' wee example by CS_TBL ' Field data:Int[,],mapvalid:int=0, mapw:Int,maph:Int, mapx:Int,mapy:Int ' mapdata, size of the map, cameraposition Field vieww:Int,viewh:Int ' viewport, the size of the game area Method Make(w:Int,h:Int) mapvalid=0 If w*h=0 Return mapvalid=1 data=New Int[w,h] mapw=w; maph=h End Method Method Viewport(w:Int,h:Int) If w*h=0 Return vieww=w; viewh=h End Method Method Rect(px:Int,py:Int,w:Int,h:Int,v:Int) If not mapvalid Return If w*h=0 Return For Local x:Int=0 To w-1 For Local y:Int=0 To h-1 Setvalue(px+x,py+y,v) Next Next End Method Method Getvalue:Int(x:Int,y:Int) If not mapvalid Return 0 If x<0 Or x>=mapw Return -1 If y<0 Or y>=maph Return -1 Return data[x,y] End Method Method Setvalue(x:Int,y:Int,v:Int) If not mapvalid Return If x<0 Or x>=mapw Return If y<0 Or y>=maph Return data[x,y]=v End Method Method Clipcamera() If mapx<0 mapx=0 If mapy<0 mapy=0 If (vieww+mapx)>mapw mapx=mapw-vieww If (viewh+mapy)>maph mapy=maph-viewh End Method Method Debug() If not mapvalid Return Local s$,v:Int,l$="+"+Replace(LSet("",vieww*2)," ","-")+"+" Print l For Local y:Int=0 To viewh-1 s="" For Local x:Int=0 To vieww-1 v=Getvalue(x+mapx,y+mapy) If v<0 s:+" " Else s:+Mid(".:x@",v+1,1) ' for this routine, the map has only 4 values: . : x and @, or: 0,1,2,3 in integers s:+" " Next Print "|"+s+"|" Next Print l End Method End Type Local map:TTilemap=New TTilemap map.Make 64,48 ' here we make a map of 64x48 tiles map.Viewport 32,24 ' the game screen is 32x24 For Local t:Int=0 To 23 ' here we fill it up with some random crap map.Rect Rnd(48),Rnd(36),Rnd(16),Rnd(12),1+Rnd(3) Next Print "0,0" map.Debug ' let's see the map at the top left (0,0) Print "~n -8,-5" map.mapx=-8;map.mapy=-5 ' move the camera to another location map.Debug Print "~n -8,-5, but eventually clipped to 0,0" map.Clipcamera ' keep the camera inside the map map.Debug Print "~n 37,29" map.mapx=37;map.mapy=29 ' move the camera to another location map.Debug Print "~n 37,29, but eventually clipped to mapw-vieww,maph-viewh" map.Clipcamera ' keep the camera inside the map map.Debug Last edited 2011 Last edited 2011 Last edited 2011 Last edited 2011 |
| ||
One could make whole games using nothing but Print, and add the visuals much later on.. ^^ ps/edit: One could rename mapx and mapy to camerax and cameray... matter of taste, technically it doesn't matter. Last edited 2011 |
| ||
Thanks for posting this code. I've learned a lot and can follow it fairly well. I just need to spend a little more time looking at the debug method's string manipulation routines and I'll have it down -craigmon |
| ||
Could one change that sample code to be a scrolling map ?? Twinprogrammer |
| ||
I know it is called "moving map", but... "It is never the map, that is moving, but always the 'camera'!" So it you want to see a scrolling part of the map, just move the 'camera' position the the right and substract it frmo the drawing position. Here is a stand alone (very reduced) basic sample: Graphics 400,400 Repeat CamX=CamX+1 Cls SetColor 1,99,1 For I=0 To 30 DrawRect (i*30)-CamX+1,101,29,29 Next Flip 1 Forever Now you could combine this with the maps-code and optimize it. In this simple code the main loop tries to draw every field.... You can add the y-part and add some input-controls. But the system keeps the same. Last edited 2011 |