Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

王林
Lepaskan: 2023-05-12 16:16:14
ke hadapan
1288 orang telah melayarinya

Kali ini, kesan yang ingin kami capai adalah seperti berikut

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Pertama sekali, hantarkan sumber yang kami perlukan ini masa

Earth.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Jupiter.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Mars.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Mercury.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Neptune.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Saturn.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Sun.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Uranus.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Venus.jpg

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Sekarang, mula menulis kod!

Mula-mula, import modul yang kami perlukan, import ursina enjin 3D, matematik perpustakaan matematik, orang pertama, sys, perpustakaan rawak yang disertakan dengan ursina

from ursina import *
from math import *
from ursina.prefabs.first_person_controller import FirstPersonController
import sys
import random as rd
Salin selepas log masuk

Kemudian, cipta aplikasi

app=Ursina()
Salin selepas log masuk

Tetapkan tetingkap ke skrin penuh dan tetapkan warna latar belakang

window.fullscreen=True
window.color=color.black
Salin selepas log masuk

Tentukan senarai untuk menyimpan bintang yang dijana

planets=[]
Salin selepas log masuk

Perkenalkan bahan semua planet

sun_texture=load_texture("texture/Sun.png")
mercury_texture=load_texture("texture/Mercury.png")
venus_texture=load_texture("texture/Venus.png")
earth_texture=load_texture("texture/Earth.png")
mars_texture=load_texture("texture/Mars.png")
jupiter_texture=load_texture("texture/Jupiter.png")
saturn_texture=load_texture("texture/Saturn.png")
uranus_texture=load_texture("texture/Uranus.png")
neptune_texture=load_texture("texture/Neptune.png")
Salin selepas log masuk

Buat Planet kelas, diwarisi daripada Entiti, _jenis masuk ialah jenis bintang, pos ialah kedudukan, skala ialah penskalaan

sudut: lengkok planet mengelilingi matahari setiap kali ia dikemas kini

Nilai fastMode ialah 1 atau 0, menunjukkan sama ada untuk meningkatkan kelajuan revolusi planet mengelilingi matahari kepada 200 kali ganda

putaran: kecondongan planet, di sini kami menjana secara rawak

rotspeed: kelajuan putaran planet

rotMode: menunjukkan putaran sepanjang salah satu paksi xyz, secara automatik memilih

_type untuk menyimpan jenis planet

tekstur ialah bahan, dan memperoleh pembolehubah melalui eval

Kemudian mulakan kelas super Model adalah sfera, yang merupakan bentuk sfera Warna ditetapkan kepada putih lulus dalam koordinat

Tentukan kaedah pusingan dan hantaran dalam sudut Selagi ia bukan matahari, maka Jalankan operasi putaran dan revolusi Jika ia dalam mod pantas, kelajuan akan ditingkatkan 200 kali. Kemudian hitung koordinat xy baharu dan gunakan exec untuk melaksanakan operasi autotransmisi

Akhir sekali tentukan kaedah input untuk menerima input pengguna Perhatikan bahawa kaedah ini Nama mesti dimasukkan, kerana ia dipanggil secara automatik sistem, dan ia akan sentiasa lulus dalam parameter, iaitu nama kekunci yang ditekan. kami mentakrifkan kelas Pemain, yang mewarisi daripada FirstPersonController

Mengapa tidak menggunakan FirstPersonController secara langsung?

Oleh kerana FirstPersonController yang didatangkan dengan ursina mempunyai graviti tersendiri, kami hanya menggunakannya sebagai perspektif orang pertama dan tidak memerlukan graviti juga ada beberapa fungsi yang kami tidak perlu gunakan, jadi kami akan menulis kelas untuk mewarisinya Kemudian tulis semula sebahagian daripada kodnya. Mula-mula, perkenalkan planet pembolehubah global, mulakan kelas super, tetapkan medan pandangan kepada 90, tetapkan kedudukan awal kepada kedudukan bumi, tetapkan graviti kepada 0, yang bermaksud tiada graviti, vspeed bermaksud kelajuan apabila meningkat. dan jatuh, dan kelajuan bermakna bergerak dalam arah mendatar Kelajuan, kepekaan tetikus ialah kepekaan tetikus, yang perlu dalam bentuk Vec2, kecuali pembolehubah vspeed di atas, yang boleh dinamakan sendiri, yang lain tidak boleh diubah suai. Seterusnya, tulis semula input untuk hanya menerima maklumat kekunci esc Apabila kita menekan esc, jika tetikus dikunci, ia akan dilepaskan, program akan keluar. Kemudian buat kaedah _update Di sini kita tidak mengatasi kaedah kemas kini yang dipanggil secara automatik oleh ursina, kerana dalam kod sistem, kaedah kemas kini masih mempunyai banyak operasi Jika kita ingin menulis semula, kita juga mungkin perlu menyalin kod sistem. Kod ini terlalu rumit Di sini kita menentukan nama sendiri dan memanggilnya sendiri dalam kod yang akan dibincangkan seterusnya , di sini kami menetapkannya untuk meningkat Kod sistem menerima maklumat kunci ruang dalam input Kami telah menulisnya semula, jadi kaedah lompat kod sistem tidak akan dicetuskan di sini.

这里讲一下input和update中进行按键事件监听操作的不同,input每次只接收一个按键,而且,如果我们一个按键一直按下,它不会一直触发,只会触发一次,然后等到该按键释放,才会重新对该按键进行监听;update相当于主循环,在任何于ursina有关的地方(比如继承自Entity、Button这样的类,或者是主程序)写update方法,ursina都会进行自动调用,我们不需要手动调用它,在update方法中监听事件,我们用到了held_keys,不难发现,held_keys有多个元素,只要按下就为True,所以每次运行到这里,只要按键按下,就执行,而input传入的key本身就是一个元素,所以只有一个,我们按下esc的操作不能连续调用,所以用input,其它移动玩家的代码时可以重复执行的,所以写在update(应该说是用held_keys)中。

class Player(FirstPersonController):
    def __init__(self):
        global planets
        super().__init__()
        camera.fov=90
        self.position=planets[3].position
        self.gravity=0
        self.vspeed=2
        self.speed=600
        self.mouse_sensitivity=Vec2(160,160)
        self.on_enable()
 
    def input(self,key):
        if key=="escape":
            if mouse.locked:
                self.on_disable()
            else:
                sys.exit()
 
    def _update(self):
        if held_keys["left mouse"]:
            self.on_enable()
        if held_keys["left shift"]:
            self.y-=self.vspeed
        if held_keys["space"]:
            self.y+=self.vspeed
Salin selepas log masuk

然后在主程序中写update方法,并在其中调用我们刚刚写的player中的_update方法,再对星球进行自转公转操作

def update():
    global planets,player
    for planet in planets:
        planet.turn(planet.angle)
    player._update()
Salin selepas log masuk

接下来,我们定义两个列表,分别表示星球名称和星球的大小,其实在实际的大小比例中,和这个相差很多,如果地球是1,太阳则大约为130000,木星和图形分别为1500多和700多,这样相差太大,做在程序里看起来很不寻常,所以我们这里对大多数星球的大小进行放大缩小,把它们大小的相差拉近点。然后遍历并绘制,每颗星球的间隔为前一个的10倍

ps=["sun","mercury","venus","earth","mars","jupiter","saturn","uranus","neptune"]
cp=[200,15,35,42,20,160,145,90,80]
x,y,z=0,0,0
for i,p in enumerate(ps):
    newPlanet=Planet(p,(x,y,z),cp[i])
    planets.append(newPlanet)
    x+=cp[i]*10
Salin selepas log masuk

最后实例化player,并运行app

player=Player()
 
if __name__ == '__main__':
    app.run()
Salin selepas log masuk

然后就能实现文章前面展示的效果啦~

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python

最后,附上代码

from ursina import *
from math import *
from ursina.prefabs.first_person_controller import FirstPersonController
import sys
import random as rd
 
app=Ursina()
window.fullscreen=True
window.color=color.black
 
planets=[]
 
class Planet(Entity):
    def __init__(self,_type,pos,scale=2):
        self.angle=rd.uniform(0.0005,0.01)
        self.fastMode=0
        self.rotation=(rd.randint(0,360) for i in range(3))
        self.rotspeed=rd.uniform(0.25,1.5)
        self.rotMode=rd.choice(["x","y","z"])
        self._type=_type
        texture=eval(f"{_type}_texture")
        super().__init__(model="sphere",
                         scale=scale,
                         texture=texture,
                         color=color.white,
                         position=pos)
 
    def turn(self,angle):
        if self._type!="sun":
            if self.fastMode:
                angle*=200
            self.x=self.x*cos(radians(angle))-self.y*sin(radians(angle))
            self.y=self.x*sin(radians(angle))+self.y*cos(radians(angle))
            exec(f"self.rotation_{self.rotMode}+=self.rotspeed")
 
    def input(self,key):
        if key=="enter":
            self.fastMode=1-self.fastMode
 
class Player(FirstPersonController):
    def __init__(self):
        global planets
        super().__init__()
        camera.fov=90
        self.position=planets[3].position
        self.gravity=0
        self.vspeed=2
        self.speed=600
        self.mouse_sensitivity=Vec2(160,160)
        self.on_enable()
 
    def input(self,key):
        if key=="escape":
            if mouse.locked:
                self.on_disable()
            else:
                sys.exit()
 
    def _update(self):
        if held_keys["left mouse"]:
            self.on_enable()
        if held_keys["left shift"]:
            self.y-=self.vspeed
        if held_keys["space"]:
            self.y+=self.vspeed
 
def update():
    global planets,player
    for planet in planets:
        planet.turn(planet.angle)
    player._update()
 
sun_texture=load_texture("texture/Sun.png")
mercury_texture=load_texture("texture/Mercury.png")
venus_texture=load_texture("texture/Venus.png")
earth_texture=load_texture("texture/Earth.png")
mars_texture=load_texture("texture/Mars.png")
jupiter_texture=load_texture("texture/Jupiter.png")
saturn_texture=load_texture("texture/Saturn.png")
uranus_texture=load_texture("texture/Uranus.png")
neptune_texture=load_texture("texture/Neptune.png")
 
ps=["sun","mercury","venus","earth","mars","jupiter","saturn","uranus","neptune"]
cp=[200,15,35,42,20,160,145,90,80]
x,y,z=0,0,0
for i,p in enumerate(ps):
    newPlanet=Planet(p,(x,y,z),cp[i])
    planets.append(newPlanet)
    x+=cp[i]*10
 
player=Player()
 
if __name__ == '__main__':
    app.run()
Salin selepas log masuk

Atas ialah kandungan terperinci Cara menggunakan enjin 3D untuk mencipta simulator planet sistem suria dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
sumber:yisu.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan