作者 | 李秋键

责编 | Carol

封图 | CSDN 下载自视觉中国

近几年来Python语言得到了快速发展,而Pygame作为Python开发应用和游戏必备的库更是展现了Python的优越性。

而今天我们就将借助Pygame建立吃豆人游戏。

吃豆人是电子游戏历史上的经典街机游戏,由Namco公司的岩谷彻设计并由Midway Games在1980年发行。Pac-Man被认为是80年代最经典的街机游戏之一,游戏的主角小精灵的形象甚至被作为一种大众文化符号,或是此产业的代表形象。

而Pygame模块是跨平台Python模块,专为电子游戏设计,包含图像、声音。建立在SDL基础上,允许实时电子游戏研发而无需被低级语言(如机器语言和汇编语言)束缚。

最终游戏效果如下可见:

实验前的准备

首先我们使用的python版本是3.6.5所用到的模块是pygame模块,用来创建游戏框架。Random模块用来随机生成方向。

素材准备

首先我们将图片放到images目录下,背景音乐放到sounds目录下。

如下图可见:

游戏搭建

1、定义一些精灵:

整体的类变量定义包括墙类,通过pygame的图片填充作为墙类的加载;同理还包括食物类和角色。而怪物的随机运动使用random产生随机运动方向。

其对应的代码如下:

import random
import pygame
'''墙类'''
class Wall(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 = xself.rect.top = y
'''食物类'''
class Food(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 = xself.rect.top = y
'''角色类'''
class Player(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 = xself.rect.top = yself.prev_x = xself.prev_y = yself.base_speed = [30, 30]self.speed = [0, 0]self.is_move = Falseself.tracks = []self.tracks_loc = [0, 0]'''改变速度方向'''def changeSpeed(self, direction):if direction[0] < 0:self.image = pygame.transform.flip(self.base_image, True, False)elif direction[0] > 0:self.image = self.base_image.copy()elif direction[1] < 0:self.image = pygame.transform.rotate(self.base_image, 90)elif direction[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]]return self.speed'''更新角色位置'''def update(self, wall_sprites, gate_sprites):if not self.is_move:return Falsex_prev = self.rect.lefty_prev = self.rect.topself.rect.left += self.speed[0]self.rect.top += self.speed[1]is_collide = pygame.sprite.spritecollide(self, wall_sprites, False)if gate_sprites is not None:if not is_collide:is_collide = pygame.sprite.spritecollide(self, gate_sprites, False)if is_collide:self.rect.left = x_prevself.rect.top = y_prevreturn Falsereturn True'''生成随机的方向'''def randomDirection(self):return random.choice([[-0.5, 0], [0.5, 0], [0, 0.5], [0, -0.5]])

2、游戏关卡定义:

在这里设置好了关卡一。关卡的定义必须包括墙的位置,不同关卡墙的位置和怪物的位置不同。更多关卡可以参照设置

对应代码如下:

import pygame
from Sprites import *
NUMLEVELS = 1
'''关卡一'''
class Level1():def __init__(self):self.info = 'level1''''创建墙'''def setupWalls(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]]for wall_position in wall_positions:wall = Wall(*wall_position, wall_color)self.wall_sprites.add(wall)return self.wall_sprites'''创建门'''def setupGate(self, gate_color):self.gate_sprites = pygame.sprite.Group()self.gate_sprites.add(Wall(282, 242, 42, 2, gate_color))return self.gate_sprites'''创建角色'''def setupPlayers(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))for each in ghost_images_path:role_name = each.split('/')[-1].split('.')[0]if role_name == 'Blinky':player = Player(287, 199, each)player.is_move = Trueplayer.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)elif role_name == 'Clyde':player = Player(319, 259, each)player.is_move = Trueplayer.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)elif role_name == 'Inky':player = Player(255, 259, each)player.is_move = Trueplayer.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)elif role_name == 'Pinky':player = Player(287, 259, each)player.is_move = Trueplayer.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)return self.hero_sprites, self.ghost_sprites'''创建食物'''def setupFood(self, food_color, bg_color):self.food_sprites = pygame.sprite.Group()for row in range(19):for col in range(19):if (row == 7 or row == 8) and (col == 8 or col == 9 or col == 10):continueelse:food = Food(30*col+32, 30*row+32, 4, 4, food_color, bg_color)is_collide = pygame.sprite.spritecollide(food, self.wall_sprites, False)if is_collide:continueis_collide = pygame.sprite.spritecollide(food, self.hero_sprites, False)if is_collide:continueself.food_sprites.add(food)return self.food_sprites

3、游戏创建:

在通过关卡定义墙等位置后以及精灵自身属性怪物运动、食物定义等后,通过调用已经创建好的类达到搭建游戏的目的。

具体如下可见:

import os
import sys
import pygame
import Levels
'''定义一些必要的参数'''
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')
'''开始某一关游戏'''
def startLevelGame(level, screen, font):clock = pygame.time.Clock()SCORE = 0wall_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 = Falsewhile True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit(-1)pygame.quit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_LEFT:for hero in hero_sprites:hero.changeSpeed([-1, 0])hero.is_move = Trueelif event.key == pygame.K_RIGHT:for hero in hero_sprites:hero.changeSpeed([1, 0])hero.is_move = Trueelif event.key == pygame.K_UP:for hero in hero_sprites:hero.changeSpeed([0, -1])hero.is_move = Trueelif event.key == pygame.K_DOWN:for hero in hero_sprites:hero.changeSpeed([0, 1])hero.is_move = Trueif event.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 = Falsescreen.fill(BLACK)for hero in hero_sprites:hero.update(wall_sprites, gate_sprites)hero_sprites.draw(screen)for hero in hero_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)for ghost in ghost_sprites:# 幽灵随机运动(效果不好且有BUG)'''res = ghost.update(wall_sprites, None)while not res:ghost.changeSpeed(ghost.randomDirection())res = ghost.update(wall_sprites, None)'''# 指定幽灵运动路径if ghost.tracks_loc[1] < ghost.tracks[ghost.tracks_loc[0]][2]:ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])ghost.tracks_loc[1] += 1else:if ghost.tracks_loc[0] < len(ghost.tracks) - 1:ghost.tracks_loc[0] += 1elif ghost.role_name == 'Clyde':ghost.tracks_loc[0] = 2else:ghost.tracks_loc[0] = 0ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])ghost.tracks_loc[1] = 0if ghost.tracks_loc[1] < ghost.tracks[ghost.tracks_loc[0]][2]:ghost.changeSpeed(ghost.tracks[ghost.tracks_loc[0]][0: 2])else:if ghost.tracks_loc[0] < len(ghost.tracks) - 1:loc0 = ghost.tracks_loc[0] + 1elif ghost.role_name == 'Clyde':loc0 = 2else:loc0 = 0ghost.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])if len(food_sprites) == 0:is_clearance = Truebreakif pygame.sprite.groupcollide(hero_sprites, ghost_sprites, False, False):is_clearance = Falsebreakpygame.display.flip()clock.tick(10)return is_clearance
'''显示文字'''
def showText(screen, font, is_clearance, flag=False):clock = pygame.time.Clock()msg = 'Game Over!' if not is_clearance else 'Congratulations, you won!'positions = [[235, 233], [65, 303], [170, 333]] if not is_clearance else [[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('Press ENTER to continue or play again.', True, WHITE),font.render('Press ESCAPE to quit.', True, WHITE)]while True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()pygame.quit()if event.type == pygame.KEYDOWN:if event.key == pygame.K_RETURN:if is_clearance:if not flag:returnelse:main(initialize())else:main(initialize())elif event.key == pygame.K_ESCAPE:sys.exit()pygame.quit()for idx, (text, position) in enumerate(zip(texts, positions)):screen.blit(text, position)pygame.display.flip()clock.tick(10)
'''初始化'''
def initialize():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('吃豆人')return screen
'''主函数'''
def main(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)for num_level in range(1, Levels.NUMLEVELS+1):if num_level == 1:level = Levels.Level1()is_clearance = startLevelGame(level, screen, font_small)if num_level == Levels.NUMLEVELS:showText(screen, font_big, is_clearance, True)else:showText(screen, font_big, is_clearance)

最终运行程序结果如下:

源码地址:

https://pan.baidu.com/s/128id8L-PDPgGOPuH-5uHDg

提取码:rj9f

作者简介:

李秋键,CSDN博客专家,CSDN达人课作者。硕士在读于中国矿业大学,开发有taptap竞赛获奖等等。

更多精彩推荐
☞时隔 15 年,苹果的自研 ARM 芯片为何能取代 Intel 处理器?
☞从微信「拍一拍」,我想到了那些神奇的一行代码功能
☞AI 又进阶!除了鉴别 PS 图片,还能一键卸妆!
☞无代码开发到底是不是伪需求?
☞程序员端午炫富指南~
☞Spring 从入门到入土——AOP 就这么简单!| 原力计划
☞硬核!国外开发者用 25 美元做了个区块链警佩相机!
你点的每个“在看”,我都认真当成了喜欢

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

  1. c语言吃豆人游戏怎么理解,python 实现简单的吃豆人游戏

    效果展示: 程序简介 1.使用pygame模组 2.在material目录下有一些素材 3.吃豆人的游戏主体 4.吃豆人怪物的AI(未使用深度学习) 主要代码 main.py import pygam ...

  2. 基于Python实现的吃豆人游戏设计

    资源下载地址:https://download.csdn.net/download/sheziqiong/86817091 资源下载地址:https://download.csdn.net/downl ...

  3. Python 中用 300 行或更少的代码创建吃豆人游戏(教程含源码)

    吃豆人是一款经典的平台游戏,今天可能已为所有人所熟知."吃豆人"这个名字来自日语单词"paku",意思是张开和合上嘴巴.创作者岩谷彻 (Toru Iwatani ...

  4. 可怜的博主跟小豆人杠起来啦!Python制作的吃豆人小游戏,快来围观!!

    相关文件 关注小编,私信小编领取哟! 当然别忘了一件三连哟~~ 对了大家可以关注小编的公众号哟~~ Python日志 开发环境 Python版本:3.6.4 相关模块: pygame模块: 以及一些P ...

  5. python五子棋游戏大作业_python-大作业之五子棋游戏(附代码)

    <python-大作业之五子棋游戏(附代码)>由会员分享,可在线阅读,更多相关<python-大作业之五子棋游戏(附代码)(6页珍藏版)>请在金锄头文库上搜索. 1.Pytho ...

  6. python 吃豆人_pacman 人工智能编程 吃豆人小游戏 可实现智能寻路 吃豆 通关 - 下载 - 搜珍网...

    Berkeley人工智能吃豆人作业-Python/ Berkeley人工智能吃豆人作业-Python/再附带一份完整工程源码吧/ Berkeley人工智能吃豆人作业-Python/再附带一份完整工程源 ...

  7. python画花女朋友_教你使用python画一朵花送女朋友

    本文实例为大家分享了用python画一朵花的具体代码,供大家参考,具体内容如下 第一种,画法 from turtle import * import time setup(600,800,0,0) s ...

  8. python有哪些码_Python有哪些神一般的蜜汁操作? 《附代码》

    有人说,"Python除了不会生孩子,Python从撩妹到装x,无所不能!什么都会!" 下载视频?我用Python: 玩跳一跳?我用Python跳到4999分: 撩妹子?依然用Py ...

  9. Get了!用Python制作数据预测集成工具 | 附代码

    作者 | 李秋键 责编 | 晋兆雨 大数据预测是大数据最核心的应用,是它将传统意义的预测拓展到"现测".大数据预测的优势体现在,它把一个非常困难的预测问题,转化为一个相对简单的描述 ...

最新文章

  1. mysql提取数据字符_如何从MySQL查询的字符串中提取数值?
  2. DynamipsGUI
  3. UART串口通信浅谈之(一)--基础概述
  4. python3字符串操作_python3-字符串操作
  5. 2017.10.12 小Q的无敌异或 失败总结
  6. javascript中将字符串转换为json格式的三种方法
  7. 1月19日学习内容整理:Scrapy框架补充之scrapy-redis组件
  8. 主题切换时如何主动去刷新一些资源?
  9. win32 sdk绘制ListBox控件
  10. 豪华版飞机大战系列(三)
  11. Editplus 3添加edtool插件文档
  12. 第二章-信源与信息熵(一)
  13. QThread 应用浅析
  14. Intellij IDEA企业版破解
  15. Oracle11G数据库的双机热备份配置--基础篇
  16. Linux安装配置MySQL8.0 打war包 启动项目
  17. 用计算机公式计算优良,『excel怎样合并单元格』如何在EXCEL中如何用公式计算全年级各班各科平均分、优秀率、合格率的方法...
  18. pandas判断和删除重复duplicated和drop_duplicates
  19. 多线程_多线程常见的面试题
  20. 如何将Word文档每页转换为图片保存?

热门文章

  1. Android 2019最新面试实战总结
  2. 剑指offer——python【第54题】字符流中第一个不重复的字符
  3. swift开发网络篇 - 用户登录POST JSON and header
  4. 【转】 谈谈C++中的swap函数
  5. 来认识下less css
  6. 《TensorFlow 2.0深度学习算法实战教材》学习笔记(四、TensorFlow 进阶)
  7. QBoxLayout中setSpacing(int)和addSpacing(int)的区别
  8. 【maven】Controller层参数如何设置传null
  9. 用python求两个人的平均身高_黄哥Python:分治算法(Divide-and-Conquer)
  10. 力扣—— 295. 数据流的中位数(困难)