Pygame实战练习之炸弹人学院游戏

导语 【Pygame实战练习之炸弹人学院游戏】在现在这个浮躁的年代:小编每次登陆王者荣耀,还有每次登陆刺激战场Z!
看着里面的聊天界面,各种代打、各种的找cp。小小编觉得,我们已经失去了玩游戏的初心。
接下来,小台将带领你们走回童年时光,一起领略我们当初玩4399的单纯与天真!
Pygame实战练习之炸弹人学院游戏
文章图片
?
还记得小时候小台每到放学时刻,就会拉着只比我小半岁的小表妹,一块去亲戚家里玩电脑
每一次打开电脑做的第一件事情就是,打开浏览器,输入4399这四个数字,那个时候觉得hao123真是一个神奇的主页!
可以让我打开4399玩各种游戏qwq,尤其是Q版泡泡堂深得我心!
?
那今天就带大家回忆一下童年也做一款经典的炸弹人的小游戏!
Pygame实战练习之炸弹人学院游戏
文章图片
?
正文 游戏规则还清楚哈, 我就不多做介绍了不清楚玩法的可以百度下下!
首先准备好相应的素材:【部分如下】
Pygame实战练习之炸弹人学院游戏
文章图片

?炸弹人主程序:

import sysimport cfgimport randomimport pygamefrom modules import * '''游戏主程序'''def main(cfg):# 初始化pygame.init()pygame.mixer.init()pygame.mixer.music.load(cfg.BGMPATH)pygame.mixer.music.play(-1, 0.0)screen = pygame.display.set_mode(cfg.SCREENSIZE)pygame.display.set_caption('炸弹人——源码基地:#959755565#')# 开始界面Interface(screen, cfg, mode='game_start')# 游戏主循环font = pygame.font.SysFont('Consolas', 15)for gamemap_path in cfg.GAMEMAPPATHS:# -地图map_parser = mapParser(gamemap_path, bg_paths=cfg.BACKGROUNDPATHS, wall_paths=cfg.WALLPATHS, blocksize=cfg.BLOCKSIZE)# -水果fruit_sprite_group = pygame.sprite.Group()used_spaces = []for i in range(5):coordinate = map_parser.randomGetSpace(used_spaces)used_spaces.append(coordinate)fruit_sprite_group.add(Fruit(random.choice(cfg.FRUITPATHS), coordinate=coordinate, blocksize=cfg.BLOCKSIZE))# -我方Herocoordinate = map_parser.randomGetSpace(used_spaces)used_spaces.append(coordinate)ourhero = Hero(imagepaths=cfg.HEROZELDAPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='ZELDA')# -电脑Heroaihero_sprite_group = pygame.sprite.Group()coordinate = map_parser.randomGetSpace(used_spaces)aihero_sprite_group.add(Hero(imagepaths=cfg.HEROBATMANPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='BATMAN'))used_spaces.append(coordinate)coordinate = map_parser.randomGetSpace(used_spaces)aihero_sprite_group.add(Hero(imagepaths=cfg.HERODKPATHS, coordinate=coordinate, blocksize=cfg.BLOCKSIZE, map_parser=map_parser, hero_name='DK'))used_spaces.append(coordinate)# -炸弹bombbomb_sprite_group = pygame.sprite.Group()# -用于判断游戏胜利或者失败的flagis_win_flag = False# -主循环screen = pygame.display.set_mode(map_parser.screen_size)clock = pygame.time.Clock()while True:dt = clock.tick(cfg.FPS)for event in pygame.event.get():if event.type == pygame.QUIT:pygame.quit()sys.exit(-1)# --↑↓←→键控制上下左右, 空格键丢炸弹elif event.type == pygame.KEYDOWN:if event.key == pygame.K_UP:ourhero.move('up')elif event.key == pygame.K_DOWN:ourhero.move('down')elif event.key == pygame.K_LEFT:ourhero.move('left')elif event.key == pygame.K_RIGHT:ourhero.move('right')elif event.key == pygame.K_SPACE:if ourhero.bomb_cooling_count <= 0:bomb_sprite_group.add(ourhero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))screen.fill(cfg.WHITE)# --电脑Hero随机行动for hero in aihero_sprite_group:action, flag = hero.randomAction(dt)if flag and action == 'dropbomb':bomb_sprite_group.add(hero.generateBomb(imagepath=cfg.BOMBPATH, digitalcolor=cfg.YELLOW, explode_imagepath=cfg.FIREPATH))# --吃到水果加生命值(只要是Hero, 都能加)ourhero.eatFruit(fruit_sprite_group)for hero in aihero_sprite_group:hero.eatFruit(fruit_sprite_group)# --游戏元素都绑定到屏幕上map_parser.draw(screen)for bomb in bomb_sprite_group:if not bomb.is_being:bomb_sprite_group.remove(bomb)explode_area = bomb.draw(screen, dt, map_parser)if explode_area:# --爆炸火焰范围内的Hero生命值将持续下降if ourhero.coordinate in explode_area:ourhero.health_value -= bomb.harm_valuefor hero in aihero_sprite_group:if hero.coordinate in explode_area:hero.health_value -= bomb.harm_valuefruit_sprite_group.draw(screen)for hero in aihero_sprite_group:hero.draw(screen, dt)ourhero.draw(screen, dt)# --左上角显示生命值pos_x = showText(screen, font, text=ourhero.hero_name+'(our):'+str(ourhero.health_value), color=cfg.YELLOW, position=[5, 5])for hero in aihero_sprite_group:pos_x, pos_y = pos_x+15, 5pos_x = showText(screen, font, text=hero.hero_name+'(ai):'+str(hero.health_value), color=cfg.YELLOW, position=[pos_x, pos_y])# --我方玩家生命值小于等于0/电脑方玩家生命值均小于等于0则判断游戏结束if ourhero.health_value <= 0:is_win_flag = Falsebreakfor hero in aihero_sprite_group:if hero.health_value <= 0:aihero_sprite_group.remove(hero)if len(aihero_sprite_group) == 0:is_win_flag = Truebreakpygame.display.update()clock.tick(cfg.FPS)if is_win_flag:Interface(screen, cfg, mode='game_switch')else:breakInterface(screen, cfg, mode='game_end') '''run'''if __name__ == '__main__':while True:main(cfg)

