The Daily Click ::. Forums ::. Klik Coding Help ::. Tilemaps in MMF
 

Post Reply  Post Oekaki 
 

Posted By Message

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 01:16:15 -

Im planning on doing something after the team compo, and ill probably use tilemaps.

I created this topic just to have some toughts on it, whats the most efficient way to do it and why?

I remember in the map editor i made, i used XML map loading, that would grab the tiles from external separate files(yeah i dont like tilesets).
So what happenned, at first i have something like this:

<tile name="grass" x="12" y="500"/>

This way, the editor would read each line of the XML, assign an active picture object the tile from the line, and paste into background. Great it worked. Slow as hell.

I was trying to make something faster than the common array stuff, no success with this method. Since at each line, it would read the picture over and over...

Then i came to a solution, which was like this:
<tiletype id="grass">
<tile x="12" y="500"/>
<tile x="13" y="500"/>
and so on...

Since it was reading the picture only once, it gone like 300 times faster than before.

That was my way to solve the problem, but i just wanted to know, how would you guys do it? Is there a way to make it go even faster?
(For a reference of how faster it should be, the source for my map editor is on downloads)

What if i had to make stacks of many tiles/items in one position? How should i go about ordering them on screen?
And btw, is there anyway to pack tiles into a file without makin a tileset??





 
n/a

Assault Andy

Administrator
I make other people create vaporware

Registered
  29/07/2002
Points
  5686

Game of the Week WinnerVIP Member360 OwnerGOTM JUNE - 2009 - WINNER!GOTM FEB - 2010 - WINNER!	I donated an open source project
29th May, 2010 at 03:47:57 -

Just checking - you're using fastloops right?

 
Creator of Faerie Solitaire:
http://www.create-games.com/download.asp?id=7792
Also creator of ZDay20 and Dungeon Dash.
http://www.Jigxor.com
http://twitter.com/JigxorAndy

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 04:24:51 -

OFC, it ran loops for each tile inside each tiletype, it was a bunch of nested loops

 
n/a

Fifth

Quadruped

Registered
  07/05/2003
Points
  5818

VIP MemberGOTW JULY 2010 WINNER!Kliktober Special Award TagGOTW HALLOWEEN 2011 WINNERPicture Me This Round 51 Winner!
29th May, 2010 at 06:27:51 -

Use the Text Blitter object, except replace the graphics for the letters with graphics for your tiles. The object can read the data as a string from a data file, and update instantly.

With four Text Blitters each loading a screen's worth of data, you can display all the tiles for a scrolling screen. There's no mess of loading individual tiles, and you only have to deal with a small portion of an enormous level at any time.

 
Go Moon!

Sketchy

Cornwall UK

Registered
  06/11/2004
Points
  1971

VIP MemberWeekly Picture Me This Round 43 Winner!Weekly Picture Me This Round 47 WinnerPicture Me This Round 49 Winner!
29th May, 2010 at 16:33:26 -

Why would you even use XML for this?
The map file is larger and requires parsing, so it's bound to be much slower than just using an array.

 
n/a

Yami



Registered
  23/12/2003
Points
  608
29th May, 2010 at 16:46:57 -

@Fifth
Since you suggest using the Text Blitter object for loading. How would you go about incorporating that concept within a level editor?

 
Image

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 17:20:31 -

@Sketchy - it was actually faster than normal arrays when i implemented the tiletype thing so it would read files only once to a bunch of tiles, i dont know a way to do this with arrays.
I was just trying the EasyXML extension, and it was actually kinda good cause i got to save not only the tilemap in one file, there was some additional stuff

@Fifth - Also curious on how to use text blitter in a level editor

 
n/a

Sketchy

Cornwall UK

Registered
  06/11/2004
Points
  1971

VIP MemberWeekly Picture Me This Round 43 Winner!Weekly Picture Me This Round 47 WinnerPicture Me This Round 49 Winner!
29th May, 2010 at 17:54:41 -


Originally Posted by A. Lino
when i implemented the tiletype thing so it would read files only once to a bunch of tiles


What?
If an array is slower, then it's because you're doing it wrong.

 
n/a

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 18:12:11 -

I think my last post was confusing

Since i was using external files, when loading an array i would loop thru it, and for each tile i would read a file with the image and paste it on the screen. The problem is, think of a great grassy area, for each grass tile, it would just read the same file over and over.

