View Full Version : [AS3]Splitting bitmapData into tiles
flashmxboy
July 17th, 2009, 11:20 AM
Hi everyone:hugegrin:
Im pretty sure this is easy, but i will ask anyway:P
I have a big movieClip that contains a level for my game.
I use bitmapData.draw() to draw it into a bitmap and use bitmapData.hitTest() to check for collisions with walls etc.
Now if i draw a realy high/wide level flash throws this error:
ArgumentError: Error #2015: Invalid BitmapData.
at flash.display::BitmapData()
or the whole level dosen`t show up:P
So i thougt the solution would be to split up the bitmapData in tiles.
Something like this:
http://nettvei.com/tile.jpg
(The red squares are tiles..)
How would i do this? And would it ruin my bitmapData.hitTest() ??
Thanks in advance:D
therobot
July 17th, 2009, 04:52 PM
BitmapData cannot exceed a certain width & height. I don't remember the exact dimensions.
You'll want to look at this: http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/BitmapData.html#draw()
In particular, the clipRect parameter which allows you to only copy portions of a movieclip to BitmapData.
In theory, breaking it up into smaller chunks like this should be feasible, but you'll probably have to change your code around a little bit to make it work.
Gnoll
July 17th, 2009, 08:44 PM
Pretty sure bitmapdata can be any size but bitmaps can only display something under roughly 2880 * 2880
Can you draw it into a bitmap data, then copypixels what is within the dimensions of the screen to the bitmap?
Gnoll
TOdorus
July 17th, 2009, 11:59 PM
Depends on what version of Flash you're using:
Flash 9: The width and height can be up to 2880 pixels.
Flash 10: The surface of the bitmap can be up to 2880^2 pixels (so you can actually have a width or height > 2880)
I believe bitmapdata's don't have that limit, so the draw to bitmapdata and copypixel to screen should be possible.
flashmxboy
July 18th, 2009, 07:26 AM
Ok so it looks like the limit is on the bitmap then...
But why does flash thow this error at me when i make a big BitmapData?
ArgumentError: Error #2015: Invalid BitmapData.
at flash.display::BitmapData()
TOdorus
July 18th, 2009, 08:18 AM
Sorry my bad, it was bitmapdata's that have the limit.
Gnoll
July 18th, 2009, 08:50 AM
I think you should just draw your level into a bitmap :P It wouldn't be as big as coming from a movieclip
Gnoll
flashmxboy
July 18th, 2009, 09:09 AM
EDIT: Draw the level into a bitmap?? How??
Ok so i have to draw the movieClips into different bitmapData`s?
That would probably ruin my hitTesting....
Then i must rewrite the hitTesting to something like:
for(i = 0; i < 10; i ++) {
if(bitmapData[i].hitTest(parameter, another parameter, yet another parameter, last parameter) {
//Do stuff
}
Right??
TOdorus
July 18th, 2009, 09:18 AM
Interesting subject those limits, did some googling around the net. Found out that bitmapdata has no limit at all. It's actually the constructer that limits the developer. Score Adobe. A workaround has been found, but it does use external images. An alternative would be to split the levels yourself into tiles.
http://www.thedesilva.com/2008/08/workaround-flash-bitmap-maximum-width-and-height/
But basicly you're going for a simple tile engine which uses blitting. The weird thing is that you use screensized tiles, so you should never have more then four tiles bieng displayed.
Btw the limit in Flash 10 is a little bigger. My memory is slipping :(
http://www.bit-101.com/blog/?p=1426 (http://www.bit-101.com/blog/?p=1426)
EDIT:
bitmapdataUnlimited might also be interesting.
flashmxboy
July 18th, 2009, 09:52 AM
The weird thing is that you use screensized tiles, so you should never have more then four tiles bieng displayed.
Wierd? I thougth displaying only the necessary parts of the level would reduce lag/give better FPS. Cause i get lower FPS when the level is big.
bitmapdataUnlimited might also be interesting.
Looks cool, but i think it would sightly reduce performance...
What do you others think??
TOdorus
July 18th, 2009, 10:12 AM
Wierd? I thougth displaying only the necessary parts of the level would reduce lag/give better FPS. Cause i get lower FPS when the level is big.
Weird as in, usaually a tile is a lot smaller then the screen. Maybe I should've used the word unique ;)
btw, if you do use external files, you're either gonna need to host those on your own server, costing bandwith as 99% of the portals want a game contained in a single swf without extra files.
flashmxboy
July 18th, 2009, 10:17 AM
Weird as in, usaually a tile is a lot smaller then the screen. Maybe I should've used the word unique ;)
Yeah...i would like my game to be art based:P..but i think i have to split up the art in tiles for performance reasons. Is this correct or??
btw, if you do use external files, you're either gonna need to host those on your own server, costing bandwith as 99% of the portals want a game contained in a single swf without extra files.
I just draw my leves in flash with a tablet. So i think that would be no problem:D
therobot
July 18th, 2009, 10:33 AM
Yeah...i would like my game to be art based:P..but i think i have to split up the art in tiles for performance reasons. Is this correct or??
I just draw my leves in flash with a tablet. So i think that would be no problem:D
you should be able to stay the course. I don't see anything wrong with keeping huge bitmaps of your levels broken up into tiles - a tile is still a tile. Of course, you're probably going to have to introduce some tile-based principles to make this work. Like Todorus said, you will have to display 1 - 4 of your tiles on screen at once, so be prepared for that.
TOdorus
July 18th, 2009, 10:46 AM
Not for rendering in this case. In the simplest form of spatial indexing (dividing up space and storing it into some index) you use a 2D grid. As you probably already know, this is used to dismiss checks. If an object is flying through a tile, it only needs to check stuff inside that tile and in the tiles surrouding it, to see if it is colliding. All the objects in other tiles aren't checked against. With rendering a tile as big as the screen you would need just 4 tiles at most (every corner of the screen is in another tile). I would actually not check how many tiles need to be rendered and always go for 4 tiles as copypixels is just so cheap and most of the time this situation will be true.
Now if you didn't use tiles you would have a huge bitmapdata (but alas you can't. Well maybe if you would use that workaround). Then you would just copypixel a rectangle at the screens topleft corner with width and height equal to the screen. This actually eliminates ANY unnecessary rendering without using tiles. So in short: it won't really give you performance on the rendering part in this unique case. You can still however, use the tile system to eliminate checks for stuff like collision and AI.
Now to actually help you ahead and get back to answering your original question :)
The reason you need to split it up in tiles is because you can't use the method from just copypixeling from a huge bitmapdata, so it's more a workaround to a Flash-imposed limitation then anything else.
To find out which tiles to render, I would convert the topleft and bottomright corner of the screen to tile coordinates and check the dX and dY.
var tileWidth:int
var tileHeight:int
var screenWidth:int
var screenHeight:int
//
var ULScreenPos:Point = new Point (1500,100) //the coordinate of the topleft of the screen in the game world. The numbers are just an example
var DRScreenPos = new Point(URScreenPos.x + screenWidth, URScreenPos.y + screenHeight)
//
var ULtilePos:Point = convertToTilePos(ULSCreenPos)
var DRtilePos:Point = convertToTilePos(DRSCreenPos)
//
var dX:int = DR.x - UL.x
var dY:int = DR.y - UL.y
//
var tileX:int
var tileY:int
var screenX:int
var screenY:int
var tileBitmapData:Bitmapdata
for(tileX = ULtilePos.x; tileX <= ULtilePos.x+dX; tileX ++){
for(tileY = ULtilePos.y; tileY <= ULtilePos.y + dY; tileY++){
tileBitmapData = tileBMPS[tileX ][tileY] //you should have a 2D array or some other kind of storage where the loop can easily find the tile needed
screenX = tileX*tileWidth
screenY = tileY*tileHeight
Screen.copypixels(tileBitmapdata, tileBitmapData.rectangle, new Point(screenX, screenY))
}
}
function convertToTilePos(SCREENPOS:Point):Point{
var TilePos:Point = new Point (Math.floor(SCREENPOS.x/tileWidth), Math.floor(SCREENPOS.y/tileHeight))
return(TilePos)
}
flashmxboy
July 18th, 2009, 01:33 PM
Bitmaps limit is so frustrating:scream:
I decided to not split up the level in different bitmapData`s because i spent so much time to make my code work on 1 bitmapData....and i dont want to do it again for 20 bitmapData`s:wasted: (I know i could use loops but....)
So i went for the bitmapDataUnlimited solution. Which not was unlimited :tired:
It was better then usual bitmapData but if the level was bigger than about 5000 x 5000 pixels flash threw this error at me:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.formatlos.as3.lib.display::BitmapDataUnlimited/draw()
And something more. I use BlendMode.ERASE for destructible terrain. And when I used bitmapDataUnlimited. Only half of the level could be erased.
So mabye i should stick to small levels??
Or is making tiles easy. I saw your code TOdorus, but i didnt unerstand all of it...Hihi
I have pretty much no experience with bitmaps....
EDIT: Btw Thanks for all your help so far :D
EDIT2: I thougth out another way to do the tiles. I can have a bitmapData that only contains what is displayed on the screen and hitTest against that... I tried it, but when i used copyPixels to copy from another bitmapData it dosent take out what it already have copied. That probably didnt make any sense. But anyway, is it possible to do bitmapData.dispose() on only a part of the bitmapData??
Gnoll
July 18th, 2009, 09:08 PM
Tiles are easy, I am working on my own collection of classes at the moment, I can post them if you want
Gnoll
Edit. My current state: http://www.swfcabin.com/open/1247974853
Powered by vBulletin® Version 4.1.10 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.