大家好,欢迎来到 Crossin的编程教室 !

今天跟大家讲一讲:如何做游戏

游戏的主题是弹球游戏《PONG》,它是史上第一款街机游戏。因此选它作为我这个游戏开发系列的第一期主题。

游戏引擎用的是 Python 的一个游戏库:pgzero。它是对 pygame 的一个封装,让你不需要写多余的套路代码,只要配置游戏的内容逻辑即可。

我们这个游戏用它来写,一共只需要100行代码。

首先需要安装 python 环境。这一步没搞定的同学,可以参考我们 python 入门教程:http://python666.cn ,上面有详细图文介绍。

然后需要安装 pgzero 库,可以命令行下通过 pip 命令安装:

pip install pgzero

安装完,运行一句

pgzrun.go()

我们的游戏世界之门就已经打开了。

现在上面还是混沌初开,一片漆黑。

设定一个矩形的左上角坐标和长宽,在游戏的绘制函数 draw 中用指定颜色填充,我们就得到了一个矩形。

pad_1 = Rect((20, 20), (10, 100))

def draw():
screen.clear()
screen.draw.filled_rect(pad_1, 'white')

适当调整一下,就得到了一块游戏中用来挡球的板。

在游戏的更新函数中增加判断,当键盘上的“上”、“下”按键被按下时,修改挡板的y坐标,就可以在游戏中控制挡板的移动了。

PAD_SPEED = 10

def update(dt):
if keyboard.up:
pad_1.y -= PAD_SPEED
elif keyboard.down:
pad_1.y += PAD_SPEED

这样就已经完成 PONG 游戏中的玩家操控角色:一块可上下移动的挡板。而现在我们用到的代码仅仅10行。

有的小伙伴可能注意到了,这里有两个函数,一个叫 draw,它是负责游戏中的画面绘制,另一个叫 update,它负责游戏中的逻辑更新。

我们经常听到说游戏运行时速度是每秒30帧、60帧之类,或者叫做 FPS(Frames Per Second)。draw 和 update 就是在游戏的“一帧”画面中所要做的事情。你的计算机或者游戏主机的性能越高,每一帧所花费的计算时间就越少,游戏帧数就可以更高,游戏体验也就更流畅。

创建一个叫做 Ball 的类型,属性值包括位置和速度。然后,在绘图函数中以小球的位置为圆心画一个圆,在更新函数中按照匀速直线运动位移公式,也就是 位移=速度x时间,计算出小球下一帧的位置。如此就实现了一个会运动的小球。

class Ball():
def __init__(self):
self.pos = [300, 200]
self.speed = [1, 1]
def update(self, dt):
for i in range(2):
self.pos[i] += self.speed[i] * dt ball = Ball() def draw():
screen.clear()
screen.draw.filled_rect(pad_1, 'white')
screen.draw.filled_circle(ball.pos, BALL_RADIUS, 'white')

再设置一下边界条件,让小球到达屏幕边缘时可以改变对应的速度方向,碰到上下边缘就将y速度分量乘以-1,超出左右边缘则位置重新设置回屏幕中心。

class Ball():
... def update(self, dt):
for i in range(2):
self.pos[i] += self.speed[i] if self.pos[1] < 0 or self.pos[1] > HEIGHT:
self.speed[1] *= -1
if self.pos[0] < 0 or self.pos[0] > WIDTH:
self.reset()

有了板,有了球,接下来就是让他们之间产生关联。

在更新函数中做一个碰撞检测:如果板子的矩形与球的圆心产生了交集,就让球反弹回去。

def update(dt):
... ball.update(dt) if pad_1.collidepoint(ball.pos) and ball.speed[0] < 0:
ball.speed[0] *= -1

到这一步,游戏的核心物理规则就已经定义完毕。

按照同样的方法,在屏幕的右侧创建第二块板,通过另外的按键进行控制。然后,当小球超出左右边界时,分别给对面一方得分。

class Ball():
... def dead(self, side):
scores[side] += 1
self.reset()

这样,一个最最简单的,双人版弹球游戏就完成了。

当然,如果你找不到另一个人陪你一起玩,也可以让自己的左手跟右手玩。

或者,给一侧板增加一点自动追踪的代码:让板的位置随着球的位置移动。这也算是一个游戏AI了。

def auto_move_pad(dt):
if ball.pos[0] > WIDTH / 2 and ball.speed[0] > 0:
if pad_2.y + pad_2.height * 0.25 > ball.pos[1]:
pad_2.y -= PAD_SPEED * dt
if pad_2.top < 0:
pad_2.top = 0
elif pad_2.y + pad_2.height * 0.75 < ball.pos[1]:
pad_2.y += PAD_SPEED * dt
if pad_2.bottom > HEIGHT:
pad_2.bottom = HEIGHT

至此,一个具备完整核心玩法的弹球游戏 PONG 已经完成了。加上空格也不到100行代码。特别适合编程新手刚刚接触游戏开发的小伙伴进行练习。

不过,我还给游戏增加了一点点细节,感兴趣的小伙伴可点击视频进行观看。喜欢的话欢迎点赞和转发!

https://www.bilibili.com/video/BV1Pr4y1s7wk/

之后我还会来尝试更多的游戏类型,更多的玩法。争取完成最初立下的FLAG:实现100个游戏。如果你想看某类游戏或者某个游戏的实现,或者对某个实现细节有疑问,也可以留言中告诉我,我会优先考虑。

代码已经开源,可通过“Crossin的编程教室”获取

https://github.com/crossin/games100


获取更多教程和案例,

欢迎搜索及关注:Crossin的编程教室

每天5分钟,轻松学编程。