开始的界面如下:
Pygame实战练习之炸弹人学院游戏
文章图片

?定义地图类:
class mapParser(): def __init__(self, mapfilepath, bg_paths, wall_paths, blocksize, **kwargs):self.instances_list = self.__parse(mapfilepath)self.bg_paths = bg_pathsself.wall_paths = wall_pathsself.blocksize = blocksizeself.height = len(self.instances_list)self.width = len(self.instances_list[0])self.screen_size = (blocksize * self.width, blocksize * self.height) '''地图画到屏幕上''' def draw(self, screen):for j in range(self.height):for i in range(self.width):instance = self.instances_list[j][i]if instance == 'w':elem = Wall(self.wall_paths[0], [i, j], self.blocksize)elif instance == 'x':elem = Wall(self.wall_paths[1], [i, j], self.blocksize)elif instance == 'z':elem = Wall(self.wall_paths[2], [i, j], self.blocksize)elif instance == '0':elem = Background(self.bg_paths[0], [i, j], self.blocksize)elif instance == '1':elem = Background(self.bg_paths[1], [i, j], self.blocksize)elif instance == '2':elem = Background(self.bg_paths[2], [i, j], self.blocksize)else:raise ValueError('instance parse error in mapParser.draw...')elem.draw(screen) '''随机获取一个空地''' def randomGetSpace(self, used_spaces=None):while True:i = random.randint(0, self.width-1)j = random.randint(0, self.height-1)coordinate = [i, j]if used_spaces and coordinate in used_spaces:continueinstance = self.instances_list[j][i]if instance in ['0', '1', '2']:breakreturn coordinate '''根据坐标获取元素类型''' def getElemByCoordinate(self, coordinate):return self.instances_list[coordinate[1]][coordinate[0]] '''解析.map文件''' def __parse(self, mapfilepath):instances_list = []with open(mapfilepath) as f:for line in f.readlines():instances_line_list = []for c in line:if c in ['w', 'x', 'z', '0', '1', '2']:instances_line_list.append(c)instances_list.append(instances_line_list)return instances_list

