• PV3D的小练习~太阳系八大行星


    源码:https://files.cnblogs.com/flash3d/8star.rar

    点击右边的几个按钮 可以跟踪查看所选的物体 然后点击左边的自由查看按钮后可以鼠标拖动屏幕 同时按方向键 和CS感觉类似~其他就不多说了,玩玩就知道!

    以下是这个动画的源代码 以后还会对注释进行加精,有问题欢迎留言!(今天实在是太困了=_=)

    stop();//进入有代码的帧一般习惯停止下,以防止动画循环导致代码重复运行
    stage.scaleMode=StageScaleMode.SHOW_ALL;//舞台的显示模式设置为全部显示不扭曲
    import org.papervision3d.lights.PointLight3D;

    import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
    import org.papervision3d.objects.DisplayObject3D;
    import org.papervision3d.objects.primitives.Sphere;
    import org.papervision3d.view.Viewport3D;
    import org.papervision3d.render.BasicRenderEngine;
    import org.papervision3d.scenes.Scene3D;
    import org.papervision3d.materials.utils.MaterialsList;
    import org.papervision3d.cameras.Camera3D;
    import org.papervision3d.materials.BitmapMaterial;//以上是导入PV3D的相关类

    var sunM:sunP=new sunP(100,100);
    var MercuryM:MercuryP=new MercuryP(100,100);
    var VenusM:VenusP=new VenusP(100,100);
    var earthM:earthP=new earthP(100,100);
    var MarsM:MarsP=new MarsP(100,100);
    var JupiterM:JupiterP=new JupiterP(100,100);
    var SaturnM:SaturnP=new SaturnP(100,100);
    var UranusM:UranusP=new UranusP(100,100);
    var NeptuneM:NeptuneP=new NeptuneP(100,100);//以上的sunM等等都是事先导入到库里面的位图,然后现在我们把它链接出来后进行实例化,以便我们在代码中能够使用这些位图,这里的位图数据做模型的贴图用

    var size:Number=0.01;//这个是全局的大小参数,和实际数据是乘除关系,控制星球的半径(太阳除外)
    var speed:Number=365;//这个是速度参数,也是乘除关系
    var distance:Number=1000;//这个是星球间的距离参数,乘除关系,同时也控制着太阳的半径
    var look:int=-1;//应该是个索引参数,0代表第一个行星的索引,1代表第二个……
    var ifplay:Boolean=true;//播放的时候值设为true,暂停的时候反之
    var iffree:Boolean=false;//自由查看状态的时候值为true,否则反之

    var star:Array=new Array();
    var sun:Array=new Array();
    sun.push({R:0.05,T:365,map:sunM});//把太阳的参数保存在数组里,R是半径,T是自转周期,map是贴图
    star.push({R:0.38,T:87.70,a:7.0,r:2440,t:58.65,map:MercuryM,con:null,ball:null});

    star.push({R:0.72,T:224.701,a:3.4,r:6051.8,t:-243.02,map:VenusM,con:null,ball:null});
    star.push({R:1.00,T:365.2422,a:7.25,r:6378.15,t:1,map:earthM,con:null,ball:null});
    star.push({R:1.52,T:686.98,a:1.8,r:3398,t:1.026,map:MarsM,con:null,ball:null});
    star.push({R:5.20,T:4332.589,a:0,r:71492,t:0.41,map:JupiterM,con:null,ball:null});
    star.push({R:9.54,T:10759.5,a:2.5,r:60268,t:0.426,map:SaturnM,con:null,ball:null});
    star.push({R:19.23,T:30799,a:0.772,r:25559,t:0.646,map:UranusM,con:null,ball:null});
    star.push({R:30.06,T:60152,a:1.769,r:24766,t:0.917,map:NeptuneM,con:null,ball:null});//以上是各星球的参数,R轨道半径,T公转周期,a轨道倾角,r星球半径,t自转周期,map贴图,con星球的容器对象,ball星球对象,另外关于AS3中数组的用法请参考帮助文档

    var viewport:Viewport3D;//定义视窗
    var scene:Scene3D;//定义3D场景
    var camera:Camera3D;//定义摄像机
    var renderer:BasicRenderEngine;//定义渲染引起,以上四个是建立一个基本的3D场景的四要素
    viewport=new Viewport3D(1024,768);//用 Viewport3D的构造函数建立一个1024*768大小的视窗
    scene=new Scene3D();//构造一个3D场景
    camera=new Camera3D();//构造一个摄像机,这里说明一下,为什么四要素要定义还要构造呢,定义可以理解为是开辟一块适合的空间用于构造,构造才是往这个空间里填充实质性的东西
    renderer= new BasicRenderEngine();//构造一个渲染引擎
    camera.z=-150;//将摄像机位置的Z坐标设为-150,在PV3D里面默认视角下,水平右方向是X正方向,竖直向上是Y正方向,垂直向里是Z正方向
    stage.addChild(viewport);//这个工作是必须的,PV3D的内容全部在视窗里显示,所以要想看到PV3D的内容前提是必须可以看到视窗,所以必须把视窗添加到舞台的显示列表,显示列表的概念可以参考帮助文档

    var sunS:Sphere;//定义一个球形物体,这个物体是用来当做太阳的
    var sunMaterial:BitmapMaterial;//定义一个贴图,用来做太阳的贴图
    sunMaterial=new BitmapMaterial(sun[0].map);//构造太阳的贴图,贴图的构造函数的参数是个BitmapData类型,这里的sun[0].map就是从我们库里面链接出来并创建的位图
    sunS=new Sphere(sunMaterial,sun[0].R*distance,15,15);//在这里解释下球体的构造函数参数,第一个是贴图数据类型,也就是上面刚刚构建的那个,第二个参数是半径,第三第四个分别是水平和竖直方向的段数,段数越高球体越圆越精细,当然对CPU的要求也就越高
    scene.addChild(sunS);//把太阳球体添加到3D场景里面
    for (var n:int=0; n<8; n++) {//这里用一个八次的循环一次性创建八个行星
    star[n].con=new DisplayObject3D();//这里创建一个当做容器用的DisplayObject3D类,这个类,我们可以把它理解成是物质,球体摄像机包括还有正方体等等都是物质,所以DisplayObject3D类就是他们的父类,他们有共同的旋转,移动等等方法,这里为什么会要当做容器,主要是后面的公转方便
    star[n].ball=new Sphere(new BitmapMaterial(star[n].map),star[0].r*size,15,15);//这里创建球体的方法和创建太阳一样,根据数组的索引我们可以访问每组星球的参数,从而可以用循环创建不同的球体
    star[n].con.addChild(star[n].ball);//这里把球体加入到容器里面
    star[n].ball.z=-star[n].R*distance;//然后球体相对于容器的Z坐标设置成公转轨道的半径
    star[n].con.rotationX+=star[n].a;//对容器绕着X旋转一个倾角(轨道倾角)
    star[n].con.rotationY+=Math.random()*360;//对容器绕着Y旋转一个随机角度,因为查了很多资料都不知道现在星球的初始状态,索性给它随机初始化^_^
    scene.addChild(star[n].con);//把容易添加到场景(这个时候球体在容易里面,就好比是影片剪辑的嵌套原理一样,应该可以理解吧)
    }


    addEventListener(Event.ENTER_FRAME,process);//当进入帧的事件下发生函数process,实际上只要影片播放,Event.ENTER_FRAME这个事件就会被不断触发,于是process函数就会被不断反复执行,这个也是为什么画面可以动起来的原因了
    function process(evt:Event):void {

    if (ifplay) {//在播放情况下执行下面代码
    sunS.rotationY-=speed/sun[0].T;//太阳自转

    for (n=0; n<8; n++) {//用循环对八个行星进行批量操作
    star[n].con.localRotationY+=speed/star[n].T;//容易自转,其实就是行星的公转

    star[n].ball.localRotationY+=speed/star[n].t;//行星自转
    }
    if (!iffree) {//在非自由查看的情况下执行下面的代码(跟踪查看)
    if (look>=0) {

    camera.lookAt(star[look].ball);//根据索引选择跟踪查看的对象
    } else {

    camera.lookAt(sunS);//跟踪查看太阳
    }

    }
    }
    renderer.renderScene(scene,camera,viewport);//不断进行渲染,要是不渲染画面就停住了(类似于刷新)

    }

    bs.addEventListener(MouseEvent.CLICK,bsg);//点击太阳按钮,进行相应的设置
    function bsg(event:MouseEvent):void {

    camera.z=-150;
    camera.x=0;
    camera.y=0;//以上是摄像机坐标设置,把相机挪到一个合适的视角
    speed=365;//对全局速度进行设置
    look=-1;//跟踪视角的索引,表示跟踪太阳
    iffree=false;//设置为非自由视角
    txt.text="太陽是距離地球最近的恆星,是太陽系的中心天體。太陽系質量的99.87%都集中在太陽。太陽系中的八大行星、小行星、流星、彗星、外海王星天體以及星際塵埃等,都圍繞著太陽運行(公轉)。";//下面显示的文字内容
    }

    b0.addEventListener(MouseEvent.CLICK,b0g);//下面的设置和太阳差不多,目的就是调节相机的位置和运行速度之类的
    function b0g(event:MouseEvent):void {

    camera.z=-500;
    camera.x=0;
    camera.y=0;
    speed=365;
    look=0;
    iffree=false;
    txt.text="水星最接近太陽,是太陽系中最小最輕的行星。水星在直徑上小於木衛三和土衛六。";
    }
    b1.addEventListener(MouseEvent.CLICK,b1g);
    function b1g(event:MouseEvent):void {
    camera.z=-800;
    camera.x=0;
    camera.y=0;
    speed=365;
    look=1;
    iffree=false;
    txt.text="八大行星之一,中國古代稱之為太白或太白金星。它有時是晨星,黎明前出現在東方天空,被稱為“啟明”;有時是昏星,黃昏後出現在西方天空,被稱為“長庚”。金星是全天中除太陽和月亮外最亮的星,猶如一顆耀眼的鑽石,於是古希臘人稱它為阿佛洛狄忒--愛與美的女神,而羅馬人則稱它為維納斯--美神。";
    }
    b2.addEventListener(MouseEvent.CLICK,b2g);
    function b2g(event:MouseEvent):void {
    camera.z=-1050;
    camera.x=0;
    camera.y=0;
    speed=365;
    look=2;
    iffree=false;
    txt.text="地球是距太陽第三顆,也是第五大行星";
    }
    b3.addEventListener(MouseEvent.CLICK,b3g);
    function b3g(event:MouseEvent):void {
    camera.z=-1600;
    camera.x=0;
    camera.y=0;
    speed=365;
    look=3;
    iffree=false;
    txt.text="火星為距太陽第四遠,也是太陽系中第七大行星";
    }
    b4.addEventListener(MouseEvent.CLICK,b4g);
    function b4g(event:MouseEvent):void {
    camera.z=-5300;
    camera.x=0;
    camera.y=0;
    speed=3650;
    look=4;
    iffree=false;
    txt.text="木星是離太陽第五顆行星,而且是最大的一顆,比所有其他的行星的合質量大2倍(地球的318倍)。被稱為“行星之王”。";
    }
    b5.addEventListener(MouseEvent.CLICK,b5g);
    function b5g(event:MouseEvent):void {
    camera.z=-9700;
    camera.x=0;
    camera.y=0;
    speed=14600;
    look=5;
    iffree=false;
    txt.text="土星是離太陽第六遠的行星,也是八大行星中第二大的行星";
    }
    b6.addEventListener(MouseEvent.CLICK,b6g);
    function b6g(event:MouseEvent):void {
    camera.z=-19280;
    camera.x=0;
    camera.y=0;
    speed=29200;
    look=6;
    iffree=false;
    txt.text="天王星是太陽系中離太陽第七遠行星,從直徑來看,是太陽系中第三大行星。天王星的體積比海王星大,質量卻比其小。";
    }
    b7.addEventListener(MouseEvent.CLICK,b7g);
    function b7g(event:MouseEvent):void {
    camera.z=-30100;
    camera.x=0;
    camera.y=0;
    speed=58400;
    look=7;
    iffree=false;
    txt.text="海王星是環繞太陽運行的第八顆行星,也是太陽系中第四大天體(直徑上)。海王星在直徑上小於天王星,但質量比它大。";
    }
    st.addEventListener(MouseEvent.CLICK,stg);//点击播放按钮
    function stg(event:MouseEvent):void {//播放参数为真
    ifplay=true;

    }
    pu.addEventListener(MouseEvent.CLICK,pug);//暂停
    function pug(event:MouseEvent):void {

    ifplay=false;
    }
    editor.addEventListener(MouseEvent.CLICK,editorg);//显示作者按钮
    function editorg(event:MouseEvent):void {

    txt.text="陳鋆";
    }

    seefree.addEventListener(MouseEvent.CLICK,seefreeg);//点击自由视角按钮,进入自由查看模式
    function seefreeg(event:MouseEvent):void {

    iffree=true;//自由查看设为真
    txt.text="自由視角操作提示:按方向上下鍵可以前進後退,鼠標按住再移動可以改變視角";

    }
    stage.addEventListener(MouseEvent.MOUSE_DOWN, MouseDown);//在舞台上按下鼠标的时候发生MouseDown函数
    stage.addEventListener(MouseEvent.MOUSE_MOVE, MouseMove);//鼠标在舞台上移动发生MouseMove函数
    stage.addEventListener(MouseEvent.MOUSE_UP, MouseUp);//鼠标在舞台上放开发生函数MouseUp
    var roll:Boolean=false;//是否处于拖动状态的参数
    var previousMouseX:Number=0;

    var previousMouseY:Number=0;//临时储存鼠标的上一个位置
    function MouseDown(event:MouseEvent):void {//按下鼠标的时候
    if (iffree) {//当然要在自由查看的状态下
    roll = true;//拖动被允许
    previousMouseX = event.stageX;

    previousMouseY = event.stageY;//获取按下鼠标的位置
    }

    }
    function MouseUp(event:MouseEvent):void {//当鼠标放开的时候
    if (iffree) {

    roll = false;//拖动被禁止
    }

    }
    function MouseMove(event:MouseEvent):void {//当移动鼠标的时候
    if (iffree) {//在自由查看的状态下
    var differenceX:Number = event.stageX - previousMouseX;

    var differenceY:Number = event.stageY - previousMouseY;//鼠标新位置和上一时刻的位置的差值,其实就是鼠标坐标的增量
    if (roll) {//在可拖动的状态下
    camera.rotationY+=differenceX;

    camera.rotationX+=differenceY;//镜头往鼠标移动的方向移动
    previousMouseX = event.stageX;

    previousMouseY = event.stageY;//临时储存新的鼠标位置
    }

    }
    }

    stage.addEventListener(KeyboardEvent.KEY_DOWN,keydown);//键盘有按键按下的情况发生keydown
    stage.addEventListener(KeyboardEvent.KEY_UP,keyup);//键盘有按键放开的情况下发生keyup
    stage.addEventListener(Event.ENTER_FRAME,go);//这个事件是上面讲过的连续发生事件,这里再连续发生go
    var movt:Boolean=false;//向前移动参数
    var movb:Boolean=false;//向后移动参数
    var s:Number=0;

    function keydown(event:KeyboardEvent):void {//有键盘按键按下
    if (iffree) {//在自由查看的情况下
    if (event.keyCode==38) {//如果按下去的键的键控代码值为38,也即是按下方向键的向上
    movt=true;//那么向前移动被允许
    movb=false;//向后移动被禁止
    } else if (event.keyCode==40) {//如果按下方向键向后
    movt=false;//向前移动被禁止
    movb=true;//向后移动被允许
    }

    }
    }
    function keyup(event:KeyboardEvent):void {//按键被松开
    if (iffree) {//在自由查看的前提下
    movt=false;

    movb=false;//先前向后均被禁止
    s=0;

    }
    }
    function go(event:Event):void {//这个事件是被不断触发的
    if (iffree) {//在自由查看的前提下
    if (movt) {//如果先前移动被允许
    camera.moveForward(s++);//那么相机就向前移动
    } else if (movb) {//否则如果向后移动被允许
    camera.moveBackward(s++);//那么相机向后移动
    }

    }
    }



  • 相关阅读:
    Windows中的库编程(三、函数调用约定 Calling Convention)
    weui
    js 压缩图片
    django 跨域访问
    html5
    有用的网站
    Chrome
    srpingBoot配置多环境配置文件
    Mysql在查询时不区分大小写
    [CentOS7]Nginx 1.20.1不支持四层负载
  • 原文地址:https://www.cnblogs.com/flash3d/p/2331902.html
Copyright © 2020-2023  润新知