从头开始学习FLASH 3D教程

教程

  效果演示:(用鼠标直接拖拽下面的物体)

点击这里下载源文件

  大家都知道三维的点都有3个坐标,但FLASH只是有二维的坐标,所以要在FLASH里实现“三维”的效果,就需要对点的坐标进行转化,简单的说,就是怎么把三维坐标转换成二维坐标。(其实,这并不是真正的三维,而是一种视觉欺骗,看上去像三维的就这么回事。所以上面三维带引号。)

  一、三维坐标系转化成二维坐标系

  (1)、坐标的转换

  flash中场景左上角为(0,0),而在数学中是场景中心为(0,0),怎样把它转成数学中的坐标系呢? 

  1.FLASH里的坐标视图

 x=Stage.width/2; // Stage.width是场景的宽;

 y=Stage.height/2; // Stage.height是场景的高;

  这样就把原坐标的原点移动了,场景的中心点,不过,Y轴还是向下,为正的。(这在后面做旋转时要注意的。)

  (2)、角度的转换

  flash中Math函数里的参数都要用到弧度,所以角度与弧度之间的转换是需要知道的。

  在flash as中,我们可以通过这样的表达式来进行转换:

hudu=jiaodu*Math.PI/180; / /把角度转换为弧度,公式为:弧度=角度 *3.14/180,3.14为pai
jiaodu=hudu*180/Math.PI; / /把弧度转换为角度,公式为:角度=弧度*180/3.14,3.14为pai
(if (jiaodu<0) { jiaodu = jiaodu+360; }/* 转换后的角度的范围从-180到180, 数学中的角度从0到360,所以小于0时加上360 */)

  2、flash中的三维坐标系

  如图3,z轴表示一个物体离屏幕的远近,当物体的z轴位置增加时,物体朝远离屏幕的方向运动,当物体的z值减小时,物体朝接近屏幕的方向运动。

图3:三维坐标系

图4:二维与三维的点的关系

  3、三维坐标转换成二维坐标

  如图4,已知一个点(x,y,z),利用三角形相似的原理,可以得出下列结论:

  d/(d+z)=y1/y,推出:y1=d*y/(d+z),可在二维平面上来表现空间上的点的位置。进一步把它简化。提出因子d/(d+z),用ratio(比率)表示,这个公式就变为
  ratio=d/(d+z);
  y1=ratio*y;同理可推出
  x1=ratio*x;

  二、控制物体的属性(大小,层次,透明度等)

  1、控制mc的大小

  在三维坐标中,当z值增大,也就是远离屏幕时,物体应越小,反之越大。

  我们可以用上满的ratio,当z增加时,ratio减少,因为在ratio中,z是作为分母的。反之,当z减少时,ratio增加。所以可用ratio来控制mc的大小。如下:

mc1._xscale=mc._xscale*ratio;
mc1._yscale=mc._yscale*ratio;

  2、控制mc的层次

  z值最大,物体应在最底层,最小,在最上层,

  所以mc的层次可以有z组成,可以用很大的数减z,也可以让z除以负数,等等,这里方法比较灵活,也是做”三维”效果的关键,主要要在调试中确定适合设计的方法。flash中,设置mc的层次用swapDepths,如下:

mc.swapDepths(1000-z);//设置mc的层次
mc.swapDepths(z/-4);

  3、控制mc的透明度

  远处的物体看上去模糊些,近处的物体清晰些,在flash中,可用_alpha来控制,方法和控制大小类似,不在介绍原理。如下:

mc._alpha=100*ratio;

  4、控制mc的角度(旋转)

  这一步最难,也最好的东东。学习以后,你将能制作出非常cool的效果
  旋转有三种,x旋转:坐标x不变,y旋转:y不变,z旋转:z不变,我们先来推导z旋转。
  如下图:从点(x,y,0)转到(x1.y1.0),求点(x1.y1.0)

  利用数学中的正弦、余弦公式得出

  x1=r*cos(a+b),而cos(a+b)=sina*cosb+cosa*sinb
  推出:x1=r(cosa*cosb-sina*sinb)
  又因为x=r*cosa,y=r*sina
  所以x1=x*cosb-y*sinb
  同样推出:y1=y*cosb+x*sinb

  这就是z旋转的公式。用同样的方法可推出x旋转,y旋转的公式。总结如下:

