이번에 이루고 싶은 효과는 다음과 같습니다
우선 이번에 필요한 자원을 보내주세요
Earth.jpg
Jupiter.jpg
Mars.j pg
Mercury.jpg
Neptune.jpg
Saturn.jpg
Sun.jpg
Uranus.jpg
Venus.jpg
이제 코드 작성을 시작해 보세요!
먼저 필요한 모듈을 가져오고 3D 엔진 ursina, 수학 라이브러리 수학, 1인칭, sys 및 ursina와 함께 제공되는 임의 라이브러리를 가져옵니다
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=[]
모든 행성의 재질을 소개합니다
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")
Plant 클래스를 만듭니다. Entity에서 상속됩니다. 들어오는 _type은 별의 유형이고 pos는
angle: 행성이 업데이트될 때마다 태양 주위를 회전하는 호
fastMode 값은 1 또는 0이며, 태양 주위 행성의 회전 속도를 200으로 늘릴지 여부를 나타냅니다. times
rotation: 행성의 기울기, 여기서는 무작위로 생성합니다.
rotspeed: 행성 회전 속도
rotMode: xyz 축 중 하나를 따른 회전을 나타내며 자동으로
_type을 선택하여 행성 유형을 저장합니다.
텍스처는 재료이고 eval
을 통해 이 변수를 얻은 다음 슈퍼 클래스 초기화를 수행합니다. 모델은 구의 모양인 구형이고 텍스처는 텍스처를 나타내며 색상은 흰색으로 설정되고 위치가 전달됩니다. 좌표
회전 방법을 정의하고 각도를 전달하며 태양이 아닌 한 회전 및 공전 작업이 수행됩니다. 고속 모드이면 속도가 200배로 증가한 다음 새로운 xy 좌표가 계산되고 자동 전송 작업에 exec가 사용됩니다
마지막으로 입력 방법은 사용자 입력을 허용하도록 정의됩니다. 여기서는 메소드 이름이 시스템에 의해 자동으로 호출되므로 입력해야 합니다. 눌린 버튼의 이름이 항상 전달됩니다. Enter를 누르면 빠른 모드와 일반 모드가 전환됩니다
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
다음으로 FirstPersonController에서 상속된 Player 클래스를 정의합니다.
FirstPersonController를 사용하면 어떨까요?
Ursina와 함께 제공되는 FirstPersonController에는 자체 중력이 있으므로 여기서는 1인칭 시점으로만 사용하고 중력이 필요하지 않은 기능도 있으므로 클래스를 작성하겠습니다. 그것을 상속받은 다음 코드의 일부만 다시 작성하십시오. 먼저 전역 변수 행성을 도입하고, 슈퍼 클래스를 초기화하고, 시야각을 90으로 설정하고, 초기 위치를 지구의 위치로 설정하고, 중력을 0으로 설정해 중력이 없다는 뜻, vspeed는 상승할 때의 속도를 뜻한다. 그리고 속도는 수평 방향으로 움직이는 것을 의미합니다. 속도, mouse_sensitivity는 Vec2 형식이어야 합니다. 사용자가 이름을 지정할 수 있는 위의 vspeed 변수를 제외하고는 다른 변수는 사용할 수 없습니다. 수정될 수 있습니다. 다음으로 esc 키의 정보만 받도록 입력을 다시 작성합니다. esc를 누르면 마우스가 잠겨 있으면 해제되고 프로그램이 종료됩니다. 그런 다음 _update 메소드를 생성하십시오. 여기서는 시스템 코드에서 업데이트 메소드에 여전히 많은 작업이 있으므로 시스템 코드를 복사해야 할 수도 있으므로 ursina가 자동으로 호출하는 업데이트 메소드를 재정의하지 않습니다. 코드가 너무 복잡합니다. 여기서는 이름을 직접 정의하고 다음에 논의할 코드에서 이를 직접 호출합니다. 이 방법에서는 마우스 왼쪽 버튼, 왼쪽 Shift 및 Space의 이벤트를 모니터링합니다. , 여기서는 상승으로 설정했습니다. 시스템 코드는 입력에서 스페이스 키 정보를 수신하므로 여기서는 시스템 코드의 점프 방법이 트리거되지 않습니다.
这里讲一下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
然后在主程序中写update方法,并在其中调用我们刚刚写的player中的_update方法,再对星球进行自转公转操作
def update(): global planets,player for planet in planets: planet.turn(planet.angle) player._update()
接下来,我们定义两个列表,分别表示星球名称和星球的大小,其实在实际的大小比例中,和这个相差很多,如果地球是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
最后实例化player,并运行app
player=Player() if __name__ == '__main__': app.run()
然后就能实现文章前面展示的效果啦~
最后,附上代码
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()
위 내용은 3D 엔진을 사용하여 Python으로 태양계 행성 시뮬레이터를 만드는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!