Python利用3D引擎写一个Pong游戏
作者:Leleprogrammer 发布时间:2021-09-13 15:56:58
前言
之前,我们用pygame做了一个2D的Pong游戏,今天我们做一个3D的,游戏画面如下:
用ad和←→操作,双人对战
实现该效果我们使用Python强大的3D引擎Ursina,基础的使用方法见这篇文章:详解Python 3D引擎Ursina如何绘制立体图形
接下来开始写代码吧!
实现方法
首先,导入ursina和随机库
from ursina import *
import random as rd
定义两个玩家的分数
scorea=scoreb=0
然后,我们创建app
app=Ursina()
ursina自带window参数,代表窗口,它还自带color参数,代表各种颜色,我们直接修改窗口的颜色
window.color=color.cyan
我们创建一个桌子,它是一个长方体,所以model为cube,颜色是橙色,然后进行缩放操作,并设置位置,还有它的材质(普通材质)
table=Entity(model="cube",color=color.orange,scale=(10,0.5,14),position=(0,0,0),texture="white_cube")
照样子,创建一个板子
paddle_A=Entity(parent=table,color=color.black,model="cube",scale=(0.2,0.03,0.05),position=(0,3.7,0.22),collider="box")
因为第二个板子和第一个板子差不多,我们只需要用duplicate函数进行实体复制,然后修改部分参数即可
paddle_B=duplicate(paddle_A,z=-0.62)
然后,把分数显示,显示文字用到了Text类,参数差不多
t=Text(text=f"Player A : Player B {scorea} : {scoreb}", position=(-0.85, 0.45), scale=2,color=color.orange)
这样运行程序,我们只看到了桌子的侧面,调整视角,改变ursina自带的camera的属性即可,设置它的倾斜度和位置
camera.position=(0,15,-26)
camera.rotation_x=30
绘制两个玩家的名字
Text(text="Player A",scale=2,position=(-0.1,0.32),color=color.orange)
Text(text="Player B",scale=2,position=(-0.1,-0.4),color=color.orange)
接下来,绘制桌子中间的分割线和球
line=Entity(parent=table,model="quad",scale=(0.88,0.2,0.1),position=(0,3.5,-0.2))
ball=Entity(parent=table,model="sphere",color=color.gold,scale=.05,position=(0,3.7,-0.2),collider="box")
设置初始x和z的速度
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
然后进入主循环
app.run()
我们在创建app前添加update函数,注意,这里名字一定要用update,然后自己无需调用,由ursina自动调用
创建函数并引入全局变量
def update():
global dx,dz,scorea,scoreb
然后判断按下了按键就对板子进行移动操作,按下按键的信息存储于held_keys中,并限制板子的移动范围
paddle_B.x-=held_keys["left arrow"]*time.dt
paddle_B.x+=held_keys["right arrow"]*time.dt
paddle_A.x-=held_keys["a"]*time.dt
paddle_A.x+=held_keys["d"]*time.dt
if paddle_A.x>0.35:
paddle_A.x=0.35
elif paddle_A.x<-0.35:
paddle_A.x=-0.35
if paddle_B.x>0.35:
paddle_B.x=0.35
elif paddle_B.x<-0.35:
paddle_B.x=-0.35
移动小球
ball.x+=dx*time.dt
ball.z+=dz*time.dt
更新比分显示
t.text=f"Player A : Player B {scorea} : {scoreb}"
进行板子和球的碰撞检测,先用intersects获取触碰到的实体列表,然后对碰到实体为两个板子的时候进行反弹、加速或减速的操作
hit_info=ball.intersects()
if hit_info.hit:
if hit_info.entity==paddle_A:
dz=-dz
if dz>-0.05:
dz-=rd.uniform(0.1,0.3)
else:
dz-=rd.uniform(-0.05,0.2)
if hit_info.entity==paddle_B:
dz=-dz
if dz<0.05:
dz+=rd.uniform(0.1,0.3)
else:
dz+=rd.uniform(-0.05,0.2)
限制球在桌子中间移动,如果一方没有接到球,就对另一方进行加分的操作
if abs(ball.x)>0.4:
dx=-dx
if ball.z>0.25:
scoreb+=1
ball.x=0
ball.z=-0.2
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
if ball.z<-0.65:
scorea+=1
ball.x=0
ball.z=-0.2
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
我们用了不到100行代码,就实现了以下效果~
完整代码
这里附上最终代码:
from ursina import *
import random as rd
scorea=scoreb=0
def update():
global dx,dz,scorea,scoreb
paddle_B.x-=held_keys["left arrow"]*time.dt
paddle_B.x+=held_keys["right arrow"]*time.dt
paddle_A.x-=held_keys["a"]*time.dt
paddle_A.x+=held_keys["d"]*time.dt
if paddle_A.x>0.35:
paddle_A.x=0.35
elif paddle_A.x<-0.35:
paddle_A.x=-0.35
if paddle_B.x>0.35:
paddle_B.x=0.35
elif paddle_B.x<-0.35:
paddle_B.x=-0.35
ball.x+=dx*time.dt
ball.z+=dz*time.dt
t.text=f"Player A : Player B {scorea} : {scoreb}"
hit_info=ball.intersects()
if hit_info.hit:
if hit_info.entity==paddle_A:
dz=-dz
if dz>-0.05:
dz-=rd.uniform(0.1,0.3)
else:
dz-=rd.uniform(-0.05,0.2)
if hit_info.entity==paddle_B:
dz=-dz
if dz<0.05:
dz+=rd.uniform(0.1,0.3)
else:
dz+=rd.uniform(-0.05,0.2)
if abs(ball.x)>0.4:
dx=-dx
if ball.z>0.25:
scoreb+=1
ball.x=0
ball.z=-0.2
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
if ball.z<-0.65:
scorea+=1
ball.x=0
ball.z=-0.2
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
app=Ursina()
window.color=color.cyan
table=Entity(model="cube",color=color.orange,scale=(10,0.5,14),position=(0,0,0),texture="white_cube")
paddle_A=Entity(parent=table,color=color.black,model="cube",scale=(0.2,0.03,0.05),position=(0,3.7,0.22),collider="box")
paddle_B=duplicate(paddle_A,z=-0.62)
t=Text(text=f"Player A : Player B {scorea} : {scoreb}", position=(-0.85, 0.45), scale=2,color=color.orange)
camera.position=(0,15,-26)
camera.rotation_x=30
Text(text="Player A",scale=2,position=(-0.1,0.32),color=color.orange)
Text(text="Player B",scale=2,position=(-0.1,-0.4),color=color.orange)
line=Entity(parent=table,model="quad",scale=(0.88,0.2,0.1),position=(0,3.5,-0.2))
ball=Entity(parent=table,model="sphere",color=color.gold,scale=.05,position=(0,3.7,-0.2),collider="box")
dx=rd.uniform(-0.4,0.15) if rd.randint(0,1)==0 else rd.uniform(0.15,0.4)
dz=rd.uniform(-0.5,0.2) if rd.randint(0,1)==0 else rd.uniform(0.2,0.5)
app.run()
来源:https://blog.csdn.net/leleprogrammer/article/details/125831586


