Python游戏开发,pygame模块,Python实现炸弹人小游戏
Posted 小雁子学Python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python游戏开发,pygame模块,Python实现炸弹人小游戏相关的知识,希望对你有一定的参考价值。
往期回顾
前言
今天用Python实现的是一个炸弹人小游戏,废话不多说,让我们愉快地开始吧~
效果展示
开发工具
Python版本: 3.6.4
相关模块:
pygame模块;
以及一些Python自带的模块。
环境搭建
安装Python并添加到环境变量,pip安装需要的相关模块即可。
原理简介
游戏规则:
玩家通过↑↓←→键控制角色zelda(绿色)行动,当玩家按下空格键时,则可以在当前位置放置炸弹。其他角色(dk和batman)则由电脑控制进行随机行动。所有角色被炸弹产生的火焰灼烧时(包括自己放置的炸弹),都将损失一定生命值;所有角色吃到水果时,均可恢复一定数值的生命值。另外,墙可以阻止炸弹产生的火焰进一步扩散。
当我方角色zelda生命值为0时,游戏失败;当电脑方所有角色生命值为0时,游戏胜利,进入下一关。
逐步实现:
首先,我们来明确一下该游戏包含哪些游戏精灵类:
-
炸弹类
-
角色类
-
墙类
-
背景类
-
水果类
墙类和背景类很好定义,只需要可以导入图片,然后把图片绑定到指定位置就行了:
'''墙类'''
class Wall(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''画到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
'''背景类'''
class Background(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''画到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
水果类定义其实也差不多,但是不同的水果可以帮助角色恢复不同数值的生命值:
'''水果类'''
class Fruit(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.kind = imagepath.split('/')[-1].split('.')[0]
if self.kind == 'banana':
self.value = 5
elif self.kind == 'cherry':
self.value = 10
else:
raise ValueError('Unknow fruit <%s>...' % self.kind)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
'''画到屏幕上'''
def draw(self, screen):
screen.blit(self.image, self.rect)
return True
炸弹类和角色类的定义就稍稍复杂一些了。角色类需要根据玩家或者电脑的指示上下左右移动,同时可以在自己的位置上产生炸弹以及吃水果之后恢复一定数值的生命值:
'''角色类'''
class Hero(pygame.sprite.Sprite):
def __init__(self, imagepaths, coordinate, blocksize, map_parser, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.imagepaths = imagepaths
self.image = pygame.image.load(imagepaths[-1])
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.rect = self.image.get_rect()
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
self.coordinate = coordinate
self.blocksize = blocksize
self.map_parser = map_parser
self.hero_name = kwargs.get('hero_name')
# 生命值
self.health_value = 50
# 炸弹冷却时间
self.bomb_cooling_time = 5000
self.bomb_cooling_count = 0
# 随机移动冷却时间(仅AI电脑用)
self.randommove_cooling_time = 100
self.randommove_cooling_count = 0
'''角色移动'''
def move(self, direction):
self.__updateImage(direction)
if direction == 'left':
if self.coordinate[0]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0]-1, self.coordinate[1]]) in ['w', 'x', 'z']:
return False
self.coordinate[0] = self.coordinate[0] - 1
elif direction == 'right':
if self.coordinate[0]+1 >= self.map_parser.width or self.map_parser.getElemByCoordinate([self.coordinate[0]+1, self.coordinate[1]]) in ['w', 'x', 'z']:
return False
self.coordinate[0] = self.coordinate[0] + 1
elif direction == 'up':
if self.coordinate[1]-1 < 0 or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]-1]) in ['w', 'x', 'z']:
return False
self.coordinate[1] = self.coordinate[1] - 1
elif direction == 'down':
if self.coordinate[1]+1 >= self.map_parser.height or self.map_parser.getElemByCoordinate([self.coordinate[0], self.coordinate[1]+1]) in ['w', 'x', 'z']:
return False
self.coordinate[1] = self.coordinate[1] + 1
else:
raise ValueError('Unknow direction <%s>...' % direction)
self.rect.left, self.rect.top = self.coordinate[0] * self.blocksize, self.coordinate[1] * self.blocksize
return True
'''随机行动(AI电脑用)'''
def randomAction(self, dt):
# 冷却倒计时
if self.randommove_cooling_count > 0:
self.randommove_cooling_count -= dt
action = random.choice(['left', 'left', 'right', 'right', 'up', 'up', 'down', 'down', 'dropbomb'])
flag = False
if action in ['left', 'right', 'up', 'down']:
if self.randommove_cooling_count <= 0:
flag = True
self.move(action)
self.randommove_cooling_count = self.randommove_cooling_time
elif action in ['dropbomb']:
if self.bomb_cooling_count <= 0:
flag = True
self.bomb_cooling_count = self.bomb_cooling_time
return action, flag
'''生成炸弹'''
def generateBomb(self, imagepath, digitalcolor, explode_imagepath):
return Bomb(imagepath=imagepath, coordinate=copy.deepcopy(self.coordinate), blocksize=self.blocksize, digitalcolor=digitalcolor, explode_imagepath=explode_imagepath)
'''画到屏幕上'''
def draw(self, screen, dt):
# 冷却倒计时
if self.bomb_cooling_count > 0:
self.bomb_cooling_count -= dt
screen.blit(self.image, self.rect)
return True
'''吃水果'''
def eatFruit(self, fruit_sprite_group):
eaten_fruit = pygame.sprite.spritecollide(self, fruit_sprite_group, True, None)
for fruit in eaten_fruit:
self.health_value += fruit.value
'''更新角色朝向'''
def __updateImage(self, direction):
directions = ['left', 'right', 'up', 'down']
idx = directions.index(direction)
self.image = pygame.image.load(self.imagepaths[idx])
self.image = pygame.transform.scale(self.image, (self.blocksize, self.blocksize))
炸弹类则需要有倒计时提示功能,以及倒计时结束之后在炸弹杀伤范围内产生火焰特效(穷,估计只值1毛钱的特效T_T,大家多担待):
'''炸弹类'''
class Bomb(pygame.sprite.Sprite):
def __init__(self, imagepath, coordinate, blocksize, digitalcolor, explode_imagepath, **kwargs):
pygame.sprite.Sprite.__init__(self)
self.image = pygame.image.load(imagepath)
self.image = pygame.transform.scale(self.image, (blocksize, blocksize))
self.explode_imagepath = explode_imagepath
self.rect = self.image.get_rect()
# 像素位置
self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize
# 坐标(元素块为单位长度)
self.coordinate = coordinate
self.blocksize = blocksize
# 爆炸倒计时
self.explode_millisecond = 6000 * 1 - 1
self.explode_second = int(self.explode_millisecond / 1000)
self.start_explode = False
# 爆炸持续时间
self.exploding_count = 1000 * 1
# 炸弹伤害能力
self.harm_value = 1
# 该炸弹是否还存在
self.is_being = True
self.font = pygame.font.SysFont('Consolas', 20)
self.digitalcolor = digitalcolor
'''画到屏幕上'''
def draw(self, screen, dt, map_parser):
if not self.start_explode:
# 爆炸倒计时
self.explode_millisecond -= dt
self.explode_second = int(self.explode_millisecond / 1000)
if self.explode_millisecond < 0:
self.start_explode = True
screen.blit(self.image, self.rect)
text = self.font.render(str(self.explode_second), True, self.digitalcolor)
rect = text.get_rect(center=(self.rect.centerx-5, self.rect.centery+5))
screen.blit(text, rect)
return False
else:
# 爆炸持续倒计时
self.exploding_count -= dt
if self.exploding_count > 0:
return self.__explode(screen, map_parser)
else:
self.is_being = False
return False
'''爆炸效果'''
def __explode(self, screen, map_parser):
explode_area = self.__calcExplodeArea(map_parser.instances_list)
for each in explode_area:
image = pygame.image.load(self.explode_imagepath)
image = pygame.transform.scale(image, (self.blocksize, self.blocksize))
rect = image.get_rect()
rect.left, rect.top = each[0] * self.blocksize, each[1] * self.blocksize
screen.blit(image, rect)
return explode_area
'''计算爆炸区域'''
def __calcExplodeArea(self, instances_list):
explode_area = []
# 区域计算规则为墙可以阻止爆炸扩散, 且爆炸范围仅在游戏地图范围内
for ymin in range(self.coordinate[1], self.coordinate[1]-5, -1):
if ymin < 0 or instances_list[ymin][self.coordinate[0]] in ['w', 'x', 'z']:
break
explode_area.append([self.coordinate[0], ymin])
for ymax in range(self.coordinate[1]+1, self.coordinate[1]+5):
if ymax >= len(instances_list) or instances_list[ymax][self.coordinate[0]] in ['w', 'x', 'z']:
break
explode_area.append([self.coordinate[0], ymax])
for xmin in range(self.coordinate[0], self.coordinate[0]-5, -1):
if xmin < 0 or instances_list[self.coordinate[1]][xmin] in ['w', 'x', 'z']:
break
explode_area.append([xmin, self.coordinate[1]])
for xmax in range(self.coordinate[0]+1, self.coordinate[0]+5):
if xmax >= len(instances_list[0]) or instances_list[self.coordinate[1]][xmax] in ['w', 'x', 'z']:
break
explode_area.append([xmax, self.coordinate[1]])
return explode_area
因为炸弹类和角色类每帧都要绑定到游戏屏幕上,所以一些倒计时操作就合并地写到draw函数里了,当然最好是重
以上是关于Python游戏开发,pygame模块,Python实现炸弹人小游戏的主要内容,如果未能解决你的问题,请参考以下文章
Python游戏开发,pygame模块,Python实现经典90坦克大战游戏
Python游戏开发,pygame模块,Python实现2048小游戏
Python游戏开发,pygame模块,Python实现过迷宫小游戏
Python游戏开发,pygame模块,Python实现记忆翻牌小游戏