Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map
Quick example of a Tile Map Quick example of a Tile Map
Quick example of a Tile Map
Go Back  Xtreme Visual Basic Talk > > > > Quick example of a Tile Map


Reply
 
Thread Tools Display Modes
  #1  
Old 12-01-2004, 02:13 PM
Iceplug's Avatar
IceplugQuick example of a Tile Map Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Lightbulb Quick example of a Tile Map


(And history repeats itself)

Anyway, I have attached an example of a tile map (this seems to be question of the month).

Note how the map is set up as a two-dimensional array of integers,
there is a bitmap for the tilesets, and the
GFX object draws onto the Backup bitmap object.

Backup = New Bitmap(304, 304)
'Backup will be initialzed to an empty bitmap
(There's no significance to the 304 in the example, either...
but it has to be large enough to accommodate the map.)

The map is drawn like:
Code:
        For LY = 0 To 7
            For LX = 0 To 7

                Thisindex = Map(LX, LY)
                'Get the index from the map.

                Tile = New Rectangle(Thisindex * Tilesize, 0, Tilesize, Tilesize)
                'Get the rectangle defining the tile.

                GFX.DrawImage(Tileset, LX * Tilesize, LY * Tilesize, Tile, GraphicsUnit.Pixel)
                'And then draw the tile onto the backup.

            Next
        Next
