VisualFreeBasic游戏趣味编程_9.6_多关卡的实现

2026-1-22 / 0 评论 / 82 阅读

为了实现多个关卡的游戏,首先利用宏定义设定关卡数目:

#define LEVEL_TOTALNUM 3 '一共多少关卡

假设一共有3关,则可以设定2维字符数组levels,存储这3关的所有地图数据:

Dim Shared level(LEVEL_TOTALNUM -1, B_NUM -1) As ZString * B_NUM + 1 = _
   {_
   {"wwwwwwww", "wwwtbeew", "weeeeeew", "weeeeeew", "weeeeeew", "weepaeew", "weeewwww", "wwwwwwww"}, _ '第1关
   {"wwwwwwww", "wwweewww", "wpetbwww", "weeebeww", "wewteeww", "weeeeeww", "weepwwww", "wwwwwwww"}, _ '第2关
   {"wwwwwwww", "wwpeewww", "weeweeww", "webabeww", "weeteeww", "wwetewww", "wwwwwwww", "wwwwwwww"} _  '第3关
   }

定义currentLevelNum表示当前玩到第几关,二维数组level存储正在玩的这一关的地图数据,则可以在startup()函数中进行初始化:

Sub startup() '初始化函数
   Dim i As Long, j As Long
      For i = 0 To B_NUM -1 '首先获得当前关的地图数据
      level(i) = levels(currentLevelNum, i)
   Next

在update()函数中,如果当前关卡完成,就将currentLevelNum加1,并调用startup()开始下一关的初始化:

   If (achievedNum = targetNum) Then ' 如果完成当前关卡了
      show() '调用显示信息,显示游戏胜利画面
      If (currentLevelNum < LEVEL_TOTALNUM -1) Then
         currentLevelNum += 1 ' 进入下一关
         startup() ' 开始下一关卡的初始化
      End If
   End If

在show()函数中,如果还有未完成的关卡,显示将要开始第几关游戏;如果所有关卡都完成了,提示游戏胜利:

   gg.Font "黑体", 20
   gg.SetColor BGR(0, 255, 255) 'GDI的颜色值。
   gg.DrawString 300, 30, "第" & currentLevelNum + 1 & "关"
   gg.Font "黑体", 11
   gg.DrawString 265, 230, "按空格键重玩当前关"
   If (achievedNum = targetNum) And currentLevelNum = LEVEL_TOTALNUM -1 Then ' 如果完成目标个数等于目标个数
      gg.Font "黑体", 30
      gg.SetColor BGR(0, 255, 255) 'GDI的颜色值。
      gg.DrawString 15, 100, "游 戏 胜 利"
   End If

另外,在update()函数中添加代码,按空格键可以重玩当前关卡:

      If IsKeyPress(VK_SPACE) Then
         pp = 1
         startup()
         Return 

读者可以尝试设计更多关卡,游戏第1关~第5关,完整代码参看后面

Type Player ' 结构体,用于记录玩家位置
   i As Long
   j As Long
End Type

#define B_SIZE 32        ' 方块大小
#define B_NUM 8          ' 方块个数,一共8*8个方块
#define LEVEL_TOTALNUM 5 '一共多少关卡
'用字符型二维数组存储地图数据
'e: empty w: wall t: target b: box a: achieved p:player
'全局变量定义
Dim Shared levels(LEVEL_TOTALNUM -1, B_NUM -1) As ZString * B_NUM + 1 = _
   {_
   {"wwwwwwww", "wwwtbeew", "weeeeeew", "weeeeeew", "weeeeeew", "weepaeew", "weeewwww", "wwwwwwww"}, _ '第1关
   {"wwwwwwww", "wwweewww", "wpetbwww", "weeebeww", "wewteeww", "weeeeeww", "weepwwww", "wwwwwwww"}, _ '第2关
   {"wwwwwwww", "wwpeewww", "weeweeww", "webabeww", "weeteeww", "wwetewww", "wwwwwwww", "wwwwwwww"}, _ '第3关
   {"wwwwwwww", "wwwwwwww", "weeeewww", "weeettew", "webbbpew", "weewetww", "wwwwwwww", "wwwwwwww"}, _ '第4关
   {"wwwwwwww", "wwwwwwww", "wwteewww", "weewebpw", "weewewew", "weaeebtw", "weeeewww", "wwwwwwww"} _  '第5关
   }
Dim Shared level(B_NUM -1) As ZString * B_NUM + 1
Dim Shared Players         As player '玩家全局变量
Dim Shared As Long targetNum, achievedNum '目标位置个数、完成目标个数
Dim Shared As Long currentLevelNum ' 当前玩到第几关
Sub startup() '初始化函数
   Dim i As Long, j As Long
   For i = 0 To B_NUM -1 '首先获得当前关的地图数据
      level(i) = levels(currentLevelNum, i)
   Next
   targetNum = 0 ' 目标个数,初始为0
   For i = 0 To B_NUM -1 '遍历关卡二维数组数据
      For j = 0 To B_NUM -1
         If Mid(level(i), j + 1, 1) = "p" Then '找到地图中player的位置
            Players.i = i '设定player的位置
            Players.j = j
            Mid(level(i), j + 1, 1) = "e" '把地图元素变成空白empty
         ElseIf Mid(level(i), j + 1, 1) = "t" Or Mid(level(i), j + 1, 1) = "a" Then ' 如果元素是target或achieved
            targetNum += 1 '目标个数+1
         End If
      Next
   Next
