【pgzero】手把手教你制作游戏——Pong

这篇具有很好参考价值的文章主要介绍了【pgzero】手把手教你制作游戏——Pong。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

今天要做的游戏叫Pong,它是世界上第一款街机游戏。(关键它好做)

制作游戏的引擎有很多,比如UnityConstruct . . . . . . ...... ......而今天我们用的既不是Unity,也不是Construct,而是Python

制作游戏的模块是pgzero,它是在 Python 比较有名的库 Pygame 上又加了一层封装,对初学者制作游戏非常友好。

安装pgzero

pgzero可以进入cmd,然后用“pip install pgzero”来安装。(前提是你得先安装Python)

完成以后,就可以开始你的游戏制作之旅了 😃

角色

首先,先写好这两行代码:

import pgzrun

pgzrun.go()

运行这两行代码,你就会发现:屏幕中多了一个黑色(指背景)窗口!

这就是pgzero的神奇之处。如果有了解过pygame的朋友肯定知道:要想让游戏窗口正常的运行,必须写上很多的代码才可以,有时候还会记错一些。

言归正传,再写上这几行代码:

import pgzrun
import os

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800

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

def draw():
	screen.clear()
	screen.draw.filled_rect(pad1, "white")

pgzrun.go()
  1. os.environ["SDL_VIDEO_CENTERED"] = '1' 用来设定pgzero窗口为居中。
  2. WIDTHHEIGHT用来定义窗口的长宽。
  3. pad1 = Rect((20, 20), (10, 100))用来定义一个矩形,参数一是矩形的位置,参数二是矩形的长宽。
  4. screen.draw.filled_rect(pad1, "white")用来填充矩形,第一个参数是目标矩形。第二个参数是颜色,与(255, 255, 255)等价。

如法炮制,再写(粘贴)出第二个球拍的代码:

import pgzrun
import os

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800

pad1 = Rect((20, 20), (10, 100))
pad1 = Rect((WIDTH - 40, 20), (10, 100))

def draw():
	screen.clear()
	screen.draw.filled_rect(pad1, "white")

pgzrun.go()

然后定义一个类,类名是 Ball,写上这样的代码:

class Ball:
	def __init__(self):
		self.pos = [WIDTH / 2, HEIGHT / 2]
		self.speed = [200, 200]

这段代码定义了一个球,有pos(位置)和speed(速度)两个列表。有人可能会问,speed 为什么也是列表,就不能是普通的 int 吗?而且 speed 里的元素这么大,这小球移动的速度不应该是非常快吗?这些代码都有什么用呢?

别着急,这段代码在后面有大用。

先实例化Ball类:

ball = Ball()

然后最关键的代码来了:在 screen 里面填充我们的小球。

screen.draw.filled_circle(ball.pos, 4, "white")

其中第一个参数是填充的位置,第二个参数是小球的半径,第三个参数是颜色。

这是现在的代码:

import pgzrun
import os

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800

class Ball:
	def __init__(self):
		self.pos = [WIDTH / 2, HEIGHT / 2]
		self.speed = [200, 200]
ball = Ball()

pad1 = Rect((20, 20), (10, 100))
pad2 = Rect((WIDTH - 40, 20), (10, 100))

def draw():
	screen.clear()
	screen.draw.filled_rect(pad1, "white")
	screen.draw.filled_rect(pad2, "white")
	screen.draw.filled_circle(ball.pos, 4, "white")

pgzrun.go()

截至目前为止,角色已经定义好了,接下来就是让他们动起来。

让他们动起来吧!

首先先定义一个 update 的函数,参数是 dt,像这样:

def update():
	pass    # 这是占位用的

随后写上让小球移动的代码:

for i in range(2):
		ball.pos[i] += speed[i] * dt

其中ball.pos[i] = speed[i] * dt是计算出小球在下一帧的位置,这就是为什么 speed 列表中的元素会这么大的原因,但是我这个代码不是唯一的,因为不同的电脑性能不同,帧数(fps)也不同。

你可能会说:循环里的代码到底是什么意思,实现的又是什么?

这个嘛…其实就是路程=速度×时间

运行上面的代码,我们就能得到一个会动的小球,但是多运行一会儿后你就会发现:小球离开屏幕后就不回来了。那么我们就能到update函数里面添加代码:

