In this episode, we'll begin to get our levels scrollable.
We are only going to have our levels scroll horizontally for now.
Vertical scrolling will be covered in the next episode.

So, in order to do horizontal scrolling, we need to have a variable that indicates which part of our scrolling map
we will be looking at.  Then, we'll coordinate all of our drawing (the Artwork section) so that the screen scrolls
the level.
So, let's declare our variable:
    Dim ScreenLeft As Integer
    'Where the display's left end is on the map.
And this represents the coordinates of the screen where the left end is, or the width of the game area that is off of the left end of the screen. Now, we can easily set this to be based on the player's left distance. The width of the screen is MAPWIDTH, and the player's width is CHARWIDTH, so, if we were to keep the character centered on the screen, we would have something like: PlayerLoc.X + CHARWIDTH \ 2 - MAPWIDTH \ 2 Of course, we can substitute our integer divisions ( \2 ) with bit shifts in .NET 2003
        ScreenLeft = PlayerLoc.X + (CHARWIDTH >> 1) - (MAPWIDTH >> 1)
        'Set the screen left end so that the screen scrolls.
But, better yet, since CHARWIDTH \ 2 - MAPWIDTH \ 2 is constant, we can make this into another constant.
    Const SCREENOFFSET As Integer = (MAPWIDTH >> 1) - (CHARWIDTH >> 1)
    'Distance from the player's left edge to left edge of scrolling screen.
And then:
        ScreenLeft = PlayerLoc.X - SCREENOFFSET
        'Set the screen left end so that the screen scrolls.
Of course, the player begins at the left end of the screen (for now), so we may want to keep this value from being negative. We can do something like this to stop this result at 0.
        ScreenLeft = PlayerLoc.X - SCREENOFFSET
        'Set the screen left end so that the screen scrolls.
        If ScreenLeft < 0 Then
            ScreenLeft = 0
            'Keep the screen left coordinate non-negative.
        End If
Now, let's go to our Artwork sub, where we will make this happen. An example of how we are already drawing our map objects:
        For Each Platform In Platforms
            'Loop through each platform in the arraylist.
            GFX.FillRectangle(Brushes.Tan, Platform)
            GFX.DrawRectangle(Pens.RosyBrown, Platform)
            'I'm not into interior decorating, so the only thing I can say about these colors is that 
            'they'd better be a light brown persuasion.  This draws the platform.
        Next
So, we'll have to first offset our rectangle before we draw it.
        For Each Platform In Platforms
            'Loop through each platform in the arraylist.
            Platform.Offset(-ScreenLeft, 0)
            GFX.FillRectangle(Brushes.Tan, Platform)
            GFX.DrawRectangle(Pens.RosyBrown, Platform)
            'I'm not into interior decorating, so the only thing I can say about these colors is that 
            'they'd better be a light brown persuasion.  This draws the platform.
            Platform.Offset(ScreenLeft, 0)
        Next
And we'll do this for all of our other drawings in artwork: Wall.Offset(-ScreenLeft, 0) and the positive Wall.Offset(ScreenLeft, 0) in the For Each Wall block. Coin.Offset(-ScreenLeft, 0) and the positive in the For Each Coin block. Lava.Offset(-ScreenLeft, 0) and the positive in the For Each Lava block. Floater.Offset(-ScreenLeft, 0) and the positive in the For Each Floater block. There are five places within the If IsGoner block and the matching Else block where I subtract ScreenLeft. If you find them all, go you(!), however if you can't find them, I put the whole block underneath.
        If IsGoner Then

            If Doompause >= DOOMTIMEOUT Then
                GFX.TranslateTransform(Convert.ToSingle(PlayerLoc.X) + (Me.CHARWIDTH >> 1) - ScreenLeft, Convert.ToSingle(PlayerLoc.Y) + (Me.CHARWIDTH >> 1))
                'Move the center point to the center of the character's midpoint.
                GFX.RotateTransform(RotateAngle)
                'Spin the character clockwise.
                RotateAngle += SPINOUTSPEED

                If IsJumping Then
                    GFX.DrawImage(PlayerBmp, -Me.CHARWIDTH >> 1, -Me.CHARHEIGHT >> 1, New Rectangle((CHARWIDTH * WALKINGFRAMECOUNT << 1) + CharDirec * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                    'Draw the character centered on the point 0, 0
                Else
                    GFX.DrawImage(PlayerBmp, -Me.CHARWIDTH >> 1, -Me.CHARHEIGHT >> 1, New Rectangle(CHARWIDTH * CharDirec * WALKINGFRAMECOUNT + AnimCycler * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                    'This draws the character to the display, based on the current character location, frame, and state.
                End If

                PlayerLoc.Offset(0, PlayerVeloc + GRAVITY >> 1)
                'Gravity-based calculations that we have already done in CharacterMovement.
                PlayerVeloc += GRAVITY

                GFX.ResetTransform()
            Else

                RotateAngle = 0.0F
                'Reset the rotateangle for our tumbling-spinning character.

                Doompause += 1
                'Increment the delay counter.
                If IsJumping Then
                    GFX.DrawImage(PlayerBmp, PlayerLoc.X - ScreenLeft, PlayerLoc.Y, New Rectangle((CHARWIDTH * WALKINGFRAMECOUNT << 1) + CharDirec * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                    'Jumping draw only.
                Else
                    GFX.DrawImage(PlayerBmp, PlayerLoc.X - ScreenLeft, PlayerLoc.Y, New Rectangle(CHARWIDTH * CharDirec * WALKINGFRAMECOUNT + AnimCycler * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                    'This draws the character to the display, based on the current character location, frame, and state.
                End If

            End If

        Else
            If IsJumping Then
                GFX.DrawImage(PlayerBmp, PlayerLoc.X - ScreenLeft, PlayerLoc.Y, New Rectangle((CHARWIDTH * WALKINGFRAMECOUNT << 1) + CharDirec * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                'Jumping draw only.
            Else
                GFX.DrawImage(PlayerBmp, PlayerLoc.X - ScreenLeft, PlayerLoc.Y, New Rectangle(CHARWIDTH * CharDirec * WALKINGFRAMECOUNT + AnimCycler * CHARWIDTH, 0, CHARWIDTH, CHARHEIGHT), GraphicsUnit.Pixel)
                'This draws the character to the display, based on the current character location, frame, and state.
            End If

        End If
Now, you should easily see your entire level scroll as you walk to the left. You'll have to walk over past halfway before the map will scroll.
To make the player walk past our MAPWIDTH boundary, remove
                If PlayerLoc.Right > MAPWIDTH Then
                    'If player goes off right edge... move him back.
                    PlayerLoc.Offset(MAPWIDTH - PlayerLoc.Right, 0)
And then change the following ElseIf to an If. Now, why does our character stop animating when we start walking past this end? Chances are that our character is falling since we have only defined the width of our bottom ground layer to be MAPWIDTH. So, we need to use another constant to determine how long our level will be. This constant will probably need to be redefined when we start to produce game levels, so let's make it large.
    Const LEVELWIDTH As Integer = MAPWIDTH << 3
    'The width of the level.  The character will not behave if we walk past this point.
And now, we change this:
        LeftEnd = 0 : RightEnd = MAPWIDTH
To
        LeftEnd = 0 : RightEnd = LEVELWIDTH
(Which occurs in the Load event procedure and in the CharacterMovement subs) And now, everything should be all right.