The XML was reading a grass tile once, and would place it on the positions, then a dirt tile, and so on

 
n/a

Sketchy

Cornwall UK

Registered
  06/11/2004
Points
  1971

VIP MemberWeekly Picture Me This Round 43 Winner!Weekly Picture Me This Round 47 WinnerPicture Me This Round 49 Winner!
29th May, 2010 at 18:40:03 -

What do you mean by "read the same file over and over"?
If you're using the "load frame" action, you load each tile image into a different animation frame, so they are all stored in memory at the same time. You never need to load the image file more than once.

 
n/a

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 18:48:53 -

Active picture, no load frame action, and, i didnt even knew that existed!
Guess i gotta explore mmf a bit more

Edited by alessandroLino

 
n/a

Sketchy

Cornwall UK

Registered
  06/11/2004
Points
  1971

VIP MemberWeekly Picture Me This Round 43 Winner!Weekly Picture Me This Round 47 WinnerPicture Me This Round 49 Winner!
29th May, 2010 at 19:56:02 -

The other nice bonus is that your tiles can have fine collision detection as well, which I don't think you get with the active picture object

 
n/a

Fifth

Quadruped

Registered
  07/05/2003
Points
  5818

VIP MemberGOTW JULY 2010 WINNER!Kliktober Special Award TagGOTW HALLOWEEN 2011 WINNERPicture Me This Round 51 Winner!
29th May, 2010 at 20:44:34 -

Originally Posted by Yami
@Fifth
Since you suggest using the Text Blitter object for loading. How would you go about incorporating that concept within a level editor?
----

Well, there's a lot that goes into it, so this is gonna be a pretty long post. So bear with me...
First of all, you need a means to store the level data, and a standardized format that you can use.


Level Data Storage Structure

I'll use what I've been using for the example: a 320x240 screen size, with 16x16 tiles. Each level is given a dimension of pages (a full screen of tiles - in this case, 20x15 tiles, 300 tiles total), and each page is kinda self-contained.
It uses the Binary Object to store the data, because you can easily manipulate the data as either strings (when grabbing a page of tiles into the Text Blitter) or bytes (when comparing or changing a single tile).

The level itself needs a header, to determine the level's dimensions, among other things, and then each page's data needs to be standardizes, each with its own header and related data.

So the format is something like this:
Level header, 64 bytes
Page header, 8 bytes - Page tile display, 300 bytes - Page tile type, 300 bytes - Page sprites, 300 bytes - Page sprite value, 300 bytes
In total, it's 64 header bytes, plus 1216 * the total number of pages.

The tile display means what each tile looks like, as determined by your tileset. That's the only one we'll be dealing with right now.

The tile type is how each tile behaves in the game - empty tile, solid obstacle, one-way platform, slope, ladder, destructible block, whatever your game calls for. It's important to separate this data from the tile display; it means that your collision code will be tidier, and that you can have more variety in your tilesets.

(Also, this is a good place to say that there is no way for an active object to collide with the Text Blitters in a by-pixel manner. This means that you'll have to manage tile collisions in a more abstract sense when it gets to the game portion.)

The sprites and sprite values aren't particularly efficient in this format, but it's easy to understand. Each tile can host one sprite, and each sprite can have a unique value to set itself apart in whatever way. Sprites, unfortunately, will have to be spawned manually; there's no way to tie them to the Text Blitter. When you get to making the game, you'll have to figure out a way to spawn/unspawn them dynamically, so that you don't load all the levels sprites all at once.

But that's for another time.


Editor Work Area

Anyway, the level editor is sort of the easy part, because we're not dealing with tile collisions or sprites just yet. It's just the raw level data, as interpreted via Text Blitters.

Set up however many Text Blitters you want for the editable area of your level (I go with 2x2 pages as a standard). These Text Blitters will be reading from your level data at all times. You get the level data directly from the Binary Object, based on what your level's dimensions are, where you currently are in the level, and which Text Blitter is accepting the data. The expression would look something like this:

("Quadrant" is the name of the work area's Text Blitters, "The Man" is just the important object that holds all the level's data.)

Quadrant - Change Text to
string$( "Binary object - Level", 64 + 16 + 1216 * (Alterable Value A( "Quadrant" ) + Page_X( "The Man" )) + 1216 * ((Alterable Value B( "Quadrant" ) + Page_Y( "The Man" )) * Dimension_X( "The Man" )), 300)


This simply reads a string from the Binary Object. It reads for 300 bytes (the size of one page), starting at a particular spot:
64 + 16
64 is the level's header, and 16 is each page's header, so it skips those.
+ 1216 * (Alterable Value A( "Quadrant" ) + Page_X( "The Man" ))
1216 is the size of one page's worth of data. Multiplied by the Value A (this is either 0 or 1, depending on the particular Text Blitter's horizontal position) and the Page_X (our current horizontal position), we get our tile data, horizontally.
+ 1216 * ((Alterable Value B( "Quadrant" ) + Page_Y( "The Man" )) * Dimension_X( "The Man" ))
The vertical data is similar ( 1216 * ( Value B + Page_Y ) ), but must also be multiplied by the level's X dimension. We're retrieving data from 1-dimensional storage, so it's important to be precise.


