zoukankan      html  css  js  c++  java
  • 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++);//那么相机向后移动
    }

    }
    }



  • 相关阅读:
    设计模式之工厂模式-抽象工厂(02)
    1036 跟奥巴马一起编程 (15 分)
    1034 有理数四则运算 (20 分)
    1033 旧键盘打字 (20 分)
    1031 查验身份证 (15 分)
    大学排名定向爬虫
    1030 完美数列 (25 分)二分
    1029 旧键盘 (20 分)
    1028 人口普查 (20 分)
    1026 程序运行时间 (15 分)四舍五入
  • 原文地址:https://www.cnblogs.com/flash3d/p/2331902.html
Copyright © 2011-2022 走看看