给定点:(x,y,z)
绕x轴旋转后的点(x1,y1,z1)
绕y轴旋转后的点(x2,y2,z2)
绕z轴旋转后的点(x3,y3,z3)

 x旋转(x不变)
 x1=x
 y1=y*cosb-z*sinb
 z1=z*cosb+y*sinb

注:x旋转要注意,在FLASH中x1=x

 y1=y*cosb+z*sinb
 z1=z*cosb-y*sinb

是先加后减,因为FLASH里的Y轴是反的,箭头向下的。

 y旋转(y不变)
 x2=x*cosb-z1*sinb
 y2=y1
 z2=z1*cosb+x*sinb
 z旋转(z不变)
 x3=x2*cosb-y1*sinb
 y3=y1*cosb+x2*sinb
 z3=z2

  从以上公式可看出,在flash要实现旋转,先要求x轴的旋转点,再求y轴的旋转点,最后再求出z轴的旋转点。最后我们来一个x旋转的应用

  三、制作x轴旋转的正方体

  1、在场景中画一小球,并按F8转换为mc,实例命名为qiu。

  2、增加一层,命名为as,接下去我们来写as,如下:

_root.onLoad = function() {
shumu = 8;
// 定义复制小球的数目
qiu._x = 6000;
// 让原始小球消失
for (var i = 0; i<shumu; i++) {
duplicateMovieClip("qiu", "qiu"+i, i);
}
// 复制小球,作为正方体的八个顶点
qiu_pos_x = new Array(100, 0, 0, 100, 100, 0, 0, 100);
qiu_pos_y = new Array(100, 100, 100, 100, 0, 0, 0, 0);
qiu_pos_z = new Array(50, 50, -50, -50, 50, 50, -50, -50);
// 从三维坐标中取正方体的8个顶点的坐标,保存在数组中
D = 200;
// 观察者与屏幕的距离
hutu = 0.001;
// 控制旋转的速度
b = hutu*180/Math.PI;
// 角、弧度的转换
};
_root.onEnterFrame = function() {
for (var i = 0; i<shumu; i++) {
x1 = qiu_pos_x[i];
y1 = qiu_pos_y[i]*Math.cos(b)-qiu_pos_z[i]*Math.sin(b);
z1 = qiu_pos_z[i]*Math.cos(b)+qiu_pos_y[i]*Math.sin(b);
// 按公式计算
qiu_pos_x[i] = x1;
qiu_pos_y[i] = y1;
qiu_pos_z[i] = z1;
// 更新数组元素
ratio = D/(D+z1);
perspective_x = x1*ratio;
perspective_y = y1*ratio;
// 按公式计算
_root["qiu"+i]._x = 275+perspective_x;
_root["qiu"+i]._y = 200-perspective_y;
/ 设置球的坐标
_root["qiu"+i]._xscale = _root["qiu"+i]._yscale=50*ratio;
// 球的大小
_root["qiu"+i].swapDepths(10000-qiu_pos_z[i]);
// 球的层次
_root["qiu"+i]._alpha=100*ratio;//设置透明度
}
};

  3、按CTRL+Enter测试,一个简单的3D旋转就形成了。

  (至此为止,上面部分的教程很大程度上是参考《flash 3D 基础教程》(作者:zjs35 文章来源:flashempire 更新时间:2004-4-7)的,本人只在上面做了微小部分的修改,主要因为这篇对FLASH_3D效果的基础理论确实写的很好。修改的部分,是本人在学习之后,自己在实践练习中发现的一些需要注意的地方。)

  接下来将为大家解析一篇某人大虾写的立方体旋转的FLASH_AS,这位大虾是用纯AS写的,只要把代码全部复制到第一桢就可以了。我将做详细的解析!!!