Selecting/Manipulating Tiles

That displays the data, so then all you need is a way to select and manipulate tiles. To select tiles, you set up a tile palette, which is actually just another Text Blitter object carrying the tileset, except displaying every possible ASCII character. This lets you see the whole set.

When you click on the tile palette, you select a tile based on where you clicked.
Something like this:

("Palette Cursor" is a blinking dot that shows me which tile is selected. It also holds the data for the currently selected tile.)

Palette Cursor - Set Tile Number to
Int((XMouse - X( "Tile Palette" )) / 16) + 32 * Int((YMouse - Y( "Tile Palette" )) / 16) + 32


And when you click on the "Quadrant" Text Blitters in your work area, you change one of the level's bytes, based on where you clicked...

("The Man" has been placed in the upper-left corner of the work area, so the mouse's position relative to the page can be determined by something like Int(((XMouse - X( "The Man" )) mod 320) / 16) )

Binary Object - Set byte
Tile Number( "Palette Cursor" )
At
64 + 16 + (Int((XMouse - X( "The Man" )) / 320) + Page_X( "The Man" )) * 1216 + (Int((YMouse - Y( "The Man" )) / 240) + Page_Y( "The Man" )) * 1216 * Dimension_X( "The Man" ) + Int(((XMouse - X( "The Man" )) mod 320) / 16) + Int(((YMouse - Y( "The Man" )) mod 240) / 16) * 20


It should look familiar, but I'll break it down a little:
64 + 16
The headers, which we can skip.
+ (Int((XMouse - X( "The Man" )) / 320) + Page_X( "The Man" )) * 1216
The selected X page, now determined in part by where the mouse is.
+ (Int((YMouse - Y( "The Man" )) / 240) + Page_Y( "The Man" )) * 1216 * Dimension_X( "The Man" )
Plus the Y page, again using the mouse.
+ Int(((XMouse - X( "The Man" )) mod 320) / 16)
Plus our horizontal tile position in that page.
+ Int(((YMouse - Y( "The Man" )) mod 240) / 16) * 20
Plus our vertical tile position, similarly multiplied by the X dimensions of a single page: 20.

It's actually a lot more simple than it looks. You just have to manage 4-dimensional space in a 1-dimensional confine. If you can get this much working, you should be able to at least draw with a tile into your level.


Sorry if that was more than you were asking for. The whole thing is simple in theory, but takes a bit of work to get working. In hindsight, this sorta thing would probably be better suited to an article...?

And for reference, here's an old picture of the old editor that I've been re-using for years now, which uses Text Blitters for tiles.
Image
You can see the four pages in the work area, separated by that little crosshair in the middle, as well as the tile palette down below.

 
Go Moon!

alessandroLino

I create vaporware

Registered
  11/03/2009
Points
  172
29th May, 2010 at 22:49:09 -

Thats some great stuff! Ill surely try it!

I presume that is some trasition when changing to a new block-of-4-pages(), or is it seamless? Or there is a way to make it seamless?

I think that you should copypaste this into an article so everyone could see it, this is some really useful stuff

Edited by alessandroLino

 
n/a

Yami



Registered
  23/12/2003
Points
  608
30th May, 2010 at 13:16:35 -

@Fifth

I wanted to know how it works so no need to appologize. Next time I have some free time I will definitely try to see if I can do it.

-Thanks

 
Image
   

Post Reply



 



Advertisement

Worth A Click