大家好,欢迎来到 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. Solution -「LOCAL」逃生

    \(\mathcal{Description}\)   有 \(n\) 个人掉进了深度为 \(h\) 的坑里,第 \(i\) 个人的肩高为 \(a_i\),臂长为 \(b_i\).设当前坑里人的集合为 ...

  2. Solution -「LOCAL」解析电车

    \(\mathcal{Description}\)   给定 \(n\) 个点 \(m\) 条边的无向图,每条边形如 \((u,v,r)\),表示 \(u,v\) 之间有一条阻值为 \(r\Omega ...

  3. MySQL架构原理之存储引擎InnoDB数据文件

    MySQL架构原理之体系架构 - 池塘里洗澡的鸭子 - 博客园 (cnblogs.com)中简单介绍了MySQL的系统文件层,其中包含了数据文件.那么InnoDB的数据文件是如何分类并存储的呢? 一. ...

  4. java的不正确使用方法以及什么情况不能使用java

    一.Python3.6新特性 什么情况下不能运用 Java 泛型   1. 前语 Java 1.5 引入了泛型来保证类型安全,避免在运行时发作类型转换反常,让类型参数化,提高了代码的可读性和重用率.可 ...

  5. io流复习+代码演示

    前置知识: 序列化和反序列化 1.序列化就是在保存数据时, 保存数据的值和数据类型 2.反序列化就是在恢复数据时, 恢复数据的值和数据类型 3.需要让某个对象支持序列化机制,则必须让其类是可序列化的, ...

  6. 私有化轻量级持续集成部署方案--06-私有镜像仓库-Harbor

    提示:本系列笔记全部存在于 Github, 可以直接在 Github 查看全部笔记 针对私有镜像仓库的问题,Docker 官方提供了搭建仓库服务的镜像服务:registry,使用此镜像就可以部署私有仓 ...

  7. Vue 源码解读(4)—— 异步更新

    前言 上一篇的 Vue 源码解读(3)-- 响应式原理 说到通过 Object.defineProperty 为对象的每个 key 设置 getter.setter,从而拦截对数据的访问和设置. 当对 ...

  8. docker安装sentinel-dashbord

    查找 sentinel-dashboard docker search sentinel-dashboard pull 镜像 docker pull bladex/sentinel-dashboard ...

  9. [题解]RQNOJ PID86 智捅马蜂窝

    链接:http://www.rqnoj.cn/problem/86 思路:单源点最短路 建图:首先根据父子关系连双向边,边权是距离/速度:再根据跳跃关系连单向边,边权是自由落体的时间(注意自由下落是一 ...

  10. 企业没有大数据技术?选择这款BI工具

    ​无论是网络时代的传统营销还是大数据营销,营销人员的任务之一就是找到目标客户,实现自己的营销目标.而我们说的大数据营销只不过是营销的工具发生了变化,营销的本质和目标是不变的. 就目前而言,现在的大数据 ...