//先给各项赋值,为后面的编辑作做准备
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]。
dx = [0, 1, -1, -1, 1, 1, -1, -1, 1]; //这里是给8个点在三维坐标定义数组,竖着看,没一行就是一个点坐标的(x,y,z) ,另没组前面多个0,是为了下面做循环调用是方便,循环可以从i=1开始。
dy = [0, 1, 1, 1, 1, -1, -1, -1, -1]; //
dz = [0, 1, 1, -1, -1, 1, 1, -1, -1]; //
colour=0x4499FF //这里定义的是立方体的颜色,其实,要6个面,每个面的颜色不同,就把这个colour定义成数组就可以了。同样前面加个0,也是上面的理由。
//colour=[0,0x4499FF,0x6F13EC,0xF1F00E,0x6CE31C,0x26D9A3,0x808080];
trans = Math.PI/180; //下面的弧度和角度的转换用
cube_width = 100; //用于设定立方体的边的长度
d = 400; //// 观察者与屏幕的距离
num_planes = plane.length-1; //num_planes=6
num_nodes = dx.length-1; //num_nodes=8
num_nodes_per_plane = plane[1].length-1;//num_nodes_per_plane=4
xz_angle_inc = 0; //下面这4个定义对用鼠标控制旋转的速度有关,
yz_angle_inc = 0;
angle_inc_factor = .1;
angle_dec_factor = .9;
o_x = Stage.width/2; //把坐标原点移到屏幕中心
o_y = Stage.height/2;
node = new Array(); //定义新数组
p_node = new Array();
//边长调整... 主要是求出8个点,在设定边长,情况下的坐标
for (i=1; i<=num_nodes; i++) {
node[i] = new Object();
node[i].x = dx[i]*(cube_width/2);
node[i].y = dy[i]*(cube_width/2);
node[i].z = dz[i]*(cube_width/2);
}
for (i=1; i<=num_planes; i++) { //建立6个空白的影片剪辑,主要用于,每天影片剪辑,画一个立方体的面。
_root.createEmptyMovieClip("plane"+i, i);
}
//版面的调整 下面的_root.onEnterFrame 会调用这里进行画立方体
//对这里不理解的,看附录一的代码!
function create_planes() {
for (var i = 1; i<=num_planes; i++) {
depth = 0; //设定深度初始值
mc = _root["plane"+i]; //每个影片剪辑画一个立方体的一个面
mc.clear(); //清除上次画的面,不用这句语句,可以看到面的连续旋转的会是什么轨迹,程序是怎么画的。不过,很难看。
mc.beginFill(colour, 100); //设置立方体面的颜色,colour可以变数组colour[i],这样每个面可以画,不同的颜色。
mc.lineStyle(3,0xFF0000,100);//设置立方体的棱的颜色
mc.moveTo(p_node[plane[i][1]].x, p_node[plane[i][1]].y);//这里设定每个正方形面,开始画时的启始点。
for (j=num_nodes_per_plane; j>=1; j--) { //这里是连续读取4个点,画好一个正方形
mc.lineTo(p_node[plane[i][j]].x, p_node[plane[i][j]].y);
depth += node[plane[i][j]].z; //求每个面上4点旋转后,4个点的深度变化,并相加
}
depth /= -num_nodes_per_plane;//注意除以负数,这样符合,FLASH的深度变化的远近情况
mc.swapDepths(depth); //有点的深度变化,来控制面的层次变化,如果没有这句,可以看到一个立方体在旋转是6个面的层次混乱。
amount = depth/50*100+15;//用深度变化,在传值,这个参数主要用于下面的语句,下面的语句,用于立方体在旋转时,面的亮度的调整,符合一定的光照效果。
new Color(mc).setTransform({ra:amount, ga:amount, ba:amount}); //这句语句可以查看FLASH_AS语法参考,可以找到的。主要是对色彩的设置。
}
}
//鼠标激发
_root.onMouseDown = function() {
mouse_down = true;
};
_root.onMouseUp = function() {
mouse_down = false;
};
_root.onEnterFrame = function() {
if (mouse_down) { //判断,鼠标情况,对鼠标移动距离的相加,如果,没有“+=”而用“=”,这样鼠标每点一次,图象就跳回初始状态。可以自己实验看下效果,进行对比。
xz_angle_inc += (_xmouse-old_mx)*angle_inc_factor;
yz_angle_inc += (_ymouse-old_my)*angle_inc_factor;
}
for (i=1; i<=num_nodes; i++) {
sin_xz = Math.sin(xz_angle_inc*trans); //对弧度与角度的转化公式。
cos_xz = Math.cos(xz_angle_inc*trans);
sin_yz = Math.sin(yz_angle_inc*trans);
cos_yz = Math.cos(yz_angle_inc*trans);
rx1 = cos_xz*node[i].x-sin_xz*node[i].z; //这里就是上面的坐标转换公式里的,先按Y轴旋转,再按X轴旋转。
ry1 = node[i].y;
rz1 = cos_xz*node[i].z+sin_xz*node[i].x;
rx2 = rx1;
ry2 = cos_yz*ry1+sin_yz*rz1;
rz2 = cos_yz*rz1-sin_yz*ry1;
node[i].x = rx2; //这里是把每个旋转后,得到的先的坐标保存在变量里
node[i].y = ry2;
node[i].z = rz2;
p_ratio = d/(d+node[i].z); //这个是上面d/(d+z)
p_node[i] = new Object();
p_node[i].x = o_x+node[i].x*p_ratio; //确定在屏幕上点的位置
p_node[i].y = o_y-node[i].y*p_ratio;
}
xz_angle_inc *= angle_dec_factor; //这个加速鼠标控制时的旋转速度
yz_angle_inc *= angle_dec_factor;
old_mx = _xmouse; //得到影片开始时的鼠标坐标
old_my = _ymouse;
create_planes(); //调用上面的函数,画出立方体
};
//点评:本人只所以选择这个例子进行解析,主要是因为画立方体,是很常见的例子,也是3D里的一个基本的画法。另,这个例子的代码是很精练,简洁,再加上代码的前部分定义的一些值,利于以后做其他项目的开发,可以把这个程序改成一个类,适合自身以后,对画立方体时调用。同时,可以在这个程序基础上做进一步开发!比如,将好几个立方体叠起来,把图片放在立方体的面上,做一些旋转立体按钮等等,都是可以的。
//附录一:
/*function create_planes(){
depth=0;
plane1.clear();
plane1.beginFill(0xAB548B,100);
plane1.lineStyle(3,0xFF0000,100);
plane1.moveTo(p_node[5].x,p_node[5].y);
plane1.lineTo(p_node[8].x,p_node[8].y);
plane1.lineTo(p_node[7].x,p_node[7].y);
plane1.lineTo(p_node[6].x,p_node[6].y);
plane1.lineTo(p_node[5].x,p_node[5].y);
depth=node[8].z+node[7].z+node[6].z+node[5].z;
depth=depth/(-4);
plane1.swapDepths(depth);
amount=depth/50*100+15;
//new Color(plane1).setTransform({ra:amount,ga:amount,ba:amount,aa:amount});
new Color(plane1).setTransform({ra:amount,ga:amount,ba:amount});
depth=0;
plane2.clear();
plane2.beginFill(0x808080,100);
plane2.lineStyle(3,0xFF0000,100);
plane2.moveTo(p_node[1].x,p_node[1].y);
plane2.lineTo(p_node[2].x,p_node[2].y);
plane2.lineTo(p_node[3].x,p_node[3].y);
plane2.lineTo(p_node[4].x,p_node[4].y);
plane2.lineTo(p_node[1].x,p_node[1].y);
depth=depth+node[4].z+node[3].z+node[2].z+node[1].z;
depth=depth/(-4);
plane2.swapDepths(depth);
amount=depth/50*100+15;
new Color(plane2).setTransform({ra:amount,ga:amount,ba:amount});
depth=0;
plane3.clear();
plane3.beginFill(0x8A0FF0,100);
plane3.lineStyle(3,0xFF0000,100);
plane3.moveTo(p_node[1].x,p_node[1].y);
plane3.lineTo(p_node[2].x,p_node[2].y);
plane3.lineTo(p_node[6].x,p_node[6].y);
plane3.lineTo(p_node[5].x,p_node[5].y);
plane3.lineTo(p_node[1].x,p_node[1].y);
depth=depth+node[1].z+node[2].z+node[6].z+node[5].z;
depth=depth/(-4);
plane3.swapDepths(depth);
amount=depth/50*100+15;
new Color(plane3).setTransform({ra:amount,ga:amount,ba:amount});
depth=0;
plane4.clear();
plane4.beginFill(0xE61A48,100);
plane4.lineStyle(3,0xFF0000,100);
plane4.moveTo(p_node[2].x,p_node[2].y);
plane4.lineTo(p_node[3].x,p_node[3].y);
plane4.lineTo(p_node[7].x,p_node[7].y);
plane4.lineTo(p_node[6].x,p_node[6].y);
plane4.lineTo(p_node[2].x,p_node[2].y);
depth=depth+node[2].z+node[3].z+node[7].z+node[6].z;
depth=depth/(-4);
plane4.swapDepths(depth);
amount=depth/50*100+15;
new Color(plane4).setTransform({ra:amount,ga:amount,ba:amount});
depth=0;
plane5.clear();
plane5.beginFill(0x49B667,100);
plane5.lineStyle(3,0xFF0000,100);
plane5.moveTo(p_node[4].x,p_node[4].y);
plane5.lineTo(p_node[3].x,p_node[3].y);
plane5.lineTo(p_node[7].x,p_node[7].y);
plane5.lineTo(p_node[8].x,p_node[8].y);
plane5.lineTo(p_node[4].x,p_node[4].y);
depth=depth+node[4].z+node[3].z+node[7].z+node[8].z;
depth=depth/(-4);
plane5.swapDepths(depth);
amount=depth/50*100+15;
new Color(plane5).setTransform({ra:amount,ga:amount,ba:amount});
depth=0;
plane6.clear();
plane6.beginFill(0xDEB321,100);
plane6.lineStyle(3,0xFF0000,100);
plane6.moveTo(p_node[1].x,p_node[1].y);
plane6.lineTo(p_node[5].x,p_node[5].y);
plane6.lineTo(p_node[8].x,p_node[8].y);
plane6.lineTo(p_node[4].x,p_node[4].y);
plane6.lineTo(p_node[1].x,p_node[1].y);
depth=depth+node[1].z+node[5].z+node[8].z+node[4].z;
depth=depth/(-4);
plane6.swapDepths(depth);
amount=depth/50*100+15;
new Color(plane6).setTransform({ra:amount,ga:amount,ba:amount});

}*/

