AS3 tile map rendering (with 1000's of tiles)
Asked Answered
F

2

6

Just first off I'll say that the context here is Actionscript 3.0 (IDE: Flashbuilder) along with the Starling Framework.

So, I want to create a Tile Map that could be used for a platformer or something similar.

I want to use 8x8 pixel tiles on an 800x600 pixel stage, and the problem I am having is that I don't know how to add these 7500+ tile objects to the stage without dramatically reducing the framerate.

I've found that the drop in performance comes from adding each tile to the stage, not from initializing each Tile object.

I know I'm not giving much specific information, but what I'm asking for is if there is a standardized way to draw thousands of static objects onto the stage without a loss of performance. I feel like there is a way, and I just have yet to find it.

Update:

After all of your kind help, I have found what seems to be a great solution. At first I wanted to implement Amy's solution, using copyPixels() and draw() to make one large bitmap data for the whole map and then render that to the screen. Then, though, I wanted to know if there was a Starling equivalent to this, because everything would be so much simpler if I didn't have to mix Starling with Native Flash.

Thanks to Amy again, I looked into Starling's RenderTexture class a bit more, and found that using it's "drawBundled()" and "draw()" methods, I could easily draw all of the tiles into a RenderTexture, and then put the RenderTexture into an Image (Starling's Image Class) and then just add that Image to the screen.

That solution is a million times faster than the silly slow solutions I tried before, with flattening sprites and such. Its faster both in it's initialization time and there seems to be no drop in framerate while the renderTexture's Image is on the screen.

The one thing I want to test with this is if it is easy to update the graphics of a tile during the gameplay. Say, if water spreads from a source (or something) and a "Grass" tile had to become a "Water" tile, would the RenderTexture and it's image be able to change their appearance without some sort of lag spike or performance hiccup. I will test this out soon.

Thank you all for your help!

Fuhrman answered 12/8, 2012 at 0:20 Comment(0)
B
9

Don't add that many objects to the stage. Instead, create a BitmpaData the size of your stage and use copyPixels() or draw() to draw onto it. Here's an article that should get you started. You can then take the concepts you learned in that post and learn anything specific you need to do that's not covered (flashandmath.com has a lot of good tutorials about pixel manipulation)

Bogoch answered 12/8, 2012 at 2:7 Comment(7)
Thank you, a starting point like this that pushes me in the right direction is just what I needed!Fuhrman
now I just have to figure out how using native flash display objects works with the Starling Framework...Fuhrman
Starling.current.nativeOverlay.addChild(your_native_displaylist_object_here); will place a normal displaylist object on top of the current starling content.Freeness
does starling have it's own version of Flash's bitmap class? is there a way to merge the tiles' textures together into one large starling texture and render that as an image?Fuhrman
Do you have to do everything 100% in Starling? Is there a way to combine it with regular ole ActionScript?Bogoch
I don't have to do it 100% in starling, as Dennis said, there is native flash functionality that can be used even with the starling framework. I just don't know how well the regular flash Display List works with the Starling display list. I guess the only way to find out is to test it though.Fuhrman
A quick web search for starling bitmapdata copypixels came up with forum.starling-framework.org/topic/bitmapdata-copypixelsBogoch
W
3

You need to manage the tiles that need to be added and removed as you move around the game. Only add to stage tiles that are with in 800 px of the center of the screen. Once the tile is beyond 800 px from center remove it. That should keep everything moving smoothly. Good luck.

or look into drawing/coping your tiles into one bitmap. You would be basically stamping your tiles onto the new bitmap. Here is an example from adobe:

import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.geom.Rectangle;
import flash.geom.Point;

var bmd1:BitmapData = new BitmapData(40, 40, false, 0x000000FF);
var bmd2:BitmapData = new BitmapData(80, 40, false, 0x0000CC44);

var rect:Rectangle = new Rectangle(0, 0, 20, 20);
var pt:Point = new Point(10, 10);
bmd2.copyPixels(bmd1, rect, pt);

var bm1:Bitmap = new Bitmap(bmd1);
this.addChild(bm1);
var bm2:Bitmap = new Bitmap(bmd2);
this.addChild(bm2);
bm2.x = 50;

More Info on the bitmapData class. I think copyPixels is what you are after.

Welles answered 12/8, 2012 at 0:37 Comment(5)
That would work in a different situation, but here the problem is not that I need to add/remove tiles as the camera moves, but that the tiles are so small that I don't know how to create the number needed to fill up the screen (7500) without dropping performance immensely.Fuhrman
how many different unique tiles are there? Could you not sample the bitmapData of the tile and copy them all into one bitmap. That way you are just building one image but from multiple tile sources.Welles
There are very few unique tiles (fewer than 16), and that sounds like it could work, but I don't really fully understand the way to implement something like thatFuhrman
I added some code for using the bitmap class. I would recommend merging all of your 16 tiles into one flat image, this would be called your "sprite sheet" and you would just pull from that sprite sheet image and copy the needed tile section onto your game image.Welles
thank you for your edit, both yours and amy's posts are very helpful!Fuhrman

© 2022 - 2024 — McMap. All rights reserved.