定义必要的一些精灵类:角色,水果等等。
'''墙类'''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] * blocksizeself.coordinate = coordinateself.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] * blocksizeself.coordinate = coordinateself.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 = https://www.it610.com/article/5elif self.kind =='cherry':self.value = https://www.it610.com/article/10else: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] * blocksizeself.coordinate = coordinateself.blocksize = blocksize '''画到屏幕上''' def draw(self, screen):screen.blit(self.image, self.rect)return True '''炸弹类'''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_imagepathself.rect = self.image.get_rect()# 像素位置self.rect.left, self.rect.top = coordinate[0] * blocksize, coordinate[1] * blocksize# 坐标(元素块为单位长度)self.coordinate = coordinateself.blocksize = blocksize# 爆炸倒计时self.explode_millisecond = 6000 * 1 - 1self.explode_second = int(self.explode_millisecond / 1000)self.start_explode = False# 爆炸持续时间self.exploding_count = 1000 * 1# 炸弹伤害能力self.harm_value = https://www.it610.com/article/1# 该炸弹是否还存在self.is_being = Trueself.font = pygame.font.SysFont('Consolas', 20)self.digitalcolor = digitalcolor '''画到屏幕上''' def draw(self, screen, dt, map_parser):if not self.start_explode:# 爆炸倒计时self.explode_millisecond -= dtself.explode_second = int(self.explode_millisecond / 1000)if self.explode_millisecond < 0:self.start_explode = Truescreen.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 Falseelse:# 爆炸持续倒计时self.exploding_count -= dtif self.exploding_count > 0:return self.__explode(screen, map_parser)else:self.is_being = Falsereturn 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.blocksizescreen.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']:breakexplode_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']:breakexplode_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']:breakexplode_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']:breakexplode_area.append([xmax, self.coordinate[1]])return explode_area '''角色类'''class Hero(pygame.sprite.Sprite): def __init__(self, imagepaths, coordinate, blocksize, map_parser, **kwargs):pygame.sprite.Sprite.__init__(self)self.imagepaths = imagepathsself.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] * blocksizeself.coordinate = coordinateself.blocksize = blocksizeself.map_parser = map_parserself.hero_name = kwargs.get('hero_name')# 生命值self.health_value = https://www.it610.com/article/50# 炸弹冷却时间self.bomb_cooling_time = 5000self.bomb_cooling_count = 0# 随机移动冷却时间(仅AI电脑用)self.randommove_cooling_time = 100self.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 Falseself.coordinate[0] = self.coordinate[0] - 1elif 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 Falseself.coordinate[0] = self.coordinate[0] + 1elif 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 Falseself.coordinate[1] = self.coordinate[1] - 1elif 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 Falseself.coordinate[1] = self.coordinate[1] + 1else:raise ValueError('Unknow direction %s...' % direction)self.rect.left, self.rect.top = self.coordinate[0] * self.blocksize, self.coordinate[1] * self.blocksizereturn True '''随机行动(AI电脑用)''' def randomAction(self, dt):# 冷却倒计时if self.randommove_cooling_count > 0:self.randommove_cooling_count -= dtaction = random.choice(['left', 'left', 'right', 'right', 'up', 'up', 'down', 'down', 'dropbomb'])flag = Falseif action in ['left', 'right', 'up', 'down']:if self.randommove_cooling_count <= 0:flag = Trueself.move(action)self.randommove_cooling_count = self.randommove_cooling_timeelif action in ['dropbomb']:if self.bomb_cooling_count <= 0:flag = Trueself.bomb_cooling_count = self.bomb_cooling_timereturn 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 -= dtscreen.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))

效果如下:
Pygame实战练习之炸弹人学院游戏
文章图片

Pygame实战练习之炸弹人学院游戏
文章图片

这精致的画面还可以吧~哈哈哈啊 快夸我快夸我~
总结 安啦!文章就写到这里,你们的支持是我最大的动力,记得三连哦~木啊!
Pygame实战练习之炸弹人学院游戏
文章图片

温馨提示:不要忘记点赞、关注、评论哦!看我手上的炸弹~
到此这篇关于Pygame实战练习之炸弹人学院游戏的文章就介绍到这了,更多相关Pygame 炸弹人学院内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    推荐阅读