Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码

_本文原始标题:Python玩出花儿了!一文教你用Python制作吃豆人游戏!|附代码
Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码
文章图片

作者|李秋键
责编|Carol
封图|CSDN下载自视觉中国
近几年来Python语言得到了快速发展 , 而Pygame作为Python开发应用和游戏必备的库更是展现了Python的优越性 。
而今天我们就将借助Pygame建立吃豆人游戏 。
Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码
文章图片

吃豆人是电子游戏历史上的经典街机游戏 , 由Namco公司的岩谷彻设计并由MidwayGames在1980年发行 。 Pac-Man被认为是80年代最经典的街机游戏之一 , 游戏的主角小精灵的形象甚至被作为一种大众文化符号 , 或是此产业的代表形象 。
而Pygame模块是跨平台Python模块 , 专为电子游戏设计 , 包含图像、声音 。 建立在SDL基础上 , 允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚 。
最终游戏效果如下可见:
Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码
文章图片

一、实验前的准备
首先我们使用的python版本是3.6.5所用到的模块是pygame模块 , 用来创建游戏框架 。 Random模块用来随机生成方向 。
素材准备
首先我们将图片放到images目录下 , 背景音乐放到sounds目录下 。
如下图可见:
Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码
文章图片

游戏搭建
1、定义一些精灵:
整体的类变量定义包括墙类 , 通过pygame的图片填充作为墙类的加载;同理还包括食物类和角色 。 而怪物的随机运动使用random产生随机运动方向 。
其对应的代码如下:
importrandom
importpygame
'''墙类'''
classWall(pygame.sprite.Sprite):
def__init__(self,x,y,width,height,color,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.Surface([width,height])
self.image.fill(color)
self.rect=self.image.get_rect
self.rect.left=x
self.rect.top=y
'''食物类'''
classFood(pygame.sprite.Sprite):
def__init__(self,x,y,width,height,color,bg_color,**kwargs):
pygame.sprite.Sprite.__init__(self)
self.image=pygame.Surface([width,height])
self.image.fill(bg_color)
self.image.set_colorkey(bg_color)
pygame.draw.ellipse(self.image,color,[0,0,width,height])
self.rect=self.image.get_rect
self.rect.left=x
self.rect.top=y
'''角色类'''
classPlayer(pygame.sprite.Sprite):
def__init__(self,x,y,role_image_path):
pygame.sprite.Sprite.__init__(self)
self.role_name=role_image_path.split('/')[-1].split('.')[0]
self.base_image=pygame.image.load(role_image_path).convert
self.image=self.base_image.copy
self.rect=self.image.get_rect
self.rect.left=x
self.rect.top=y
self.prev_x=x
self.prev_y=y
self.base_speed=[30,30]
self.speed=[0,0]
self.is_move=False
self.tracks=[]
self.tracks_loc=[0,0]
'''改变速度方向'''
defchangeSpeed(self,direction):
ifdirection[0]<0:
self.image=pygame.transform.flip(self.base_image,True,False)
elifdirection[0]>0:
self.image=self.base_image.copy
elifdirection[1]<0:
self.image=pygame.transform.rotate(self.base_image,90)
elifdirection[1]>0:
self.image=pygame.transform.rotate(self.base_image,-90)
self.speed=[direction[0]*self.base_speed[0],direction[1]*self.base_speed[1]]
returnself.speed
'''更新角色位置'''
defupdate(self,wall_sprites,gate_sprites):
ifnotself.is_move:
returnFalse
x_prev=self.rect.left
y_prev=self.rect.top
self.rect.left+=self.speed[0]
self.rect.top+=self.speed[1]
is_collide=pygame.sprite.spritecollide(self,wall_sprites,False)
ifgate_spritesisnotNone:
ifnotis_collide:
is_collide=pygame.sprite.spritecollide(self,gate_sprites,False)
ifis_collide:
self.rect.left=x_prev
self.rect.top=y_prev
returnFalse
returnTrue
'''生成随机的方向'''
defrandomDirection(self):
returnrandom.choice([[-0.5,0],[0.5,0],[0,0.5],[0,-0.5]])
2、游戏关卡定义:
在这里设置好了关卡一 。 关卡的定义必须包括墙的位置 , 不同关卡墙的位置和怪物的位置不同 。 更多关卡可以参照设置
对应代码如下:
importpygame
fromSpritesimport*
NUMLEVELS=1
【Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码】'''关卡一'''
classLevel1:
def__init__(self):
self.info='level1'
'''创建墙'''
defsetupWalls(self,wall_color):
self.wall_sprites=pygame.sprite.Group
wall_positions=[[0,0,6,600],
[0,0,600,6],
[0,600,606,6],
[600,0,6,606],
[300,0,6,66],
[60,60,186,6],
[360,60,186,6],
[60,120,66,6],
[60,120,6,126],
[180,120,246,6],
[300,120,6,66],
[480,120,66,6],
[540,120,6,126],
[120,180,126,6],
[120,180,6,126],
[360,180,126,6],
[480,180,6,126],
[180,240,6,126],
[180,360,246,6],
[420,240,6,126],
[240,240,42,6],
[324,240,42,6],
[240,240,6,66],
[240,300,126,6],
[360,240,6,66],
[0,300,66,6],
[540,300,66,6],
[60,360,66,6],
[60,360,6,186],
[480,360,66,6],
[540,360,6,186],
[120,420,366,6],
[120,420,6,66],
[480,420,6,66],
[180,480,246,6],
[300,480,6,66],
[120,540,126,6],
[360,540,126,6]]
forwall_positioninwall_positions:
wall=Wall(*wall_position,wall_color)
self.wall_sprites.add(wall)
returnself.wall_sprites
'''创建门'''
defsetupGate(self,gate_color):
self.gate_sprites=pygame.sprite.Group
self.gate_sprites.add(Wall(282,242,42,2,gate_color))
returnself.gate_sprites
'''创建角色'''
defsetupPlayers(self,hero_image_path,ghost_images_path):
self.hero_sprites=pygame.sprite.Group
self.ghost_sprites=pygame.sprite.Group
self.hero_sprites.add(Player(287,439,hero_image_path))
foreachinghost_images_path:
role_name=each.split('/')[-1].split('.')[0]
ifrole_name=='Blinky':
player=Player(287,199,each)
player.is_move=True
player.tracks=[[0,-0.5,4],[0.5,0,9],[0,0.5,11],[0.5,0,3],[0,0.5,7],[-0.5,0,11],[0,0.5,3],
[0.5,0,15],[0,-0.5,15],[0.5,0,3],[0,-0.5,11],[-0.5,0,3],[0,-0.5,11],[-0.5,0,3],
[0,-0.5,3],[-0.5,0,7],[0,-0.5,3],[0.5,0,15],[0,0.5,15],[-0.5,0,3],[0,0.5,3],
[-0.5,0,3],[0,-0.5,7],[-0.5,0,3],[0,0.5,7],[-0.5,0,11],[0,-0.5,7],[0.5,0,5]]
self.ghost_sprites.add(player)
elifrole_name=='Clyde':
player=Player(319,259,each)
player.is_move=True
player.tracks=[[-1,0,2],[0,-0.5,4],[0.5,0,5],[0,0.5,7],[-0.5,0,11],[0,-0.5,7],
[-0.5,0,3],[0,0.5,7],[-0.5,0,7],[0,0.5,15],[0.5,0,15],[0,-0.5,3],
[-0.5,0,11],[0,-0.5,7],[0.5,0,3],[0,-0.5,11],[0.5,0,9]]
self.ghost_sprites.add(player)
elifrole_name=='Inky':
player=Player(255,259,each)
player.is_move=True
player.tracks=[[1,0,2],[0,-0.5,4],[0.5,0,10],[0,0.5,7],[0.5,0,3],[0,-0.5,3],
[0.5,0,3],[0,-0.5,15],[-0.5,0,15],[0,0.5,3],[0.5,0,15],[0,0.5,11],
[-0.5,0,3],[0,-0.5,7],[-0.5,0,11],[0,0.5,3],[-0.5,0,11],[0,0.5,7],
[-0.5,0,3],[0,-0.5,3],[-0.5,0,3],[0,-0.5,15],[0.5,0,15],[0,0.5,3],
[-0.5,0,15],[0,0.5,11],[0.5,0,3],[0,-0.5,11],[0.5,0,11],[0,0.5,3],[0.5,0,1]]
self.ghost_sprites.add(player)
elifrole_name=='Pinky':
player=Player(287,259,each)
player.is_move=True
player.tracks=[[0,-1,4],[0.5,0,9],[0,0.5,11],[-0.5,0,23],[0,0.5,7],[0.5,0,3],
[0,-0.5,3],[0.5,0,19],[0,0.5,3],[0.5,0,3],[0,0.5,3],[0.5,0,3],
[0,-0.5,15],[-0.5,0,7],[0,0.5,3],[-0.5,0,19],[0,-0.5,11],[0.5,0,9]]
self.ghost_sprites.add(player)
returnself.hero_sprites,self.ghost_sprites
'''创建食物'''
defsetupFood(self,food_color,bg_color):
self.food_sprites=pygame.sprite.Group
forrowinrange(19):
forcolinrange(19):
if(row==7orrow==8)and(col==8orcol==9orcol==10):
continue
else:
food=Food(30*col+32,30*row+32,4,4,food_color,bg_color)
is_collide=pygame.sprite.spritecollide(food,self.wall_sprites,False)
ifis_collide:
continue
is_collide=pygame.sprite.spritecollide(food,self.hero_sprites,False)
ifis_collide:
continue
self.food_sprites.add(food)
returnself.food_sprites
3、游戏创建:
在通过关卡定义墙等位置后以及精灵自身属性怪物运动、食物定义等后 , 通过调用已经创建好的类达到搭建游戏的目的 。
具体如下可见:
importos
importsys
importpygame
importLevels
'''定义一些必要的参数'''
BLACK=(0,0,0)
WHITE=(255,255,255)
BLUE=(0,0,255)
GREEN=(0,255,0)
RED=(255,0,0)
YELLOW=(255,255,0)
PURPLE=(255,0,255)
SKYBLUE=(0,191,255)
BGMPATH=os.path.join(os.getcwd,'resources/sounds/bg.mp3')
ICONPATH=os.path.join(os.getcwd,'resources/images/icon.png')
FONTPATH=os.path.join(os.getcwd,'resources/font/ALGER.TTF')
HEROPATH=os.path.join(os.getcwd,'resources/images/pacman.png')
BlinkyPATH=os.path.join(os.getcwd,'resources/images/Blinky.png')
ClydePATH=os.path.join(os.getcwd,'resources/images/Clyde.png')
InkyPATH=os.path.join(os.getcwd,'resources/images/Inky.png')
PinkyPATH=os.path.join(os.getcwd,'resources/images/Pinky.png')
'''开始某一关游戏'''
defstartLevelGame(level,screen,font):
clock=pygame.time.Clock
SCORE=0
wall_sprites=level.setupWalls(SKYBLUE)
gate_sprites=level.setupGate(WHITE)
hero_sprites,ghost_sprites=level.setupPlayers(HEROPATH,[BlinkyPATH,ClydePATH,InkyPATH,PinkyPATH])
food_sprites=level.setupFood(YELLOW,WHITE)
is_clearance=False
whileTrue:
foreventinpygame.event.get:
ifevent.type==pygame.QUIT:
sys.exit(-1)
pygame.quit
ifevent.type==pygame.KEYDOWN:
ifevent.key==pygame.K_LEFT:
forheroinhero_sprites:
hero.changeSpeed([-1,0])
hero.is_move=True
elifevent.key==pygame.K_RIGHT:
forheroinhero_sprites:
hero.changeSpeed([1,0])
hero.is_move=True
elifevent.key==pygame.K_UP:
forheroinhero_sprites:
hero.changeSpeed([0,-1])
hero.is_move=True
elifevent.key==pygame.K_DOWN:
forheroinhero_sprites:
hero.changeSpeed([0,1])
hero.is_move=True
ifevent.type==pygame.KEYUP:
if(event.key==pygame.K_LEFT)or(event.key==pygame.K_RIGHT)or(event.key==pygame.K_UP)or(event.key==pygame.K_DOWN):
hero.is_move=False
screen.fill(BLACK)
forheroinhero_sprites:
hero.update(wall_sprites,gate_sprites)
hero_sprites.draw(screen)
forheroinhero_sprites:
food_eaten=pygame.sprite.spritecollide(hero,food_sprites,True)
SCORE+=len(food_eaten)
wall_sprites.draw(screen)
gate_sprites.draw(screen)
food_sprites.draw(screen)
forghostinghost_sprites:
#幽灵随机运动(效果不好且有BUG)
'''
res=ghost.update(wall_sprites,None)
whilenotres:
ghost.changeSpeed(ghost.randomDirection)
res=ghost.update(wall_sprites,None)
'''
#指定幽灵运动路径
ifghost.tracks_loc[1]<ghost.tracks[ghost.tracks_loc[0]][2]:
ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0:2])
ghost.tracks_loc[1]+=1
else:
ifghost.tracks_loc[0]<len(ghost.tracks)-1:
ghost.tracks_loc[0]+=1
elifghost.role_name=='Clyde':
ghost.tracks_loc[0]=2
else:
ghost.tracks_loc[0]=0
ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0:2])
ghost.tracks_loc[1]=0
ifghost.tracks_loc[1]<ghost.tracks[ghost.tracks_loc[0]][2]:
ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0:2])
else:
ifghost.tracks_loc[0]<len(ghost.tracks)-1:
loc0=ghost.tracks_loc[0]+1
elifghost.role_name=='Clyde':
loc0=2
else:
loc0=0
ghost.changeSpeed(ghost.tracks[loc0][0:2])
ghost.update(wall_sprites,None)
ghost_sprites.draw(screen)
score_text=font.render("Score:%s"%SCORE,True,RED)
screen.blit(score_text,[10,10])
iflen(food_sprites)==0:
is_clearance=True
break
ifpygame.sprite.groupcollide(hero_sprites,ghost_sprites,False,False):
is_clearance=False
break
pygame.display.flip
clock.tick(10)
returnis_clearance
'''显示文字'''
defshowText(screen,font,is_clearance,flag=False):
clock=pygame.time.Clock
msg='GameOver!'ifnotis_clearanceelse'Congratulations,youwon!'
positions=[[235,233],[65,303],[170,333]]ifnotis_clearanceelse[[145,233],[65,303],[170,333]]
surface=pygame.Surface((400,200))
surface.set_alpha(10)
surface.fill((128,128,128))
screen.blit(surface,(100,200))
texts=[font.render(msg,True,WHITE),
font.render('PressENTERtocontinueorplayagain.',True,WHITE),
font.render('PressESCAPEtoquit.',True,WHITE)]
whileTrue:
foreventinpygame.event.get:
ifevent.type==pygame.QUIT:
sys.exit
pygame.quit
ifevent.type==pygame.KEYDOWN:
ifevent.key==pygame.K_RETURN:
ifis_clearance:
ifnotflag:
return
else:
main(initialize)
else:
main(initialize)
elifevent.key==pygame.K_ESCAPE:
sys.exit
pygame.quit
foridx,(text,position)inenumerate(zip(texts,positions)):
screen.blit(text,position)
pygame.display.flip
clock.tick(10)
'''初始化'''
definitialize:
pygame.init
icon_image=pygame.image.load(ICONPATH)
pygame.display.set_icon(icon_image)
screen=pygame.display.set_mode([606,606])
pygame.display.set_caption('吃豆人')
returnscreen
'''主函数'''
defmain(screen):
pygame.mixer.init
pygame.mixer.music.load(BGMPATH)
pygame.mixer.music.play(-1,0.0)
pygame.font.init
font_small=pygame.font.Font(FONTPATH,18)
font_big=pygame.font.Font(FONTPATH,24)
fornum_levelinrange(1,Levels.NUMLEVELS+1):
ifnum_level==1:
level=Levels.Level1
is_clearance=startLevelGame(level,screen,font_small)
ifnum_level==Levels.NUMLEVELS:
showText(screen,font_big,is_clearance,True)
else:
showText(screen,font_big,is_clearance)
最终运行程序结果如下:
Python 玩出花儿了!一文教你用 Python 制作吃豆人游戏! | 附代码
文章图片

源码地址:
https://pan.baidu.com/s/128id8L-PDPgGOPuH-5uHDg
提取码:rj9f
作者简介:
李秋键 , CSDN博客专家 , CSDN达人课作者 。 硕士在读于中国矿业大学 , 开发有taptap竞赛获奖等等 。


    推荐阅读