Python利用3D引擎寫(xiě)一個(gè)Pong游戲
前言
之前,我們用pygame做了一個(gè)2D的Pong游戲,今天我們做一個(gè)3D的,游戲畫(huà)面如下:
用ad和←→操作,雙人對(duì)戰(zhàn)
實(shí)現(xiàn)該效果我們使用Python強(qiáng)大的3D引擎Ursina,基礎(chǔ)的使用方法見(jiàn)這篇文章:詳解Python 3D引擎Ursina如何繪制立體圖形
接下來(lái)開(kāi)始寫(xiě)代碼吧!
實(shí)現(xiàn)方法
首先,導(dǎo)入ursina和隨機(jī)庫(kù)
from ursina import * import random as rd
定義兩個(gè)玩家的分?jǐn)?shù)
scorea=scoreb=0
然后,我們創(chuàng)建app
app=Ursina()
ursina自帶window參數(shù),代表窗口,它還自帶color參數(shù),代表各種顏色,我們直接修改窗口的顏色
window.color=color.cyan
我們創(chuàng)建一個(gè)桌子,它是一個(gè)長(zhǎng)方體,所以model為cube,顏色是橙色,然后進(jìn)行縮放操作,并設(shè)置位置,還有它的材質(zhì)(普通材質(zhì))
table=Entity(model="cube",color=color.orange,scale=(10,0.5,14),position=(0,0,0),texture="white_cube")
照樣子,創(chuàng)建一個(gè)板子
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")
因?yàn)榈诙€(gè)板子和第一個(gè)板子差不多,我們只需要用duplicate函數(shù)進(jìn)行實(shí)體復(fù)制,然后修改部分參數(shù)即可
paddle_B=duplicate(paddle_A,z=-0.62)
然后,把分?jǐn)?shù)顯示,顯示文字用到了Text類(lèi),參數(shù)差不多
t=Text(text=f"Player A : Player B {scorea} : {scoreb}", position=(-0.85, 0.45), scale=2,color=color.orange)
這樣運(yùn)行程序,我們只看到了桌子的側(cè)面,調(diào)整視角,改變ursina自帶的camera的屬性即可,設(shè)置它的傾斜度和位置
camera.position=(0,15,-26) camera.rotation_x=30
繪制兩個(gè)玩家的名字
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)
接下來(lái),繪制桌子中間的分割線(xiàn)和球
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")
設(shè)置初始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)
然后進(jìn)入主循環(huán)
app.run()
我們?cè)趧?chuàng)建app前添加update函數(shù),注意,這里名字一定要用update,然后自己無(wú)需調(diào)用,由ursina自動(dòng)調(diào)用
創(chuàng)建函數(shù)并引入全局變量
def update(): global dx,dz,scorea,scoreb
然后判斷按下了按鍵就對(duì)板子進(jìn)行移動(dòng)操作,按下按鍵的信息存儲(chǔ)于held_keys中,并限制板子的移動(dòng)范圍
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
移動(dòng)小球
ball.x+=dx*time.dt ball.z+=dz*time.dt
更新比分顯示
t.text=f"Player A : Player B {scorea} : {scoreb}"
進(jìn)行板子和球的碰撞檢測(cè),先用intersects獲取觸碰到的實(shí)體列表,然后對(duì)碰到實(shí)體為兩個(gè)板子的時(shí)候進(jìn)行反彈、加速或減速的操作
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)
限制球在桌子中間移動(dòng),如果一方?jīng)]有接到球,就對(duì)另一方進(jìn)行加分的操作
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行代碼,就實(shí)現(xiàn)了以下效果~
完整代碼
這里附上最終代碼:
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()
到此這篇關(guān)于Python利用3D引擎寫(xiě)一個(gè)Pong游戲的文章就介紹到這了,更多相關(guān)Python Pong游戲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Python+Pygame編寫(xiě)一個(gè)Pong游戲
- Python+Pygame實(shí)戰(zhàn)之俄羅斯方塊游戲的實(shí)現(xiàn)
- Python Pygame實(shí)戰(zhàn)之實(shí)現(xiàn)經(jīng)營(yíng)類(lèi)游戲夢(mèng)想小鎮(zhèn)代碼版
- Python+Pygame實(shí)現(xiàn)接小彈珠游戲
- Python+Pygame實(shí)戰(zhàn)之詩(shī)詞填空游戲的實(shí)現(xiàn)
- Python+numpy實(shí)現(xiàn)一個(gè)蜘蛛紙牌游戲
- Python+Pygame實(shí)戰(zhàn)之文字劇情游戲的實(shí)現(xiàn)
- Python+Pygame實(shí)戰(zhàn)之炫舞小游戲的實(shí)現(xiàn)
- Python之freegames?零代碼的22個(gè)小游戲集合
相關(guān)文章
python筆記之mean()函數(shù)實(shí)現(xiàn)求取均值的功能代碼
這篇文章主要介紹了python筆記之mean()函數(shù)實(shí)現(xiàn)求取均值的功能代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07python 實(shí)現(xiàn)將字典dict、列表list中的中文正常顯示方法
今天小編就為大家分享一篇python 實(shí)現(xiàn)將字典dict、列表list中的中文正常顯示方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07Python搭建Keras CNN模型破解網(wǎng)站驗(yàn)證碼的實(shí)現(xiàn)
這篇文章主要介紹了Python搭建Keras CNN模型破解網(wǎng)站驗(yàn)證碼的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Python入門(mén)學(xué)習(xí)之類(lèi)的相關(guān)知識(shí)總結(jié)
今天帶大家復(fù)習(xí)python的基礎(chǔ)知識(shí),文中對(duì)類(lèi)的相關(guān)知識(shí)作了非常詳細(xì)的介紹,對(duì)正在學(xué)習(xí)python的小伙伴們有很好地幫助,需要的朋友可以參考下2021-05-05pytorch實(shí)現(xiàn)查看當(dāng)前學(xué)習(xí)率
這篇文章主要介紹了pytorch實(shí)現(xiàn)查看當(dāng)前學(xué)習(xí)率,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-06-06用Python實(shí)現(xiàn)換行符轉(zhuǎn)換的腳本的教程
這篇文章主要介紹了用Python實(shí)現(xiàn)換行符轉(zhuǎn)換的腳本的教程,代碼非常簡(jiǎn)單,包括一個(gè)對(duì)操作說(shuō)明的功能的實(shí)現(xiàn),需要的朋友可以參考下2015-04-04python mysql實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python mysql實(shí)現(xiàn)學(xué)生成績(jī)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10Python基本數(shù)據(jù)類(lèi)型之字符串str
字符串是編程中最重要的數(shù)據(jù)類(lèi)型,也是最常見(jiàn)的,今天小編抽空給大家講解下Python基本數(shù)據(jù)類(lèi)型之字符串str的實(shí)例代碼,感興趣的朋友跟隨小編一起看看吧2021-07-07