End Sub

Sub show(gg As yGDI) '绘制函数
   gg.Cls BGR(150, 150, 150) '灰色背景。
   Dim i As Long, j As Long

   For i = 0 To B_NUM -1 '遍历关卡二维数组数据
      For j = 0 To B_NUM -1
         If Mid(level(i), j + 1, 1) = "e" Then 'empty元素是空白区域
            gg.Pen 0, 0 '框
            gg.Brush BGR(150, 150, 150) '绘制灰色地面
            gg.DrawFrame j *B_SIZE, i *B_SIZE, B_SIZE, B_SIZE
         ElseIf Mid(level(i), j + 1, 1) = "w" Then 'wall元素是墙
            gg.Pen 1, BGR(120, 120, 120) '框
            gg.Brush BGR(155, 0, 0) '绘制淡红色、灰色线的方框
            gg.DrawFrame j *B_SIZE, i *B_SIZE, B_SIZE, B_SIZE
         ElseIf Mid(level(i), j + 1, 1) = "b" Then 'box元素是可移动的箱子
            gg.Pen 1, BGR(150, 150, 150) '框
            gg.Brush BGR(255, 255, 0) '绘制一个黄色的方块
            gg.DrawFrame j *B_SIZE, i *B_SIZE, B_SIZE, B_SIZE
         ElseIf Mid(level(i), j + 1, 1) = "t" Then 'target元素是目标
            gg.Pen 0, 0 '框
            gg.Brush BGR(255, 255, 255)
            gg.DrawFrame(j + 0.25) *B_SIZE, (i + 0.25) *B_SIZE, B_SIZE * 0.5, B_SIZE * 0.5
         ElseIf Mid(level(i), j + 1, 1) = "a" Then 'achieved 元素是已完成目标
            gg.Pen 0, 0 '框
            gg.Brush BGR(255, 255, 0) '绘制一个黄色的方块
            gg.DrawFrame j *B_SIZE, i *B_SIZE, B_SIZE, B_SIZE
            gg.Pen 1, BGR(150, 150, 150) '框
            gg.Brush BGR(255, 255, 255)
            gg.DrawFrame(j + 0.25) *B_SIZE, (i + 0.25) *B_SIZE, B_SIZE * 0.5, B_SIZE * 0.5
         ElseIf Mid(level(i), j + 1, 1) = "p" Then 'player 元素是玩家,绘制一个人脸图案

         End If
      Next
   Next
   i = Players.i
   j = Players.j
   '一个红色圆脸
   gg.Pen 0, 0 '框
   gg.Brush BGR(255, 0, 0) '一个红色圆脸
   gg.DrawEllipse(j + 0.1) *B_SIZE, (i + 0.1) *B_SIZE, B_SIZE * 0.8, B_SIZE * 0.8
   '两个黑色眼睛
   gg.Brush BGR(90, 90, 90) 'GDI的颜色值。
   gg.DrawEllipse(j + 0.2) *B_SIZE, (i + 0.35) *B_SIZE, B_SIZE  * 0.25, B_SIZE * 0.25
   gg.DrawEllipse(j + 0.55) *B_SIZE, (i + 0.35) *B_SIZE, B_SIZE * 0.25, B_SIZE * 0.25
   '一个深灰色嘴巴
   gg.DrawFrame(j + 0.3) *B_SIZE, (i + 0.7) *B_SIZE, B_SIZE * 0.4, B_SIZE * 0.1

   gg.Font "黑体", 20
   gg.SetColor BGR(0, 255, 255) 'GDI的颜色值。
   gg.DrawString 300, 30, "第" & currentLevelNum + 1 & "关"
   gg.Font "黑体", 11
   gg.DrawString 265, 230, "按空格键重玩当前关"
   If (achievedNum = targetNum) And currentLevelNum = LEVEL_TOTALNUM-1  Then ' 如果完成目标个数等于目标个数
      gg.Font "黑体", 30
      gg.SetColor BGR(0, 255, 255) 'GDI的颜色值。
      gg.DrawString 15, 100, "游 戏 胜 利"
   End If
   gg.Redraw
End Sub

Sub updateWithoutInput() '与输入无关的更新

   Sleep 10 '暂停若干毫秒
