Navigation

    Fuze Arena Logo
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Popular
    • Users
    • Groups
    • Help
    • Discord

    Request for "background" creation and functionality in code, not quite like maps

    General Discussion
    3
    6
    273
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Discostew
      Discostew F last edited by Discostew

      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.

      1 Reply Last reply Reply Quote 2
      • N
        Nisse5 F last edited by

        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.

        Discostew 1 Reply Last reply Reply Quote 0
        • Discostew
          Discostew F @Nisse5 last edited by

          @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.

          1 Reply Last reply Reply Quote 0
          • Dave
            Dave Fuze Team last edited by

            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!

            Discostew 1 Reply Last reply Reply Quote 0
            • Discostew
              Discostew F @Dave last edited by

              @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.

              1 Reply Last reply Reply Quote 1
              • Discostew
                Discostew F last edited by Discostew

                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
                
                1 Reply Last reply Reply Quote 1
                • First post
                  Last post