Python利用3D引擎写一个Pong游戏

 更新时间:2023年01月05日 16:41:27   作者:Leleprogrammer  
之前,我们尝试过用pygame做了一个2D的Pong游戏。本文将利用强大的3D引擎Ursina制作一个3D版的Pong游戏。文中的示例代码讲解详细,感兴趣的可以了解一下

前言

之前,我们用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()

到此这篇关于Python利用3D引擎写一个Pong游戏的文章就介绍到这了,更多相关Python Pong游戏内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Python字符串逐字符或逐词反转方法

    Python字符串逐字符或逐词反转方法

    这篇文章主要介绍了Python字符串逐字符或逐词反转方法,本文对逐字符或逐词分别给出两种方法,需要的朋友可以参考下
    2015-05-05
  • Python OpenCV实现识别信用卡号教程详解

    Python OpenCV实现识别信用卡号教程详解

    本文将介绍如何通过 OpenCV 和 Python 使用模板匹配来执行光学字符识别 (OCR),再应用我们的模板匹配 OCR 方法来识别信用卡类型以及 16 位信用卡数字。代码具有一定价值,感兴趣的童鞋可以了解一下
    2021-11-11
  • Django中间件工作流程及写法实例代码

    Django中间件工作流程及写法实例代码

    这篇文章主要介绍了Django中间件工作流程及写法实例代码,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-02-02
  • python smtplib发送带附件邮件小程序

    python smtplib发送带附件邮件小程序

    这篇文章主要为大家详细介绍了python smtplib发送带附件邮件小程序,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • ubuntu 16.04下python版本切换的方法

    ubuntu 16.04下python版本切换的方法

    这篇文章主要为大家详细介绍了ubuntu 16.04下python版本切换的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-06-06
  • python3.x 将byte转成字符串的方法

    python3.x 将byte转成字符串的方法

    今天小编就为大家分享一篇python3.x 将byte转成字符串的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-07-07
  • 使用Python实现文字转语音并播放功能

    使用Python实现文字转语音并播放功能

    这篇文章主要给大家介绍了使用Python实现文字转语音并播放功能,文中通过代码示例给大家讲解的非常详细,对大家的学习或工作有一定的帮助,需要的朋友可以参考下
    2024-01-01
  • 一文教你彻底解决Python包下载慢问题

    一文教你彻底解决Python包下载慢问题

    在利用python中,我们经常需要使用到各种各样的库。其中,pip是我们常用的安装工具,一般情况下我们基本上是直接pip方法安装第三方包,下面这篇文章主要给大家介绍了关于如何彻底解决Python包下载慢问题的相关资料,需要的朋友可以参考下
    2023-05-05
  • 对Python进行数据分析_关于Package的安装问题

    对Python进行数据分析_关于Package的安装问题

    下面小编就为大家带来一篇对Python进行数据分析_关于Package的安装问题。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05
  • Python实现像awk一样分割字符串

    Python实现像awk一样分割字符串

    这篇文章主要介绍了Python实现像awk一样分割字符串,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-09-09

最新评论