End Sub
Sub updateWithInput(hWndForm As hWnd, gg As ygdi) ' 和输入有关的更新
   Static pp As Long '预防一直按下,造成一直移动
   If pp = 1 Then
      If IsKeyPress(&H57) = 0 And IsKeyPress(&H53) = 0 And IsKeyPress(&H41) = 0 And IsKeyPress(&H44) = 0 And IsKeyPress(VK_SPACE) = 0 Then
         pp = 0
      End If
   Else
      If IsKeyPress(VK_SPACE) Then
         pp = 1
         startup()
         Return 
      ElseIf IsKeyPress(&H57) Then ' 上
         pp = 1
      ElseIf IsKeyPress(&H53) Then ' 下
         pp = 1
      ElseIf IsKeyPress(&H41) Then ' 左
         pp = 1
      ElseIf IsKeyPress(&H44) Then '  右
         pp = 1
      End If
      If pp = 1 Then
         Dim goal_i     As Long = players.i ' 移动的目标位置
         Dim goal_j     As Long = players.j
         Dim goalNext_i As Long = goal_i '目标位置再向前的一个位置
         Dim goalNext_j As Long = goal_j
         ' 根据用户的不同按键输入,获得目标位置、再向前的一个位置
         If IsKeyPress(&H57) Then ' 上
            goal_i     = Players.i - 1 ' 目标位置在玩家位置的下边
            goalNext_i = goal_i    - 1 ' 目标的下一个位置,在其再下边
         ElseIf IsKeyPress(&H53) Then ' 下
            goal_i     = Players.i + 1 ' 目标位置在玩家位置的下边
            goalNext_i = goal_i    + 1 ' 目标的下一个位置,在其再下边
         ElseIf IsKeyPress(&H41) Then ' 左
            goal_j     = Players.j -1 ' 目标位置在玩家位置的左边
            goalNext_j = goal_j -1    ' 目标的下一个位置,在其再左边
         ElseIf IsKeyPress(&H44) Then '  右
            goal_j     = Players.j + 1 ' 目标位置在玩家位置的右边
            goalNext_j = goal_j    + 1 ' 目标的下一个位置,在其再右边
         End If
         '根据不同地图元素的情况,判断如何移动角色和更新地图元素
         If Mid(level(goal_i), goal_j + 1, 1) = "e" Or Mid(level(goal_i), goal_j + 1, 1) = "t" Then
            '如果目标位置是empty,或者target
            Players.i = goal_i
            Players.j = goal_j
         ElseIf Mid(level(goal_i), goal_j + 1, 1) = "b" And Mid(level(goalNext_i), goalNext_j + 1, 1) = "e" Then
            ' 如果目标位置是box,再前面一个是empty
            Players.i = goal_i ' 玩家移动到目标位置
            Players.j = goal_j
            Mid(level(goal_i), goal_j + 1, 1)         = "e" ' 目标位置变成empty
            Mid(level(goalNext_i), goalNext_j + 1, 1) = "b" ' 再前面变成box
         ElseIf Mid(level(goal_i), goal_j + 1, 1) = "b" And Mid(level(goalNext_i), goalNext_j + 1, 1) = "t" Then
            ' 如果目标位置是box,再前面一个是target
            Players.i = goal_i ' 玩家移动到目标位置
            Players.j = goal_j
            Mid(level(goal_i), goal_j + 1, 1)         = "e" ' 目标位置变成empty
            Mid(level(goalNext_i), goalNext_j + 1, 1) = "a" '再前面变成achieved
         ElseIf Mid(level(goal_i), goal_j + 1, 1) = "a" And Mid(level(goalNext_i), goalNext_j + 1, 1) = "e" Then
            '如果目标位置是achieved,再前面一个是empty
            Players.i = goal_i ' 玩家移动到目标位置
            Players.j = goal_j
            Mid(level(goal_i), goal_j + 1, 1)         = "t" ' 目标位置变成target
            Mid(level(goalNext_i), goalNext_j + 1, 1) = "b" ' 再前面变成box
         ElseIf Mid(level(goal_i), goal_j + 1, 1) = "a" And Mid(level(goalNext_i), goalNext_j + 1, 1) = "t" Then
            '如果目标位置是achieved,再前面一个是target
            Players.i = goal_i ' 玩家移动到目标位置
            Players.j = goal_j
            Mid(level(goal_i), goal_j + 1, 1)         = "t" ' 目标位置变成target
            Mid(level(goalNext_i), goalNext_j + 1, 1) = "a" ' 再前面变成achieved
         Else '其他情况都推不动
            Return ' 不做任何处理,函数直接返回
         End If
         Dim i As Long, j As Long
         achievedNum = 0 ' 完成目标个数,初始为0
         For i = 0 To B_NUM -1 '遍历关卡二维数组数据
            For j = 0 To B_NUM -1
               If Mid(level(i), j + 1, 1) = "a" Then ' 如果元素是achieved
                  achievedNum += 1 '完成目标个数+1
                  If (achievedNum = targetNum) Then ' 如果完成当前关卡了
                     If (currentLevelNum < LEVEL_TOTALNUM -1) Then
                        currentLevelNum += 1 ' 进入下一关
                        achievedNum =0 
                        startup() ' 开始下一关卡的初始化
                     End If
                  End If
               End If
            Next
         Next
      End If
   End If
End Sub
Sub 游戏执行过程(hWndForm As hWnd)
   Dim gg As yGDI = hWndForm
   startup()
   Do
      show(gg)
      updateWithInput(hWndForm, gg)
      updateWithoutInput()
   Loop

End Sub

评论一下?

OωO
取消