python游戏开发(贪吃蛇游戏、五子棋游戏、大球吃小球游戏)
目录
一、使用Pygame进行游戏开发
1、制作游戏窗口
2、在窗口中绘图
3、加载图像
4、实现动画效果
5、碰撞检测
6、事件处理
二、五子棋
三、贪吃蛇游戏
一、使用Pygame进行游戏开发
Pygame是一个开源的Python模块,专门用于多媒体应用(如电子游戏)的开发,其中包含对图像、声音、视频、事件、碰撞等的支持。Pygame建立在SDL的基础上,SDL是一套跨平台的多媒体开发库,用C语言实现,被广泛的应用于游戏、模拟器、播放器等的开发。而Pygame让游戏开发者不再被底层语言束缚,可以更多的关注游戏的功能和逻辑。
下面我们来完成一个简单的小游戏,游戏的名字叫“大球吃小球”
1、制作游戏窗口
import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
2、在窗口中绘图
可以通过pygame中draw模块的函数在窗口上绘图,可以绘制的图形包括:线条、矩形、多边形、圆、椭圆、圆弧等。需要说明的是,屏幕坐标系是将屏幕左上角设置为坐标原点(0, 0)
,向右是x轴的正向,向下是y轴的正向,在表示位置或者设置尺寸的时候,我们默认的单位都是像素。所谓像素就是屏幕上的一个点,你可以用浏览图片的软件试着将一张图片放大若干倍,就可以看到这些点。pygame中表示颜色用的是色光三原色表示法,即通过一个元组或列表来指定颜色的RGB值,每个值都在0~255之间,因为是每种原色都用一个8位(bit)的值来表示,三种颜色相当于一共由24位构成,这也就是常说的“24位颜色表示法”。
import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)screen.fill((242, 242, 242))# 绘制一个圆(参数分别是: 屏幕, 颜色, 圆心位置, 半径, 0表示填充圆)pygame.draw.circle(screen, (255, 0, 0,), (100, 100), 30, 0)# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)pygame.display.flip()running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
3、加载图像
如果需要直接加载图像到窗口上,可以使用pygame中image模块的函数来加载图像,再通过之前获得的窗口对象的blit
方法渲染图像,代码如下所示。
import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 设置窗口的背景色(颜色是由红绿蓝三原色构成的元组)screen.fill((255, 255, 255))# 通过指定的文件名加载图像ball_image = pygame.image.load('./res/ball.png')# 在窗口上渲染图像screen.blit(ball_image, (50, 50))# 刷新当前窗口(渲染窗口将绘制的图像呈现出来)pygame.display.flip()running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseif __name__ == '__main__':main()
4、实现动画效果
说到动画这个词大家都不会陌生,事实上要实现动画效果,本身的原理也非常简单,就是将不连续的图片连续的播放,只要每秒钟达到了一定的帧数,那么就可以做出比较流畅的动画效果。如果要让上面代码中的小球动起来,可以将小球的位置用变量来表示,并在循环中修改小球的位置再刷新整个窗口即可。
import pygamedef main():# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')# 定义变量来表示小球在屏幕上的位置x, y = 50, 50running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsescreen.fill((255, 255, 255))pygame.draw.circle(screen, (255, 0, 0,), (x, y), 30, 0)pygame.display.flip()# 每隔50毫秒就改变小球的位置再刷新窗口pygame.time.delay(50)x, y = x + 5, y + 5if __name__ == '__main__':main()
5、碰撞检测
通常一个游戏中会有很多对象出现,而这些对象之间的“碰撞”在所难免,比如炮弹击中了飞机、箱子撞到了地面等。碰撞检测在绝大多数的游戏中都是一个必须得处理的至关重要的问题,pygame的sprite(动画精灵)模块就提供了对碰撞检测的支持,这里我们暂时不介绍sprite模块提供的功能,因为要检测两个小球有没有碰撞其实非常简单,只需要检查球心的距离有没有小于两个球的半径之和。为了制造出更多的小球,我们可以通过对鼠标事件的处理,在点击鼠标的位置创建颜色、大小和移动速度都随机的小球,当然要做到这一点,我们可以把之前学习到的面向对象的知识应用起来。
from enum import Enum, unique
from math import sqrt
from random import randintimport pygame@unique
class Color(Enum):"""颜色"""RED = (255, 0, 0)GREEN = (0, 255, 0)BLUE = (0, 0, 255)BLACK = (0, 0, 0)WHITE = (255, 255, 255)GRAY = (242, 242, 242)@staticmethoddef random_color():"""获得随机颜色"""r = randint(0, 255)g = randint(0, 255)b = randint(0, 255)return (r, g, b)class Ball(object):"""球"""def __init__(self, x, y, radius, sx, sy, color=Color.RED):"""初始化方法"""self.x = xself.y = yself.radius = radiusself.sx = sxself.sy = syself.color = colorself.alive = Truedef move(self, screen):"""移动"""self.x += self.sxself.y += self.syif self.x - self.radius <= 0 or \self.x + self.radius >= screen.get_width():self.sx = -self.sxif self.y - self.radius <= 0 or \self.y + self.radius >= screen.get_height():self.sy = -self.sydef eat(self, other):"""吃其他球"""if self.alive and other.alive and self != other:dx, dy = self.x - other.x, self.y - other.ydistance = sqrt(dx ** 2 + dy ** 2)if distance < self.radius + other.radius \and self.radius > other.radius:other.alive = Falseself.radius = self.radius + int(other.radius * 0.146)def draw(self, screen):"""在窗口上绘制球"""pygame.draw.circle(screen, self.color,(self.x, self.y), self.radius, 0)
6、事件处理
可以在事件循环中对鼠标事件进行处理,通过事件对象的type
属性可以判定事件类型,再通过pos
属性就可以获得鼠标点击的位置。如果要处理键盘事件也是在这个地方,做法与处理鼠标事件类似。
def main():# 定义用来装所有球的容器balls = []# 初始化导入的pygame中的模块pygame.init()# 初始化用于显示的窗口并设置窗口尺寸screen = pygame.display.set_mode((800, 600))# 设置当前窗口的标题pygame.display.set_caption('大球吃小球')running = True# 开启一个事件循环处理发生的事件while running:# 从消息队列中获取事件并对事件进行处理for event in pygame.event.get():if event.type == pygame.QUIT:running = False# 处理鼠标事件的代码if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:# 获得点击鼠标的位置x, y = event.posradius = randint(10, 100)sx, sy = randint(-10, 10), randint(-10, 10)color = Color.random_color()# 在点击鼠标的位置创建一个球(大小、速度和颜色随机)ball = Ball(x, y, radius, sx, sy, color)# 将球添加到列表容器中balls.append(ball)screen.fill((255, 255, 255))# 取出容器中的球 如果没被吃掉就绘制 被吃掉了就移除for ball in balls:if ball.alive:ball.draw(screen)else:balls.remove(ball)pygame.display.flip()# 每隔50毫秒就改变球的位置再刷新窗口pygame.time.delay(50)for ball in balls:ball.move(screen)# 检查球有没有吃到其他的球for other in balls:ball.eat(other)if __name__ == '__main__':main()
二、五子棋
游戏程序如下
import pygameEMPTY = 0
BLACK = 1
WHITE = 2black_color = [0, 0, 0]
white_color = [255, 255, 255]class RenjuBoard(object):def __init__(self):self._board = [[]] * 15self.reset()def reset(self):for row in range(len(self._board)):self._board[row] = [EMPTY] * 15def move(self, row, col, is_black):if self._board[row][col] == EMPTY:self._board[row][col] = BLACK if is_black else WHITEreturn Truereturn Falsedef draw(self, screen):for index in range(1, 16):pygame.draw.line(screen, black_color,[40, 40 * index], [600, 40 * index], 1)pygame.draw.line(screen, black_color,[40 * index, 40], [40 * index, 600], 1)pygame.draw.rect(screen, black_color, [36, 36, 568, 568], 4)pygame.draw.circle(screen, black_color, [320, 320], 5, 0)pygame.draw.circle(screen, black_color, [160, 160], 5, 0)pygame.draw.circle(screen, black_color, [480, 480], 5, 0)pygame.draw.circle(screen, black_color, [480, 160], 5, 0)pygame.draw.circle(screen, black_color, [160, 480], 5, 0)for row in range(len(self._board)):for col in range(len(self._board[row])):if self._board[row][col] != EMPTY:ccolor = black_color \if self._board[row][col] == BLACK else white_colorpos = [40 * (col + 1), 40 * (row + 1)]pygame.draw.circle(screen, ccolor, pos, 20, 0)def main():board = RenjuBoard()is_black = Truepygame.init()pygame.display.set_caption('五子棋')screen = pygame.display.set_mode([640, 640])screen.fill([255, 255, 0])board.draw(screen)pygame.display.flip()running = Truewhile running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseelif event.type == pygame.KEYUP:passelif event.type == pygame.MOUSEBUTTONDOWN\and event.button == 1:x, y = event.posrow = round((y - 40) / 40)col = round((x - 40) / 40)if board.move(row, col, is_black):is_black = not is_blackscreen.fill([255, 255, 0])board.draw(screen)pygame.display.flip()pygame.quit()if __name__ == '__main__':main()
三、贪吃蛇游戏
代码如下
from abc import ABCMeta, abstractmethod
from enum import Enum, unique
from random import randrange
from threading import Threadimport pygameclass Color(object):"""颜色"""GRAY = (242, 242, 242)BLACK = (0, 0, 0)GREEN = (0, 255, 0)PINK = (255, 20, 147)@unique
class Direction(Enum):"""方向"""UP = 0RIGHT = 1DOWN = 2LEFT = 3class GameObject(object, metaclass=ABCMeta):"""游戏中的对象"""def __init__(self, x=0, y=0, color=Color.BLACK):"""初始化方法:param x: 横坐标:param y: 纵坐标:param color: 颜色"""self._x = xself._y = yself._color = color@propertydef x(self):return self._x@propertydef y(self):return self._y@abstractmethoddef draw(self, screen):"""绘制:param screen: 屏幕"""passclass Wall(GameObject):"""围墙"""def __init__(self, x, y, width, height, color=Color.BLACK):"""初始化方法:param x: 横坐标:param y: 纵坐标:param width: 宽度:param height: 高度:param color: 颜色"""super().__init__(x, y, color)self._width = widthself._height = height@propertydef width(self):return self._width@propertydef height(self):return self._heightdef draw(self, screen):pygame.draw.rect(screen, self._color,(self._x, self._y, self._width, self._height), 4)class Food(GameObject):"""食物"""def __init__(self, x, y, size, color=Color.PINK):"""初始化方法:param x: 横坐标:param y: 纵坐标:param size: 大小:param color: 颜色"""super().__init__(x, y, color)self._size = sizeself._hidden = Falsedef draw(self, screen):if not self._hidden:pygame.draw.circle(screen, self._color,(self._x + self._size // 2, self._y + self._size // 2),self._size // 2, 0)self._hidden = not self._hiddenclass SnakeNode(GameObject):"""蛇身上的节点"""def __init__(self, x, y, size, color=Color.GREEN):"""初始化方法:param x: 横坐标:param y: 纵坐标:param size: 大小:param color: 颜色"""super().__init__(x, y, color)self._size = size@propertydef size(self):return self._sizedef draw(self, screen):pygame.draw.rect(screen, self._color,(self._x, self._y, self._size, self._size), 0)pygame.draw.rect(screen, Color.BLACK,(self._x, self._y, self._size, self._size), 1)class Snake(GameObject):"""蛇"""def __init__(self, x, y, size=20, length=5):"""初始化方法:param x: 横坐标:param y: 纵坐标:param size: 大小:param length: 初始长度"""super().__init__()self._dir = Direction.LEFTself._nodes = []self._alive = Trueself._new_dir = Nonefor index in range(length):node = SnakeNode(x + index * size, y, size)self._nodes.append(node)@propertydef dir(self):return self._dir@propertydef alive(self):return self._alive@propertydef head(self):return self._nodes[0]def change_dir(self, new_dir):"""改变方向:param new_dir: 新方向"""if new_dir != self._dir and \(self._dir.value + new_dir.value) % 2 != 0:self._new_dir = new_dirdef move(self):"""移动"""if self._new_dir:self._dir, self._new_dir = self._new_dir, Nonesnake_dir = self._dirx, y, size = self.head.x, self.head.y, self.head.sizeif snake_dir == Direction.UP:y -= sizeelif snake_dir == Direction.RIGHT:x += sizeelif snake_dir == Direction.DOWN:y += sizeelse:x -= sizenew_head = SnakeNode(x, y, size)self._nodes.insert(0, new_head)self._nodes.pop()def collide(self, wall):"""撞墙:param wall: 围墙"""head = self.headif head.x < wall.x or head.x + head.size > wall.x + wall.width \or head.y < wall.y or head.y + head.size > wall.y + wall.height:self._alive = Falsedef eat_food(self, food):"""吃食物:param food: 食物:return: 吃到食物返回True否则返回False"""if self.head.x == food.x and self.head.y == food.y:tail = self._nodes[-1]self._nodes.append(tail)return Truereturn Falsedef eat_self(self):"""咬自己"""for index in range(4, len(self._nodes)):node = self._nodes[index]if node.x == self.head.x and node.y == self.head.y:self._alive = Falsedef draw(self, screen):for node in self._nodes:node.draw(screen)def main():def refresh():"""刷新游戏窗口"""screen.fill(Color.GRAY)wall.draw(screen)food.draw(screen)snake.draw(screen)pygame.display.flip()def handle_key_event(key_event):"""处理按键事件"""key = key_event.keyif key == pygame.K_F2:reset_game()elif key in (pygame.K_a, pygame.K_w, pygame.K_d, pygame.K_s):if snake.alive:if key == pygame.K_w:new_dir = Direction.UPelif key == pygame.K_d:new_dir = Direction.RIGHTelif key == pygame.K_s:new_dir = Direction.DOWNelse:new_dir = Direction.LEFTsnake.change_dir(new_dir)def create_food():"""创建食物"""unit_size = snake.head.sizemax_row = wall.height // unit_sizemax_col = wall.width // unit_sizerow = randrange(0, max_row)col = randrange(0, max_col)return Food(wall.x + unit_size * col, wall.y + unit_size * row, unit_size)def reset_game():"""重置游戏"""nonlocal food, snakefood = create_food()snake = Snake(250, 290)def background_task():nonlocal running, foodwhile running:if snake.alive:refresh()clock.tick(10)if snake.alive:snake.move()snake.collide(wall)if snake.eat_food(food):food = create_food()snake.eat_self()"""class BackgroundTask(Thread):def run(self):nonlocal running, foodwhile running:if snake.alive:refresh()clock.tick(10)if snake.alive:snake.move()snake.collide(wall)if snake.eat_food(food):food = create_food()snake.eat_self()"""wall = Wall(10, 10, 600, 600)snake = Snake(250, 290)food = create_food()pygame.init()screen = pygame.display.set_mode((620, 620))pygame.display.set_caption('贪吃蛇')# 创建控制游戏每秒帧数的时钟clock = pygame.time.Clock()running = True# 启动后台线程负责刷新窗口和让蛇移动# BackgroundTask().start()Thread(target=background_task).start()# 处理事件的消息循环while running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falseelif event.type == pygame.KEYDOWN:handle_key_event(event)pygame.quit()if __name__ == '__main__':main()
https://github.com/jackfrued/Python-100-Dayshttps://github.com/jackfrued/Python-100-Days
python游戏开发(贪吃蛇游戏、五子棋游戏、大球吃小球游戏)相关推荐
- python练习---大球吃小球游戏
要求: 鼠标点击屏幕会自动产生不同大小的小球,小球会自动移动,碰到屏幕边界反弹回来,当不同大小的小球相遇在一起发生碰撞,大的小球会吃掉较小的小球,变得更大 代码: import pygame impo ...
- java swing 大球吃小球游戏 功能完善 完整代码 下载即可以运行
今天天气不错,利用一段时间给大家分享一个大球吃小球的游戏,该游戏也属于一个比较优秀的作品.整个系统界面漂亮,有完整得源码,希望大家可以喜欢.喜欢的帮忙点赞和关注.一起编程.一起进步!! 开发环境 开发 ...
- python游戏模块 - 26 小项目-坦克行动 / 大球吃小球
1. 小项目 - 坦克行动 import pygame from sys import exit from enum import Enum, unique """e ...
- java编写游戏_java编写小游戏-大球吃小球
游戏界面: 点击火箭开始游戏 点击Exit退出游戏 左上角显示当前成绩和历史最高分 退出自动保存最高成绩 代码获取 扫码关注微信公众号[程序猿声] 在后台回复[EBG]不包括[]即可获取. 玩法: 玩 ...
- JAVA编程实战之编写小游戏-大球吃小球(eat ball game)
游戏界面: 点击火箭开始游戏 点击Exit退出游戏 左上角显示当前成绩和历史最高分 退出自动保存最高成绩 代码获取 扫码关注微信公众号[程序猿声] 在后台回复[EBG]不包括[]即可获取. 玩法: 玩 ...
- Python第三周习题集(一) (工资结算系统 抽象类 静态方法 贪吃蛇 分数的重写 五子棋 大球吃小球 )...
# 工资结算系统 1. 部门经理 1.5万元/月 2. 程序员 工作时间 150元/小时 3.销售员 1200底薪,+ %5销售额的提成 # 给你员工,得出工资. 员工类,父类 下面3类子类.#我写的 ...
- python入门学习记录之pygame实现简单动画游戏:大球吃小球
引言: 文章python示例主要是跟着CSDN博客专家:骆昊来学习python开发的,有兴趣的可以学习一下 骆昊:<<https://blog.csdn.net/jackfrued> ...
- 自学一周python做的一个小游戏《大球吃小球》
需求 1,显示一个窗口. 2,我们要做到的功能有鼠标点击屏幕生成小球. 3,生成的小球大小随机,颜色随机,向随机方向移动,速度也随机. 4,大的球碰到小球时可以吃掉小球,吃掉后会变大. 5,球碰到边界 ...
- 大球吞小球html5游戏在线玩,大球吃小球大作战
大球吃小球大作战是以大鱼吃小鱼这个定论做的一款休闲类游戏,游戏玩法如题,尽量多的吃掉比你小的,不要被比你大的吃掉了哟. 官方介绍 大球吃小球大作战是一款酷萌的休闲游戏,玩家在游戏中就要大球吃小球,努力 ...
- Python大球吃小球
本小游戏采用了pygame模块 1.产生随机颜色的小球.2.小球具有移动.吃别的小球.绘制这3个方法.3.鼠标点击事件 上源码 // 大球吃小球 from enum import Enum, uniq ...
最新文章
- 华为鸿蒙被扒出来安卓,华为鸿蒙被“实锤”,操作界面曝光,为何被吐槽是换皮安卓?...
- Windows下LATEX排版论文攻略—CTeX、JabRef使用心得
- git每次操作都要输入账号密码 解决方案
- Hibernate的关联映射--一对多、
- java线程池延期执行一次_Java使用者的延期执行
- c语言字符型数据怎么输入输出,C语言基础之数据类型与输入/输出
- python中的类及self详解_python中的self详解与对照与网站分享
- 互联网后端技术栈大全,建议收藏!
- vs+python 更新pip 成功解决You are using pip version 9.0.3, however version 10.0.1 is available.
- STM32cube配置编码器和电机
- 软考高项-质量管理论文范文
- 从来不流鼻涕php没有毛病,睡觉的时候为什么不会流鼻涕?
- 魅蓝s6手机sim卡不显示无服务器,科普OPPOA57怎么截图及魅蓝S6怎么插卡
- 使用VLC把视频转换为一帧一帧的图片
- java web 小学期实训小节
- linux读取class下的文件路径,Class类getResource方法获取文件路径
- php实现简单的留言板
- Excel 神器 —— OpenPyXl
- 浏览器刷新、关闭页面与统计在线人数
- 运行时异常和受检查异常的区别
热门文章
- 学以致用——Excel报表自动化方案 (Automation solution of complicated manual Excel Report)
- 【Matlab车牌识别】BP神经网络车牌识别【含GUI源码 669期】
- 三星s20 android 10.0,三星S20猎户CPU系列安卓10.0 TWRP Recovery V3.4.0.10
- Go 每日一库之 roaring
- python冒号_python数组冒号取值操作
- 桌面图标变白,任务栏图标变白
- 敞开拥抱中国,荷兰光刻机巨头ASML丝毫不受“大火”影响
- 怎么把日程提醒放在手机桌面
- Debian上安装 Proxmox VE 7
- eclipse使用技巧——备注格式的定义与模板