📄 flash_3d教程——闪吧 flash8.htm
字号:
face=宋体> 这就是z旋转的公式。用同样的方法可推出x旋转,y旋转的公式。总结如下:</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>给定点:(x,y,z)</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>绕x轴旋转后的点</FONT><FONT
face=宋体>(x1,y1,z1)<BR>绕y轴旋转后的点</FONT><FONT
face=宋体>(x2,y2,z2)<BR>绕z轴旋转后的点(x3,y3,z3)</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT><FONT face=宋体> x旋转(x不变</FONT><FONT
face=宋体>)<BR> </FONT><FONT face=宋体>x1=x<BR> </FONT><FONT
face=宋体>y1=y*cosb-z*sinb<BR> z1=z*cosb+y*sinb</FONT></DIV>
<DIV></DIV>
<P>
<P><FONT face=宋体>
<TABLE cellSpacing=0 cellPadding=0 width="100%">
<TBODY>
<TR>
<TD>
<DIV v:shape="_x0000_s1037">
<DIV>注:x旋转要注意,在FLASH中x1=x<BR> y1=y*cosb+z*sinb<BR> z1=z*cosb-y*sinb</DIV>
<DIV></DIV>
<P>
<DIV>是先加后减,因为FLASH里的Y轴是反的,箭头向下的。</DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV>
<DIV></DIV></DIV></TD></TR></TBODY></TABLE></FONT></P>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体></FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体> y旋转(y不变</FONT><FONT face=宋体>)<BR> </FONT><FONT
face=宋体>x2=x*cosb-z1*sinb<BR> </FONT><FONT
face=宋体>y2=y1<BR> z2=z1*cosb+x*sinb</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体> z旋转(z不变</FONT><FONT face=宋体>)<BR> </FONT><FONT
face=宋体>x3=x2*cosb-y1*sinb<BR> </FONT><FONT
face=宋体>y3=y1*cosb+x2*sinb<BR> z3=z2</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT
face=宋体> 从以上公式可看出,在flash要实现旋转,先要求x轴的旋转点,再求y轴的旋转点,最后再求出z轴的旋转点。最后我们来一个x旋转的应用</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>三、制作x轴旋转的正方体</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体> 1、在场景中画一小球,并按F8转换为mc,实例命名为qiu。</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体> 2、增加一层,命名为as,接下去我们来写as,如下:</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>_root.onLoad = function() {<BR>shumu = 8;<BR>//
</FONT><FONT face=宋体>定义复制小球的数目</FONT><BR><FONT face=宋体>qiu._x =
6000;<BR>// </FONT><FONT face=宋体>让原始小球消失</FONT><BR><FONT face=宋体>for
(var i = 0; i<shumu; i++) {<BR>duplicateMovieClip("qiu", "qiu"+i,
i);<BR>}<BR>// </FONT><FONT face=宋体>复制小球,作为正方体的八个顶点</FONT><BR><FONT
face=宋体>qiu_pos_x = new Array(100, 0, 0, 100, 100, 0, 0,
100);<BR>qiu_pos_y = new Array(100, 100, 100, 100, 0, 0, 0,
0);<BR>qiu_pos_z = new Array(50, 50, -50, -50, 50, 50, -50,
-50);<BR>// </FONT><FONT
face=宋体>从三维坐标中取正方体的8个顶点的坐标,保存在数组中</FONT><BR><FONT face=宋体>D =
200;<BR>// </FONT><FONT face=宋体>观察者与屏幕的距离</FONT><BR><FONT
face=宋体>hutu = 0.001;<BR>// </FONT><FONT
face=宋体>控制旋转的速度</FONT><BR><FONT face=宋体>b = hutu*180/Math.PI;<BR>//
</FONT><FONT face=宋体>角、弧度的转换</FONT><BR><FONT
face=宋体>};<BR>_root.onEnterFrame = function() {</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>for (var i = 0; i<shumu; i++) {<BR>x1 =
qiu_pos_x[i];<BR>y1 =
qiu_pos_y[i]*Math.cos(b)-qiu_pos_z[i]*Math.sin(b);<BR>z1 =
qiu_pos_z[i]*Math.cos(b)+qiu_pos_y[i]*Math.sin(b);<BR>//
</FONT><FONT face=宋体>按公式计算</FONT><BR><FONT face=宋体>qiu_pos_x[i] =
x1;<BR>qiu_pos_y[i] = y1;<BR>qiu_pos_z[i] = z1;<BR>// </FONT><FONT
face=宋体>更新数组元素</FONT><BR><FONT face=宋体>ratio =
D/(D+z1);<BR>perspective_x = x1*ratio;<BR>perspective_y =
y1*ratio;<BR>// </FONT><FONT face=宋体>按公式计算</FONT><BR><FONT
face=宋体>_root["qiu"+i]._x = 275+perspective_x;<BR>_root["qiu"+i]._y
= 200-perspective_y;<BR>/ </FONT><FONT
face=宋体>设置球的坐标</FONT><BR><FONT face=宋体>_root["qiu"+i]._xscale =
_root["qiu"+i]._yscale=50*ratio;<BR>// </FONT><FONT
face=宋体>球的大小</FONT><BR><FONT
face=宋体>_root["qiu"+i].swapDepths(10000-qiu_pos_z[i]);<BR>//
</FONT><FONT face=宋体>球的层次</FONT><BR><FONT
face=宋体>_root["qiu"+i]._alpha=100*ratio;//</FONT><FONT
face=宋体>设置透明度</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>}<BR>};</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>3、按CTRL+Enter测试,一个简单的3D旋转就形成了。</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>(至此为止,上面部分的教程很大程度上是参考《<B>flash 3D
</B><B>基础教程</B>》(作者:zjs35 文章来源:flashempire
更新时间:2004-4-7)的,本人只在上面做了微小部分的修改,主要因为这篇对FLASH_3D效果的基础理论确实写的很好。修改的部分,是本人在学习之后,自己在实践练习中发现的一些需要注意的地方。)</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT
face=宋体>接下来将为大家解析一篇某人大虾写的立方体旋转的FLASH_AS,这位大虾是用纯AS写的,只要把代码全部复制到第一桢就可以了。我将做详细的解析!!!</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>//</FONT><FONT
face=宋体>先给各项赋值,为后面的编辑作做准备</FONT><FONT face=宋体> <BR>plane = [0, [0,
1, 2, 3, 4], [0, 5, 6, 7, 8], [0, 1, 2, 6, 5], [0, 2, 3, 7, 6], [0,
4, 3, 7, 8], [0, 1, 4, 8, 5]];
//给立方体的8个点都标上数,这里定义的数组是立方体的6个面,每个面上4个点,上面的数字就是哪四个点组成一个面,每组前面多个0,是为了下面做循环调用是方便,循环可以从i=1开始。大家自己可以根据上面的数组。画出它在三维坐标中的立体图形。另,第一“0“,其实是[0,0,0,0,0]。</FONT><BR><FONT
face=宋体>dx = [0, 1, -1, -1, 1, 1, -1, -1, 1]; //</FONT><FONT
face=宋体>这里是给8个点在三维坐标定义数组,竖着看,没一行就是一个点坐标的(x,y,z)
,另没组前面多个0,是为了下面做循环调用是方便,循环可以从i=1开始。</FONT><BR><FONT face=宋体>dy = [0,
1, 1, 1, 1, -1, -1, -1, -1]; //<BR>dz = [0, 1, 1, -1, -1, 1, 1, -1,
-1]; //<BR>colour=0x4499FF //</FONT><FONT
face=宋体>这里定义的是立方体的颜色,其实,要6个面,每个面的颜色不同,就把这个colour定义成数组就可以了。同样前面加个0,也是上面的理由。</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT
face=宋体>//colour=[0,0x4499FF,0x6F13EC,0xF1F00E,0x6CE31C,0x26D9A3,0x808080];</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>trans = Math.PI/180; //</FONT><FONT
face=宋体>下面的弧度和角度的转换用</FONT><BR><FONT face=宋体>cube_width = 100;
//</FONT><FONT face=宋体>用于设定立方体的边的长度</FONT><BR><FONT face=宋体>d = 400;
//// </FONT><FONT face=宋体>观察者与屏幕的距离</FONT><BR><FONT
face=宋体>num_planes = plane.length-1; //num_planes=6<BR>num_nodes =
dx.length-1; //num_nodes=8<BR>num_nodes_per_plane =
plane[1].length-1;//num_nodes_per_plane=4 <BR>xz_angle_inc = 0;
//</FONT><FONT face=宋体>下面这4个定义对用鼠标控制旋转的速度有关,</FONT><BR><FONT
face=宋体>yz_angle_inc = 0; <BR>angle_inc_factor = .1;
<BR>angle_dec_factor = .9; <BR>o_x = Stage.width/2; //</FONT><FONT
face=宋体>把坐标原点移到屏幕中心</FONT><BR><FONT face=宋体>o_y = Stage.height/2;
<BR>node = new Array(); //</FONT><FONT face=宋体>定义新数组</FONT><BR><FONT
face=宋体>p_node = new Array(); <BR>//</FONT><FONT face=宋体>边长调整...
主要是求出8个点,在设定边长,情况下的坐标</FONT><BR><FONT face=宋体>for (i=1;
i<=num_nodes; i++) { <BR>node[i] = new Object(); <BR>node[i].x =
dx[i]*(cube_width/2); <BR>node[i].y = dy[i]*(cube_width/2);
<BR>node[i].z = dz[i]*(cube_width/2); <BR>} <BR>for (i=1;
i<=num_planes; i++) { //</FONT><FONT
face=宋体>建立6个空白的影片剪辑,主要用于,每天影片剪辑,画一个立方体的面。</FONT><BR><FONT
face=宋体>_root.createEmptyMovieClip("plane"+i, i); <BR>}
<BR>//</FONT><FONT face=宋体>版面的调整 下面的_root.onEnterFrame
会调用这里进行画立方体</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>//</FONT><FONT
face=宋体>对这里不理解的,看附录一的代码!</FONT><BR><FONT face=宋体>function
create_planes() { <BR>for (var i = 1; i<=num_planes; i++) {
<BR>depth = 0; //</FONT><FONT face=宋体>设定深度初始值</FONT><BR><FONT
face=宋体>mc = _root["plane"+i]; //</FONT><FONT
face=宋体>每个影片剪辑画一个立方体的一个面</FONT><BR><FONT face=宋体>mc.clear();
//</FONT><FONT
face=宋体>清除上次画的面,不用这句语句,可以看到面的连续旋转的会是什么轨迹,程序是怎么画的。不过,很难看。</FONT><BR><FONT
face=宋体>mc.beginFill(colour, 100); //</FONT><FONT
face=宋体>设置立方体面的颜色,colour可以变数组colour[i],这样每个面可以画,不同的颜色。</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT
face=宋体>mc.lineStyle(3,0xFF0000,100);//设置立方体的棱的颜色</FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>mc.moveTo(p_node[plane[i][1]].x,
p_node[plane[i][1]].y);//</FONT><FONT
face=宋体>这里设定每个正方形面,开始画时的启始点。</FONT><FONT face=宋体> <BR>for
(j=num_nodes_per_plane; j>=1; j--) {
//这里是连续读取4个点,画好一个正方形</FONT><BR><FONT
face=宋体>mc.lineTo(p_node[plane[i][j]].x, p_node[plane[i][j]].y);
<BR>depth += node[plane[i][j]].z; //</FONT><FONT
face=宋体>求每个面上4点旋转后,4个点的深度变化,并相加</FONT><BR><FONT face=宋体>} <BR>depth
/= -num_nodes_per_plane;//</FONT><FONT
face=宋体>注意除以负数,这样符合,FLASH的深度变化的远近情况</FONT><FONT face=宋体>
<BR>mc.swapDepths(depth);
//有点的深度变化,来控制面的层次变化,如果没有这句,可以看到一个立方体在旋转是6个面的层次混乱。</FONT><BR><FONT
face=宋体>amount = depth/50*100+15;//</FONT><FONT
face=宋体>用深度变化,在传值,这个参数主要用于下面的语句,下面的语句,用于立方体在旋转时,面的亮度的调整,符合一定的光照效果。</FONT><FONT
face=宋体> <BR>new Color(mc).setTransform({ra:amount, ga:amount,
ba:amount}); //这句语句可以查看FLASH_AS语法参考,可以找到的。主要是对色彩的设置。</FONT><BR><FONT
face=宋体>} <BR>} <BR><BR>//</FONT><FONT face=宋体>鼠标激发</FONT><FONT
face=宋体> <BR>_root.onMouseDown = function() { <BR>mouse_down = true;
<BR>}; <BR>_root.onMouseUp = function() { <BR>mouse_down = false;
<BR>}; <BR>_root.onEnterFrame = function() { <BR>if (mouse_down) {
//判断,鼠标情况,对鼠标移动距离的相加,如果,没有“+=”而用“=”,这样鼠标每点一次,图象就跳回初始状态。可以自己实验看下效果,进行对比。</FONT><BR><FONT
face=宋体>xz_angle_inc += (_xmouse-old_mx)*angle_inc_factor;
<BR>yz_angle_inc += (_ymouse-old_my)*angle_inc_factor; <BR>} <BR>for
(i=1; i<=num_nodes; i++) { <BR>sin_xz =
Math.sin(xz_angle_inc*trans); //</FONT><FONT
face=宋体>对弧度与角度的转化公式。</FONT><BR><FONT face=宋体>cos_xz =
Math.cos(xz_angle_inc*trans); <BR>sin_yz =
Math.sin(yz_angle_inc*trans); <BR>cos_yz =
Math.cos(yz_angle_inc*trans); <BR>rx1 =
cos_xz*node[i].x-sin_xz*node[i].z; //</FONT><FONT
face=宋体>这里就是上面的坐标转换公式里的,先按Y轴旋转,再按X轴旋转。</FONT><BR><FONT face=宋体>ry1 =
node[i].y; <BR>rz1 = cos_xz*node[i].z+sin_xz*node[i].x; <BR>rx2 =
rx1; <BR>ry2 = cos_yz*ry1+sin_yz*rz1; <BR>rz2 =
cos_yz*rz1-sin_yz*ry1; <BR>node[i].x = rx2; //</FONT><FONT
face=宋体>这里是把每个旋转后,得到的先的坐标保存在变量里</FONT><BR><FONT face=宋体>node[i].y =
ry2; <BR>node[i].z = rz2; <BR>p_ratio = d/(d+node[i].z);
//</FONT><FONT face=宋体>这个是上面</FONT><FONT
face=宋体>d/(d+z)<BR>p_node[i] = new Object(); <BR>p_node[i].x =
o_x+node[i].x*p_ratio; //确定在屏幕上点的位置</FONT><BR><FONT
face=宋体>p_node[i].y = o_y-node[i].y*p_ratio; <BR>} <BR>xz_angle_inc
*= angle_dec_factor; //</FONT><FONT
face=宋体>这个加速鼠标控制时的旋转速度</FONT><BR><FONT face=宋体>yz_angle_inc *=
angle_dec_factor; <BR>old_mx = _xmouse; //</FONT><FONT
face=宋体>得到影片开始时的鼠标坐标</FONT><BR><FONT face=宋体>old_my = _ymouse;
<BR>create_planes(); //</FONT><FONT
face=宋体>调用上面的函数,画出立方体</FONT><BR><FONT face=宋体>}; </FONT></DIV>
<DIV></DIV>
<P>
<DIV><FONT face=宋体>//</FONT><FONT
face=宋体>点评:本人只所以选择这个例子进行解析,主要是因为画立方体,是很常见的例子,也是3D里的一个基本的画法。另,这个例子的代码是很精练,简洁,再加上代码的前部分定义的一些值,利于以后做其他项目的开发,可以把这个程序改成一个类,适合自身以后,对画立方体时调用。同时,可以在这个程序基础上做进一步开发!比如,将好几个立方体叠起来,把图片放在立方体的面上,做一些旋转立体按钮等等,都是可以的。</FONT><BR><FONT
face=宋体>//</FONT><FONT face=宋体>附录一:</FONT></DIV>
<DIV></DIV>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -