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

作者:Leleprogrammer 时间:2021-09-13 15:56:58 

前言

之前,我们用pygame做了一个2D的Pong游戏,今天我们做一个3D的,游戏画面如下:

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

用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行代码,就实现了以下效果~

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

完整代码

这里附上最终代码:

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

标签:Python,3D,Pong,游戏
0
投稿

猜你喜欢

  • Go语言集成开发环境之VS Code安装使用

    2023-08-29 13:06:38
  • Python turtle画图库&&画姓名实例

    2021-07-03 09:02:02
  • pyqt5 使用label控件实时显示时间的实例

    2021-01-29 14:54:17
  • Python多分支if语句的使用

    2022-07-17 17:52:54
  • Python部署web开发程序的几种方法

    2023-08-24 06:30:32
  • python的keyword模块用法实例分析

    2022-04-06 07:56:22
  • python网络爬虫学习笔记(1)

    2023-12-24 04:08:16
  • 浅谈Python中列表生成式和生成器的区别

    2023-03-21 11:50:39
  • PHP children()函数讲解

    2023-06-13 04:38:38
  • 详解Python中Addict模块的使用方法

    2021-11-04 00:06:04
  • 自然选择:自然界的颜色与界面设计[译]

    2009-09-19 17:17:00
  • python如何实现从视频中提取每秒图片

    2023-10-15 11:36:25
  • 实例讲解python中的协程

    2022-08-10 20:10:38
  • 高质量Python代码编写的5个优化技巧

    2022-04-20 16:49:16
  • Python 爬虫性能相关总结

    2021-02-04 05:45:26
  • setInterval 和 setTimeout 会产生内存溢出

    2008-03-08 13:10:00
  • PyCharm License Activation激活码失效问题的解决方法(图文详解)

    2021-11-20 12:52:23
  • asp中把数据表映射成ajax可调用的json格式的方法

    2010-01-22 15:27:00
  • 转换字符串单词的第一个字母为大写

    2007-10-18 10:50:00
  • Python正确调用 jar 包加密得到加密值的操作方法

    2021-02-26 12:12:19
  • asp之家 网络编程 m.aspxhome.com