【编程教室】PONG - 100行代码写一个弹球游戏的更多相关文章

  1. 100行代码实现一个RISC-V架构下的多线程管理框架

    1. 摘要 本文将基于RISC-V架构和qemu仿真器实现一个简单的多线程调度和管理框架, 旨在通过简单的代码阐明如何实现线程的上下文保存和切换, 线程的调度并非本文的重点, 故线程调度模块只是简单地 ...

  2. python实战:用70行代码写了一个山炮计算器!

    python实战训练:用70行代码写了个山炮计算器! 好了...好了...各位因为我是三年级而发牢骚的各位伙伴们,我第一次为大家插播了python的基础实战训练.这个,我是想给,那些python基础一 ...

  3. 100行代码让您学会JavaScript原生的Proxy设计模式

    面向对象设计里的设计模式之Proxy(代理)模式,相信很多朋友已经很熟悉了.比如我之前写过代理模式在Java中实现的两篇文章: Java代理设计模式(Proxy)的四种具体实现:静态代理和动态代理 J ...

  4. 通过 Mesos、Docker 和 Go,使用 300 行代码创建一个分布式系统

    [摘要]虽然 Docker 和 Mesos 已成为不折不扣的 Buzzwords ,但是对于大部分人来说它们仍然是陌生的,下面我们就一起领略 Mesos .Docker 和 Go 配合带来的强大破坏力 ...

  5. 【转】100行代码实现最简单的基于FFMPEG+SDL的视频播放器

    FFMPEG工程浩大,可以参考的书籍又不是很多,因此很多刚学习FFMPEG的人常常感觉到无从下手.我刚接触FFMPEG的时候也感觉不知从何学起. 因此我把自己做项目过程中实现的一个非常简单的视频播放器 ...

  6. 100行代码实现现代版Router

      原文:http://www.html-js.com/article/JavaScript-version-100-lines-of-code-to-achieve-a-modern-version ...

  7. Shell 命令行,写一个自动整理 ~/Downloads/ 文件夹下文件的脚本

    Shell 命令行,写一个自动整理 ~/Downloads/ 文件夹下文件的脚本 在 mac 或者 linux 系统中,我们的浏览器或者其他下载软件下载的文件全部都下载再 ~/Downloads/ 文 ...

  8. 100行代码实现最简单的基于FFMPEG+SDL的视频播放器(SDL1.x)【转】

    转自:http://blog.csdn.net/leixiaohua1020/article/details/8652605 版权声明:本文为博主原创文章,未经博主允许不得转载.   目录(?)[-] ...

  9. 通过Mesos、Docker和Go,使用300行代码创建一个分布式系统

    [摘要]虽然 Docker 和 Mesos 已成为不折不扣的 Buzzwords ,但是对于大部分人来说它们仍然是陌生的,下面我们就一起领略 Mesos .Docker 和 Go 配合带来的强大破坏力 ...

随机推荐

  1. tomcat的基本使用及项目部署

    tomcat介绍 我们在学习Javaweb的时候,最普遍使用的服务器j就是阿帕奇的tomcat,主要是用来处理jsp和servlet的请求以及响应 tomcat的启动和关闭 在我们安装完tomcat后 ...

  2. MyBatis缓存Cache包

    Mybatis默认使用了一级缓存为数据查询提供效率,其底层数据结构为PerpetualCache.同时MyBatis不止实现了PerpetualCache,还有其他实现提供其他功能,如下: 可以从UM ...

  3. Anchor-free目标检测综述 -- Keypoint-based篇

      早期目标检测研究以anchor-based为主,设定初始anchor,预测anchor的修正值,分为two-stage目标检测与one-stage目标检测,分别以Faster R-CNN和SSD作 ...

  4. go 互斥锁实现原理

    目录 go 互斥锁的实现 1. mutex的数据结构 1.1 mutex结构体,抢锁解锁原理 1.2 mutex方法 2. 加解锁过程 2.1 简单加锁 2.2 加锁被阻塞 2.3 简单解锁 2.4 ...

  5. 命令行下Git调用IDEA的diff功能

    命令行下git diff, 有人欢喜有人厌, 本文以IDEA diff为例, 介绍如何更换Git的diff工具. IDEA diff IDEA作为一个图形化工具, 其实也提供了极少一部分命令行接口, ...

  6. c++基础的记录(随笔记录一些基础的东西)

    1.父类的析构函数为什么要加上virtual关键字. 比如说,父类A,子类B.在A* a = new B()的语句的时候,如果父类析构函数没有virtual,我们在delete指针a的时候,会走父类的 ...

  7. 宿主机ping不通虚拟机,虚拟机能ping通宿主机

    最近,微信提升群里好几个小伙伴遇到了如题的问题. 问了下原因,原来是我说的把宿主机网卡ip获取方式改为自动,结果他们把宿主机上虚拟网卡的ip改为自动了. 当然,分析"宿主机ping不通虚拟机 ...

  8. CVE-2017-0213漏洞复现

    CVE-2017-0213漏洞形成的原因 类型混淆的漏洞通常可以通过内存损坏的方式来进行利用.然而漏洞发现者在利用时,并未采用内存损坏的方式来进行漏洞利用.按照漏洞发现者的说法,内存损坏的利用方式需要 ...

  9. 挖到一款免费好用的web报表插件

    最近公司项目需要用到报表,公司领导要求我来调研下报表工具.开始的时候了解了目前市场上功能强大,占有率高的两款报表工具,帆软报表和润乾报表,这两款报表工具功能比较强大,覆盖的行业较广,基本能满足所有的报 ...

  10. UML 包图 详细介绍

      6.1 包图的概念 包是一种常规用途的组合机制.UML中的一个包直接对应于Java中的一个包,C#中的命名空间.在Java中,一个包可能含有其他包.类或者同时含有这两者.进行建模时,通常使用逻辑性 ...