Request for "background" creation and functionality in code, not quite like maps
-
I had asked some time ago about the chance the map editor could include the ability for animated tiles, but was told it doesn't really work that way. So I went about making my own method, based on how retro consoles handled the task. So, I'd have a "map" array that holds a reference to tiles of equal size from a tiled image. Just tile references, no position or any other kind of data, so it draws sequentially, left to right, top to bottom. With the workaround for animated tiles, I can effectively keep the map array static unless I deem it to change.
The problem? It's a bit slow, due to FUZE's design. I just recently made a post in the Hints and Tips thread about how to optimize loops with high iterations and variables inside them, but even after that, looping to draw a tiled map is still intense. Drawing a map straight away with no positioning or additional functionality, it takes around 1ms to draw 350 tiles of 16x16 pixel size via
drawSheet
, enough to fill a buffer that is 400x224 in dimension. Might be fine for that simple case, but there may be cases where someone might want to use smaller-sized tiles, use bigger buffers, have multiple tile layers, etc. That execution time will certainly shoot up.So, much in the way that we can create images and sprites in our code, what about making and manipulating tile maps in code as well? Not quite the kind the map editor can make though. We could separate them by calling them backgrounds, or BG for short. Here are my thoughts on functions....
// Most functions would be similar to sprite functions, like Location, // Rotation, Origin, Colour, etc. The ones below are more specific // to backgrounds. // "tile" is a vector which contains the tile index, rotation (by 90 degree // increments), and horizontal/vertical flipping. // "data" is an array that contains a collection of "tile" information during // creation. If no data supplied, all tiles will default to tile index 0, with no // rotation and no h/v flipping. // "wrap" is a boolean, where if set to true, wrap around occurs during // tiled BG drawing (such as if the edge of a tiled BG is reached when // drawing, it will grab from the opposite side of the tile BG). handle = createBG( width, height ) handle = createBG( width, height, data ) removeBG( bg ) tile = getBGTile( bg, pos ) tile = getBGTile( bg, xpos, ypos ) setBGTile( bg, pos, tile ) setBGTile( bg, xpos, ypos, tile ) setBGTile( bg, pos, tileidx, rotation, hflip, vflip ) setBGTile( bg, xpos, ypos, tileidx, rotation, hflip, vflip ) // clears the whole tile background with default data clearBG( bg ) // fills either the entire tile background, or a section of it with "tile" data fillBG( bg, tile ) fillBG( bg, x, y, w, h, tile ) image = getBGImage( bg ) setBGImage( bg, image ) // tile width/height default to 16/32 if image is not tiled? setBGImage( bg, image, tileWidth, tileHeight ) wrap = getBGWrap( bg ) setBGWrap( bg, wrap )
To note, backgrounds would not have collision information stored in them like maps do.
-
FWIW, I'm using double-buffering in my projects that have tiled backgrounds. I draw the contents that are currently on screen to an image buffer, and when the background needs an update, I change that part only.
-
@Nisse5 Indeed. I was not suggesting otherwise, but for it to only examine and draw the tiles that would be visible to the assigned draw target. Just mentioning how with manually going through just those visible tiles (via clipping the area), it still takes a decent amount of time for not many tiles to be ran through.
-
After thinking about this one @Discostew, and talking with @Willpowered, it seems the best thing to do would be to use map layers to animate tiles! @Willpowered 's amazing demo Super Mega Arena Blaster uses this technique to animate the backgrounds and it looks great. So, may be much easier than I initially thought. The ease of this is certainly contingent on which tilesheet you are using, due to different layouts. Use
drawMapLayer
to draw each animated layer in a series! -
@Dave said in Request for "background" creation and functionality in code, not quite like maps:
After thinking about this one @Discostew, and talking with @Willpowered, it seems the best thing to do would be to use map layers to animate tiles! @Willpowered 's amazing demo Super Mega Arena Blaster uses this technique to animate the backgrounds and it looks great. So, may be much easier than I initially thought. The ease of this is certainly contingent on which tilesheet you are using, due to different layouts. Use
drawMapLayer
to draw each animated layer in a series!I looked into that. The thing about that is you'd have to have a separate layer for each frame of animation. It's one thing if you have very few frames overall and in a small confined area to work with, but each additional frame adds that much more work when one could just draw over the tile itself in the source image to obtain the same effect, without having to juggle layers or create addition ones.
-
I'd even settle for an extension to the current
drawSheet
command to work with an array. For purposes of demonstration, I made 2 versions which get the job done, but are slow. The first draws a horizontal sequence of tiles, which has a start index to the array and a count to loop through. The second draws a 2D grid of tiles,which requires input on width to figure out the height based on array size. It also has a source vector for starting x/y position, as well as the width and height counts to draw). I incorporated wrap-around into them as well.// Draw a horizontal sequenced set of tiles function drawASheet( image, tileArray, start, count, xpos, ypos, scale ) size = tileSize( image, 0 ) * scale if( size.x > 0 ) then width = len( tileArray ) if( wrap ) then if( start < 0 ) then start = ( start % width ) + width endIf for i = 0 to ncount loop drawSheet( image, tileArray[( start + i ) % width ], xpos + ( i * size.x ), ypos, scale ) repeat else if( start < 0 ) then xpos -= start * size.x count -= start start = 0 endIf ncount = min( start + count, width) - start for i = 0 to ncount loop drawSheet( image, tileArray[ start + i ], xpos + ( i * size.x * scale ), ypos, scale ) repeat endIf endIf return void // Draw a 2D grid of tiles function drawASheetEx( image, tileArray, width, sourceV, xpos, ypos, scale, wrap ) size = tileSize( image, 0 ) * scale height = int( len( tileArray ) / width ) ty = height * width if( size.x > 0 and height > 0 ) then if( wrap ) then if( sourceV.y < 0 ) then sourceV.y = ( sourceV.y % height ) + height endIf clip = 0 for i = 0 to sourceV.w loop clip = (( i + sourceV.y ) * width ) % ty drawASheet( image, tileArray[ clip : clip + width - 1 ], sourceV.x, sourceV.z, xpos, ypos + ( i * size.y ), scale, 1 ) repeat else if( sourceV.y < 0 ) then ypos -= sourceV.y * size.y sourceV.w -= sourceV.y sourceV.y = 0 endIf ncount = min( sourceV.y + sourceV.w, height ) - sourceV.y for i = 0 to ncount loop drawASheet( image, tileArray[( i + sourceV.y ) * width : ( i + sourceV.y + 1 ) * width - 1 ], sourceV.x, sourceV.z, xpos, ypos + ( i * size.y ), scale, 0 ) repeat endIf endIf return void