Grid based worlds and moving a character based on a grid system (Post #4)

Now that we created a basic map, let's create a character and move it through our map.

Changing our sprite sheet

 For this post I'll change a bit the textures from Post #3 and add a sprite sheet for player textures as shown below.


Also add a second Resource to load (which means on the declarations create another bitmap and another texturebrush)

    Public TestPlayerS As Bitmap
    Public TestPlayerB As TextureBrush

And on SoftRender("LOAD") added the following assign

    TestDrawingS = New Bitmap(My.Resources.TileMapN) 'Resource
    TestPlayerS = New Bitmap(My.Resources.PlayerSheet) 'Resource

Now on our events, we add the following code to our form for pressing keys

  Private Sub F_SRender_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
        Select Case e.KeyCode
            Case Keys.D
                ScreenClicked("D")
            Case Keys.A
                ScreenClicked("A")
            Case Keys.W
                ScreenClicked("W")
            Case Keys.S
                ScreenClicked("S")
        End Select
    End Sub

Now we change our world creating sub since we changed a bit the tiles and we want to add a flag for tiles that are walkable or not.

  Public Sub GridCalls(ByVal Func As String)
        Dim X, Y, Z As Integer

        If Func = "CREATE" Then
            For X = 0 To MaxGridX
                For Y = 0 To MaxGridY
                    GridWorld(X, Y).X = X * GridWidth
                    GridWorld(X, Y).Y = Y * GridWidth
                    GridWorld(X, Y).Z = Z * GridWidth
                    GridWorld(X, Y).ID = Int(Rnd() * 7) 'Assigning random values for tile ID
                Next
            Next

            'Now we'll create a worm like algorithm to create random connected dirt through our grid world
            Dim StartX As Integer = 20
            Dim StartY As Integer = 12
            Dim WormSteps As Integer = 360
            Dim Direction As Integer = 0

            Randomize()
            GridWorld(StartX, StartY).ID = 7
            For Z = 0 To WormSteps
                Direction = Int(Rnd() * 4)
                If Direction = 0 Then
                    StartY -= 1
                ElseIf direction = 1 Then
                    StartX += 1
                ElseIf direction = 2 Then
                    StartY += 1
                ElseIf direction = 3 Then
                    StartX -= 1
                End If
                If StartX < 0 Then StartX = 0
                If StartX > MaxGridX Then StartX = MaxGridX
                If StartY < 0 Then StartY = 0
                If StartY > MaxGridY Then StartY = MaxGridY

                GridWorld(StartX, StartY).ID = 7
            Next

            For X = 0 To MaxGridX
                For Y = 0 To MaxGridY
                    If GridWorld(X, Y).ID >= 4 And GridWorld(X, Y).ID <= 6 Then
                        GridWorld(X, Y).Blocked = 1
                    End If
                Next
            Next

        End If
    End Sub

And on our module we create the following sub

    Public Sub ScreenClicked(ByVal KeyClicked As String)
        Select Case KeyClicked
            Case "W"
                PlayerDirection = 4
                PlayerTargetTy = PlayerTileY - 1
                playertargettx = PlayerTileX
            Case "S"
                PlayerDirection = 2
                PlayerTargetTy = PlayerTileY + 1
                playertargettx = PlayerTileX
            Case "A"
                PlayerDirection = 3
                PlayerTargetTx = PlayerTileX - 1
                playertargetty = PlayerTileY
            Case "D"
                PlayerDirection = 1
                PlayerTargetTx = PlayerTileX + 1
                playertargetty = PlayerTileY
        End Select

    End Sub


And the following declarations and Sub for controlling the player

     Public PlayerX As Integer
    Public PlayerY As Integer
    Public PlayerTileX As Integer
    Public PlayerTileY As Integer
    Public PlayerTargetTX As Integer
    Public PlayerTargetTY As Integer
    Public PlayerFrameDouble As Integer
    Public PlayerFrame As Integer
    Public PlayerMoving As Integer
    Public PlayerDirection As Integer

 Public Sub Player(ByVal Func As String)

        If Func = "LOAD" Then
            GridWorld(14, 14).ID = 0
            PlayerTileX = 14
            PlayerTileY = 14
            PlayerX = GridWorld(PlayerTileX, PlayerTileY).X
            PlayerY = GridWorld(PlayerTileX, PlayerTileY).Y - 48 'Subtract the offset since we created the player sheet like out tilesheet

        ElseIf func = "REFRESH" Then

            If PlayerDirection = 0 Then
                If PlayerFrameDouble < 14 Then
                    PlayerFrameDouble += 1
                Else
                    PlayerFrameDouble = 0
                End If
                PlayerFrame = PlayerFrameDouble \ 4
            Else
                If PlayerFrameDouble < 23 Then
                    PlayerFrameDouble += 1
                Else
                    PlayerFrameDouble = 0
                End If
                PlayerFrame = PlayerFrameDouble \ 4
            End If



        ElseIf func = "MOVE" Then


            If GridWorld(PlayerTargetTX, PlayerTargetTY).Blocked = 0 Then
                If PlayerDirection = 1 Then
                    PlayerX += 1
                ElseIf PlayerDirection = 3 Then
                    PlayerX -= 1
                ElseIf PlayerDirection = 2 Then
                    PlayerY += 1
                ElseIf PlayerDirection = 4 Then
                    PlayerY -= 1
                End If
            Else
                PlayerDirection = 0
            End If

            PlayerTileX = PlayerX / GridWidth
            PlayerTileY = PlayerY / GridWidth

            If PlayerX = GridWorld(PlayerTargetTX, PlayerTargetTY).X And PlayerY = GridWorld(PlayerTargetTX, PlayerTargetTY).Y Then
                PlayerDirection = 0
            End If


        End If

    End Sub

So on the above code we created an instance for our player which spawns on tile (14,14) and gets the pixel position based on our grid. (Don't forget to add Player("LOAD") on the form load events) and (Player("MOVE") on our Timer_Tick events)

Then we created a frame sequencer (different for idle and moving) and slowed it down by dividing a second variable.

And lastly we created a direction identifier which changes the pixel X,Y of the character if the next block is walkable.

For rendering the character on screen I changed the SoftRender("DRAW") code to the following.

            Player("REFRESH")
            For Y = 0 To MaxGridY
                For X = 0 To MaxGridX
                    QRect = New Rectangle(GridWorld(X, Y).ID * 24, 0, 24, 72) 'We select the tile (From Tile ID - X position and Width and Height)
                    TestDrawingB = New TextureBrush(TestDrawingS, QRect)
                    TestDrawingB.TranslateTransform(GridWorld(X, Y).X, GridWorld(X, Y).Y - 48) 'Subtracting our tilemap offset
                    TRect = New Rectangle(GridWorld(X, Y).X, GridWorld(X, Y).Y - 48, 24, 72)
                    TestDrawingB.ScaleTransform(1, 1)
                    Gs.FillRectangle(TestDrawingB, TRect)
                    TestDrawingB.Dispose()

                    If Y = PlayerTileY And X = PlayerTileX Then
                        If PlayerDirection <> 0 Then
                            PlayerMoving = 3
                        Else
                            PlayerMoving = 0
                        End If

                        QRect = New Rectangle((PlayerMoving + PlayerFrame) * 24, 0, 24, 72) 'We select the animation frame
                        TestPlayerB = New TextureBrush(TestPlayerS, QRect)
                        TestPlayerB.TranslateTransform(PlayerX, PlayerY - 48) 'Subtracting our tilemap offset
                        TRect = New Rectangle(PlayerX, PlayerY - 48, 24, 72)
                        TestPlayerB.ScaleTransform(1, 1)
                        Gs.FillRectangle(TestPlayerB, TRect)
                        TestPlayerB.Dispose()
                    End If
                Next
            Next

            Dim fontT As New Font("Arial", 12)
            Gs.DrawString(PlayerTileX & "," & PlayerTileY & " | " & PlayerTargetTX & "," & PlayerTargetTY, fontT, Brushes.Black, 10, 10)

Now when pressing <WASD> the character will move till the next tile is reached, depending which key we pressed. If the next tile is a tree or a rock it won't move.

 

Animation of the year award


 

Comments