为了实现多个关卡的游戏,首先利用宏定义设定关卡数目:
#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
评论一下?