猜你喜欢
- ProblemPython中str类自带的find、index方法可以返回第一个匹配的子串的位置,但是如果实际使用中需要查找第2个甚至第n个
- ASP里两种常用的生成文件的方式是:利用ADODB.Stream生成文件和利用Scripting.FileSystemObject生成文件1
- CocosCreator版本:2.3.4cocos没有List组件,所以要自己写。从cocos的example项目中找到assets/cas
- python标准库OS模块简介os就是“operating system”的缩写,顾名思义,os模块提供的就是各种 Python 程序与操作
- Python之所以这么流行,是因为它不仅能够应用于科技领域,还能用来做许多其他学科的研究工具,绘制地图便是其功能之一。今天我们用matplo
- 使用Keras作前端写网络时,由于训练图像尺寸较大,需要做类似 tf.random_crop 图像裁剪操作。为此研究了一番Keras下已封装
- 1. 过滤器Python 具有通过列表解析 将列表映射到其它列表的强大能力。这种能力同过滤机制结合使用,使列表中的有些元素被映射的同时跳过另
- 泰勒展开与e的求法大家伙儿知道计算机里的 e是怎么求出来的吗?这还要从神奇的泰勒展开讲起……简单
- 一、StreamVR问题:1.运行项目时不显示手柄控制器:出现这种情况一般会在头显中提示不能加载按键配置文件,出现这种提示时请直接打开ste
- 本文实例讲述了PHP开发实现微信退款功能。分享给大家供大家参考,具体如下:最近在调微信退款接口,发现有许多坑,更大家分享一下① 要是在测试的
- 1.sonarqube是一款代码分析的工具,通过soanrScanner扫描后的数据传递给sonarqube进行分析2.sonarqube社
- 小毅的blog:http://andymao.com/andy/注:本文实例在IE5.x下可能会显示不出来,请使用IE6、IE7、Firef
- 现状≠将来?程序员做设计本身就很悲哀,纠结于客户与坚持之间就更是如此。无论我今后的路会怎么走,我想始终不变的事情就是与客户博弈了。无论是放弃
- 当你链接到应用程序以使用MySQL客户端库时,可能会遇到以mysql_开始的未定义引用错误,如下所示:/tmp/ccFKsdPa.o: 在函
- 本文实例讲述了python使用htmllib分析网页内容的方法。分享给大家供大家参考。具体实现方法如下:import htmllib, ur
- 前言其实全文检索在MySQL里面很早就支持了,只不过一直以来只支持英文。缘由是他从来都使用空格来作为分词的分隔符,而对于中文来讲,显然用空格
- 本文实例讲述了python实现通过代理服务器访问远程url的方法。分享给大家供大家参考。具体如下:import urllibproxies
- 查找出SQLServer的死锁和阻塞的源头 --查找出SQLServer死锁和阻塞的源头use mastergodeclare @spid
- 本文通过图文并茂的方式给大家展示SQL SERVER数据库表记录只保留N天图文教程,具体方法步骤请看下文:第一步:首先设置SQL Serve
- 前言最近写了个CNode 社区的微信小程序版本,把在微信小程序中使用npm包,踩的坑记录一下,希望能给遇到类似问题的小伙伴,提供一些思路和方