时间: 2016-07-08

从头开始学习FLASH 3D教程的相关文章

Flash图文教程:flash文字跳动(教程)

教程 中国教程网  作者:深秋枫叶 文字的动画,在flash动画里面出现的较多,具有常用性.本教程除了要告诉大家制作方法以外,更想让大家明白的是:简单的操作,也会有生动的动画!关键在于我们要学会思考,学会总结! 本教程制作上用的软件是flash mx,主要讲述动画的主体部份,即文字动画的制作. 现在,我们就进入教程的学习,本教程的效果,并没有用到任何的As程序,对程序怀有恐惧感的人,大可放心的看下去.呵呵. 在制作之前,我们先分析一下,动画文字的跳动,很明显的出现了一个压缩变形的效果,这就让我们

FLASH创意设计教程:试读-“都市恋爱”

教程|设计 1.3 基础效果制作 1.3.1帧动画 1. 都市恋爱 在充满诗意的黄昏,都市的大厦闪烁着灯光,逐渐的灯光隐灭,留下了"LOVE"恋爱的音符--这个创意来源于网络,看到过一个大学生宿舍灯光求爱的图片,所以想到了这个效果. 效果展示 其中一帧画面如图1.3.1所示(完整效果参见光盘中的"\第一部分\第三章\都市恋爱.swf") 点击这里下载源文件 效果讲解 在Flash中,朋友们可以通过改变连续排列的帧内容来实现动画.创建动画序列有两种方法.逐帧动画和渐变

