上篇我们讨论了有关旋转摄像机些知识在这篇文章中我们将讲解如何定点旋转摄像机以及把移动和旋转摄像机结合在起当我们只运用旋转摄像机时 在屏幕上我们看到物体围绕着摄像机旋转动画并不是那么"3D"不过这个是我们必经的路等你完全明白了旋转这个概念后我们添加上摄像机在3D 空间移动那样你就不会觉得乏味了首先我们来看个定点旋转摄像机例子当作热身
这个例子我们还是使用我们小P不过是很多小P这样使我们场景看起来更加有层次感运行我们(效果如下)所有物体都在围绕摄像机旋转我想你会有摄像机在不停旋转错觉(或者没有...)
定点旋转摄像机
动画制作步骤:
1. 开始还是些老步骤设定原点建立个舞台还有定义我们摄像机这些都是前几篇所讨论过就不再过多解释了
//sameasusual
varorigin=Object;
origin.x=stage.stageWidth/2;
origin.y=stage.stageHeight/2;
origin.z=0;
varscene=Sprite;
scene.x=origin.x;
scene.y=origin.y;
this.addChild(scene);
varcamera=Object;
camera.x=0;
camera.y=0;
camera.z=0;
camera.panning=0;
varfocal_length=300;
2. 下面定义些常量比如物体总数量PI和物体z间距
//constants
varMAX_OBJ=100;
varPI=3.1415926535897932384626433832795;
varDISTANCE_Z=20; //thedistancetoyourcamera
3. 下面是化所有物体我们运用随机数产生小P所在角度(对于摄像机)递增小P所在点到摄像机距离(3D空间)使用 3角我们就可以得到小Px和z我们同样使用随机数产生它y最后把它添加到舞台上
//nowcreatelotsofballsaroundyourcamera
for(vari=0;i<MAX_OBJ;i)
{
varball=Sphere;
ball.angle=Math.random*(0-PI*2)+PI*2; //thisistherotateangleonthexzplane
ball.dist_center=140+(MAX_OBJ-i)*DISTANCE; //thedistancetoyourcamera
ball.x_3d=Math.cos(ball.angle)*ball.dist_center; //thenweurigtogetx
ball.z_3d=Math.sin(ball.angle)*ball.dist_center; //andz
ball.y_3d=Math.random*(-240-240)+240; //nowputtheballatrandomy
scene.addChild(ball); //addtheballtothecollection
}
4. 对于每个物体我们在摄像机转动角度时刷新它大小和位置于是我们下步写个来达到目首先我们要确定小P相对于我们摄像机旋转角度然 后我们根据这个角度和他们的间垂直距离算出它到摄像机xz和y距离最后还是运用我们的前学过算法缩放和移动物体
//updateballsizeandposition
functionupdate(obj)
{
//gettheanglerelativetoyourcamerapanningangle
varangle=obj.angle-camera.panning;
varx_pos=Math.cos(angle)*obj.dist_center-camera.x; //urigcalculatethex
varz_pos=Math.sin(angle)*obj.dist_center-camera.z; //andz
vary_pos=obj.y_3d-camera.y; //calculatetherelativey
(z_pos>0) //theballisinfrontofthecamera
{
(!obj.visible)
obj.visible=true; //maketheballvisibleanyway
varscale=focal_length/(focal_length+z_pos); //calthescaleoftheball
obj.x=x_pos*scale; //calcualtethexpositioninacameraview
obj.y=y_pos*scale; //andyposition
obj.scaleX=obj.scaleY=scale; //scaletheballtoaproperstate
}
{
obj.visible=false;
}
}
5. 写个循环在每次执行时递增摄像机角度并且刷新舞台上所有物体
functionrun(e:Event)
{
camera.panning0.01; //increahepanningangle
(camera.panning>2*PI)
camera.panning-=2*PI;
(camera.panning<-1*2*PI)
camera.panning2*PI;
for(vari=0;i<scene.numChildren;i) //updatealltheballsonthescreen
{
update(scene.getChildAt(i));
}
}
//addloopeventlistener
this.addEventListener(Event.ENTER_FRAME,run);
注意:
这里我们提到旋转都是在保持y不变情况下横向旋转摄像机换句话说让我们摄像机绕着y轴旋转当然同理我们可以写出摄像机围绕着x轴旋转操作另外同时进行上述两种旋转我将在后面文章里进行介绍
移动和旋转组合
那 么现在你已经知道如何横向旋转摄像机并且前几篇文章中也已经介绍了如何移动摄像机如果我们把这两个操作结合在起那定很棒我想你应该觉得不会很 困难我们前面已经把两个分开操作学会了下面我们所要做只是把这两种操作组合在起来看个动画其中发灰摄像机是运动前位置另外个是 向后(沿摄像机镜头反方向)移动后位置(当摄像机镜头垂直向上看得时候移动得到)从动画中可以看到对于摄像机镜头来说景物位置是不样
移动加旋转摄像机
再来看个图例在这个图片中摄像机沿BO方向向后移动我们可以看出摄像机转角是不变那么我们就可以结合摄像机移动位置和 3角就可以算出它x移动量(图中红色实线)和y移动量(图中蓝色实线)进而我们便可以算出对于移动后摄像机而言小Px和y
移动和旋转角度图解
需要注意是当你首先旋转摄像机然后向后或者向前移动摄像机那么摄像机是沿着摄像机旋转过后角度运动至于移动量和物体到现在摄像机距离我们样可以使用 3角得到( 3角!Nice!)下面我们就看个应用例子:
定点旋转摄像机WS前后移动摄像机AD旋转
动画制作步骤:
1. 重复前面3步
//constants
varMAX_OBJ=100;
varPI=3.1415926535897932384626433832795;
varDISTANCE_Z=20; //thezdistancetoyourcamera
//sameasusual
varorigin=Object;
origin.x=stage.stageWidth/2;
origin.y=stage.stageHeight/2;
origin.z=0;
varscene=Sprite;
scene.x=origin.x;
scene.y=origin.y;
this.addChild(scene);
varcamera=Object;
camera.x=0;
camera.y=0;
camera.z=0;
camera.panning=0;
varmovement=0;
varfocal_length=300;
varpan_left;
varpan_right;
varmove_forward;
varmove_backward;
//nowcreatelotsofballsaroundyourcamera
for(vari=0;i<MAX_OBJ;i)
{
varball=Sphere;
ball.angle=Math.random*(0-PI*2)+PI*2; //thisistherotateangleonthexzplane
ball.dist_center=(MAX_OBJ-i)*DISTANCE_Z; //thezdistancetoyourcamera
ball.x_3d=Math.cos(ball.angle)*ball.dist_center; //thenweurigtogetx
ball.z_3d=Math.sin(ball.angle)*ball.dist_center; //andz
ball.y_3d=Math.random*(-300-300)+300; //nowputtheballatrandomy
scene.addChild(ball); //addtheballtothecollection
}
2. 下面这个是和上面例子中区别主要部分首先我们要得到物体和摄像机xy和z距离然后我们使用反 3角就可以得出物体所在角度同时使用勾股定理得到物体和摄像机距离(注意y距离为0)同理使用 3角我们便可以得到在摄像机移动的后物体x和z然后再根据物体x和z对物体进行2D 空间缩放和移动
//updateballsizeandposition
functiondisplay(obj)
{
varx_pos=obj.x_3d-camera.x; //calculatethexdistancefromobbjecttothecamera
vary_pos=obj.y_3d-camera.y; //andydistance
varz_pos=obj.z_3d-camera.z; //andzdistance
varangle=Math.atan2(z_pos,x_pos); //caculatetherelativeangle
//nowgettheactualobjectradiusaroundcamera
varradius=Math.sqrt(z_pos*z_pos+x_pos*x_pos);
x_pos=Math.cos(angle+camera.panning)*radius; //getthexpositionafterpanning
z_pos=Math.sin(angle+camera.panning)*radius; //andyposition
(z_pos>0) //theballisinfrontofthecamera
{
(!obj.visible)
obj.visible=true; //maketheballvisibleanyway
varscale=focal_length/(focal_length+z_pos); //calthescaleoftheball
obj.x=x_pos*scale; //calcualtethexpositioninacameraview
obj.y=y_pos*scale; //andyposition
obj.scaleX=obj.scaleY=scale; //scaletheballtoaproperstate
}
{
obj.visible=false;
}
txt_z.text=(camera.z)+"";
txt_panning.text=Number(camera.panning*(180/Math.PI)).toFixed(1)+"";
}
3. 写个循环在每次执行时刷新舞台上所有物体
functionrun(e:Event)
{
(camera.panning>2*PI)
camera.panning-=2*PI;
(camera.panning<-1*2*PI)
camera.panning2*PI;
for(vari=0;i<scene.numChildren;i) //updatealltheballsonthescreen
{
display(scene.getChildAt(i));
}
}
4. 下面设置些键盘相应事件使用WS我们可以使摄像机前进和后退AD旋转我们摄像机键盘事件我们在前面提到过就不多说了如果有什么问题话可以查看下前面例子
functionrun(e:Event)
{
(camera.panning>2*PI)
camera.panning-=2*PI;
(camera.panning<-1*2*PI)
camera.panning2*PI;
for(vari=0;i<scene.numChildren;i) //updatealltheballsonthescreen
{
display(scene.getChildAt(i));
}
}
functionkey_down(e:KeyboardEvent):void
{
(e.keyCode65)
pan_left=true;
(e.keyCode68)
pan_right=true;
(e.keyCode87)
move_forward=true;
(e.keyCode83)
move_backward=true;
}
functionkey_up(e:KeyboardEvent):void
{
(e.keyCode65)
pan_left=false;
(e.keyCode68)
pan_right=false;
(e.keyCode87)
move_forward=false;
(e.keyCode83)
move_backward=false;
}
functionkey_response(e:Event):void
{
(pan_left)
camera.panning0.015; //increahepanningangle
(pan_right)
camera.panning-=0.015; //decreahepanningangle
(move_forward)
{
movement=20;
}
(move_backward)
{
movement=-20;
}
(move_forward||move_backward)
{
camera.xMath.sin(camera.panning)*movement;
camera.zMath.cos(camera.panning)*movement;
}
}
//addloopeventlistener
this.addEventListener(Event.ENTER_FRAME,run);
this.addEventListener(Event.ENTER_FRAME,key_response);
stage.addEventListener(KeyboardEvent.KEY_DOWN,key_down);
stage.addEventListener(KeyboardEvent.KEY_UP,key_up);
注意:
我们在这两个例子里并没有涉及到物体层次当然如果你在开发时候最好加上个层次排序这个算法我们在第篇文章里就已经实现你可以试着把那个添加到这两个例子里
建议:
在开发时候我建议你使用面向对象书写方式这样便于你管理我直没有使用OO写法是我不想给读者阅读造成不必要困惑你可以试着把例子中代码写成类然后从.fla文件例如你可以把我们例子中小P写成个类它可以具有x_3dy_3dz_3d等属性
相关文章:
Flash和3D编程探秘( 7)- 3D物体框架
Flash和3D编程探秘( 6)- 全方位旋转摄像机
Flash和3D编程探秘()- Flash和3D空间
Flash和3D编程探秘( 5)- 摄像机旋转和移动
Flash和3D编程探秘( 4)- 摄像机旋转基础知识
Flash和3D编程探秘( 3)- 摄像机(Camera)
作者:YangZhou
出处:http://yangzhou1030.cnblogs.com/
感谢:Yunqing
最新评论