少儿编程教学:手把手教你用Python编写推星星游戏(三)
游戏分享:手把手教你用Python编写推星星
游戏(三)
2017.12.06
这一部分游戏代码较多
理解起来也有点难
学习一定要给自己充分的缓冲时间
不要拿兴趣做牺牲
122.
123.def runLevel(levels,levelNum):
124.global currentImage
125.levelObj=levels[levelnum]
126.mapObj=decorateMap(levelObj['mapObj'],levelObj['startState']['player']) 127.gameStateObj=copy.deepcopy(levelObj['startState'])
关卡列表包括所有从关卡文件里读取的关卡。当前关卡对象(levelNum设定的)将储存在levelObj变量里。一个对象映射(区分地图内外方块以及装饰)将由函数decorateMap()反馈。而为了监测玩家所玩关卡的游戏状态,我们可以通过copy.deepcopy()函数从levelObj中复制一个游戏状态的对象用以监测。
复制游戏状态对象是因为储存在levelObj[‘startState’]中的对象意味着游戏刚开始的状态,而我们并不需要去修改它。而如果我们修改了,玩家在重启关卡时将无法读取初始游戏状态。
在这里使用copy.deepcopy()函数因为游戏状态对象是一个包含元组的字典。在这里使用一个命令语句来复制字典,我们所得到的不是字典所引用的值而是字典引用的对象。所以复制和初始的库仍将引用相同的元组。
copy.deepcopy()函数通过复制字典里确实存在的元组来解决这一问题。通过这个方法我们能保证在改变单个字典时不会对另一个字典造成影响。
(推星星第一关)
128.mapNeedsRedraw=True#设置为True来调用drawmap()
129.levelSurf=BASICFONT.render('Level%s of%s'%
(levelObj['levelNum']+1,totalNumOfLevels),1,TEXTCOLOR)
130.levelRect=levelSurf.get_rect()
131.levelRect.bottomleft=(20,WINHEIGHT-35)
132.mapWidth=len(mapObj)*TILEWIDTH
133.mapHeight=(len(mapObj[0])-1)*(TILEHEIGHT-TILEFLOORHEIGHT)+TILEHEIGHT
134.MAX_CAM_X_PAN=abs(HALF_WINHEIGHT-int(mapHeight/2))+ TILEWIDTH
135.MAX_CAM_Y_PAN=abs(HALF_WINWIDTH-int(mapWidth/2))+ TILEHEIGHT
136.
137.levelIsComplete=False
138.#跟踪镜头的移动
139.cameraOffsetX=0
140.cameraOffsetY=0
141.#监测是否按下了移动镜头的键
142.cameraUp=False
143.cameraDown=False
144.cameraLeft=False
145.cameraRight=False
现在更多变量将在关卡开始前设置好。
mapWidth和mapHeight变量是用像素来设置地图大小的变量。
用来计算mapHeight的表达式有一点复杂因为所有方块互相重合。只有底排的方块能展示完整的高度(所以加上了TILEHEIGHT这段表达式),而其他所有排的方块((len(mapObj[0]-1)))都有一部分重合。
这意味着他们都(TILEHEIGHT-TILEFLOORHEIGHT)像素高。
而在推星星游戏中的镜头可以随着玩家的控制独立移动。这也是为什么镜头需要它自己的移动变量cameraUp,cameraDown,cameraLeft,和cameraRight. cameraOffsetX和cameraOffsetY变量监测镜头的位置。
147.while True:#主要游戏循环
148.#重设变量:
149.playerMoveTo=None
150.keyPressed=False
151.
152.for event in pygame.event.get():#处理其他情况的循环
153.if event.type==QUIT:
154.#玩家按下游戏窗口的右上角的X
155.terminate()
156.
playerMoveTo变量将设置为玩家想要控制角色移动方向的方向常量。keyPressed变量监测在游戏循环中是否有任意一个键是按下的,而这个变量将在玩家通过关卡后检查。
157.elif event.type==KEYDOWN:
158.#处理按键
159.keyPressed=True
160.if event.key==K_LEFT:
161.playerMoveTo=LEFT
162.elif event.key==K_RIGHT:
163.playerMoveTo=RIGHT
164.elif event.key==K_UP:
165.playerMoveTo=UP
166.elif event.key==K_DOWN:
167.playerMoveTo=DOWN
168.
169.#设定镜头移动模式.
170.elif event.key==K_a:
171.cameraLeft=True
172.elif event.key==K_d:
173.cameraRight=True
174.elif event.key==K_w:
175.cameraUp=True
176.elif event.key==K_s:
177.cameraDown=True
178.
179.elif event.key==K_n:
180.return'next'
181.elif event.key==K_b:
182.return'back'
183.
184.elif event.key==K_ESCAPE:
185.terminate()#ESC=关闭.
186.elif event.key==K_BACKSPACE:
187.return'reset'#重启关卡.
188.elif event.key==K_p:
189.#更改为下一个角色图片
190.currentImage+=1
191.if currentImage>=len(PLAYERIMAGES):
192.#在使用最后一个玩家图片时选择更换将返回第一张193.currentImage=0
194.mapNeedsRedraw=True
195.
196.elif event.type==KEYUP:
197.#重设镜头移动模式
198.if event.key==K_a:
199.cameraLeft=False
200.elif event.key==K_d:
201.cameraRight=False
202.elif event.key==K_w:
203.cameraUp=False
204.elif event.key==K_s:
205.cameraDown=False
这段代码将处理多个按键一起按下的情况
207.if playerMoveTo!=None and not levelIsComplete:
208.#随着玩家按键而移动
209.#推动所有可推动的星星.
210.moved=makeMove(mapObj,gameStateObj,playerMoveTo) 211.
212.if moved:
213.#记录移动步数.
214.gameStateObj['stepCounter']+=1
215.mapNeedsRedraw=True
216.
217.if isLevelFinished(levelObj,gameStateObj):
218.#当关卡通关时显示solve画面
219.levelIsComplete=True
220.keyPressed=False
如果playerMoveTo变量没有设置为None,那么我们就能知道玩家想要移动。这时调用函数makeMove()来改变玩家所控制的角色在gameStateObj中的XY坐标,包括推动星星。
而makeMove()的反馈值将储存在moved中。如果这个值是True,那么玩家的角色将会向所按方向键移动,反之则玩家移动的方向有障碍物。
(未完待续)