FLASH创意设计教程:试读-临摹绘画技术

教程|设计 上一节:FLASH创意设计教程:试读-"都市恋爱" 2.2 临摹绘画 Flash动画主要有两个部分组成,其一为绘画,其二为电影等姊妹艺术的表现方法.初学朋友们在创作Flash动画过程中,往往无法准确.生动地把自己头脑中构思的角色形象在电脑中表现出来.如何提高创作者本身的美术技能技巧,是朋友们非常关心的问题.我们在论坛上也经常遇到朋友提出这样的问题"没有学习过美术,能制作出优秀的Flash动画吗?",答案非常明确"不能".因为,Flas

由浅入深学习Flash制作高射炮游戏(续)

接着上篇:由浅入深学习Flash制作高射炮游戏我们制作一个完整的游戏. 上篇讲到了,可以设置一定角度发炮弹了!这时接着做,首先我们把炮弹去掉,只要炮弹出来舞台左.右和下我们就将该MC去掉. 代码: Mouse.hide();gravity = 2;attachMovie("crosshair", "crosshair", 1);attachMovie("tank", "tank", 2, {_x:230, _y:350});c

Flash入门教程:给任意照片添加雪景动画

本例是Flash入门教程:给任意照片添加雪景动画,学习视频文件的导入.嵌入,影片剪辑的创建操作.先看看效果演示: 准备工作:雪景图片.下雪的视频. 1.打开Flash,新建FLA文件. 2.导入图片:选菜单中的[文件]-[导入]-[导入到库]把图片导入到库中. 3.导入视频:选菜单中的[文件]-[导入]-[导入视频]打开导入视频面板,选文件路径:点击浏览,在打开面板中找到视频文件,点击打开.在导入视频面板中选中:在SWF中嵌入FLV并在时间轴中播放,点击下一步,嵌入视频,点击下一步,完成频频导入

