Results 1 to 12 of 12

Thread: [VB.Net] 2d Map Tile-Based Engine

  1. #1

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    [VB.Net] 2d Map Tile-Based Engine

    Features
    Allows you to render images to simulate a map in a game.

    Drawbacks
    The LoadMap sub can take a while depending on how large your map file is.

    DLL
    MapEngine.zip

    Notes
    Thanks to Jacob Roman for showing a technique that allows the tiles to be rendered quickly.

    Source Code
    See Post #8. The amount of text was too long to fit in just this post, so I posted the source in #8 and kept the DLL in this post.
    Last edited by dday9; Dec 2nd, 2014 at 12:04 PM.

  2. #2
    Discovering Life Siddharth Rout's Avatar
    Join Date
    Feb 2005
    Location
    Mumbai, India
    Posts
    12,001

    Re: 2d Map Engine

    Thread moved to `Game Demos` as per OP's request.
    A good exercise for the Heart is to bend down and help another up...
    Please Mark your Thread "Resolved", if the query is solved


    MyGear:
    ★ CPU ★ Ryzen 5 5800X
    ★ GPU ★ NVIDIA GeForce RTX 3080 TI Founder Edition
    ★ RAM ★ G. Skill Trident Z RGB 32GB 3600MHz
    ★ MB ★ ASUS TUF GAMING X570 (WI-FI) ATX Gaming
    ★ Storage ★ SSD SB-ROCKET-1TB + SEAGATE 2TB Barracuda IHD
    ★ Cooling ★ NOCTUA NH-D15 CHROMAX BLACK 140mm + 10 of Noctua NF-F12 PWM
    ★ PSU ★ ANTEC HCG-1000-EXTREME 1000 Watt 80 Plus Gold Fully Modular PSU
    ★ Case ★ LIAN LI PC-O11 DYNAMIC XL ROG (BLACK) (G99.O11DXL-X)
    ★ Monitor ★ LG Ultragear 27" 240Hz Gaming Monitor
    ★ Keyboard ★ TVS Electronics Gold Keyboard
    ★ Mouse ★ Logitech G502 Hero

  3. #3

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: 2d Map Engine

    Thank you sid!
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  4. #4
    Lively Member
    Join Date
    Jul 2011
    Posts
    65

    Re: [VB.Net] 2d Map Tile-Based Engine

    Looks great man, do you have a video tut explaining how to build it? Video tuts on these topics are so hard to find and really good stuff for learning. Please share if you have the time. Thank you.

  5. #5
    College Grad!!! Jacob Roman's Avatar
    Join Date
    Aug 2004
    Location
    Miami Beach, FL
    Posts
    5,339

    Re: [VB.Net] 2d Map Tile-Based Engine

    Im not sure he moved the map using my method. But my method has 0 slowdown regardless of the map size, even if the map is 10000x10000:

    vb.net Code:
    1. Private Sub Draw_Map()
    2.  
    3.         Dim imageFile As Image
    4.         Dim g As Graphics
    5.         Dim newGraphics As Graphics
    6.         Dim Coordinates As Vector 'Tile Coordinates of the position on map such as 5,10 or 24, 8
    7.         Dim X1 As Integer, Y1 As Integer, X2 As Integer, Y2 As Integer
    8.         Dim X As Integer, Y As Integer
    9.         Dim R As RECT
    10.  
    11.         R.Left = 0
    12.         R.Top = 0
    13.         R.Right = Me.Width
    14.         R.Bottom = Me.Height
    15.  
    16.         Coordinates.X = Int(-(Map.Position.X) / TILE_WIDTH)
    17.         Coordinates.Y = Int(-(Map.Position.Y) / TILE_HEIGHT) 'converts your position into tile coordinates
    18.  
    19.         'This here allows the world to be as gigantic as you want with zero slow down like 5000x5000 for example. Only draws what is on screen.
    20.  
    21.         X1 = Coordinates.X
    22.         Y1 = Coordinates.Y
    23.         X2 = Coordinates.X + Map.Screen_Tile_Width
    24.         Y2 = Coordinates.Y + Map.Screen_Tile_Height
    25.  
    26.         If X2 <= 0 Then X2 = 0
    27.         If Y2 <= 0 Then Y2 = 0
    28.         If Y2 >= Map.Height - 1 Then Y2 = Map.Height - 1
    29.         If X2 >= Map.Width - 1 Then X2 = Map.Width - 1
    30.         If X1 <= 0 Then X1 = 0
    31.         If Y1 <= 0 Then Y1 = 0
    32.         If X1 >= X2 Then X1 = X2
    33.         If Y1 >= Y2 Then Y1 = Y2
    34.  
    35.         For Y = Y1 To Y2
    36.             For X = X1 To X2
    37.                 If Running = True Then
    38.                     If Not ((Map.Position.X + ((TILE_WIDTH * X) + TILE_WIDTH) < R.Left) Or (Map.Position.X + ((TILE_WIDTH * X)) > R.Right) Or (Map.Position.Y + ((TILE_HEIGHT * Y) + TILE_HEIGHT) < R.Top) Or (Map.Position.Y + ((TILE_HEIGHT * Y)) > R.Bottom)) Then
    39.                         imageFile = Image.FromFile(Map.Texture_List(Map.Tile(X, Y)))
    40.                         g = Me.CreateGraphics()
    41.                         newGraphics = Graphics.FromImage(imageFile)
    42.                         g.DrawImage(imageFile, New RectangleF(Map.Position.X + (TILE_WIDTH * X), Map.Position.Y + (TILE_HEIGHT * Y), TILE_WIDTH + 3, TILE_HEIGHT + 3))
    43.                         newGraphics.Dispose()
    44.                         g.Dispose()
    45.                     End If
    46.                 End If
    47.             Next X
    48.         Next Y
    49.  
    50.     End Sub

    Now do you see this area of the code?

    Code:
            Coordinates.X = Int(-(Map.Position.X) / TILE_WIDTH)
            Coordinates.Y = Int(-(Map.Position.Y) / TILE_HEIGHT) 'converts your position into tile coordinates
    
            X1 = Coordinates.X
            Y1 = Coordinates.Y
            X2 = Coordinates.X + Map.Screen_Tile_Width
            Y2 = Coordinates.Y + Map.Screen_Tile_Height
    This guarantees the For loops will never be bigger than the number of tiles shown on screen. Screen tile width is actually the number of tiles you are allowed to see on screen horizontally. Screen tile height is the number of tiles you are allowed to see on screen vertically. So you are only able to see 32 x 16 tiles on screen at once.

    As you move, all the X1 Y1 X2 Y2 values keep within the range of 32 x 16. So its like you are moving a rectangular shaped magnifying glass within your massively sized world map. For example. Lets say your Tile Coordinates are 10, 10. So your values are now this:

    Code:
    X1 = 10
    Y1 = 10
    X2 = 42
    Y2 = 26
    If you move to the right about 5 tiles and you stop, you are now here:

    Code:
    X1 = 15
    Y1 = 10
    X2 = 47
    Y2 = 26
    So if you for loop X1 to X2, Y1 to Y2, you still are only going through only 32 x 16 tiles. Your loop will never get bigger, even if the values are within the 1000s range. This is why this chunk of code is important:

    Code:
            X1 = Coordinates.X
            Y1 = Coordinates.Y
            X2 = Coordinates.X + Map.Screen_Tile_Width
            Y2 = Coordinates.Y + Map.Screen_Tile_Height
    Dday I don't think used this method at all according to his code. But he should. As it is fast, efficient, and he can create worlds the size of World of Warcraft...in 2D if course. I kinda wish programmers in the past found this method out. Lord knows the RPGs in the past would be gigantic if this were so. But I think its a method I personally invented

    Oh and one last thing, if you are confused about what to do with Map.Position, this can be changed to Player.Position because your player is moving through the map while the player appears to stay in the middle of the screen. And to move the map it was simply this:

    vb.net Code:
    1. Private Sub frmMain_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
    2.  
    3.         If e.KeyCode = Keys.Left Then Map.Position.X += 10
    4.         If e.KeyCode = Keys.Right Then Map.Position.X -= 10
    5.         If e.KeyCode = Keys.Up Then Map.Position.Y += 10
    6.         If e.KeyCode = Keys.Down Then Map.Position.Y -= 10
    7.  
    8.     End Sub

  6. #6

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [VB.Net] 2d Map Tile-Based Engine

    Quote Originally Posted by Jacob Roman View Post
    Im not sure he moved the map using my method. But my method has 0 slowdown regardless of the map size, even if the map is 10000x10000:
    This guarantees the For loops will never be bigger than the number of tiles shown on screen.
    That's what I do in the move_map sub. The loop looks like this:
    Code:
            For col As Integer = x - 4 To x + 5
                For row As Integer = y - 4 To y + 5
    Where x and y are the current position's x/y coordinates. In the post I made, if x = 10 and y = 15 the loop will run:
    Code:
     For col As Integer = 6 To 15
       For row As Integer = 11 To 20
    The only difference is how I set the map size. I set it x - 4 to x + 5 which is 10 and then y - 4 to y + 5 which is 10. So the loop will always only loop a 10x10 grid.

    So I still use your idea of only rendering on screen what's being viewed at that moment, only a bit differently. I still get 0 slow down even at 1000x1000 map sizes.

    The only slow down that I have is how I load the map initially in the load_map sub, in which case using splash screen saying the game is loading and using a backgroundworker to actually load the map would be a bit more user friendly.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  7. #7

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [VB.Net] 2d Map Tile-Based Engine

    I've updated the code. Much more efficient now and also allows for comments and blank spaces in the map file. In the map file, if you wish to have a comment or a blank space then you must do so before the mapping begins. The comments are designated by the pound sign(#) at the beginning of the line.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  8. #8

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [VB.Net] 2d Map Tile-Based Engine

    Update!
    Source Code
    Code:
    Public Class Tile
    
        ''' <summary>
        ''' Gets or sets the unique value of the tile.
        ''' </summary>
        ''' <value>System.Int32</value>
        ''' <returns>System.Int32</returns>
        ''' <remarks>This property is NOT required for the class to work properly.</remarks>
        <System.ComponentModel.Description("Gets or sets the unique value of the tile.")> _
        Public Property ID As System.Int32
    
        ''' <summary>
        ''' Gets or sets the path to the image the tile represents.
        ''' </summary>
        ''' <value>System.String</value>
        ''' <returns>System.String</returns>
        ''' <remarks>Image location can only end with a valid image extension.</remarks>
        <System.ComponentModel.Description("Gets or sets the path to the image the tile represents.")> _
        Public Property ImageLocation As System.String
    
        ''' <summary>
        ''' Gets or sets the depth level the tiles sits from lowest to highest.
        ''' </summary>
        ''' <value>System.Int32</value>
        ''' <returns>System.Int32</returns>
        ''' <remarks>The lowest level may have the least visible area because other tiles sitting on top of it may obstruct the view of the image.</remarks>
        <System.ComponentModel.Description("Gets or sets the depth level the tiles sits from lowest to highest.")> _
        Public Property Level As System.Int32
    
        ''' <summary>
        ''' Gets or sets if the user can pass through the tile.
        ''' </summary>
        ''' <value>System.Boolean</value>
        ''' <returns>System.Boolean</returns>
        ''' <remarks>If true, then the user cannot pass through the tile.</remarks>
        <System.ComponentModel.Description("Gets or sets the user can pass through the tile.")> _
        Public Property Obstruction As System.Boolean
    
        ''' <summary>
        ''' Gets or sets the position of the tile in relation to it's map.
        ''' </summary>
        ''' <value>System.Drawing.Point</value>
        ''' <returns>System.Drawing.Point</returns>
        <System.ComponentModel.Description("Gets or sets the position of the tile in relation to it's map.")> _
        Public Property RelativeLocation As System.Drawing.Point
    
        ''' <summary>
        ''' Saves the tile into an XML file.
        ''' </summary>
        ''' <param name="folder">Defines the folder in which the tile will be saved to</param>
        ''' <remarks>Uses XML serialization to serialize each individual tile</remarks>
        Protected Friend Sub SaveTile(ByVal folder As System.String)
    
            Using writer As System.IO.StreamWriter = New System.IO.StreamWriter(System.IO.Path.Combine(folder, Me.RelativeLocation.ToString & ".xml"))
                Dim x As System.Xml.Serialization.XmlSerializer = New System.Xml.Serialization.XmlSerializer(Me.GetType)
                x.Serialize(writer, Me)
            End Using
    
        End Sub
    
    End Class
    
    Public Class Map : Inherits System.Windows.Forms.Control
    
        ''' <summary>
        ''' Gets or sets the center tile of the map.
        ''' </summary>
        ''' <remarks>If map has an even height or width then the X/Y position will round down to determine the center.</remarks>
        Private cTile As Tile
        <System.ComponentModel.Description("Gets or sets the center tile of the map.")> _
        Public ReadOnly Property CenterTile() As Tile
            Get
                Return cTile
            End Get
        End Property
    
        ''' <summary>
        ''' Gets or sets the RelativeLocation of the tile in the upper-left hand corner of the map.
        ''' </summary>
        Private cPosition As System.Drawing.Point
        <System.ComponentModel.Description("Gets or sets the RelativeLocation of the tile in the upper-left hand corner of the map.")> _
        Public Property CurrentPosition() As System.Drawing.Point
            Get
                Return cPosition
            End Get
            Set(ByVal value As System.Drawing.Point)
                If cPosition <> value Then
                    cPosition = value
                    RaiseEvent CurrentPositionChanged(Me, System.EventArgs.Empty)
                End If
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the tiles that make up the content the map.
        ''' </summary>
        Private mTiles As Tile(,)
        <System.ComponentModel.Description("Gets or sets the tiles that make up the content the map.")> _
        Public Property Tiles() As Tile(,)
            Get
                Return mTiles
            End Get
            Set(ByVal value As Tile(,))
                If mTiles IsNot value Then
                    mTiles = value
                    RaiseEvent TilesChanged(Me, System.EventArgs.Empty)
                End If
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the size of all the tiles that make up the map.
        ''' </summary>
        ''' <remarks>The default size is 32x32.</remarks>
        Private tSize As System.Drawing.Size
        <System.ComponentModel.Description("Gets or sets the size of all the tiles that make up the map.")> _
        Public Property TileSize() As System.Drawing.Size
            Get
                Return tSize
            End Get
            Set(ByVal value As System.Drawing.Size)
                If tSize <> value Then
                    tSize = value
                    RaiseEvent TileSizeChanged(Me, System.EventArgs.Empty)
                End If
            End Set
        End Property
    
        ''' <summary>
        ''' Gets or sets the amount tiles by width and height that make up the map.
        ''' </summary>
        ''' <remarks>The default size is 10x10.</remarks>
        Private vArea As System.Drawing.Size
        <System.ComponentModel.Description("Gets or sets the amount tiles by width and height that make up the map.")> _
        Public Property VisibleArea() As System.Drawing.Size
            Get
                Return vArea
            End Get
            Set(ByVal value As System.Drawing.Size)
                If vArea <> value Then
                    vArea = value
                    RaiseEvent VisibleAreaChanged(Me, System.EventArgs.Empty)
                End If
            End Set
        End Property
    
        ''' <summary>
        ''' Occurs when the CurrentPosition property changes
        ''' </summary>
        ''' <param name="sender">The Map that changes the CurrentPosition property</param>
        ''' <param name="e">Empty</param>
        ''' <remarks></remarks>
        Public Event CurrentPositionChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        ''' <summary>
        ''' Occurs after the Load method finishes
        ''' </summary>
        ''' <param name="sender">The Map that gets loaded</param>
        ''' <param name="e">Empty</param>
        Public Event Loaded(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        ''' <summary>
        ''' Occurs after the Save method finishes
        ''' </summary>
        ''' <param name="sender">The Map that gets saved</param>
        ''' <param name="e">Empty</param>
        Public Event Saved(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        ''' <summary>
        ''' Occurs when the Tiles property changes
        ''' </summary>
        ''' <param name="sender">The Map that changes the Tiles property</param>
        ''' <param name="e">Empty</param>
        Public Event TilesChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        ''' <summary>
        ''' Occurs when the TileSize property changes 
        ''' </summary>
        ''' <param name="sender">The Map that changes the TileSize property</param>
        ''' <param name="e">Empty</param>
        Public Event TileSizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        ''' <summary>
        ''' Occurs when the VisibleArea property changes
        ''' </summary>
        ''' <param name="sender">The Map that changes the VisibleArea property</param>
        ''' <param name="e">Empty</param>
        Public Event VisibleAreaChanged(ByVal sender As System.Object, ByVal e As System.EventArgs)
    
        Private Sub Map_CurrentPositionChanged(ByVal sender As Object, ByVal e As EventArgs) Handles Me.CurrentPositionChanged
            Me.Draw()
        End Sub
    
        Private Sub Map_Loaded(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.Loaded
            Me.CreateControls()
            Me.Draw()
        End Sub
    
        Private Sub Map_TilesChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.TilesChanged
            Me.CreateControls()
            Me.Draw()
        End Sub
    
        Private Sub Map_TileSizeChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.TileSizeChanged
            Me.CreateControls()
            Me.Draw()
        End Sub
    
        Private Sub Map_VisibleAreaChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Me.VisibleAreaChanged
            Me.CreateControls()
            Me.Draw()
        End Sub
    
        ''' <summary>
        ''' Creates the tiles that make up the map.
        ''' </summary>
        ''' <remarks>The tiles are represented as a System.Windows.Forms.PictureBox</remarks>
        Private Sub CreateControls()
            Me.Controls.Clear()
    
            Dim pb As System.Windows.Forms.PictureBox
            For x As System.Int32 = 0 To vArea.Width - 1
                For y As System.Int32 = 0 To vArea.Height - 1
                    pb = New System.Windows.Forms.PictureBox
    
                    With pb
                        .Location = New System.Drawing.Point(x * tSize.Width, y * tSize.Height)
                        .Size = tSize
                        .SizeMode = Windows.Forms.PictureBoxSizeMode.StretchImage
                        .Tag = New System.Drawing.Point(x, y)
                    End With
    
                    Me.Controls.Add(pb)
                Next
            Next
    
        End Sub
    
        ''' <summary>
        ''' Draws the images that represent the tiles.
        ''' </summary>
        ''' <remarks>The images are drawn by using the PictureBox.Load() method.</remarks>
        Public Sub Draw()
    
            If mTiles IsNot Nothing Then
                Dim pb As System.Windows.Forms.PictureBox
                Dim t As Tile = Nothing
                For x As System.Int32 = 0 To vArea.Width - 1
                    For y As System.Int32 = 0 To vArea.Height - 1
                        pb = Me.Controls.OfType(Of System.Windows.Forms.PictureBox).FirstOrDefault(Function(p) p.Tag.ToString = New System.Drawing.Point(x, y).ToString)
    
                        If cPosition.X + x <= mTiles.GetUpperBound(0) AndAlso cPosition.Y + y <= mTiles.GetUpperBound(1) Then
                            t = mTiles(cPosition.X + x, cPosition.Y + y)
                        End If
    
                        If t IsNot Nothing Then
                            pb.Load(t.ImageLocation)
    
                            If CInt(Math.Floor((vArea.Width - 1) / 2)) = x AndAlso CInt(Math.Floor((vArea.Height - 1) / 2)) = y Then
                                cTile = t
                            End If
                        End If
                    Next
                Next
            End If
    
        End Sub
    
        ''' <summary>
        ''' Loads a map from a previously saved state.
        ''' </summary>
        ''' <param name="folder">Defines the folder in which the tiles will be loaded from</param>
        ''' <remarks>Deserializes all the tiles from the folder into a List(Of Tile). Then the List(Of Tile) is converted to a 2d Tile array.</remarks>
        Public Sub Load(ByVal folder As System.String)
            Dim files() As System.String = New IO.DirectoryInfo(folder).GetFiles.Select(Function(f) f.FullName).ToArray
    
            Dim tempTiles As System.Collections.Generic.List(Of Tile) = New System.Collections.Generic.List(Of Tile)
    
            For i As System.Int32 = 0 To files.Length - 1
    
                Using reader As System.IO.StreamReader = New System.IO.StreamReader(files(i))
                    Dim x As System.Xml.Serialization.XmlSerializer = New System.Xml.Serialization.XmlSerializer(GetType(Tile))
                    tempTiles.Add(DirectCast(x.Deserialize(reader), Tile))
                End Using
    
            Next
    
            Dim maxX As System.Int32 = tempTiles.Max(Function(t) t.RelativeLocation.X)
            Dim maxY As System.Int32 = tempTiles.Max(Function(t) t.RelativeLocation.Y)
    
            ReDim mTiles(maxX, maxY)
    
            For Each item As Tile In tempTiles
                mTiles(item.RelativeLocation.X, item.RelativeLocation.Y) = item
            Next
    
            RaiseEvent Loaded(Me, System.EventArgs.Empty)
        End Sub
    
        ''' <summary>
        ''' Attempts to move the CurrentPosition property's Y position down by a specified amount.
        ''' </summary>
        ''' <param name="increment">The specified amount to move the CurrentPosition property's Y position down</param>
        ''' <remarks>Will not move the map if the increment falls out of the Tiles bounds</remarks>
        Public Sub MoveDown(ByVal increment As System.Int32)
    
            If cPosition.Y + increment <= mTiles.GetUpperBound(1) Then
                cPosition = New System.Drawing.Point(cPosition.X, cPosition.Y + increment)
                Me.Draw()
            End If
    
        End Sub
    
        ''' <summary>
        ''' Attempts to move the CurrentPosition property's X position left by a specified amount.
        ''' </summary>
        ''' <param name="increment">The specified amount to move the CurrentPosition property's X position left</param>
        ''' <remarks>Will not move the map if the increment falls out of the Tiles bounds</remarks>
        Public Sub MoveLeft(ByVal increment As System.Int32)
    
            If cPosition.X - increment >= 0 Then
                cPosition = New System.Drawing.Point(cPosition.X - increment, cPosition.Y)
                Me.Draw()
            End If
    
        End Sub
    
        ''' <summary>
        ''' Attempts to move the CurrentPosition property's X position right by a specified amount.
        ''' </summary>
        ''' <param name="increment">The specified amount to move the CurrentPosition property's X position right</param>
        ''' <remarks>Will not move the map if the increment falls out of the Tiles bounds</remarks>
        Public Sub MoveRight(ByVal increment As System.Int32)
    
            If cPosition.X + increment <= mTiles.GetUpperBound(0) Then
                cPosition = New System.Drawing.Point(cPosition.X + increment, cPosition.Y)
                Me.Draw()
            End If
    
        End Sub
    
        ''' <summary>
        ''' Attempts to move the CurrentPosition property's Y position up by a specified amount.
        ''' </summary>
        ''' <param name="increment">The specified amount to move the CurrentPosition property's Y position up</param>
        ''' <remarks>Will not move the map if the increment falls out of the Tiles bounds</remarks>
        Public Sub MoveUp(ByVal increment As System.Int32)
    
            If cPosition.Y - increment >= 0 Then
                cPosition = New System.Drawing.Point(cPosition.X, cPosition.Y - increment)
                Me.Draw()
            End If
    
        End Sub
    
        ''' <summary>
        ''' Saves all the tiles in the map.
        ''' </summary>
        ''' <param name="folder">Defines the folder in which the tiles will be saved to</param>
        Public Sub Save(ByVal folder As System.String)
    
            For Each item As Tile In mTiles
                item.SaveTile(folder)
            Next
    
            RaiseEvent Saved(Me, EventArgs.Empty)
    
        End Sub
    
        Sub New()
            cPosition = New System.Drawing.Point(0, 0)
            tSize = New System.Drawing.Size(32, 32)
            vArea = New System.Drawing.Size(10, 10)
            Me.CreateControls()
            Me.Draw()
        End Sub
    
    End Class
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  9. #9
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: [VB.Net] 2d Map Tile-Based Engine

    Quote Originally Posted by Jacob Roman View Post
    ...
    I kinda wish programmers in the past found this method out. Lord knows the RPGs in the past would be gigantic if this were so. But I think its a method I personally invented
    ...
    No new invention here. Been doing it for more than 30 years, and I'm sure others even longer.
    Of course, when you had less than 64K of memory to work with, and slow 8-bit processors, you had to be efficient and of course only drew what was visible on the screen, and often less (only partial updates of only the parts that have changed).
    Have you actually seen code that loops though all the tiles when drawing, other than possible amatures programming a game as their first programming exercise?

  10. #10

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [VB.Net] 2d Map Tile-Based Engine

    @Passel, do you have any tips on the initial loading of the tiles? I'm currently uses the Load method which deserializes a folder of XML files which represent a tile. This can take a good bit if the map is greater than 100 x 100.
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

  11. #11
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,582

    Re: [VB.Net] 2d Map Tile-Based Engine

    Well, I'm not sure how long your loading is taking per tile and how many fit on the screen (I guess you said 10x10), but probably the first thing to try would be to put the tile loading in a background thread, and choose to load the tiles around your starting position first, and work your way out from there.
    That way you should be able to display the currently area of the map fairly quickly and if they choose to move, the near tiles should be available as tiles are being loaded in the background.
    If you had a really large map, you might choose to never load all the tiles, but maintain a cache of 400 or so tiles and load 10 or 20 at a time when needed.
    Also, part of the efficient of a tile based game is that you reuse a lot of tiles, so you shouldn't have 10,000 unique tiles in a 100x100 gaming area.
    The Map data should be using indexes to the tiles so be much smaller, and quicker to load.
    I haven't done too many tile based applications over the last 30+ years, but have done tactical plots and scrolling maps, etc. from way back.
    More recently I did do several versions of a test case of a large scrolling area using VB.Net, but it isn't technically tile based.
    It just uses a textured background that scrolls so you can perceive motion, and you place a lot of objects around the map (which could be tiles), but can be placed at any point. In my test case, I just grabbed a couple of bit maps that had a number of plant, bushes and trees, and scattered them around the area.
    In my test case, the area is 256K by 256K pixels in size, and I limited myself to placing a million plants/bushes/trees around the area. I didn't use all one million slots, something like 600000+ I think. So, even though there are 600000+ items located all over the gaming area, there are probably less than 200 unique images that have to be loaded to draw them. And of course, only the items in a 2000 by 2000 pixels area around the center of the drawing area is considered when drawing.
    The area is divided into 1K by 1K sized logical areas, and the things that are located in those areas are linked to a linked list in that area, so you only have to look at a very small number of the one million items for things like drawing, hit testing and collision testing.
    I have a bunch of versions of the thing, playing around with different aspects. None are really optimized and the drawing isn't done in the best way. I haven't messed with it for a year or two, but I could probably find some reasonable version of it to post somewhere on the forum. I have a lot of various test projects, none polished. All the polished stuff is for work, and none of that, until lately, has been any form of VB.
    99% of my VB programming (since 1991) has been personal hobby stuff.
    Last edited by passel; Dec 2nd, 2014 at 05:18 PM.

  12. #12

    Thread Starter
    Super Moderator dday9's Avatar
    Join Date
    Mar 2011
    Location
    South Louisiana
    Posts
    11,715

    Re: [VB.Net] 2d Map Tile-Based Engine

    That does give me some idea's to rewrite the program. I'll work on it some more!
    "Code is like humor. When you have to explain it, it is bad." - Cory House
    VbLessons | Code Tags | Sword of Fury - Jameram

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width