-
[AS3] Need Help Creating Tile-Based Map
I'm working on a platform game and I'm a little stuck on the map building part. I've already got a working example that takes a set of tiles and draws a map with them, but it only works if all the tiles are aligned in one row on the same tile sheet. This is fine for my test level, which only has 4 different tiles, but I'm planning on making bigger and more complex maps with 50 or more different tiles.
Is there a way I can make an array that will store the x and y position of each tile? If not, what other method should I use? An XML file maybe? I'd also like to be able to group similar tiles together in their own tile sheets - grass/trees/bushes in one, dirt/stone/sand in another, etc. How would I tell the map builder function which tile sheet the tile is in, though?
-
http://www.tilemap.co.uk/mappy.php
http://board.flashkit.com/board/show...ght=map+editor
http://tilestudio.sourceforge.net/
http://mapeditor.org/screenshots.html
http://www.codeproject.com/KB/game/mapeditor.aspx
...
*google is your friend*
or simply code your own,- if you have the engine working a few code lines would be enough to:
- register the mouse tile/cell position
- fill it with a defined ID (the map array)
- export function to trace out the array as string
-
Hype over content...
The first one of those links, Mappy, is the one I've used for years. It uses lua as the scripting language for the exporter, so you can just code your own to spit the map data out in whatever format you want ( Funnily enough just updated my code a couple of days ago, and according to the comments I did the original in 2005, so yeah Mappy is more than good enough to use in real world environments ).
As to the actual tile plotting, you can go a couple of ways with that. When you load the tilesheet you can copyPixel out each tile into their own bitmap and then just attach them to the holder ( ie tile ) mc when updating them.
Or you can use a simple bit of maths to find each tile when you need it. If you know your tile width and height, and the width of the tilesheet you can easily calculate the x / y coords of any tile on it.
For setting different tilesheets for different levels, have a very simple levelObject in your game. This will hold basic info like:
* map data
* tileSheet
* player start x/y
Basically it's a case of pulling in all your dumb data from the server ( images / maps ) and then parsing them into something you can actually use in the game, and then storing easy references to that.
( I'm just doing all this in as3 for the first time, and it's just as simple as as2 to be honest ).
Squize.
-
I've got a basic map builder working already. I have an array that stores the position of each tile in the tile sheet (0, 1, 2, etc.). Then I have a Bitmap that contains the entire tile sheet for my level and another Bitmap that I copy all of the tiles into to create the map. Since each tile is 40x40, I multiply the number in the array by 40 and use that as my starting point, then copy a 40x40 section out of the tile sheet to get my tile and place it on the map. My map builder function runs through the entire array and copies each corresponding tile to the map Bitmap, then adds that Bitmap to the stage. The whole thing is done with copyPixels and BitmapData.
This all works fine, except all the tiles have to be in one row and on the same tile sheet. I can't have a tile sheet that's 5 tiles wide and 5 tiles tall, for example, or gather tiles from more than one sheet, because my arrays only store one value per tile. I need a way to supply more than just one value to the map builder, so I could tell it which tile sheet to copy the tile from, how many tiles over it is, and how many tiles down. I don't know of any way to do this using an array like I'm doing now, but I also don't know of any other way to manage my level data. That's what I need help with. I've read through at least a dozen different tutorials already, but they all assume you'll only be working with 4 or 5 different tiles on one sheet.
I do like the Tiled map editor that render posted, though. Mostly because it works on my Mac. I've tried Mappy before on Windows and I liked it a lot, but I can't justify installing an XP virtual machine just to run a map editor.
-
hmm maybe these threads might be of inspiration
http://board.flashkit.com/board/showthread.php?t=725001
http://board.flashkit.com/board/showthread.php?t=706063
in booth cases I used a mix of libary and library item information to define a single tile. I use this concept even today in newer engines that dont have that much in common with tiles.
The idea is that you can have multiple spriteSheets or librarys and each of course multiple sprites.
a excerpt of the 1st link
Originally Posted by renderhjs
...
some samples (all: 3x3 matrix) I could imagine:
simplified text:
Code:
1,2,3
5,3,44
11,12,1
simplified array:
Code:
map = [[1,2,3],[5,3,44],[11,12,1]];
simplified xml:
Code:
<row>1,2,3</row>
<row>5,3,44</row>
<row>11,12,1</row>
simplified xml B:
Code:
<r v="1,2,3"/>
<r v="5,3,44"/>
<r v="11,12,1"/>
advanced xml (library association, allowing to use multiple sprite sets)
see my zelda engine for input or details on this:
http://board.flashkit.com/board/showthread.php?t=706063
Code:
<r>a-1,a-2,e-3</r>
<r>water-5,rock-3,rock-44</r>
<r>water-11,water-12,rock-1</r>
the last one is what I meant- of course you would have to define somewhere else (usually a header) what a, rock or water stands for e.g which spriteSheet.
-
Pumpkin Carving 2008
I'm going to assume 5 different tile sheets in the library are conveniently named "sheetA" through "sheetE"...
Code:
var levelmap = new BitmapData(200, 200, true, 0);
var p = new Point(0, 0);
var r = new Rectangle(40, 40);
mapdata =
[["E-3", "E-1", "E-2", "E-1", "E-4"],
["E-6", "A-2", "C-4", "A-2", "E-6"],
["E-6", "A-2", "C-3", "A-2", "E-6"],
["E-6", "A-2", "A-2", "A-2", "E-6"],
["E-5", "E-7", "A-2", "E-8", "E-9"]];
for (var i = 0; i< mapdata.length; i++) {
for (var j = 0; j< mapdata.length; i++) {
var bmd = new BitmapData.loadBitmap("sheet" + mapdata[i][j].split("-")[0]);
var frame = mapdata[i][j].split("-")[1];
p.x = i*40;
p.y = j*40;
r.x = frame*40;
levelmap.copyPixels(bmd, r, p);
}
}
Sorry. It'll need to be ported to AS3.
Also, I assumed your tilesheets were a single row of tiles. If they are say, all 5 tiles wide, then you can do this instead:
Code:
r.x = int(frame/5)*40;
r.y = (frame%5)*40;
Last edited by ImprisonedPride; 03-22-2009 at 12:59 PM.
The 'Boose':
ASUS Sabertooth P67 TUF
Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
8GB G.Skill Ripjaws 1600 DDR3
ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
New addition: OCZ Vertex 240GB SATA III SSD
WEI Score: 7.6
-
in addition to whats already been said here- going with XML is good and perhaps a essential way to go- as it lets you store the map files out of flash get the real benefit out of a map editor.
Writing bloated arrays in actionscript is not always nice to manage - hence the option to go with XML.
-
Pumpkin Carving 2008
It was an example. I'm not going to demonstrate importing xml for him.
The 'Boose':
ASUS Sabertooth P67 TUF
Intel Core i7-2600K Quad-Core Sandy Bridge 3.4GHz Overclocked to 4.2GHz
8GB G.Skill Ripjaws 1600 DDR3
ASUS ENGTX550 TI DC/DI/1GD5 GeForce GTX 550 Ti (Fermi) 1GB 1GDDR5 (Overclocked to 1.1GHz)
New addition: OCZ Vertex 240GB SATA III SSD
WEI Score: 7.6
-
So basically you're saying I could use an XML file, and then define the tile sheet, row and column inside that? I took a look at the posts you linked to but it doesn't make much sense to me. I think it's all a little over my head. Could I just use something like this instead?
PHP Code:
<tilerow> <tilecol> <tilesheet>water</tilesheet> <rownum>0</rownum> <colnum>0</colnum> </tilecol> </tilerow>
Then I could just reference them with xmlFile.tilerow[0].tilecol[0].tilesheet, right?
-
that might be a code friendly XML but a terrible one to read and edit in a editor - and that should be the main goal in this case if you go with XML.
If you write the maps like that you have like 70 - 80% wasted filesize in your XML - use less characters and a less bloated architecture.
e.g sample:
PHP Code:
<map a="sprite_1.png" e="sprite_2.png" >
<r>a-1,a-2,e-3</r>
<r>b-5,b-3,b-44</r>
<r>d-11,d-12,d-1</r>
</map>
which is a perfect valid XML but its way more easy to read with the eyes and by that fix.
-
How would I actually use something like that, though? I know how to get any given value using my method, even if it would be a nightmare to create and edit. Ideally I'd like to be able to do something like this:
PHP Code:
<map> <r>water-0-0, water-0-1, water-0-2</r> <r>dirt-0-1, dirt-3-2, dirt-4-4</r> </map>
And then use the first value as the tile sheet, the second one as the row number, and the third one as the column number. How would I differentiate between them, though? I've got essentially the same thing working using ImprisonedPride's method - is there some way to mimic the Array.split() method with an XML file? If not I might just stick with using arrays like I was originally planning.
-
And then use the first value as the tile sheet, the second one as the row number, and the third one as the column number.
does not make one bit sense to me,- perhaps rethink that.
with:
PHP Code:
<map>
<r>water-1, water-2, water-4</r>
<r>dirt-1, dirt-2, dirt-4</r>
</map>
you already have 2 rows and 3 columns which you could read as:
PHP Code:
water-1 | water-2 | water-4
dirt-1 | dirt-2 | dirt-4
and reagarding reading it something like this would do:
PHP Code:
function getTileId(row,column):Object{
var item:String = xml.firstChild.childNodes[row-1].firstChild.split[","][column-1];
var category:String = item.slice(0,item.indexOf("-"));//e.g water, dirt
var nr:Number = int(Number( item.slice(item.lastIndexOf("-")+1,item.length) ));
the XML should imo. also be help of the structual information so that you can read somewhat how many rows and columns there are
-
Originally Posted by renderhjs
does not make one bit sense to me,- perhaps rethink that.
What I mean is, say I have a tile sheet called "water" with 15 tiles, which is 5 tiles wide and 3 tiles tall. In my XML file, if I wanted to refer to tile 3,1 (3 over and 1 down) from the water sheet, I'd use "water-3-1" and it would find the appropriate tile when I built my map.
As for your function, basically what you're doing is parsing the XML file into a string, then splitting that string into the individual entries, like IP was doing with the array?
-
Here's what I've got so far, adapted from your example.
PHP Code:
var xmlSplit:String = xml.r[0].split(",")[0]; var xmlSheet:String = xmlSplit.split("-")[0]; var xmlRow:int = xmlSplit.split("-")[1]; var xmlCol:int = xmlSplit.split("-")[2]; trace(xmlSheet, xmlRow, xmlCol);
With the follow XML file as a source:
PHP Code:
<map> <r>water-0-1</r> </map>
The trace output is "water 0 1"
Success! Thanks to everyone who responded. Now I just have to get to work writing the XML files.
-
ah okay makes sense now - so the spritesheet is devided in rows and columns as well. Its just that I imagined (the way I did things so far ) is that you automaticly tile the spritesheet based on possible dividing columns/rows,
e,g (not perfect but roughly the way)
PHP Code:
getSpriteSheetTile(5);
function getSpriteSheetTile(nr:int):BitmapData{
var w = math.floor(spriteSheet.width / 32);
var h = Math.floor(spriteSheet.height / 32);
var y = Math.floor( nr / w );
var x = nr % w;
var bmp = new BitmapData(32,32);
bmp.copyPixels(spriteSheet,new Rectangle(x*32,y*32,32,32));
}
which would make adressing things easier + the xml alot smaler
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|