ImageTile manipulation

BlitzMax Forums/BlitzMax Beginners Area/ImageTile manipulation

Emmett(Posted 2005) [#1]
Hope someone will help me through this.

Got 50 tiles loaded into fiftytiles:Timage
Screen displays 1st 4 tiles. Perfect

The problem:
Player destroys one of the tiles as required.
For example tile #3.
How do I now get tile 1,2,4,5 to display instead of 1,2,3,4?

Thank You


xlsior(Posted 2005) [#2]
It's not very clear what kind of 'tile' system you have in mind by your posting, but typically I find it easiest to use a two-dimensional array to keep track of the layout of a tile-based game.

For example, you can translate your screen position (=tile) to a slot in the array, where you can keep track of which tile to draw where.
If there is no tile, put use a -1 or something for the value. Any time a tiles changes, you need to figure out which position it was in, and update that location in the array accordingly to reflect the new value.

If you use LoadAnimImage to load the info into your 'fiftytiles'TImage, then you can address the various tiles by their frame number.

When drawing the screen, you would do something like this:

local Leveldata[15,10]

For y=0 to 9
   For x=0 to 14
      If leveldata[x,y] <> -1 Then
         DrawImage(fiftytiles,x*50,y*50,leveldata[x,y])
      End If
   Next
Next


The above assumes a tile width and height of 50x50. Obviously change this to reflect your tiles, and unless you want to start in the upper left corner of the screen with your tiles, add an X and Y offset to the drawimage stuff as well.

(BlitzMax has a built-in TileImage command, but since it only draws blocks of identical tiles, you will have to draw your tiles individually in this case.)


tonyg(Posted 2005) [#3]
Xlsior is right, It depends on how you're using the Timages. If they are in a list and the player 'deletes' one then you run through the list again and it will display
1,2,4,5 as if they are 1,2,3,4...won't it?


ImaginaryHuman(Posted 2005) [#4]
I'm not exactly clear on the question either but it seems you might be thinking of using an array to store all the TImages?

Using an array you can implement a manually-controlled linked list system quite simply. All you need is a `Watermark` which is a variable to keep track of how many tiles are stored in the array (also acts as an index) and a variable to keep track of how much space the array actually has.

Let's say, you have a maximum of 50 tiles,

Local TileArray:TImage[50]
Local Watermark:Int=0
Local Space:Int=50

You load your images in and each time you add one to the TileArray[] you add it at the Watermark position (starts at 0), and increment the watermark by 1. Continue until all tiles are loaded, then Watermark should =50.

You can now use EachIn or similar to go through the array, where the last image to work on or use will be Watermark-1.

Then to remove images, you copy the highest-numbered tile in the array to the position of the tile you want to remove. Ie you overwrite the entry you want released with the highest entry, which is at Watermark-1, and decrease Watermark by 1. This auto-defragments the space in the array. Then you can again use EachIn to go through the array up to Watermark-1.

If you need to keep track of which tiles are which, if it's necessary for your engine, you might then want to maintain another array which acts as an index remapper. You give each tile a number and, at that numbered index in the ramap array (of int's) you store the number of what actual position in the Tile array it is stored at. If you don't need to know which images are representing what, you can ignore this part.

Maybe that helps, I dunno.

I am using these watermarked/auto-defragmenting arrays in my app a lot. When I need to add more items than there is space for in the array I just do array=array[..newsize] - it copies the handles to the objects to the new array, rather than copying all the object data.

You're basically maintaining a fixed space (array of 50 for example) which can be filled by different amounts of items; when you want to add an item you add it at the watermark and increase it by 1, and to remove you copy the item from watermark-1 to the item you want removed and decrease the watermark.


Emmett(Posted 2005) [#5]
@xlsior
Ok an array. Will do some experiments with that.

How does leveldata[x,y] equal a frame number?
DrawImage(fiftytiles,x*50,y*50,leveldata[x,y])

@AngleDaniel
Whew - now that's way over my head but I will study what you said, do some experimenting and learn some more.

I guess the original post should have included my code snippet:
Global fiftytiles:TImage
Global x=60
fiftytiles:TImage = LoadAnimImage ("media/images/tiles.png",126,25,0,50)
Function gettiles()
     For n=0 To 3
          DrawImage fiftytiles,x,120,frame
          x:+131
          frame:+1
     Next
          frame=0
          x=60
End Function

If I can change the DrawImage line to:
DrawImage fiftytiles,x,120,tilearray[n]
then the rest of my problem should be an easy fix. I would change the tilearray in the function that carries out the tile destruction. (I think)
{edit}
Yes, I added this: Global tilearray[]=[0,1,2,3] and changed:
this - DrawImage fiftytiles,x,120,frame
to this - DrawImage fiftytiles,x,120,tilearray[n]
Yea, it's all coming together quickly now.
Thanks a whole bunch folks.


xlsior(Posted 2005) [#6]
How does leveldata[x,y] equal a frame number?
DrawImage(fiftytiles,x*50,y*50,leveldata[x,y])


It doesn't equal a framenumber, but represents a grid that contains the relative postition for each tile.

Then the position in the array holds the framenumber of tile that should be drawn at that place.

But the best way of doing this greatly depends on exactly what it is that you're trying to accomplish and what kind of game you're writing.

If you only ever have 4 tiles in a row, remove one from the middle, and have the others slide over & see a new one appear, (as I now realize you might be trying to do), things would be different.


Emmett(Posted 2005) [#7]
@xlsior
Yes, 4 tiles on screen. Player selects one, it goes, tiles move left as required.
It is working as desired now using two one dimensional arrays.
The first array holds the frame numbers of the 4 tiles on screen.
The second array holds the pointer tile frame number.


ImaginaryHuman(Posted 2005) [#8]
You'd probably want an array at each [x,y] location within the leveldata array.

ie each element in leveldata[x,y] points to a frames[num] array, holding the numbers of the sequence of animation frames.

You could make it a triple-dimension array, e.g.

leveldata[x,y,frame] .... like leveldata[50,50,10] - ie a map 50x50 tiles, with 10 frames of animation per tile.

Or, you could have a separate array defining the animation sequence for each tile number and just use that to decide which frame to draw.