if ball.pos[1] >= HEIGHT or ball.pos[1] <= 0:
		ball.speed[1] *= -1

这两行代码是为了检测小球是否碰到上下边缘,如果碰到,那就让小球反弹。

接下来就是检测小球是否碰到两边,如果碰到,就直接重置小球。

在这之前,我们要先解决两个问题:

  • 小球碰到边缘后怎么重置?
  • 如何检测碰到边缘?

首先解决第一个问题:小球碰到边缘后重置。

这个问题很简单,只需修改Ball类的代码:

class Ball:
	def __init__(self):
		self.reset()
	
	def reset(self):
		self.pos = [WIDTH / 2, HEIGHT / 2]
		self.speed = [200, 200]
  • 小球碰到边缘后重置

再解决第二个问题,如何检测碰到边缘。

update函数里添加代码:

if ball.pos[0] >= WIDTH or ball.pos[0] <= 0:
		ball.reset()

这样就实现了小球碰到边缘的检测。

  • 小球碰到边缘的检测

小球的问题解决了。接下来应该看球拍了。

在Pong里,小球碰到球拍是能动的,如何让球拍动呢?可以用keyboard检测按键是否被按下。(直接用就可以了 ,是不是很人性化

首先先新建一个常量:PAD_SPEED,把它赋值为10

然后检测按键:

if keyboard.w:
		pad1.y -= PAD_SPEED
	elif keyboard.s:
		pad1.y += PAD_SPEED

	if keyboard.up:
		pad2.y -= PAD_SPEED
	elif keyboard.down:
		pad2.y += PAD_SPEED

球拍能动了,如何检测小球碰到拍子呢?这就涉及到一个函数:collidepoint

collidepoint是用来检测角色碰到坐标点的,可以这样用:

a.collidepoint(b)

根据这个函数我们就能写出如下代码:

if pad1.collidepoint(ball.pos) or pad2.collidepoint(ball.pos):
		ball.speed[0] *= -1

把以上所有的代码都按照提示写进你的代码后,你的代码应该是这样的:

import pgzrun
import os
import time

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800
PAD_SPEED = 10

pad1 = Rect((20, 20), (10, 100))
pad2 = Rect((WIDTH - 20, 20), (10, 100))

class Ball:
	def __init__(self):
		self.reset()
	
	def reset(self):
		self.pos = [WIDTH / 2, HEIGHT / 2]
		self.speed = [200, 200]


ball = Ball()


def draw():
	screen.clear()
	screen.draw.filled_rect(pad1, "white")
	screen.draw.filled_rect(pad2, "white")
	screen.draw.filled_circle(ball.pos, 4, "white")



def update(dt):

	if keyboard.w:
		pad1.y -= PAD_SPEED
	elif keyboard.s:
		pad1.y += PAD_SPEED

	if keyboard.up:
		pad2.y -= PAD_SPEED
	elif keyboard.down:
		pad2.y += PAD_SPEED

	for i in range(2):
		ball.pos[i] += ball.speed[i] * dt

	if ball.pos[1] >= HEIGHT or ball.pos[1] <= 0:
		ball.speed[1] *= -1

	if ball.pos[0] >= WIDTH or ball.pos[0] <= 0:
		ball.reset()

	if pad1.collidepoint(ball.pos) or pad2.collidepoint(ball.pos):
		ball.speed[0] *= -1


pgzrun.go()

写到这,游戏的基本功能就写完了,接下来就是给他添加分数列表,小球在哪重置,就给对面的玩家加分,修改后代码是这样的:

import pgzrun
import os
import time

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800
PAD_SPEED = 10
scores = [0, 0]

pad1 = Rect((20, 20), (10, 100))
pad2 = Rect((WIDTH - 20, 20), (10, 100))

class Ball:
	def __init__(self):
		self.reset()
	
	def reset(self):
		self.pos = [WIDTH / 2, HEIGHT / 2]
		self.speed = [200, 200]


ball = Ball()


def draw():
	global scores
	screen.clear()
	screen.draw.filled_rect(pad1, "white")
	screen.draw.filled_rect(pad2, "white")
	screen.draw.filled_circle(ball.pos, 4, "white")
	screen.draw.text(":", midtop=(WIDTH // 2, 20), fontname=None, fontsize=64)
	screen.draw.text(f"{scores[0]}", topright=(WIDTH // 2 - 40, 20), fontname=None, fontsize=64)
	screen.draw.text(f"{scores[1]}", topright=(WIDTH // 2 + 60, 20), fontname=None, fontsize=64)



def update(dt):
	global scores
	if keyboard.w:
		pad1.y -= PAD_SPEED
	elif keyboard.s:
		pad1.y += PAD_SPEED

	if keyboard.up:
		pad2.y -= PAD_SPEED
	elif keyboard.down:
		pad2.y += PAD_SPEED

	for i in range(2):
		ball.pos[i] += ball.speed[i] * dt

	if ball.pos[1] >= HEIGHT or ball.pos[1] <= 0:
		ball.speed[1] *= -1

	if ball.pos[0] <= 0:
		scores[1] += 1
		ball.reset()
	if ball.pos[0] >= WIDTH:
		scores[0] += 1
		ball.reset()

	if pad1.collidepoint(ball.pos) or pad2.collidepoint(ball.pos):
		ball.speed[0] *= -1


pgzrun.go()

其他优化

如果还嫌做的不够好,还可以用random模块实现方向随机和位置随机(作者这里做的不太好)

import pgzrun
import os
import random

os.environ["SDL_VIDEO_CENTERED"] = '1'

WIDTH = 1000
HEIGHT = 800
PAD_SPEED = 10
scores = [0, 0]

pad1 = Rect((20, 20), (10, 100))
pad2 = Rect((WIDTH - 20, 20), (10, 100))

class Ball:
	def __init__(self):
		self.reset()
	
	def reset(self):
		self.pos = [WIDTH / 2, random.randint(1, HEIGHT - 1)]
		randomx = random.randint(200, 400)
		randomy = random.randint(200, 400)
		sx = random.choice([randomx, randomx * -1])
		sy = random.choice([randomy, randomy * -1])
		self.speed = [sx, sy]


ball = Ball()


def draw():
	global scores
	screen.clear()
	screen.draw.filled_rect(pad1, "white")
	screen.draw.filled_rect(pad2, "white")
	screen.draw.filled_circle(ball.pos, 4, "white")
	screen.draw.text(":", midtop=(WIDTH // 2, 20), fontname=None, fontsize=64)
	screen.draw.text(f"{scores[0]}", topright=(WIDTH // 2 - 40, 20), fontname=None, fontsize=64)
	screen.draw.text(f"{scores[1]}", topright=(WIDTH // 2 + 60, 20), fontname=None, fontsize=64)



def update(dt):
	global scores
	if keyboard.w:
		pad1.y -= PAD_SPEED
	elif keyboard.s:
		pad1.y += PAD_SPEED

	if keyboard.up:
		pad2.y -= PAD_SPEED
	elif keyboard.down:
		pad2.y += PAD_SPEED

	for i in range(2):
		ball.pos[i] += ball.speed[i] * dt

	if ball.pos[1] >= HEIGHT or ball.pos[1] <= 0:
		ball.speed[1] *= -1

	if ball.pos[0] <= 0:
		scores[1] += 1
		ball.reset()
	if ball.pos[0] >= WIDTH:
		scores[0] += 1
		ball.reset()

	if pad1.collidepoint(ball.pos) or pad2.collidepoint(ball.pos):
		ball.speed[0] *= -1


pgzrun.go()

以上就是关于pgzero制作游戏的教程了,希望你们喜欢。文章来源地址https://www.toymoban.com/news/detail-842854.html

球关注

到了这里,关于【pgzero】手把手教你制作游戏——Pong的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 若依ruoyi——手把手教你制作自己的管理系统【二、修改样式】

    阿里图标一( ̄︶ ̄*)) 图片白嫖一((* ̄3 ̄)╭ ********* 专栏略长 ==== 爆肝万字 ==== 细节狂魔 ==== 请准备好一键三连 ********* 运行成功后: idea后台正常先挂着 我习惯用VScode操作 当然如果有两台机子 一个挂后台一个改前端就更好了 只需修改 vue.config.js 配置文件即可 eg:按 Win+R 打

    2024年02月03日
    浏览(36)
  • 手把手教你制作一块Linux开发板(基于Planck-pi)

    攻城狮星河:Hello,各位野生钢铁侠们! 这篇文章初衷是帮助想自己制作linux小板子的小白们,文中会讲的比较基础,大佬勿喷~ 本教程会以稚晖君开源的 planck-pi 为基础,从0开始手把手教学直到成功复刻 Planck-pi复刻互助群:287810522 提示:以下是本篇文章正文内容,下面案例

    2024年02月01日
    浏览(35)
  • 若依ruoyi——手把手教你制作自己的管理系统【三、代码生成】

    增删改查导一( ̄︶ ̄*)) 按钮换个色一((* ̄3 ̄)╭ ********* 专栏略长 ==== 爆肝万字 ==== 细节狂魔 ==== 请准备好一键三连 ********* 修改后的页面: 干干净净贼舒服一Ψ( ̄∀ ̄)Ψ——Ψ( ̄∀ ̄)Ψ一 接下来我们要达到的效果如下(自定义菜单 里面有列表数据回显+增删改查) 一、修改

    2023年04月25日
    浏览(32)
  • 手把手教你使用Python写贪吃蛇游戏(pygame,附源码)

    贪吃蛇游戏是有史以来最受欢迎的街机游戏之一。在这个游戏中,玩家的主要目标是在不撞墙或不撞墙的情况下抓住最大数量的水果。在学习 Python 或 Pygame 时,可以将创建蛇游戏视为一项挑战。这是每个新手程序员都应该接受的最好的初学者友好项目之一。学习构建视频游戏

    2024年02月16日
    浏览(34)
  • 手把手教你使用Python实现推箱子小游戏(附完整源码)

    我们这个项目是一个基于Python实现的推箱子小游戏,名叫Sokoban: 这个游戏的目的是让玩家,也就是大写的 P ,推着箱子 # ,填充用小写的 o 标记的地面上的洞 该版本的Sokoban的规则如下: 游戏在矩形的二维网格上举行,其 原点(0,0) 位于左上方 网格上的每个单元格可以随时包

    2024年02月03日
    浏览(35)
  • 用HTML语言制作一个非常浪漫的生日祝福网,手把手教你制作炫酷生日祝福网页

    明天就是女朋友的生日了, 是时候展现专属于程序员的浪漫了!你打算怎么给心爱的人表达爱意?鲜花礼物?代码表白?还是创意DIY?或者…无论那种形式,快来秀我们一脸吧! HTML生日祝福网页制作(粉色主题)程序员专属生日表白网站 💬 注:以下代码为部分演示,如需完整

    2024年02月16日
    浏览(38)
  • 手把手教你制作登录、注册界面 SpringBoot+Vue.js(cookie的灵活运用,验证码功能)

    实现思路:用户在界面输入用户名和密码传入变量。用post方法传输到后端,后端接收整个实体对象。将用户名提取出。在dao层方法中通过select注解查询,返回数据库对应的数据对象。如果返回为空则return false。不为空则通过比对数据库返回的密码和用户输入的密码,如果二者

    2024年02月03日
    浏览(37)
  • 超详细AI二维码制作教程:手把手教你如何用Stable Diffusion 生成一个创意二维码?

    AI已来,未来已来! 来势汹汹的人工智能,如同创世纪的洪水,正在全世界的范围内引发一场史无前例的科技革命。AI正在改变世界!而我们正是这场巨变的见证者。 今天我们要介绍的内容就是:如何利用AI工具Stable Diffusion,生成你的专属创意二维码? (下文包含详细图文教

    2024年02月16日
    浏览(47)
  • 手把手教你SHA-256

    SHA-256是SHA-2协议簇的一部分,也是当前最流行的协议算法之一。在本篇文章中,我们会了解这个密码学算法的每一个步骤,并且通过实例演示。SHA-2因它的安全性(比SHA-1强很多)和速度为人所知。在没有键(keys)生成的情况下,例如挖掘比特币,像SHA-2这样的快速哈希算法很

    2024年02月13日
    浏览(56)
  • 手把手教你暴力破解

    暴力破解是一种攻击手段,使用大量的认证信息在认证接口尝试登录,直到得到正确的结果。 2.1标题基于表单的暴力破解 2.1.1 第一步:打开burpsuite拦截 2.1.2 第二步:将拦截到的包右击发送到intruder模块 (其中简单介绍一下intruder模块) Target主要是设置暴力破解访问的host地址

    2024年02月07日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包