flash基础教程之绘制和编辑图形对象

  这一课我们将学习Flash图形的绘制和编辑图形对象 Flash中的图形一般都是矢量图形,每个对象都有自己的属性,像直线就有颜色,线型,粗细等属性,可以在"属性"面板中修改; 现在我们试着创建简单的图形,最基本的对象当然是直线对象,启动Flash,新建一个文档,先在手形工具   上双击一下,调整好工作区大小; 在工具箱中单击选中直线工具   ,在下边的属性面板中,按照从左到右的顺序,选择直线的颜色为红色,选择粗细改为3,"实线"不变;   然后将鼠标移到工作区,当

新手快速学习JavaScript免费教程资源汇总

  这篇文章主要介绍了新手快速学习JavaScript免费教程资源汇总,都是非常不错的学习站点,有需要的小伙伴可以参考下. "JavaScript"的名头相信大家肯定是耳熟能详,但只有一小部分人群了解它的使用与应用程序构建方式.这"一小部分"人指的当然是技术过硬的有为青年.网络程序员以及IT专业人员.但对于一位新手或者说外行人而言,"JavaScript"只不过是复杂计算机编程学科当中的另一个不知所云的术语. 那么,JavaScript到底是什么

学习-flash可以制作什么类型动画片,二维的吗。

问题描述 flash可以制作什么类型动画片,二维的吗. 学习flash后可以制作什么,有哪些动画片是二维的,名侦探柯南是不是二维动画片

学习Flash:AS入门教程

教程|入门教程 AS基础 做过Flash动画的Flash爱好者们都知道,要做好一个Flash动画,AS是必不可少的,即使只是很简单的几句代码也能起到整个Flash画龙点睛的作用.这里我只简单的介绍一下AS的基本常识. 首先我们要了解AS要写在什么地方,什么时候AS会被触发执行. 1.帧: 写在关键帧上面的AS,当时间轴上的指针走到这个关键帧的时候,就写在这个帧上面的AS就被触发执行了.常见的例子有在影片结尾的帧写上 stop() 等.操作方法就是点选关键帧,然后打开AS面板. 2.按钮: 不同于