Tile editor
BlitzMax Forums/BlitzMax Beginners Area/Tile editor
| ||
I'm trying to make a basic tile editor: I've made a type that should create the set amount of tiles right from the start, then if I wanted to change the tiles all I would do is click on it and it would change the frame of that particular tile (rather than create a new tile). But it doesn't work, apparently the image inside of the Draw() method is null... I'm lost. Anyone know how to get this working? All it needs to do is fill the screen with frame 0 of the tileset: ![]() -Thanks |
| ||
I'm confused why you have this `tile` type which seems to be being used to describe the whole tilemap (all the tiles), while at the same time you're using this same type to define each individual tile within the map. It obviously isn't going to draw a given tile with an image, because you haven't copied over the image data from the main master tile, to the sub tiles. In your Create() method you need to make a new tile instance, set the x and y, and also set its other flags. I think frankly that you'd be less confused if you had two separate types. A TileMap type, and a Tile type. The tilemap type should be only used to store the tileset image and the grid of tile objects. Each Tile type should be used to store only the number of the image from the tileset. To draw a specific tile you would then go TileMap.Tile[x,y].Draw(), which would just retrieve the number of the tile to use, and then DrawImage with the image that is in the parent type (TileMap), ie DrawImage Parent.tset,x,y Keep your tilemap in an array in the TileMap type and then just have Tile types for storing the frame number. At the moment you are confusing yourself by reusing the tile type for both purposes, and apparently you are just re-creating one tile over and over because when you Return t from the Create() method it isn't going anywhere. |
| ||
@po HILocal tset:TImage=LoadAnimImage(timg$,tsx,tsy,0,tfrms)This isnt being attached to the Object But angel is right, whislt doable to stick it all in one type. Unless there is some "mechanic" reason not to, Its normally a lot better to stick this sort of thing into two types If you want to stick to a one type model, then you need to brushup on Global/Local within types |
| ||
Ah thanks guys, that clears things up a bit. |
| ||
Yah welcome. Seems like there is renewed interest in tilemap editors lately. |
| ||
Isnt there some TileMap code in the archive? I would be very supprised if one of the early addopters hadnt written something |
| ||
Ermm.. I'm still confused :) I'm not too familiar with arrays unfortunately, as I've never had to use them before. I tried anyways. I added a template type just to be tidy. So there is supposed to be a tile array inside the Create() function in the tilemap type right? It will store the positions of all of the tiles? Then I draw each tile individually inside the Draw() method in the tile type using the tile array's data? EDIT: H&K this was fairly helpful: http://www.blitzbasic.com/codearcs/codearcs.php?code=1361 |
| ||
Yes, TileMap needs to contain as a field an array of type Tile. Unless you wish to continue down your path of TLists, in which case make it a Tlist (But I wouldnt know how to do this) Dont forget the aim is for Tile.draw to be called from TileMap.Draw |
| ||
Ohhh.. So with the array in there, there's no need for lists.. |
| ||
Well....... some people would say its good practice to keep a full Tlist of your objects. But I dont bother |
| ||
A good universal (2d) map-editor would be handy, but many of them are too specific/limited or just have a terrible interface to work with. |
| ||
Let me get this straight (see the above code). tile[j,i] is an array when used, will give me the x and y coords of an individual tile? If not then how do I get the x/y coords and draw all the tiles? |
| ||
Hi Po. I worte this for you. It's a Single Screen TileMap editor using an Array to store the tiles. Press space to change the tile and use the LMB to place a tile. Theres no border checking so you'll get an error when you try to draw outside the screen. It's simple to put border checking in and I'll add it if you want me to. Hopefully you can adapt this to your game or use the method to implement a Type based Map Editor. :) '######################################## '### TileMap Editor Example for Po # '### Author - Amon # '### Version 0.2 # '### Date 29th/June/2006 # '######################################## SuperStrict Graphics 800,600,32,60 Global tiles:TImage = LoadAnimImage("tileset.png",32,32,0,7) Global TileSize:Int = 32 ' The size of our tiles Global MapWidth:Int = 800/TileSize 'The width of our Map Array. Divide the screenwidth by the tileSize to get max tiles on screens width Global MapHeight:Int = 600/TileSize ' Same as Above but divide by Screen Height Global MapArray:Int[MapWidth,MapHeight] 'Setup our TileMAp Array which holds the tiles. Global MX:Int, MY:Int ' MouseX & MouseY Global CurrentTile:Int = 0 ' Holds the current tile number For Local xiter:Int = 0 To MapWidth-1 For Local yiter:Int = 0 To MapHeight-1 MapArray[xiter,yiter] = 0 ' fill our Map Array with a number to respresent a blank tile Next Next While Not KeyHit(KEY_ESCAPE) Cls MX = MouseX()/TileSize*TileSize MY = MouseY()/TileSize*TileSize ChangeTile() PlaceTile() DrawMap() DrawImage tiles,MX,MY,CurrentTile Flip Wend '####################################### '# DrawMap Function # '# Returns = None # '# Draws our map to screen # '####################################### Function DrawMap() For Local x:Int = 0 To MapWidth-1 For Local y:Int = 0 To MapHeight-1 DrawImage tiles,x*TileSize,y*TileSize,MapArray[x,y] Next Next End Function '###################################### '#Place Tile Function # '#Returns = none # '#Places our tiles on screen # '###################################### Function PlaceTile() If MouseDown(MOUSE_LEFT) MapArray[ MouseX()/TileSize , MouseY()/TileSize ] = CurrentTile EndIf End Function '###################################### '#Change the current Tile # '#Returns = None # '#Changes the current tile # '###################################### Function ChangeTile() If KeyHit(KEY_SPACE) CurrentTile:+1 EndIf If CurrentTile >6 Then CurrentTile = 0 End Function Put the tileset in the same directory as the bmx file. |
| ||
CS_TBL I'm working on an editor at the moment which will have lots of tilemapping capabilities plus lots of other things. It should be more what you're seeking, when it gets done ;-) |
| ||
Thanks Amon, I'll try and get it working with types. |
| ||
this might give you some ideas maxgui map editor with source www.scottshaver2000.com/forum/viewtopic.php?t=140 and you'll need the map module from here www.scottshaver2000.com/blitz/bmaxmods/sas.mod.zip |
| ||
OK, I've figured some things out, and I now know what's really confusing me :) How do you make an array of a type? Current Code: That damned array is the only thing stopping this thing from working, if you try to run it right now you get: Compile Error: Expression of type 'Type' cannot be indexed. I found nothing in the docs about creating arrays of types. I think I understand how to make Int arrays, but not how to create an array of a type (in this case type tile). |
| ||
That because you are putting the array into the draw of Type tile. The array wants to be 1) A field of type Tilemap 2) Used to draw the individual tiles from Tilemap.Draw What you want to do, is finish The Tile type BEFORE the tilemap type. In Tile.draw(x,y), pass to it the x,and y position of where it only is to be printed, and just print that one tile Then Make the Tilemap type, and inculed in its fields an array of TILES. The when you are in TileMAP.draw loop through the tiles you have, and call the ones you need to print <ie Tilearray[i,j].draw (x*24,y*24)> , passing (X,Y) Dont forget the "Object", in this case a TILE, does not (Well need not), know of anyother Tiles, so dont reffer to ANY tile otherthan self, when in a tile function/method <--- This is NOT a LAW When you are happy with that. (ie when it works), try to think where it would be better to put the Graphics/Pxc/jpeg etc for the tilemap. Would it be better attached to a tile. (Each tile has its own Graphic or a pointer to a graphic), or would it be better attached to TileMap, or should you make a new Type? |
| ||
OK, I think I've figured it out: Still doesn't work, but at least it compiles now :) Tells me I'm trying to access a null field/method on this line: tiles[x,y].tfrm=0 If I can't do that, then how am I going to create all the tiles from the beginning? I'm storing what frame each tile is as a tfrm:int field inside the tile type. |
| ||
Either in the create for tyle map, (Or in the field Tiles:Tile[0,0]), you need to actuaaly "Create space" for the array. In fields What you are doing at the moment is creating an array of 0,0, then not resizing it (edit what you Might have done at the moment is crate a pointer to an [0,0], but not created any array). I would (As you seem to only want one TileMap, or if all tilemaps will be the same size), allocate the space for the array, in the Field allocation. BUT going the way you have chossen you are not returning your tilemap object from Create. Add a return TM, and you need to refer to the tile array as Tilemap:Tiles or TM.Tiles (When in the FUNCTION). And most impotantly you need a NEW array to allocate (This might mean you need to change the field to [,] :but Im not sure) Po, I am impressed that you have continued with your code rather than with amons. But you do realise that there will come a point when the only person who can tell why it isnt working will be you? |
| ||
Heh, I apologise for asking so many questions, but I have a bad habbit of not getting things finished. I am determined this time though, which is the reason for the questions. I am sooooo close now. So what you're saying is the I need to include the tiles[] array in this part: Local tm:tilemap=New tilemap tm.tset=LoadAnimImage(timg$,tsx,tsy,0,frms) Return tm But no matter how I try and work it in there I only get errors. Again, sorry to be a bother, but I'm new at this sory of thing, and I am too close to give up now. |
| ||
You need either thisField Tiles:Tile[,] = New Tiles[MaxMapX,MaxMapY]In side Type Tilemap or Field Tiles:Tiles[,] 'Then in the create:TileMap TM.Tiles = new Tile[MaxMapx,MaxMapy]As you can see You need to do two things. First tell the type that it will have an array "Field ArrayName:ArrayType[,]" then you need to make the space "New ArrayType[num,num]" If you know how big the map in tile map is going to be, put everything into the field. To be able to have different map sizes then put it into the Create NOTE --------------------------------------------- Field ANY:Int[,] = New Int[20,22], will produce an error in some versions of the community IDE. If you have this problem, delete any spaces inside the [] that the ide adds, then use the up or down keys to leave the line |
| ||
Alright, I did the second option you have there, as the amount of tiles on the map are decided by the user. It says these two methods/fields lines are null though: tiles[x,y].Draw(x*tsx,y*tsy) and tiles[MouseX()/tsx,MouseY()/tsy].tfrm=ctile I am oblivious as to why this isn't working.. No matter what I do those lines are always null.. |
| ||
The return tm, wants to be at the end of the function. Anything after it isnt being run. Move it, let me know if the error disapears. |
| ||
After moving Return tm to the bottom of the function, those two lines are fine, but now this line is attemting to access field or method of null object:tm.tiles[x,y].tfrm=0 |
| ||
x and y should be from 0 to tnumx-1 and tnumy-1 respectivly An array[10,10] runs from [0,0] to [9,9] You need to change it in both draw and create |
| ||
I changed it, but I still get the same error on the same line. |
| ||
Sorry totaly my fault. Do you remember when I said that the array need space given to it? Well the Int in title also needs space. Field tfrm:Int = 0 |
| ||
I gave Field tfrm:int an =0 at the end, but I still get the same error on the same line :) |
| ||
Well, Im stuck,tm.tiles[x,y].tfrm=0This would only give the error you have if 1) Tm doesnt exist. (Which it does) 2) X or Y are greater than tnumx or tnumy (Which you changed in both loop, right?) 3 Tiles[,] is unallocated, which it isnt or/and 4) tfrm is unallocated, which it isnt Post the whole code again, and Ill look, but try to see if you have made an error in any of the four above. oh and 5) 0 (Zero), isnt a number. errr |
| ||
Full source: EDIT: Let's try and cancel out the probable causes here. The full error says: Unhandled Exception:Attempt to access field or method of Null object on this line: tm.tiles[x,y].tfrm=0 1) Tm doesnt exist. (Which it does) You're right, tm does exist, we made a new one, then we returned it in the Create() function: Local tm:tilemap=New tilemap tm.tset=LoadAnimImage(timg$,tsx,tsy,0,frms) tm.tiles=New tile[tnumx,tnumy] For Local x:Int=0 To tnumx-1 For Local y:Int=0 To tnumy-1 tm.tiles[x,y].tfrm=0 Next Next Return tm 2) X or Y are greater than tnumx or tnumy (Which you changed in both loop, right?) Yes, as you can see both For loops are from 0 to tnumx/tnumy-1: Draw() method: For Local x:Int=0 To tnumx-1 For Local y:Int=0 To tnumy-1 tiles[x,y].Draw(x*tsx,y*tsy) Next Next Create() function: For Local x:Int=0 To tnumx-1 For Local y:Int=0 To tnumy-1 tm.tiles[x,y].tfrm=0 Next Next Also, tnumx and tnumy couldn't possibly change seeing as how they are both Const's set at the top of the code. 3 Tiles[,] is unallocated, which it isnt or/and 4) tfrm is unallocated, which it isnt Exactly, they both have predetermined values: Field tset:TImage,tiles:tile[,] and Field tfrm:Int=0 So I just can't figure it out. Can you? |
| ||
Any solutions anyone? |
| ||
Point three is allocated here,tm.tiles=New tile[tnumx,tnumy]But other than that your synopses is right. Ill actualy test it tomorrow for you. As a "It cannot possibly be that", put the field for tiles[,] on a different line |
| ||
Yeah, putting it on a new line doesn't cange things. Thanks for testing it in advance though. |
| ||
Doooh. @ H&K Change tm.tiles[x,y].tfrm = 0to tm.tiles[x,y] = New tile What was happening was that Although the array had been allocated, each individual Tile had not. This now means the types are finished, you still get an error, (In Max2d), so that probably something to do with the image, (Which Im even more usless at than this) |
| ||
Yesssssssssssssssssssssssssssssssssss! Thanks for all your help, it finally works! |