作者Toby,持牌照消费金融公司模型专家,拥有国家算法相关专利,曾担任过国内最大医药数据中心负责人,和中科院有慢病数据挖掘项目合作。擅长python 机器学习,应用于医疗,英语,金融风控领域。
课程介绍
曾经我也沉迷游戏,连续玩十几个小时竞技游戏可以不吃饭。游戏只是别人写好程序,与其沉迷于他人设计好程序,为何不自己设计游戏,至少学会编程后,我们的月收入上万不是问题。于是便有了录制这部pygame菜鸟游戏编程教程动力。不要沉迷于游戏,我们人生还有许多事情要做,旅游,找到另一个伴侣,成立一个家庭,照顾父母。。。。
编程正在逐步改变世界,程序员不是搬砖的。但传统计算教育程面临枯燥乏味课程,让学生感到乏味。
兴趣是学习最好老师!此课程目的是激发大家对编程兴趣,给广大Python入门初学者带来无穷乐趣。
游戏涉及童年玩过经典小游戏,包括贪吃蛇,消消乐,俄罗斯方块,植物大战僵尸,扫雷等等。视频的参考资料可下载脚本。脚本已经编译好,可直接运行!
感谢妻子对家庭支持,让我周末和节假日有时间录制教学视频,我会继续加油!
Have Fun!
课程目录
章节1前言
课时1我的所有教学视频系列介绍
课时2如何联系作者和访问我的主页
课时3欢迎项目合作
课时4游戏脚本和素材下载地址
章节2Python基础环境搭建
课时5python官网
课时6Anaconda安装
课时7canopy下载安装
课时8python第三方包安装(pip和conda install)
课时9Python非官方扩展包下载地址
章节3python基础知识
课时10文件基本操作
课时11变量_表达式_运算符_值
课时12字符串
课时13程序基本构架0
课时14数据类型_函数_面向对象编程
课时15编程技巧和学习方法
课时16python2和3区别_编码基础
课时17更多python基础知识_网络教学资源推荐
课时18python异常处理
章节4pygame基础知识
课时19pygame官网介绍
课时20pygame安装
课时21pygame基础语法概述
章节5植物大战僵尸
课时22植物大战僵尸plant VS zombie游戏概述
课时23游戏帧数介绍pygame.time.clock
课时24pygame.init() quit()模块初始化和卸载
课时25pygame.locals调用常量更方便
课时26初始化游戏窗口pygame.display.set_mode()
课时27建立一个僵尸吃猫的游戏窗口
课时28加载僵尸图片pygame.image.load
课时29加载游戏声音pygame.mixer.music
课时30鼠标设置不可见pygame.mouse.set_visible
课时31加载植物角色到游戏界面
课时32图片加载别弄错了surface.blit VS pygame.display.update()
课时33游戏窗口输入文本pygame.font
课时34操作键盘,植物可以自由移动了
课时35冲突检测-植物碰到僵尸后咋整?
课时36植物可以发射子弹啦
课时37丧尸狂潮-随机生成一大波移动丧尸
课时38移除子弹击中后丧尸
课时39移除超越游戏界面的子弹
课时40丧尸吃掉植物,游戏结束了
课时41游戏角色可以不断丰富,新增黄帽子丧尸
章节6贪吃蛇游戏Snake
课时42pygame.display创建一个基本游戏框架
课时43event事件
课时44event_type.QUIT游戏结束按键事件
课时45RGB颜色填充
课时46draw.draw图形绘制
课时47pygame.KEYDOWN图形左右移动
课时48pygame.KEYDOWN移动对象
课时49每秒帧数_控制物体移动速度
课时50pygame.KEYUP键盘释放键
课时51pygame.K_UP,pygame.K_DOWN键盘上下移动物体
课时52边界障碍物设置和hardCode
课时53pygame.font.SysFont游戏文字交互
课时54gameloop和游戏结束优化
课时55random函数_随机生成一个红苹果
课时56苹果和蛇的触碰探测0
课时57蛇吃掉苹果后,生成新的苹果
课时58蛇吃掉苹果后,身体变长
课时59pygame.mixer.Sound游戏声音添加
课时60游戏标题和logo设置pygame.display.set_caption
章节7AI人工智能游戏开发(课外英语阅读)
课时61星际争霸人工智能发展史(课外英语阅读)
课时62星际争霸深度学习游戏开发指南(课外英语阅读)
章节8附录1_十大经典游戏python脚本下载
课时63经典游戏概述
课时64sprites and sounds
课时65大松鼠吃小松鼠
课时66推箱子box_pusher
课时67开心消消乐
课时68贪吃蛇
课时69俄罗斯方块Tetris
课时70奥赛罗棋reverse
课时71颜色拼图inkSpill
课时72赛车比赛
课时73扫雷(基于神经网络算法)
章节9附录2_AI人机大战游戏视频收录
课时74基于神经网络算法的马里奥游戏
课时75DOTA游戏 pain战队VS openAI
课时76DOTA游戏 中国明星战队VS openAI
课时77星际争霸AI(人族)VS人类(人族)
课时78星际争霸AI(人族)VS人类(虫族)
课时79韩国星际争霸大赛AI挑战多名明星选手
章节10诚谢开源的朋友
课时80诚谢开源圈朋友
课时81孙子兵法-不变应万变的秘密
课时82勇于探索,保持一颗好奇心
下图展示视频中几个经典童年游戏,植物大战僵尸
《植物大战僵尸》是由PopCap Games开发的一款益智策略类单机游戏,于2009年5月5日发售。玩家通过武装多种植物切换不同的功能,快速有效地把僵尸阻挡在入侵的道路上。不同的敌人,不同的玩法构成五种不同的游戏模式,加之黑夜、浓雾以及泳池之类的障碍增加了游戏挑战性。
《植物大战僵尸》是一款极富策略性的小游戏。可怕的僵尸即将入侵,每种僵尸都有不同的特点,例如铁桶僵尸拥有极强的抗击打能力,矿工僵尸可以挖地道绕过种植在土壤表面的植物等。玩家防御僵尸的方式就是栽种植物。49种植物每种都有不同的功能,例如樱桃炸弹可以和周围一定范围内的所有僵尸同归于尽,而食人花可以吃掉最靠近自己的一只僵尸。玩家可以针对不同僵尸的弱点来合理地种植植物,这也是胜利的诀窍。游戏根据玩法不同分为五种游戏模式:冒险、生存、花瓶破碎者、小游戏、花园。加之黑夜、屋顶、浓雾以及泳池之类的障碍增加了其挑战性该游戏近乎永无止境。
奥赛罗棋,人工智能AI范畴,英国每年有比赛
黑白棋,又叫反棋(Reversi)、奥赛罗棋(Othello)、苹果棋或翻转棋。黑白棋在西方和日本很流行。游戏通过相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。它的游戏规则简单,因此上手很容易,但是它的变化又非常复杂。有一种说法是:只需要几分钟学会它,却需要一生的时间去精通它。黑白棋的棋盘是一个有8*8方格的棋盘。把自己颜色的棋子放在棋盘的空格上,而当自己放下的棋子在横、竖、斜八个方向内有一个自己的棋子,则被夹在中间的全部翻转会成为自己的棋子。并且,只有在可以翻转棋子的地方才可以下子。黑白棋是19世纪末英国人发明的。直到上个世纪70年代一个日本人将其发展,借用莎士比亚名剧奥赛罗(othello)为这个游戏重新命名,也就是现在大家玩的黑白棋。为何借用莎士比亚名剧呢?是因为奥赛罗是莎士比亚一个名剧的男主角。他是一个黑人,妻子是白人,因受小人挑拨,怀疑妻子不忠一直情海翻波,最终亲手把妻子杀死。后来真相大白,奥赛罗懊悔不已,自杀而死。黑白棋就是借用这个黑人白人斗争的故事而命名。
游戏期间,位置比点数更重要!要着眼于长远利益,因为点数的领先很可能是暂时的。四个角上是必须争取占据的好位置,因为无法移开这些位置上的棋子。设法使自己走一步时,牵制着对手无法移动任何棋子!这样可以在一排中连续走两步。
当然我们没有必要用一生的时间去精通它。用python程序可以去模拟游戏,找到最佳下棋算法。
开心消消乐,手机玩的很high的爆款游戏
《开心消消乐》是一款乐元素研发的一款三消类休闲游戏。一天晚上,天空中掉下一颗神奇的豌豆种子,正好落在了梦之森林的村长屋附近,种子落地后吸收了池塘的水分,迅速成长,一夜之间变成参天大藤蔓…… 第二天早上,村民们醒来后看到巨大的藤蔓都惊呆了,聚在一起议论纷纷。有人说他似乎看到村长的房子在高耸入云的藤蔓上,房子似乎还在上升,有人号召说应该爬上去救村长,玩家需要爬到藤曼顶部救出村长。
色彩拼图游戏,AI范畴,基于算法,在规定时间内完成色彩统一,这需要一定思考能力哟。
游戏编程模块pygame介绍
pygame是一组旨在编写视频游戏的Python模块。Pygame可以使用python语言创建功能齐全的游戏和多媒体程序。Pygame具有高度的可移植性,几乎可以在所有平台和操作系统上运行。Pygame至今已被下载了数百万次。Pygame非常流行的一个原因是免费。根据LGPL许可证发布的内容,您可以使用它创建开源,免费软件,共享软件和商业游戏。Pygame历史开始于2000年10月。六个月后发布了pygame 1.0版。pygame的目标是使可视化游戏编程变得简单。pygame是Python和SDL混合的产物。SDL由Sam Lantinga创建,与DirectX相比,SDL是用于控制多媒体的跨平台C库。它已用于数百种商业和开源游戏。
迫不及待的想用pygame写一个自己的游戏了吗?用pip install pygame安装此模块吧。
pygame官网
学员查询pygame模块基础语法最好方法是访问官方文档,网址为
https://www.pygame.org/docs/ref/surface.html
pygame模块最常用的对象包括:顶层pygame包,颜色, 显示,绘画,事件,字体,图片,键盘,鼠标,常量, 多媒体,矩形, 表面,时间,音乐
高级对象包括:游标,游戏杆, 图像蒙版,精灵,转换,计算机字体, 绘制形状,重叠式展示,像素阵列,像素复制,数学
其他对象包括:相机,音频CDROM控制,例子,事件和队列交互, 快速事件,剪贴板支持,测试,触摸,版本。
pygame 包是可供使用的最顶层的包。Pygame 被分成许多子模块,但是并不会影响程序使用 Pygame。
pygame常见函数如下:
pygame.init() — 初始化所有导入的 pygame 模块
pygame.quit() — 卸载所有导入的 pygame 模块
pygame.error() — 标准 pygame 异常模块
pygame.get_error() — 获得当前错误信息
pygame.set_error() — 设置当前错误信息
pygame.get_sdl_version() — 获得 SDL 的版本号
pygame.get_sdl_byteorder() — 获得 SDL 的字节顺序
pygame.register_quit() — 注册一个函数,这个函数将在 pygame 退出时被调用
pygame.encode_string() — 对 unicode 或字节对象编码
pygame.encode_file_path() — 将 unicode 或字节对象编码为文件系统路径
pygame常用对象为:
pygame.Surface表面
pygame.draw绘图
pygame.font字体
pygame.image图片
pygame.sprite精灵
pygame.transform转换
pygame.event事件
pygame.time时间
pygame.mixer.Sound声音
Pygame语法比较多,且pygame不支持互动shell,不能一行行执行命令,因此最好学习方式是结合游戏实战编程。我们先用10行代码就完成第一个pygame游戏窗口,顺便了解pygame最主要的语法。
首先输入import pygame,sys导入具有所有可用pygame模块的包和系统模块。
pygame.display.
set_mode
()游戏窗口设置
初始化游戏窗口
set_mode(size=(0, 0), flags=0, depth=0, display=0) -> Surface
size参数是一对数字,代表宽度和高度。flags参数是其他选项的集合。
depth参数代表用于颜色的位数。颜色位数范围range is {8...32},通常最好不要传递depth参数。对于系统,它将默认为最佳和最快的颜色深度。如果您的游戏需要特定的颜色格式,则可以使用此参数控制深度。Pygame将模拟不可用的颜色深度,该深度可能很慢。
如果我们想要让游戏窗口在显示器上全屏展示,我们用pygame.FULLSCREEN对象。
windowSurface=pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT),pygame.FULLSCREEN)
颜色color
pygame.locals
此模块包含pygame使用的各种常量。它的内容会自动放置在pygame模块的命名空间中。但是,应用程序可以使用pygame.locals仅包含pygame.locals import *的pygame常量。
Event对象有一个名为type的成员变量(member variable,也叫作属性,attributes或properties),它告诉我们对象表示何种事件。针对pygame.locals模块中的每一种可能的类型,Pygame都有一个常量变量。第9行检查Event对象的type是否等于常量QUIT。记住,由于我们使用了from pygame.locals import *形式的import语句,主要输入QUIT就可以了,而不必输入pygame.locals.QUIT。
如果Event对象是一个停止事件,就会调用pygame.quit()和sys.exit()函数。pygame. quit()是pygame.init()函数的一种相反的函数,它运行的代码会使得Pygame库停止工作。在调用sys.exit()终止程序之前,总是应该先调用pygame.quit()。通常,由于程序退出之前,Python总是会关闭pygame,这不会真的有什么问题。但是,在IDLE中有一个bug,如果一个Pygame程序在调用pygame.quit()之前就终止了,将会导致IDLE挂起。
键盘按键
event.key==ord('a')
字母a-z: ord('a')----ord('z'), ord()内字母必须小写,否则出错。传递的是键盘对应小写字母的ASCII值
event.key==K_LEFT
箭头键arrow keys: K_LEFT, K_RIGHT, K_UP, K_DOWN.键盘右边的四个箭头按键
退出键ESC: K_ESCAPE
因为导入了from pygame.locals import*,所以我们可以用K_LEFT代替pygame.locals.K_LEFT
Pygame Constant Variable | Keyboard Key | Pygame Constant Variable | Keyboard Key |
---|---|---|---|
K_LEFT | Left arrow | K_HOME | Home |
K_RIGHT | Right arrow | K_END | End |
K_UP | Up arrow | K_PAGEUP | PgUp |
K_DOWN | Down arrow | K_PAGEDOWN | PgDn |
K_ESCAPE | Esc | K_F1 | F1 |
K_BACKSPACE | Backspace | K_F2 | F2 |
K_TAB | Tab | K_F3 | F3 |
K_RETURN | Return or Enter | K_F4 | F4 |
K_SPACE | Space bar | K_F5 | F5 |
K_DELETE | Del | K_F6 | F6 |
K_LSHIFT | Left Shift | K_F7 | F7 |
K_RSHIFT | Right Shift | K_F8 | F8 |
K_LCTRL | Left Ctrl | K_F9 | F9 |
K_RCTRL | Right Ctrl | K_F10 | F10 |
K_LALT | Left Alt | K_F11 | F11 |
K_RALT | Right Alt | K_F12 | F12 |
函数
pygame.event.pump() — 让 Pygame 内部自动处理事件
pygame.event.get() — 从队列中获取事件
pygame.event.poll() — 从队列中获取一个事件
pygame.event.wait() — 等待并从队列中获取一个事件
pygame.event.peek() — 检测某类型事件是否在队列中
pygame.event.clear() — 从队列中删除所有的事件
pygame.event.event_name() — 通过 id 获得该事件的字符串名字
pygame.event.set_blocked() — 控制哪些事件禁止进入队列
pygame.event.set_allowed() — 控制哪些事件允许进入队列
pygame.event.get_blocked() — 检测某一类型的事件是否被禁止进入队列
pygame.event.set_grab() — 控制输入设备与其他应用程序的共享
pygame.event.get_grab() — 检测程序是否共享输入设备
pygame.event.post() — 放置一个新的事件到队列中
pygame.event.Event() — 创建一个新的事件对象
pygame.event.EventType — 代表 SDL 事件的 Pygame 对象
Pygame 通过事件队列控制所有的时间消息。该模块中的程序将帮你管理事件队列。输入队列很大程度依赖于 pygame 的 display 模块。如果 display 没有被初始化,显示模式没有被设置,那么事件队列就还没有开始真正工作。
常规的队列是由 pygame.event.EventType 定义的事件对象的组成,有多种方法来访问里边的事件对象:从简单的检测事件是否存在,到直接从栈中获取它们。
为了保持 Pygame 和系统同步,你需要调用 pygame.event.pump() 确保实时更新,你将在游戏的每次循环中调用这个函数。
在做测试时,你可以输出事件对象以及相应的类型和成员。来自系统的事件都有一个事件类型和对应的成员属性,下边是每个事件类型以及对应的成员属性列表:
pygame.event.get()
从队列中获取事件。
get() -> Eventlist
get(type) -> Eventlist
get(typelist) -> Eventlist
这将获取并从队列中删除事件。如果指定一个或多个 type 参数,那么只获取并删除指定类型的事件。
请注意,如果你只从队列中获取和删除指定的事件,那么久而久之,队列可能被你不关注的事件所填满。
pygame.font字体
1.从系统字体库创建一个 Font 对象
font = pygame.font.SysFont(None, 48) #不熟悉字体名的就用None
pygame.font.SysFont(“字体”,字体大小)
举例
font = pygame.font.SysFont('Arial', 48)
2.使用对象里的 render方法渲染文字
render(text, antialias, color, background=None) -> Surface
举例
textobj = font.render(“”hello“”, 1, TEXTCOLOR)
3.获取字体矩形坐标
textrect = textobj.get_rect()
4.字体矩形坐标左上点赋值
textrect.topleft = (x, y)
5.字体更新到游戏窗口上
surface.blit(textobj, textrect)
drawText('Zombie VS Plants', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 4))
image图像
>>> pygame.image.__doc__
'pygame module for image transfer'
>>> dir(pygame.image)
['__doc__', '__file__', '__name__', '__package__', 'frombuffer', 'fromstring', 'get_extended', 'load', 'load_basic', 'load_extended', 'save', 'save_extended', 'tostring']
2
图形尺寸转换的函数:
>>> pygame.transform.scale.__doc__
'scale(Surface, (width, height), DestSurface = None) -> Surface\nresize to new resolution'
zombieImage=pygame.image.load('zombie.png')
zombieImageStretchedImage=pygame.transform.scale(zombieImage,(40,40))
pygame.transform.scale()函数可以放大或缩小精灵。
第一个参数是pygame.Surface 对象上画的图像。第二个参数是图形新尺寸。
pygame.transform.scale()函数返回一个pygame.Surface对象,此对象上的图像被赋予新尺寸。我们把原尺寸图像保存在变量playerImage 。但新的图像保存在变量playerStretchedImage。
playerImage and foodImage中保存的surface对象和用于window的surface对象一样。游戏中,我们把这些图像,字体的surfaces复制到window的surface,这样用户就可以在window窗口一目了然。Font 对象render()方法产生的surface对象也一样,为了显示文字,我们不得不复制surface对象到window surface对象。最后通过update()方法把window surface对象显示到屏幕上。
当矩形对象代表player的位置和尺寸时,player的图像也被保存在 playerStretchedImage变量中。我们用 pygame.transform.scale()函数改变了图像尺寸。确保传递原surface对象到变量 playerImage ,而不是到变量playerStretchedImage。图像尺寸变化后,图像会有点受损。如果反复变化尺寸,受损会越来越明显。但我们把原图像赋予新尺寸,受损只有小小一次。这就是为什么我们把playerImage变量作为第一个参数传递给pygame.transform.scale()
3
图形载入的函数
>>> pygame.image.load.__doc__
'pygame module for image transfer'
pygame.image.load()函数被传递一个图形文件的字符串参数,然后加载。value of pygame.image.load()返回一个surface对象,这个对象中,图像文件中图像画在它的surface上。我们把这surface对象保存在playerimage内。要确保图像位置和python目录一致。
sprite精灵代表一个二维图像,并作为屏幕上图形一部分。
这是精灵作为全图的例子
精灵图像被画在背景顶部。注意我们可以水平翻转精灵图像,这样精灵貌似朝着另一个方向。我们可以在同一个窗口画多个相同精灵。我们也可以重新定义精灵的尺寸,变大或变小。背景图像可以被看做一个大精灵。
精灵图像被画在背景顶部。注意我们可以水平翻转精灵图像,这样精灵貌似朝着另一个方向。我们可以在同一个窗口画多个相同精灵。我们也可以重新定义精灵的尺寸,变大或变小。背景图像可以被看做一个大精灵。
精灵被保存在电脑图像文件中pygame用的图像格式包括: BMP, PNG, JPG (and JPEG), and GIF.你也可以从web浏览器下载图像,你也可以用绘图程序制作图像。绘图工具有photoshop,MS Paint or Tux Paint.
pygame.rect()
rect = pygame.Rect(300, 100, 40, 40)
Pygame 通过 Rect 对象存储和操作矩形区域。一个 Rect 对象可以由 left,top,width,height 几个值创建。
rect对象是用来存储矩形对象的,rect对象有一些虚拟属性,
比如top.left,bottom.right这些是用来固定矩形的位置的,
还有size,width,height,这些是描述矩形大小,宽高分别是多大,
center为矩形的中心点,其实就是关于横纵坐标的二元组,因此又有centerx,centery两个属性。此外,还有x,y。
2.来自Pygame中文文档的解释:
class pygame.Rect
Rect是用于存储矩形坐标的pygame对象。
“构造”方法:
1).rect = pygame.Rect( left , top, width, height )
2). rect = pygame.Rect(( left , top),( width, height) )
3).rect = pygame.Rect(object)
Rect.move_ipmoves the rectangle, in placeRect.move_ip(x, y): return None
Same as the Rect.move - moves the rectangle method, but operates in place.
区别在于move_ip改变直接调整对象,move返回一个改变后的对象。
surface.blit VS pygame.display.update()
surface.blit是在游戏窗口surface上绘制对象
pygame.display.update()是把游戏窗口surface加载到电脑显示屏幕上
Surface.blit()
windowSurface.blit(bouncerStretchedImage,rect)
做出blit这个动作的人是一个Surface类的实例,
这个人即将在自己身上画图,
他需要两个参数:要画的图片,和画的位置,即source和rect.
source的类型是Surface, pygame.image.load(图片路径)返回的就是Surface
rect需要指定两个值,left和top,Surface类有get_rect()方法,返回Rect
Rect 是这个样子:
Rect(left, top, width, height) -> Rect
(left,top)坐标确定图片所在位置,width和height确定图片宽和高
冲突检测
图形化游戏最常见行为就是冲突检测。冲突检测指:屏幕上两个对象是否重叠。如果玩家碰到敌人,则可能损失生命值。在矩形弹动游戏中,冲突检测指两个矩形是否重叠。
>>> pygame.Rect.colliderect.__doc__
'colliderect(Rect) -> bool\ntest if two rectangles overlap'
#测试玩家是否触碰到僵尸def playerHasHitZombie(playerRect, zombies): for z in zombies: #test if two rectangles overlap测试是否触碰到僵尸 if playerRect.colliderect(z['rect']): return True return False #测试子弹是否触碰到僵尸。如果是,就把该僵尸移除def bulletHasHitZombie(bullets, zombies): for b in bullets: if b['rect'].colliderect(z['rect']): bullets.remove(b) return True return False #测试子弹是否触碰到新僵尸。如果是,就把该僵尸移除def bulletHasHitCrawler(bullets, newKindZombies): for b in bullets: if b['rect'].colliderect(c['rect']): bullets.remove(b) return True return False
首先输入import pygame,sys导入具有所有可用pygame模块的包和系统模块。创建一个简单的游戏窗口
现在游戏窗口还没有任何内容,之后我们可以逐步添加,设计自己的游戏。我已经用pygame完成了贪吃蛇,植物大战僵尸,俄罗斯方块,开心消消乐等知名游戏。
2.实例:python代码写个植物大战僵尸游戏
植物大战僵尸
《植物大战僵尸》是由PopCap Games开发的一款益智策略类单机游戏,发售于2009年5月5日。玩家通过利用多种植,并切换不同的功能,快速有效地把僵尸阻挡在入侵的道路上。
游戏里有26种僵尸,包括铁桶,报纸,铁门,橄榄球头盔,雪橇车,南瓜头,矿工帽,铁梯僵尸。这些僵尸会入侵我们后花园,我们要用各种植物消灭入侵僵尸。
49种植物每种都有不同的功能,例如樱桃炸弹可以和周围一定范围内的所有僵尸同归于尽,而食人花可以吃掉最靠近自己的一只僵尸。玩家可以针对不同僵尸的弱点来合理地种植植物,这也是胜利的诀窍。
下图是我用pygame编写的简易版植物大战僵尸游戏一个蓝色植物正在吐出圆球攻击僵尸,僵尸数量和移动速度可以自己控制。如果集中一个僵尸,score分数会增加一分,zombies gotten past记录有多少僵尸已经越过植物。当然我还可以设计一些作弊的按键,非常有趣!
不同的敌人,不同的玩法构成五种不同的游戏模式,加之黑夜、浓雾以及泳池之类的障碍增加了游戏挑战性。
这是房顶上植物们拼命抵抗僵尸入侵场景。
这是在后花园的游泳池里植物们拼命抵抗僵尸入侵场景。
僵尸挺聪明的,如果白天入侵不成功,就晚上搞偷袭。这是在深夜植物们拼命抵抗僵尸入侵场景。
这款python代码当然不是复现原款游戏所有功能,而是简单模拟一下其中乐趣。首先我们准备好以下素材。包括三张僵尸图片:
BucketheadZombie.gif,ConeheadZombie.gif,zombie.png。
一张植物图片plant.gif,一张背景图片background.png,一张子弹图片bullet.png
一首背景音乐background.mp3,一首游戏结束音乐gameover.mp3。由于游戏是之前基于python2.7版本写的,因此建议素材名称使用英文,python2版本对中文支持不太友好。
由于这款游戏代码量太大,这里就不一一展开说明,我建议你们直接去下载源代码和图片,然后根据自己爱好,更改一下背景音乐,图片,和僵尸数量,移动速度等参数设置。我对游戏一些重要语法做一些说明。
pygame.display.set_caption(words)设置窗口标题
pygame.display.set_caption(words)方法是设置窗口标题,words参数是窗口标题。我们沿用之前脚本运行下面脚本,我们就生成了一个有Zombie VS Plants标题的窗口。
pygame.event事件
常见事件有QUIT,KEYDOWN,KEYUP
while True: #main game loop游戏主循环 for event in pygame.event.get(): #遍历pygame事件列表 if event.type==QUIT: #如果点击关闭按钮(window右上) pygame.quit() #关闭pygame库 sys.exit() #系统退出
import pygame,sys #导入pygame和sys模块from pygame.locals import* #导入pygame 局部变量pygame.init() #pygame所有模块初始化screen=pygame.display.set_mode((400,300))#设置屏幕长和宽值pygame.display.set_caption('Zombie VS Plants')# 设置窗口标题while True: #main game loop游戏主循环 for event in pygame.event.get(): #遍历pygame事件列表 if event.type==QUIT: #如果点击关闭按钮(window右上) pygame.quit() #关闭pygame库 sys.exit() #系统退出
建立一个简单游戏窗口
pygame.time.Clock
pygame.time.Clock创建一个新的Clock对象,该对象可用于跟踪时间量。时钟还提供了多种功能来帮助控制游戏的帧频。
pygame中的时间以毫秒(1/1000秒)表示。大多数平台的时间分辨率有限,大约为10毫秒。该分辨率(以毫秒为单位)在TIMER_RESOLUTION常量中给出。
pygame.time.Clock.tick
()
tick(framerate=0) -> milliseconds
每帧应调用一次此方法。 它将计算自上次调用以来经过了多少毫秒。如果您传递可选的帧速率参数,该功能将延迟以使游戏的运行速度低于给定的每秒滴答声。 这可以用来帮助限制游戏的运行速度。 通过每帧调用Clock.tick(40)一次,该程序将永远不会以每秒40帧以上的速度运行。一般情况framerate设置为40.
游戏运行时每秒所运行的帧数(简称FPS,Frames Per Second) 和视频一样,FPS越大,在屏幕上的视频就越来越平滑,直到一个临界点(大约是100FPS),超过这个临界点,再高的FPS都只是一个令人惊奇的数值,400FPS和100FPS在人的视觉中几乎没有差别。
FPS取决于显卡,其次是内存,CPU,然后是网络(如果是网络游戏的话)与硬盘。
一般游戏都是40左右fps就可以称之为流畅了。比如策略类(三国志什么的)5fps也是可以接受的。但赛车类 5fps根本玩不下去。
每款游戏都会有一个官方提供的最低配置要求,尤其是网络游戏,但这个最低配置仅仅适用于将游戏内的所有视频效果全部关闭的状态下使用,而且网络游戏中对于网速的问题是忽略不计的。
只有提高电脑的显卡、内存才能在网络因素不确定的情况下达到最理想的游戏流畅效果。
音乐music
我们曾经玩任何游戏都会伴随动听的背景音乐。pygame.mixer是一个用来处理声音的模块,其含义为“混音器”。因此我们准备用以下方法pygame.mixer.music.load('background.mp3')加载mp3格式背景音乐并准备播放。这样游戏就会深动形象。
pygame.mixer.music.play(loop, start)方法用于播方音乐,loop表示循环次数,如果loop=1表示音乐播方一次。如果loop=2, 表示音乐播方两次。如果loop=-1,表示音乐不停循环。start 参数控制音乐从哪里开始播放。开始的位置取决于音乐的格式。MP3 和 OGG 使用时间表示播放位置(以秒为单位)。MOD使用模式顺序编号表示播放位置。如果音乐文件无法设置开始位置,则传递了start参数后会产生一个NotImplementedError 错误。
pygame.mixer.music.stop()方法用于结束音乐播放。如果游戏结束,我们可以加上这句方法,停止播放音乐。
pygame.mixer.music.load('background.mp3') ##载入一个音乐文件用于播放#,如果 loops = -1,则表示无限重复播放。start 参数控制音乐从哪里开始播放。pygame.mixer.music.play(-1, 0.0) #开始播放音乐流pygame.mixer.music.stop()#停止音乐播放
我们把加载和播方声音的代码加入主程序,这样游戏窗口就有音乐了。
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes'''import pygame,sys #导入pygame和sys模块from pygame.locals import* #导入pygame 局部变量pygame.init() #pygame所有模块初始化screen=pygame.display.set_mode((400,300))#设置屏幕长和宽值pygame.display.set_caption('Zombie VS Plants') pygame.mixer.music.load('background.mp3') ##载入一个音乐文件用于播放#,如果 loops = -1,则表示无限重复播放。start 参数控制音乐从哪里开始播放。pygame.mixer.music.play(-1, 0.0) #开始播放音乐流while True: #main game loop游戏主循环 for event in pygame.event.get(): #遍历pygame事件列表 if event.type==QUIT: #如果点击关闭按钮(window右上) pygame.quit() #关闭pygame库 sys.exit() #系统退出pygame.mixer.music.stop()#停止音乐播放
游戏结束时也会有相应音乐,我们文件里游戏结束音乐时wav格式的,和之前mp3格式不一样,我们用gameOverSound = pygame.mixer.Sound('gameover.wav')方法把游戏结束音乐放入gameOverSound变量。gameOverSound.play()方法播放游戏结束音乐。gameOverSound.stop()方法用于停止游戏结束声音播放。
1 2 3 4 |
|
参数前置
我们用pygame.display.set_mode((400,300))方法设置屏幕大小时候400,300为屏幕的长和宽。在大型程序设计时,一般不把具体数字放入方法里,而是用变量代替。我们用WINDOWWIDTH表示游戏窗口宽度,用WINDOWHEIGHT 表示游戏窗口高度,WINDOWWIDTH = 1024,WINDOWHEIGHT = 600。我们用以下代码实现游戏窗口大小的参数前置。
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes'''import pygame,sys #导入pygame和sys模块from pygame.locals import* #导入pygame 局部变量#设置变量参数,参数前置WINDOWWIDTH = 1024 #游戏窗口宽度WINDOWHEIGHT = 600 #游戏窗口高度pygame.init() #pygame所有模块初始化screen=pygame.display.set_mode((400,300))#设置屏幕长和宽值pygame.display.set_caption('Zombie VS Plants')#设置窗口大小windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))pygame.mixer.music.load('background.mp3') ##载入一个音乐文件用于播放#,如果 loops = -1,则表示无限重复播放。start 参数控制音乐从哪里开始播放。pygame.mixer.music.play(-1, 0.0) #开始播放音乐流while True: #main game loop游戏主循环 for event in pygame.event.get(): #遍历pygame事件列表 if event.type==QUIT: #如果点击关闭按钮(window右上) pygame.mixer.music.stop()#停止播放音乐 pygame.quit() #关闭pygame库 sys.exit() #系统退出
如果我们想要让游戏窗口在显示器上全屏展示,我们用pygame.FULLSCREEN对象。
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes'''import pygame,sys #导入pygame和sys模块from pygame.locals import* #导入pygame 局部变量#设置变量参数,参数前置WINDOWWIDTH = 1024 #游戏窗口宽度WINDOWHEIGHT = 600 #游戏窗口高度pygame.init() #pygame所有模块初始化screen=pygame.display.set_mode((400,300))#设置屏幕长和宽值pygame.display.set_caption('Zombie VS Plants')#设置窗口大小windowSurface=pygame.display.set_mode((WINDOWWIDTH,WINDOWHEIGHT),pygame.FULLSCREEN)pygame.mixer.music.load('background.mp3') ##载入一个音乐文件用于播放#,如果 loops = -1,则表示无限重复播放。start 参数控制音乐从哪里开始播放。pygame.mixer.music.play(-1, 0.0) #开始播放音乐流while True: #main game loop游戏主循环 for event in pygame.event.get(): #遍历pygame事件列表 if event.type==QUIT: #如果点击关闭按钮(window右上) pygame.mixer.music.stop() #停止播放音乐 pygame.quit() #关闭pygame库 sys.exit() #系统退出
鼠标
#鼠标设置不可见
pygame.mouse.set_visible(False)
键盘设置
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes'''while True: for event in pygame.event.get(): if event.type==QUIT: terminate() if event.type==pygame.locals.KEYDOWN: #change the keyboard variables键盘键设置上下左右 if event.key==pygame.locals.K_LEFT or event.key==ord('a'): moveRight=False moveLeft=True if event.key==pygame.locals.K_RIGHT or event.key==ord('d'): moveLeft=False moveRight=True if event.key==pygame.locals.K_UP or event.key==ord('w'): moveDown=False moveUp=True if event.key==pygame.locals.K_DOWN or event.key==ord('s'): moveDown=True moveUp=False #有KEYDOWN就一定有KEYUP,否则游戏对象会持续移动 if event.type==pygame.locals.KEYUP: if event.key==pygame.locals.K_ESCAPE: pygame.quit() sys.exit() if event.key==pygame.locals.K_LEFT or event.key==ord('a'): moveLeft=False if event.key==K_RIGHT or event.key==ord('d'): moveRight=False if event.key==K_UP or event.key==ord('w'): moveUp=False if event.key==K_DOWN or event.key==ord('s'): moveDown=False # move the bouncer data structure if moveDown and p_destination.bottom p_destination.top+=PLAYERMOVERATE if moveUp and p_destination.top>0: p_destination.top-=PLAYERMOVERATE if moveLeft and p_destination.left>0: p_destination.left-=PLAYERMOVERATE if moveRight and p_destination.right p_destination.right+=PLAYERMOVERATE # Draw the game world on the window. windowSurface.blit(rescaledBackground, (0, 0)) windowSurface.blit(zombieStretchedImage,z_destination) windowSurface.blit(playerImage,p_destination)
发射子弹
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes''''''playerRect = playerImage.get_rect()playerRect.topleft = (50, WINDOWHEIGHT /2) #子弹图像加载bulletImage = pygame.image.load('SnowPeashooterBullet.gif')bulletRect = bulletImage.get_rect() #连续发射两个子弹的距离,值越小,子弹距离越近,反之亦然BULLETSPEED = 30#新增子弹速度,值越小,子弹发射越快ADDNEWBULLETRATE = 5b['rect'].move_ip(1 * BULLETSPEED, 0)#增加子弹计数器bulletAddCounter = 0''' import pygame, random, sys, timefrom pygame.locals import * #set up some variablesWINDOWWIDTH = 1024WINDOWHEIGHT = 600#值设置低一些,僵尸移动速度变慢FPS = 20PLAYERMOVERATE = 15#连续发射两个子弹的距离,值越小,子弹距离越近,反之亦然BULLETSPEED = 30#新增子弹速度,值越小,子弹发射越快ADDNEWBULLETRATE = 5shoot = False#增加子弹计数器bulletAddCounter = 0RED = (255, 0, 0) #结束游戏def terminate(): pygame.quit() sys.exit() # set up pygame, the window, and the mouse cursorpygame.init()#reate an object to help track timemainClock = pygame.time.Clock()windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))#, pygame.FULLSCREEN)#窗口标题pygame.display.set_caption('Zombie Defence')#鼠标设置不可见#pygame.mouse.set_visible(False) # set up fonts设置字体font = pygame.font.SysFont(None, 48) #加载声音pygame.mixer.music.load('grasswalk.mp3') # set up imagesplayerImage = pygame.image.load('SnowPea.gif')#get the rectangular area of the Surface#Returns a new rectangle covering the entire surface. This rectangle will#always start at (0, 0) with a width and height the same size as the image.playerRect = playerImage.get_rect()#子弹图像加载bulletImage = pygame.image.load('SnowPeashooterBullet.gif')bulletRect = bulletImage.get_rect() zombieImage=pygame.image.load("zombie.png")zombieStretchedImage=pygame.transform.scale(zombieImage,(80,80))z_destination=pygame.Rect(944, 300, 80, 80)#游戏背景图片加载backgroundImage = pygame.image.load('background.png')#对背景图片尺寸重新调整大小,宽为WINDOWWIDTH,长为WINDOWHEIGHTrescaledBackground = pygame.transform.scale(backgroundImage, (WINDOWWIDTH, WINDOWHEIGHT)) zombies = []bullets = []playerRect.topleft = (50, WINDOWHEIGHT /2)moveLeft = moveRight = FalsemoveUp=moveDown = False pygame.mixer.music.play(-1, 0.0) #游戏开始循环while True: # the game loop runs while the game part is playing for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == K_UP or event.key == ord('w'): moveDown = False moveUp = True if event.key == K_DOWN or event.key == ord('s'): moveUp = False moveDown = True if event.key == K_SPACE: shoot = True if event.type == KEYUP: if event.key == K_ESCAPE: terminate() if event.key == K_UP or event.key == ord('w'): moveUp = False if event.key == K_DOWN or event.key == ord('s'): moveDown = False if event.key == K_SPACE: shoot = False # add new bullet新增子弹 #新增子弹计数器 bulletAddCounter += 1 print("bulletAddCounter:",bulletAddCounter) #当while循环次数大于ADDNEWBULLETRATE时,才能发射子弹 if bulletAddCounter >= ADDNEWBULLETRATE and shoot == True: print("shoot") #if shoot == True: #如果不限制,子弹会连发,没有距离感 bulletAddCounter = 0 #playerRect.centery-25是为了让子弹上升一点,与植物炮口平行,centerx+10是为了子弹在前面点出现 newBullet = {
'rect':pygame.Rect(playerRect.centerx+10, playerRect.centery-30, bulletRect.width, bulletRect.height), 'surface':pygame.transform.scale(bulletImage, (bulletRect.width, bulletRect.height)), } bullets.append(newBullet) # Move the player around. if moveUp and playerRect.top > 30: playerRect.move_ip(0,-1 * PLAYERMOVERATE) if moveDown and playerRect.bottom < WINDOWHEIGHT-10: playerRect.move_ip(0,PLAYERMOVERATE) # move the bullet移动子弹 for b in bullets: b['rect'].move_ip(1 * BULLETSPEED, 0) #print(b['rect']) # Draw the game world on the window. windowSurface.blit(rescaledBackground, (0, 0)) # Draw the player's rectangle, rails windowSurface.blit(playerImage, playerRect) windowSurface.blit(zombieStretchedImage,z_destination) # draw each bullet将所有子弹绘制到游戏界面上 for b in bullets: windowSurface.blit(b['surface'], b['rect']) # update the display pygame.display.update() #tick(framerate=0) -> milliseconds #帧速率参数,该功能将延迟以使游戏的运行速度低 mainClock.tick(FPS) #print("bullets",bullets)
random.randint(a,b)随机生成若干移动僵尸
在python中的random.randint(a,b)用于生成一bai个指定范围内的整数。du其中参数zhia是下限,参数b是上限,生成的随机dao数n: a <= n <= b。
'''僵尸移动作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes''' import pygame, random, sys, timefrom pygame.locals import * #set up some variablesWINDOWWIDTH = 1024WINDOWHEIGHT = 600#值设置低一些,僵尸移动速度变慢FPS = 20PLAYERMOVERATE = 15#连续发射两个子弹的距离,值越小,子弹距离越近,反之亦然BULLETSPEED = 30#新增子弹速度,值越小,子弹发射越快ADDNEWBULLETRATE = 5shoot = False#增加子弹计数器bulletAddCounter = 0#增加僵尸计数器zombieAddCounter=0 ZOMBIESIZE = 100 #includes newKindZombies#新增丧尸速度,值设置大些,丧失数量少些ADDNEWZOMBIERATE = 50ADDNEWKINDZOMBIE = ADDNEWZOMBIERATE NORMALZOMBIESPEED = 2NEWKINDZOMBIESPEED = NORMALZOMBIESPEED / 2 # set up the colors颜色值设置,可用于背景颜色BLACK = (0, 0, 0)GREEN = (0, 255, 0)WHITE = (255, 255, 255)RED=(255, 0, 0)#结束游戏def terminate(): pygame.quit() sys.exit() # set up pygame, the window, and the mouse cursorpygame.init()#reate an object to help track timemainClock = pygame.time.Clock()windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))#, pygame.FULLSCREEN)#窗口标题pygame.display.set_caption('Zombie Defence')#鼠标设置不可见#pygame.mouse.set_visible(False) # set up fonts设置字体font = pygame.font.SysFont(None, 48) #加载声音pygame.mixer.music.load('grasswalk.mp3') # set up imagesplayerImage = pygame.image.load('SnowPea.gif')#get the rectangular area of the Surface#Returns a new rectangle covering the entire surface. This rectangle will#always start at (0, 0) with a width and height the same size as the image.playerRect = playerImage.get_rect()#子弹图像加载bulletImage = pygame.image.load('SnowPeashooterBullet.gif')bulletRect = bulletImage.get_rect() zombieImage=pygame.image.load("zombie.png")zombieStretchedImage=pygame.transform.scale(zombieImage,(80,80))z_destination=pygame.Rect(944, 300, 80, 80)#游戏背景图片加载backgroundImage = pygame.image.load('background.png')#对背景图片尺寸重新调整大小,宽为WINDOWWIDTH,长为WINDOWHEIGHTrescaledBackground = pygame.transform.scale(backgroundImage, (WINDOWWIDTH, WINDOWHEIGHT)) zombies = []bullets = []playerRect.topleft = (50, WINDOWHEIGHT /2)moveLeft = moveRight = FalsemoveUp=moveDown = False pygame.mixer.music.play(-1, 0.0) #游戏开始循环while True: # the game loop runs while the game part is playing for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == K_UP or event.key == ord('w'): moveDown = False moveUp = True if event.key == K_DOWN or event.key == ord('s'): moveUp = False moveDown = True if event.key == K_SPACE: shoot = True if event.type == KEYUP: if event.key == K_ESCAPE: terminate() if event.key == K_UP or event.key == ord('w'): moveUp = False if event.key == K_DOWN or event.key == ord('s'): moveDown = False if event.key == K_SPACE: shoot = False # Add new zombies at the top of the screen, if needed.增加上市 zombieAddCounter += 1 if zombieAddCounter == ADDNEWKINDZOMBIE: zombieAddCounter = 0 zombieSize = ZOMBIESIZE newZombie = {
'rect': pygame.Rect(WINDOWWIDTH, random.randint(10,WINDOWHEIGHT-zombieSize-10), zombieSize, zombieSize), 'surface':pygame.transform.scale(zombieImage, (zombieSize, zombieSize)), } zombies.append(newZombie) # add new bullet新增子弹 #新增子弹计数器 bulletAddCounter += 1 print("bulletAddCounter:",bulletAddCounter) #当while循环次数大于ADDNEWBULLETRATE时,才能发射子弹 if bulletAddCounter >= ADDNEWBULLETRATE and shoot == True: print("shoot") #if shoot == True: #如果不限制,子弹会连发,没有距离感 bulletAddCounter = 0 #playerRect.centery-25是为了让子弹上升一点,与植物炮口平行,centerx+10是为了子弹在前面点出现 newBullet = {
'rect':pygame.Rect(playerRect.centerx+10, playerRect.centery-30, bulletRect.width, bulletRect.height), 'surface':pygame.transform.scale(bulletImage, (bulletRect.width, bulletRect.height)), } bullets.append(newBullet) # Move the player around. if moveUp and playerRect.top > 30: playerRect.move_ip(0,-1 * PLAYERMOVERATE) if moveDown and playerRect.bottom < WINDOWHEIGHT-10: playerRect.move_ip(0,PLAYERMOVERATE) # move the bullet移动子弹 for b in bullets: b['rect'].move_ip(1 * BULLETSPEED, 0) #print(b['rect']) # Move the zombies. for z in zombies: z['rect'].move_ip(-1*NORMALZOMBIESPEED, 0) # Draw the game world on the window. windowSurface.blit(rescaledBackground, (0, 0)) # Draw the player's rectangle, rails windowSurface.blit(playerImage, playerRect) windowSurface.blit(zombieStretchedImage,z_destination) # draw each bullet将所有子弹绘制到游戏界面上 for b in bullets: windowSurface.blit(b['surface'], b['rect']) # Draw each baddie for z in zombies: windowSurface.blit(z['surface'], z['rect']) # update the display pygame.display.update() #tick(framerate=0) -> milliseconds #帧速率参数,该功能将延迟以使游戏的运行速度低 mainClock.tick(FPS) #print("bullets",bullets)
完整的植物大战僵尸游戏代码如下。你们可以根据自己偏好来改变人物图片,背景,配音。
'''作者QQ:231469242微信公众号:pythonEducationPython菜鸟快乐游戏编程_pygame:http://dwz.date/cfGs作者教学主页:http://dwz.date/bwes'''import pygame, random, sys, timefrom pygame.locals import * #set up some variablesWINDOWWIDTH = 1024WINDOWHEIGHT = 600#值设置低一些,僵尸移动速度变慢FPS = 20MAXGOTTENPASS = 10ZOMBIESIZE = 100 #includes newKindZombies#新增丧尸速度,值设置大些,丧失数量少些ADDNEWZOMBIERATE = 50ADDNEWKINDZOMBIE = ADDNEWZOMBIERATENORMALZOMBIESPEED = 2NEWKINDZOMBIESPEED = NORMALZOMBIESPEED / 2PLAYERMOVERATE = 15#子弹速度BULLETSPEED = 20ADDNEWBULLETRATE = 15 TEXTCOLOR = (255, 255, 255)RED = (255, 0, 0) #结束游戏def terminate(): pygame.quit() sys.exit()#等待玩家按键def waitForPlayerToPressKey(): while True: for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == K_ESCAPE: # pressing escape quits terminate() if event.key == K_RETURN: return #测试玩家是否触碰到僵尸def playerHasHitZombie(playerRect, zombies): for z in zombies: #test if two rectangles overlap测试是否触碰到僵尸 if playerRect.colliderect(z['rect']): return True return False #测试子弹是否触碰到僵尸。如果是,就把该僵尸移除def bulletHasHitZombie(bullets, zombies): for b in bullets: if b['rect'].colliderect(z['rect']): bullets.remove(b) return True return False #测试子弹是否触碰到新僵尸。如果是,就把该僵尸移除def bulletHasHitCrawler(bullets, newKindZombies): for b in bullets: if b['rect'].colliderect(c['rect']): bullets.remove(b) return True return False #输入文字显示def drawText(text, font, surface, x, y): textobj = font.render(text, 1, TEXTCOLOR) textrect = textobj.get_rect() textrect.topleft = (x, y) #draw one image onto another surface.blit(textobj, textrect) # set up pygame, the window, and the mouse cursorpygame.init()#reate an object to help track timemainClock = pygame.time.Clock()windowSurface = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT))#, pygame.FULLSCREEN)#窗口标题pygame.display.set_caption('Zombie VS Plants')#鼠标设置不可见pygame.mouse.set_visible(False)# set up fonts设置字体font = pygame.font.SysFont(None, 48)# set up sounds设置声音gameOverSound = pygame.mixer.Sound('gameover.wav')#加载声音pygame.mixer.music.load('background.mp3')# set up imagesplayerImage = pygame.image.load('plant.gif')#get the rectangular area of the Surface#Returns a new rectangle covering the entire surface. This rectangle will#always start at (0, 0) with a width and height the same size as the image.playerRect = playerImage.get_rect()#子弹图像加载bulletImage = pygame.image.load('bullet.gif')bulletRect = bulletImage.get_rect()zombieImage = pygame.image.load('zombie.png')newKindZombieImage = pygame.image.load('ConeheadZombie.gif')#newKindZombieImage = pygame.image.load('trump31.png')#游戏背景图片加载backgroundImage = pygame.image.load('background.png')#对背景图片尺寸重新调整大小,宽为WINDOWWIDTH,长为WINDOWHEIGHTrescaledBackground = pygame.transform.scale(backgroundImage, (WINDOWWIDTH, WINDOWHEIGHT)) # show the "Start" screenwindowSurface.blit(rescaledBackground, (0, 0))windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 70))drawText('Zombie VS Plants', font, windowSurface, (WINDOWWIDTH / 4), (WINDOWHEIGHT / 4))drawText('Press Enter to start', font, windowSurface, (WINDOWWIDTH / 3) - 10, (WINDOWHEIGHT / 3) + 50)pygame.display.update()waitForPlayerToPressKey()#主循环while True: # set up the start of the game zombies = [] newKindZombies = [] bullets = [] zombiesGottenPast = 0 score = 0 playerRect.topleft = (50, WINDOWHEIGHT /2) moveLeft = moveRight = False moveUp=moveDown = False shoot = False zombieAddCounter = 0 newKindZombieAddCounter = 0 bulletAddCounter = 40 pygame.mixer.music.play(-1, 0.0) #游戏开始循环 while True: # the game loop runs while the game part is playing for event in pygame.event.get(): if event.type == QUIT: terminate() if event.type == KEYDOWN: if event.key == K_UP or event.key == ord('w'): moveDown = False moveUp = True if event.key == K_DOWN or event.key == ord('s'): moveUp = False moveDown = True if event.key == K_SPACE: shoot = True if event.type == KEYUP: if event.key == K_ESCAPE: terminate() if event.key == K_UP or event.key == ord('w'): moveUp = False if event.key == K_DOWN or event.key == ord('s'): moveDown = False if event.key == K_SPACE: shoot = False # Add new zombies at the top of the screen, if needed.增加上市 zombieAddCounter += 1 if zombieAddCounter == ADDNEWKINDZOMBIE: zombieAddCounter = 0 zombieSize = ZOMBIESIZE newZombie = {
'rect': pygame.Rect(WINDOWWIDTH, random.randint(10,WINDOWHEIGHT-zombieSize-10), zombieSize, zombieSize), 'surface':pygame.transform.scale(zombieImage, (zombieSize, zombieSize)), } zombies.append(newZombie) # Add new newKindZombies at the top of the screen, if needed. newKindZombieAddCounter += 1 if newKindZombieAddCounter == ADDNEWZOMBIERATE: newKindZombieAddCounter = 0 newKindZombiesize = ZOMBIESIZE newCrawler = {
'rect': pygame.Rect(WINDOWWIDTH, random.randint(10,WINDOWHEIGHT-newKindZombiesize-10), newKindZombiesize, newKindZombiesize), 'surface':pygame.transform.scale(newKindZombieImage, (newKindZombiesize, newKindZombiesize)), } newKindZombies.append(newCrawler) # add new bullet bulletAddCounter += 1 if bulletAddCounter >= ADDNEWBULLETRATE and shoot == True: bulletAddCounter = 0 newBullet = {
'rect':pygame.Rect(playerRect.centerx+10, playerRect.centery-25, bulletRect.width, bulletRect.height), 'surface':pygame.transform.scale(bulletImage, (bulletRect.width, bulletRect.height)), } bullets.append(newBullet) # Move the player around. if moveUp and playerRect.top > 30: playerRect.move_ip(0,-1 * PLAYERMOVERATE) if moveDown and playerRect.bottom < WINDOWHEIGHT-10: playerRect.move_ip(0,PLAYERMOVERATE) # Move the zombies down. for z in zombies: z['rect'].move_ip(-1*NORMALZOMBIESPEED, 0) # Move the newKindZombies down. for c in newKindZombies: c['rect'].move_ip(-1*NEWKINDZOMBIESPEED,0) # move the bullet for b in bullets: b['rect'].move_ip(1 * BULLETSPEED, 0) # Delete zombies that have fallen past the bottom. for z in zombies[:]: if z['rect'].left < 0: zombies.remove(z) zombiesGottenPast += 1 # Delete newKindZombies that have fallen past the bottom. for c in newKindZombies[:]: if c['rect'].left <0: newKindZombies.remove(c) zombiesGottenPast += 1 for b in bullets[:]: if b['rect'].right>WINDOWWIDTH: bullets.remove(b) # check if the bullet has hit the zombie 检查子弹是否触碰到僵尸 for z in zombies: if bulletHasHitZombie(bullets, zombies): score += 1 zombies.remove(z) #检查子弹是否触碰到新僵尸 for c in newKindZombies: if bulletHasHitCrawler(bullets, newKindZombies): score += 1 newKindZombies.remove(c) # Draw the game world on the window. windowSurface.blit(rescaledBackground, (0, 0)) # Draw the player's rectangle, rails windowSurface.blit(playerImage, playerRect) # Draw each baddie for z in zombies: windowSurface.blit(z['surface'], z['rect']) for c in newKindZombies: windowSurface.blit(c['surface'], c['rect']) # draw each bullet for b in bullets: windowSurface.blit(b['surface'], b['rect']) # Draw the score and how many zombies got past drawText('zombies gotten past: %s' % (zombiesGottenPast), font, windowSurface, 10, 20) drawText('score: %s' % (score), font, windowSurface, 10, 50) # update the display pygame.display.update() # Check if any of the zombies has hit the player. if playerHasHitZombie(playerRect, zombies): break if playerHasHitZombie(playerRect, newKindZombies): break # check if score is over MAXGOTTENPASS which means game over if zombiesGottenPast >= MAXGOTTENPASS: break #tick(framerate=0) -> milliseconds #帧速率参数,该功能将延迟以使游戏的运行速度低 mainClock.tick(FPS) # Stop the game and show the "Game Over" screen.游戏结束执行命令 pygame.mixer.music.stop() gameOverSound.play() #播放游戏结束时声音 time.sleep(1) if zombiesGottenPast >= MAXGOTTENPASS: windowSurface.blit(rescaledBackground, (0, 0)) windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 70)) drawText('score: %s' % (score), font, windowSurface, 10, 30) drawText('GAME OVER', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3)) drawText('YOUR COUNTRY HAS BEEN DESTROIED', font, windowSurface, (WINDOWWIDTH / 4)- 80, (WINDOWHEIGHT / 3) + 100) drawText('Press enter to play again or escape to exit', font, windowSurface, (WINDOWWIDTH / 4) - 80, (WINDOWHEIGHT / 3) + 150) pygame.display.update() waitForPlayerToPressKey() if playerHasHitZombie(playerRect, zombies): windowSurface.blit(rescaledBackground, (0, 0)) windowSurface.blit(playerImage, (WINDOWWIDTH / 2, WINDOWHEIGHT - 70)) drawText('score: %s' % (score), font, windowSurface, 10, 30) drawText('GAME OVER', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3)) drawText('YOU HAVE BEEN KISSED BY THE ZOMMBIE', font, windowSurface, (WINDOWWIDTH / 4) - 80, (WINDOWHEIGHT / 3) +100) drawText('Press enter to play again or escape to exit', font, windowSurface, (WINDOWWIDTH / 4) - 80, (WINDOWHEIGHT / 3) + 150) pygame.display.update() waitForPlayerToPressKey() gameOverSound.stop() #游戏结束声音停止
这一章我们学习了python的pygame模块,了解了pygame模块的基础知识和如何编写植物大战僵尸的DIY游戏。总之pygame在编写视频游戏上方便,高效,且具有高度的可移植性,几乎可以在所有平台和操作系统上运行。不要等了,赶紧去安装pygame模块,开始第一个游戏编程之旅吧。
https://study.163.com/provider/400000000398149/index.htm?share=2&shareId=400000000398149(博主视频教学主页)
博主的Python视频教学中心:https://m.study.163.com/user/1135726305.htm?utm_campaign=share&utm_medium=iphoneShare&utm_source=weixin&utm_u=1015941113