And the project (in .NET 2003), although you only need the .vb file and the pictures, and you can make a new project in .NET 2002 that does the same.
Attached Files
File Type: zip TileMap.zip (15.9 KB, 416 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
  #2  
Old 12-12-2004, 04:53 PM
Iceplug's Avatar
IceplugQuick example of a Tile Map Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Arrow Tile Map with animating character on it.

Well, the second installment here. This time I have a character on the map.
I use a collision detection to check if the character collides with the chess tile or the edge of the board.

New highlights here:
Code:
    Dim Charpics(3) As Bitmap        'Hold each frame in one of the array elements.
    Dim Cyc As Integer                  'This number tells which frame to draw.
The character animations are in separate frames.

Code:
        For LY = 0 To 15
            Ln = SR.ReadLine()  'One row of tiles from the file.

            For LX = 0 To 15    'Goes through each column.

                Chs = Ln.Substring(LX, 1)   'Get a string with one character in it.

                Map(LX, LY) = Integer.Parse(Chs)  'Convert this string into its matching number.
                '"0" -> 0, "1" -> 1 ...
                'The number is put into the map.

            Next

        Next

        SR.Close()
The map is read from the included text file.

Since the character is animating, I have created a form object
Dim FormGFX As Graphics 'Draws to the form.
That draws the map on demand.

Dim Backup As Bitmap 'Backup picture holds the map that we've just drawn.

GFX = Graphics.FromImage(Backup) 'GFX draws onto the backup picture.
FormGFX = Me.CreateGraphics() 'Draw to the form.

And now, we can draw the map to the form in the draw subroutine.
Code:
        'Map code.
        GFX.DrawImage(Charpics(Cyc), CharacterLocation.X * 16, CharacterLocation.Y * 16)
        'Draw the character to the display at the location.

        'At this point the whole map should reside on the backup bitmap.  The bitmap is not visible, so it must be made visible.
        FormGFX.DrawImage(Backup, Me.ClientRectangle())
The * 16 is the tilewidth, so this converts our player's tile location into a screen location, so that the player appears to be walking on the map.

We need to update the map display in order to show the character's animation.

Code:
    Private Sub Clock_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Clock.Tick
        Cyc = (Cyc + 1) Mod 4   'Cyc cycles through 0, 1, 2, 3, 0, 1, 2, 3, 0, 1 ...
        Draw()      'Draw.
    End Sub
And finally the collision detection.
Code:
   Private Sub TileTest_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles MyBase.KeyDown

        Dim Collided As Boolean

        'This is the basic movement.  Collision detection always comes after this movement caused by the user.
        If e.KeyCode = Keys.Left Then
            CharacterLocation.Offset(-1, 0)
        ElseIf e.KeyCode = Keys.Up Then
            CharacterLocation.Offset(0, -1)
        ElseIf e.KeyCode = Keys.Right Then
            CharacterLocation.Offset(1, 0)
        ElseIf e.KeyCode = Keys.Down Then
            CharacterLocation.Offset(0, 1)
        End If

        'Check for collisions after moving the character.
        If CharacterLocation.X < 0 OrElse CharacterLocation.X > Map.GetUpperBound(0) OrElse CharacterLocation.Y < 0 OrElse CharacterLocation.Y > Map.GetUpperBound(1) Then
            Collided = True
        ElseIf Map(CharacterLocation.X, CharacterLocation.Y) = 3 Then
            Collided = True

        End If

        'If we have collded, then the character needs to move back immediately.
        If Collided Then
            'Take all of the keycodes and reverse their operation.
            If e.KeyCode = Keys.Left Then
                CharacterLocation.Offset(1, 0)
            ElseIf e.KeyCode = Keys.Up Then
                CharacterLocation.Offset(0, 1)
            ElseIf e.KeyCode = Keys.Right Then
                CharacterLocation.Offset(-1, 0)
            ElseIf e.KeyCode = Keys.Down Then
                CharacterLocation.Offset(0, -1)
            End If

        End If

        'Note that the keydown event can fire more than once over the 100 ms that the timer is not drawing.
    End Sub
Of course, I've attached the commented project as well.
Attached Files
File Type: zip TileMap2.zip (21.0 KB, 228 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
  #3  
Old 01-03-2005, 09:33 AM
Iceplug's Avatar
IceplugQuick example of a Tile Map Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Default Moving character on scrolling map.

Third installment here.
This demonstrates a possible way to have a scrolling map where the character remains in the center of the screen (except for when the character is close to the edges of the map).

The map display size in the attachment is 7x7 measured in tiles, so there are 7 tiles across and 7 tiles down, the character remains mostly on the 4th row and 4th column in this display, three tiles away from all edges of the screen, as indicated in the constant value.
Code:
    Const NumofTilesBetweenCharacterAndScreenEdge As Integer = 3
The Bitmap display is set to be 112x112 (written as 16*7 so it's clearer)
Code:
        Backup = New Bitmap(16 * 7, 16 * 7)           'Backup will be initialzed to an empty bitmap
Everything else is the same.

Now, to determine what part of the map to draw, I use two variables, CamX and CamY, to indicate the 'camera', which only indicate the tile that I'd like to use to start drawing from.

Under normal circumstances, the camera will always be three tiles to the upper left from the character.
Code:
            'The usual... camera remains 3 tiles away from the character, until the character moves near the edge of the map.
            CamX = CharacterLocation.X - Me.NumofTilesBetweenCharacterAndScreenEdge
'...
            CamY = CharacterLocation.Y - Me.NumofTilesBetweenCharacterAndScreenEdge
Of course, I'd need to alter the camera's location when the player gets near the edges:
Code:
        'The camera represents the tile that will be in the upper left corner of the screen.
        If CharacterLocation.X - Me.NumofTilesBetweenCharacterAndScreenEdge < 0 Then
            CamX = 0  'This keeps the camera from going off of the left edge of the map.
        ElseIf CharacterLocation.X + Me.NumofTilesBetweenCharacterAndScreenEdge >= Map.GetUpperBound(0) Then
            CamX = Map.GetUpperBound(0) - 2 * Me.NumofTilesBetweenCharacterAndScreenEdge
            'Same but for the right edge of the map.
        Else
            'The usual... camera remains 3 tiles away from the character, until the character moves near the edge of the map.
            CamX = CharacterLocation.X - Me.NumofTilesBetweenCharacterAndScreenEdge
        End If
        If CharacterLocation.Y - Me.NumofTilesBetweenCharacterAndScreenEdge < 0 Then
            CamY = 0
        ElseIf CharacterLocation.Y + Me.NumofTilesBetweenCharacterAndScreenEdge >= Map.GetUpperBound(1) Then
            CamY = Map.GetUpperBound(1) - 2 * Me.NumofTilesBetweenCharacterAndScreenEdge
        Else
            CamY = CharacterLocation.Y - Me.NumofTilesBetweenCharacterAndScreenEdge
        End If
Where each condition except for the Else checks if the character is close to the left, right, top, and bottom edges, respectively.

Then the drawing for the map with the camera becomes:
Code:
        For LY = 0 To Me.NumofTilesBetweenCharacterAndScreenEdge + Me.NumofTilesBetweenCharacterAndScreenEdge
            For LX = 0 To Me.NumofTilesBetweenCharacterAndScreenEdge + Me.NumofTilesBetweenCharacterAndScreenEdge

                Thisindex = Map(CamX + LX, CamY + LY)
                'Get the index from the map.
                'Since the camera changes, we need to extract the tiles from a different location in the map.
                'Everything else is drawing the tile we give it, so it doesn't change.

                Tile = New Rectangle(Thisindex * Tilesize, 0, Tilesize, Tilesize)
                'Get the rectangle defining the tile.

                GFX.DrawImage(Tileset, LX * Tilesize, LY * Tilesize, Tile, GraphicsUnit.Pixel)
                'And then draw the tile onto the backup.

            Next
        Next


        'Map code.
        GFX.DrawImage(Charpics(Cyc), (CharacterLocation.X - CamX) * 16, (CharacterLocation.Y - CamY) * 16)
Of course, you can download this commented project as well.
Attached Files
File Type: zip TileMap3.zip (19.9 KB, 175 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
  #4  
Old 02-10-2005, 05:34 PM
Iceplug's Avatar
IceplugQuick example of a Tile Map Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Arrow Smooth Movement between Tiles

The previous post was about getting the character and the map to scroll as the character walked from tile to tile... but the movement was choppy.

Here, we get the character to move smoothly along the tilemap by allowing the character to occupy more than one tile. This can be accomplished by changing the Character location to represent their pixel location instead of their tile location.
Code:
Me.CharacterLocation = New Point(16, 16)           'Character location now represents a pixel location on the map.
Of course, the movements will have to be tweaked as well. In addition, the player can occupy up to four tiles... so the collision detection would have to check all 4 of these tiles for collision. This can be done by taking the X and Y locations and rounding down/up to the nearest tile. The four combinations (two for X and two for Y) will give all of the tiles that the player is occupying. If the player is only on one, all results will yield the same tile.
SymbolicTile contains the values of dividing the player's location coordinates by 16 (the tile size)
Code:
        If CharacterLocation.X < 0 OrElse CharacterLocation.X > Map.GetUpperBound(0) * 16 OrElse CharacterLocation.Y < 0 OrElse CharacterLocation.Y > Map.GetUpperBound(1) * 16 Then
            Collided = True
            'Don't ask why Ceiling and Floor return doubles.
        ElseIf Map(Convert.ToInt32(Math.Floor(SymbolicTileloc.X)), Convert.ToInt32(Math.Floor(SymbolicTileloc.Y))) = 3 Then
            Collided = True
        ElseIf Map(Convert.ToInt32(Math.Ceiling(SymbolicTileloc.X)), Convert.ToInt32(Math.Floor(SymbolicTileloc.Y))) = 3 Then
            Collided = True
        ElseIf Map(Convert.ToInt32(Math.Floor(SymbolicTileloc.X)), Convert.ToInt32(Math.Ceiling(SymbolicTileloc.Y))) = 3 Then
            Collided = True
        ElseIf Map(Convert.ToInt32(Math.Ceiling(SymbolicTileloc.X)), Convert.ToInt32(Math.Ceiling(SymbolicTileloc.Y))) = 3 Then
            Collided = True

        End If
SymbolicTile is updated after the player moves the character.

Now, this is just the character's interaction with the map. Things still need to be drawn.
First, our camera's location is now in pixels as well. The display still has an odd number of tiles on the screen. The camera's X value is moved to 0 if the player is too close to the left end of the screen, and is also capped off at the other end at (Mapsize - Displaysize) * Tilesize
Code:
        CamX = Me.CharacterLocation.X - Me.NumofTilesBetweenCharacterAndScreenEdge * Me.Tilesize
        'The camera must also remain in the range.
        If CamX < 0 Then
            CamX = 0
        ElseIf CamX > (Me.Mapsizeintiles - Me.ViewTileCount) * Me.Tilesize Then
            CamX = (Me.Mapsizeintiles - Me.ViewTileCount) * Me.Tilesize  'This is the calculated value of the camera's maximum location in the map.
        End If  'The View width is subtracted from the map width
        CamY = Me.CharacterLocation.Y - 48
        If CamY < 0 Then
            CamY = 0
        ElseIf CamY > (Me.Mapsizeintiles - Me.ViewTileCount) * Me.Tilesize Then
            CamY = (Me.Mapsizeintiles - Me.ViewTileCount) * Me.Tilesize
        End If
To simplify the explanation, I added six other variables:
StartX and StartY indicate while tile will be drawn in the upper left corner of the screen. This tile may or may not be wholly visible but as long as we know which tile is in the upper left, this can still be done.
OffX and OffY determine how far the upper left tile is off of the screen... it also determines the amount that all of the other tiles are offset.
EndX and EndY are the last tile in the bottom right corner... this is not always a fixed value from StartX and StartY... when the player is directly on a tile, there are 7x7 tiles on the screen, but if the player is not on a tile, there could be 8x7, 7x8, or even 8x8.
Code:
        Dim StartX, StartY, EndX, EndY As Integer

        'This is the tile that corresponds to the upper left corner on the display.
        StartX = CamX \ Me.Tilesize
        StartY = CamY \ Me.Tilesize

        Dim OffX, OffY As Integer
        'If the camera is 4 greater than a value that is the upperleft corner of a tile, then the tile
        'will be drawn -4 away from the tile position that would fit neatly within the map.
        OffX = CamX Mod Me.Tilesize
        OffY = CamY Mod Me.Tilesize

        If OffX = 0 Then
            EndX = StartX + Me.ViewTileCount - 1  'the last tile on the end is six tiles past the beginning tile.
        Else
            EndX = StartX + Me.ViewTileCount  'here it would be 7.
        End If
        If OffY = 0 Then
            EndY = StartY + Me.ViewTileCount - 1
        Else
            EndY = StartY + Me.ViewTileCount
        End If
        For LY = StartY To EndY
            For LX = StartX To EndX

                Thisindex = Map(LX, LY)
                'Get the index from the map.
                'The values of LX and LY already depend on the camera position, so no need to add it again.

                Tile = New Rectangle(Thisindex * Tilesize, 0, Tilesize, Tilesize)
                'Get the rectangle defining the tile.  (same)

                GFX.DrawImage(Tileset, (LX - StartX) * Tilesize - OffX, (LY - StartY) * Tilesize - OffY, Tile, GraphicsUnit.Pixel)
                'And then draw the tile onto the backup.

            Next
        Next
Attached Files
File Type: zip TileMap4.zip (21.0 KB, 212 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
  #5  
Old 02-12-2005, 01:48 PM
Iceplug's Avatar
IceplugQuick example of a Tile Map Iceplug is offline
MetaCenturion

Retired Moderator
* Guru *
 
Join Date: Aug 2001
Location: Iowa, USA
Posts: 16,583
Lightbulb Hexagon Tile Maps

Setting up a Hexagon Tile Map is a bit different from the regular Tile Maps above.
First of all, it's important to figure out how the hexagon map will be laid out, how it will be shaped, and how the hexagons will be assigned tile locations.
After all, a hexagon map represents a two-dimensional array... so each hexagon on the map should have an X and a Y tile location.
The first thing to do is determine how the X and Y tile location values change as you move to adjacent hexagons. There are two examples in the hexref picture below of how you might do this: The left method is starting with a hexagon that has the tile location of (5, 5) and from there, linearly assigning
tile location to all of the surrounding hexagons (below, moving to the lower right hexagon, there will be the same Y value as on the previous hexagon).
The second method on the right is taking the six directions of movement and indicating how much each tile location changes as you move in this direction. for example, moving to the lower left hexagon causes the X location to increase by 1, but Y remains constant (changes by 0).

After you do this (its recommended that you do the 'differential' if you choose the left method), you should look at the hexagon that models the tiles in the map. Look at the hexmetrics picture - all of the properties of the hexagon are measured - find these properties by looking at the images that you are using for the hexagon tiles - these values will be constants in the program. (The hexagons in the file are 32 wide)

The map is still a 2D array, as well as the character location is still unchanged. The map is still read from the same type of file.

The next thing that needs to be figured is the drawing of the hexagon map.
Drawing it like a regular tile map leaves lots of holes and doesn't look hexagonal at all. The drawing subroutine needs to draw the map 'hexagonally'... and this is done by a 'transformation', (that's what I call it). The transformation will transform a tile location into a display location.

The tilemaps that have drawn before would have transformation functions of
xX = 16 * LX, where xX is a screen X location, and LX is a tile location.
and similarly, xY = 16 * LY
16 would be the width and height of each tile representing the amount to skip over in each direction when going to the next tile, and the first tile (the one at (0, 0) ) is drawn at the upper left corner of the map, at screen coordinates (0, 0).
These are not the same with a hexagon map.
In the project, you'll see the transformation function in the X direction also depends on the Y tile location as well as the X tile location... similarly xY depends on LX and LY.
In the project, they are xX = 24 * LX - 24 * LY and xY = 16 * LX + 16 * LY, or
xX = 24 (LX - LY), and xY = 16(LX + LY)
The 24 and 16 are expressed as constants in the project - keep your eye out for them .
Also, you have to find the zero point (like the y-intercept for line equations in algebra)... this is the coordinates where the hexagon at tile location (0,0) will be drawn. In the project, each coordinate is a constant expressed in terms of the other constants (that define the hexagon sizes). The zero point in the project is (264,0), the 0 for the top would be pretty obvious.
These zero values need to be added to the expressions for the transform functions.

Code:
        GFX.FillRectangle(Brushes.Black, New Rectangle(0, 0, Me.MapViewWidth, Me.MapViewHeight))

        For LY = 0 To Me.MapSizeInTilesE
            For LX = 0 To Me.MapSizeInTilesE

                Thistile = Map(LX, LY)

                Tile = New Rectangle(32 * Thistile, 0, 32, 32)


                xX = (Me.HexagonEdgesWidth + Me.HexagonTopEndWidth) * (LX - LY) + Me.ZeroPointLeft
                xY = Me.HexagonEdgesHeight * (LX + LY) + Me.ZeroPointTop


                GFX.DrawImage(Tileset, xX, xY, Tile, GraphicsUnit.Pixel)

            Next
        Next

        'Also, to draw the character, we use the same translation but with character location instead of LX and LY.
        xX = (Me.HexagonEdgesWidth + Me.HexagonTopEndWidth) * (CharacterLocation.X - CharacterLocation.Y) + Me.ZeroPointLeft
        xY = Me.HexagonEdgesHeight * (CharacterLocation.X + CharacterLocation.Y) + Me.ZeroPointTop


        GFX.DrawImage(Charpics(Cyc), xX, xY, 32, 32)

        FormGFX.DrawImage(Backup, Me.ClientRectangle())
Also, there's the character movement, where the differential comes in handy to determine how much the character coordinates should increase with each direction. (I used 7, 8, 9, 1, 2, and 3 on the numpad for controls).
The collision detection is still the same.

Have fun.
Attached Images
File Type: jpg hexmetrics.jpg (14.3 KB, 228 views)
File Type: jpg hexref.jpg (31.0 KB, 206 views)
File Type: jpg screeny.jpg (23.2 KB, 265 views)
Attached Files
File Type: zip TileMap5.zip (43.1 KB, 292 views)
__________________

Iceplug, USN
Quadrill 1 Quadrill 2 (full) Quadrill 3 JumpCross .NET Website is ALIVE! - DL Platform Tour for VB.NET! Posting Guidelines Hint: Specify your location in your user cp profile if you want compassion!
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map Quick example of a Tile Map
Quick example of a Tile Map
Quick example of a Tile Map
 
Quick example of a Tile Map
Quick example of a Tile Map
 
-->