坐标、地图、关卡、游戏状态
是不是已经要晕了?
一定要搞清楚弄明白才行
代码部分
469. #循环通过搜索地图上方块
470. # 并找到@,.,和$字符来初始化游戏状态
471. startx = None # 这里的XY代表玩家的初始坐标
472. starty = None
473. goals = [] # 这里的xy元组列表是每个星标方块的坐标
474. stars = [] # 这是每个星星的初始坐标
475. for x in range(maxWidth):
476. for y in range(len(mapObj[x])):
477. if mapObj[x][y] in ('@', '+'):
478. # & goal @是玩家 +是玩家和星标方块
479. startx = x
480. starty = y
481. if mapObj[x][y] in ('.', '+', '*'):
482. # .是星标方块,*是星星和星标方块
483. goals.append((x, y))
484. if mapObj[x][y] in ('$', '*'):
485. # $是星星
486. stars.append((x, y))
在创建地图对象后,475和476行的嵌套循环将检查每个方块的XY坐标来了解一下三件事情:
1. 玩家的初始位置。这将储存在startx和starty变量里,这将在494行储存进游戏状态对象里。
2. 所有星星的初始位置。这将储存进stars列表里,在496行时储存进游戏状态对象里。
3. 所有星标方块的位置。储存进goals列表,在500行储存进关卡对象中。
记住,游戏状态对象包含了所有可以改变的对象。这也是为什么玩家和星星的坐标储存在其中(因为玩家和星星的坐标将移动),所以不可移动的星标方块的坐标储存在关卡对象里。
488. # 基础断言检查:
489. assert startx != None and starty != None, 'Level %s (around line %s) in %s is missing a "@" or "+" to mark the start point.' % (levelNum+1, lineNum, filename)
490. assert len(goals) > 0, 'Level %s (around line %s) in %s must have at least one goal.' % (levelNum+1, lineNum, filename)
491. assert len(stars) >= len(goals), 'Level %s (around line %s) in %s is impossible to solve. It has %s goals but only %s stars.' % (levelNum+1, lineNum, filename, len(goals), len(stars))
这时,关卡已经被写入和处理过了。为了保证关卡可以运行,代码必须通过一些断言。如果这些断言反馈False,那么python将会出现错误并告知你关卡文件的错误在哪里。
489行的第一个断言是检查玩家坐标是否在地图内。第二个断言是检查在地图上是否至少有一个星标方块。第三个断言是确认星星和星标方块的数量是否对等(星星的数量超过星标方块是允许的)
493. # 创建关卡对象并启动游戏状态对象
494. gameStateObj = {'player': (startx, starty),
495. 'stepCounter': 0,
496. 'stars': stars}
497. levelObj = {'width': maxWidth,
498. 'height': len(mapObj),
499. 'mapObj': mapObj,
500. 'goals': goals,
501. 'startState': gameStateObj}
502.
503. levels.append(levelObj)
最终这些对象将储存在游戏状态对象中,而这些对象也会储存在关卡对象中。而这个关卡对象将在503行储存到关卡对象列表里。当所有地图处理完毕,levels列表将通过readLevelsFile()函数返回值。
506. mapTextLines = []
507. mapObj = []
508. gameStateObj = {}
509. levelNum += 1
510. return levels
现在这关的地图已经冲力完毕,mapTextLines,mapObj和gameStateObj这些变量应设为空白以储存下一关的值。levelNum变量也要增加1。
513. def floodFill(mapObj, x, y, oldCharacter, newCharacter):
514. """将所有在地图上符合旧字符的值的对象
515. 替换到新字符的位置
516.
517.
518. # 游戏中,泛洪填充算法区分了内外方块
519. #这是一个递归函数
520.
521.
522. if mapObj[x][y] == oldCharacter:
523. mapObj[x][y] = newCharacter
行522和523将传递给floodFill()的XY坐标的图块转换为newCharacter字符串,与原来的oldCharacter字符串相同。
525. if x < len(mapObj) - 1 and mapObj[x+1][y] == oldCharacter:
526. floodFill(mapObj, x+1, y, oldCharacter, newCharacter) # 右
527. if x > 0 and mapObj[x-1][y] == oldCharacter:
528. floodFill(mapObj, x-1, y, oldCharacter, newCharacter) # 左
529. if y < len(mapObj[x]) - 1 and mapObj[x][y+1] == oldCharacter:
530. floodFill(mapObj, x, y+1, oldCharacter, newCharacter) # 下
531. if y > 0 and mapObj[x][y-1] == oldCharacter:
532. floodFill(mapObj, x, y-1, oldCharacter, newCharacter) # 上
这四个if语句是检查方块和oldCharacter中的方块XY坐标是否相同,如果是,将用递归函数更改坐标。
(未完待续)