Flash制作3D类动画的教程

所属分类: 媒体动画 / Flash教程 阅读数: 40
收藏 0 赞 0 分享
最近对Flash3D效果产生了兴趣,下决心学习一下Sandy。一下将学习的体会的感受写下来,一来帮助大家熟悉Sandy,二来加强自己的记忆。

先从基础开始吧(基础解释转自Flash3D研究所)

原理解释:

窗口:
用户观看的窗口,简单的可以想成就是flash里面的画布大小。窗口也可以理解成渲染的尺寸,否则画面就无限大了 场景:
场景是指整个三维的场景。 摄像机:
很多人要问,为什么有了摄像机还要窗口呢?摄像机是用来拍画面的,看画面还是得电视机/窗口不是吗,^_^
渲染器:如果没有这个东西,所有以上的东西都只是数据,渲染器就是把所有数据变成图像的东西。

下面这幅图虽然并不算准确的表述,但希望能帮助我们理解:

然后开始写代码了(目前感觉Sandy的代码还是比较简洁的):

要先将Sandy的类库下载下来哦!!(在这里要谢谢 tenzn 的提醒,呵呵。)
官方网站:http://www.flashsandy.org
下载地址:http://sandy.googlecode.com/files/Sandy3-1-1_src_rev1008.zip

先尝试创建一个立方体。

package
{
import flash.display.Sprite;
import flash.events.Event;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;

/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.z = -300;
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
}
var box = new Box("box", 100, 100, 100);
public function createScene() {
var g:Group = new Group();
g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
}

}

成功了,效果如下:

接下来尝试给这个立方体着色。

这里需要用到 sandy.materials.attributes 类。

其中为线着色的方法 LineAttributes 有三个属性:
LineAttributes(p_nThickness:uint = 1, p_nColor:uint = 0, p_nAlpha:Number = 1)

p_nThickness:uint (default = 1) — 线的粗细 p_nColor:uint (default = 0) — 线的颜色 p_nAlpha:Number (default = 1) — 线的透明度

这里设置是否使用光,需要先设置 lightingEnable = true 。
LightAttributes(p_bBright:Boolean = false, p_nAmbient:Number = 0.3)

p_bBright:Boolean (default = false) — 设置是否支持光 p_nAmbient:Number (default = 0.3) — 设置光的亮度(数值范围是 0 - 1)

为立方体渲染用
ColorMaterial(p_nColor:uint = 0x00, p_nAlpha:Number = 1, p_oAttr:MaterialAttributes = null)

p_nColor:uint (default = 0x00) — 颜色 p_nAlpha:Number (default = 1) — 透明度 p_oAttr:MaterialAttributes (default = null) — 线设置

代码如下:

package
{
import flash.display.Sprite;
import flash.events.Event;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;

/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.z = -300;
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
}
var box = new Box("box", 100, 100, 100);
public function createScene() {
var g:Group = new Group();
//设置立方体的颜色、线条色和环境光
material.lightingEnable = true;
var materialAttr:MaterialAttributes = new MaterialAttributes(
new LineAttributes( 0.5, 0x000000, 0.4 ),
new LightAttributes( true, 0.2)
);
var material:Material = new ColorMaterial( 0xCC3300, 1, materialAttr );
var app:Appearance = new Appearance( material );

box.appearance = app;

g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
}

}

这是效果:

继续试试看用图片为立方体贴图。

首先导入一张位图到库里,并声明类名为 MyPalm

package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.net.URLRequest;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;

/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.z = -300;
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
}
var box = new Box("box", 100, 100, 100);
public function createScene() {
var g:Group = new Group();
//设置立方体的贴图
var bitmap:BitmapData = new MyPalm(0, 0);
var material:Material = new BitmapMaterial( bitmap );
var app:Appearance = new Appearance( material );

box.appearance = app;

g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
}

}

效果:

#p#

继续上次的学习,接下来要试试摄像机的移动了。
这里需要涉及几个概念,摄像机的坐标(x, y, z)和视觉角度(LookAt)
摄像机的位置可以使用(x, y, z)来定位;
视觉角度可以定义如何通过窗口来看场景。
lookAt(p_nX:Number, p_nY:Number, p_nZ:Number)
如:lookAt(0,0,0);//可以理解为通过摄像机的位置看场景。

摄像机的移动方式比较有意思,如果直接修改x、y、z坐标,视觉效果会与现实看到的情况相同;
而tilt、pan则是与场景平行移动;
roll是以z轴移动,通过摄像机视野看上去是摄像机的旋转效果。

额外说一下 Line3D 是在场景中绘制了线段,这里用做参考线,代码不难理解我就不过多解释了。

代码如下:

package
{
import flash.display.Sprite;
import flash.events.*;
import flash.ui.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.net.URLRequest;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;
import sandy.core.data.*;

/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.x = 100;
camera.y = 100;
camera.z = -300;
camera.lookAt(0,0,0);
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPressed);
}
var box = new Box("box", 100, 100, 100);
var Plane:Plane3D;
public function createScene() {
var g:Group = new Group();

//在场景画一个坐标定位点
Plane = new Plane3D("Texture", 300, 300);
var myXLine:Line3D = new Line3D( "x-coord", new Point3D( -20, 0, 0), new Point3D( 20, 0, 0 ));
var myYLine:Line3D = new Line3D( "y-coord", new Point3D(0, -20, 0), new Point3D( 0, 20, 0 ));
var myZLine:Line3D = new Line3D( "z-coord", new Point3D(0, 0, -20), new Point3D( 0, 0, 20 ));

g.addChild(myXLine);
g.addChild(myYLine);
g.addChild(myZLine);
g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
public function keyPressed(_evt:KeyboardEvent):void {
switch(_evt.keyCode) {
case Keyboard.UP:
camera.tilt += 2;
//camera.y -= 2;
break;
case Keyboard.DOWN:
camera.tilt -= 2;
//camera.y += 2;
break;
case Keyboard.RIGHT:
camera.pan -= 2;
//camera.x += 2;
break;
case Keyboard.LEFT:
camera.pan += 2;
//camera.x -= 2;
break;
case Keyboard.CONTROL:
camera.roll += 2;
break;
case Keyboard.PAGE_DOWN:
camera.z -= 5;
break;
case Keyboard.PAGE_UP:
camera.z += 5;
break;
}
}
}

}

效果:

还有场景自适应的问题,需要说明一下。

摄像机的镜头可视角度使用 fov(vertical field of view angle)来定义。

换算公式:

var fl:Numer = (viewport.height / 2) / Math.tan (camera.fov / 2 * (Math.PI / 180));

代码:

package
{
import flash.display.Sprite;
import flash.events.*;
import flash.ui.*;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.Stage;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import sandy.core.Scene3D;
import sandy.core.scenegraph.*;
import sandy.primitive.*;
import sandy.materials.*;
import sandy.materials.attributes.*;
import sandy.core.data.*;

/**
* ...
* @author ever5u
*/
public class fuxi extends Sprite
{
private var scene:Scene3D;
private var camera:Camera3D;
public function fuxi() {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
//创建一个摄像机
camera = new Camera3D(300, 300);
camera.x = 100;
camera.y = 100;
camera.z = -300;
camera.lookAt(0,0,0);
//创建一个 Group
var root:Group = createScene();
//创建场景
scene = new Scene3D( "scene", this, camera, root );
//创建实时侦听
addEventListener( Event.ENTER_FRAME, enterFrameHandler );
stage.addEventListener (Event.RESIZE, onResize);
}
var box = new Box("box", 100, 100, 100);
var Plane:Plane3D;
public function createScene() {
var g:Group = new Group();

//在场景画一个坐标定位点
Plane = new Plane3D("Texture", 300, 300);
var myXLine:Line3D = new Line3D( "x-coord", new Point3D( -20, 0, 0), new Point3D( 20, 0, 0 ));
var myYLine:Line3D = new Line3D( "y-coord", new Point3D(0, -20, 0), new Point3D( 0, 20, 0 ));
var myZLine:Line3D = new Line3D( "z-coord", new Point3D(0, 0, -20), new Point3D( 0, 0, 20 ));

g.addChild(myXLine);
g.addChild(myYLine);
g.addChild(myZLine);
g.addChild( box );
return g;
}
public function enterFrameHandler(_evt:Event) {
box.rotateX = mouseX;
box.rotateY = mouseY;
scene.render();
}
function onResize (e:Event):void{
// 获取场景宽高
var w:Number = stage.stageWidth;
var h:Number = stage.stageHeight;
// 设置视野宽高
scene.camera.viewport.width = w;
scene.camera.viewport.height = h;
// 获取物体box与摄像机间的距离
var d:Number = box.getPosition ("camera").getNorm ();
// 保持摄像机观看比例
scene.camera.fov = 2 * Math.atan2 (h / 2, d) * (180 / Math.PI);
// 执行渲染
scene.render();
}
}

}

效果:

更多精彩内容其他人还在看

Flash cs3绘制人物高级行走动画教程

本教程向大家介绍Flash cs3绘制人物高级行走动画效果,教程难度不是很大,绘制方法及过程介绍的也非常详细,教程很实用,转发过来,希望大家喜欢
收藏 0 赞 0 分享

Flash CS4来制作漂亮的气泡动画教程

本教程向脚本之家的朋友介绍用Flash CS4来制作漂亮的气泡动画,制作出来气泡真的很好看,制作效果是采用代码形式实现,觉得很不错,转发过来,感兴趣的朋友可以一起来学习
收藏 0 赞 0 分享

flash基础教程:帧、关键帧、空白帧概念及区别介绍

动画的产生是帧来实现的,那什么是帧?帧、关键帧和空白帧之间又有什么区别?本文就为大家介绍一下三者之间的关系
收藏 0 赞 0 分享

Flash教程:动画背景的绘制方法之透视篇(给新手)

Flash动画在网络上的广泛传播,已经成为上网一族喜闻乐见的一种艺术形式。动画背景的绘制方法有很多,也有很多表现方法。这里将结合透视学的基础知识向大家简单的介绍一下动画背景的绘制。
收藏 0 赞 0 分享

Flash AS入门教程:Flash AS3.0制作有年份有日期的时钟

本教程是向大家介绍利用Flash AS3.0制作有年份有日期的时钟,虽然制作时钟老套了点,但它确可以较全面地应用到时间日期和间隔等知识,仍不失为较好的入门练习,转发给大家,希望对大家有所帮助
收藏 0 赞 0 分享

Flash相册制作大师具体该如何使用 Flash相册制作大师使用教程

在本文中我们将会看到的是Flash相册制作大师的具体使用的方法
收藏 0 赞 0 分享

flash基础教程:混色器面板图文介绍

混色器面板是Flash中用于色彩处理的一个重要面板,熟练地使用该面板,可以帮助用户快速地完成色彩的填充,编辑出色彩丰富的图形。本教程为大家详细介绍一下混色器面板,希望对大家有所帮助
收藏 0 赞 0 分享

25个绝对让你应接不暇的Flash网站创意

在Web设计过程中,运用成熟的Flash技术可以把你任意想到的idea表现到产品页面中。这里为你整理发现了25个绝对让你应接不暇的 Flash网站创意,更好地体现网站的互动应用,同时可以让你大饱眼福,一起来欣赏吧
收藏 0 赞 0 分享

教你用Flash制作非常酷的二进制时钟动画

今天在这个教程中我们将学习用Flash做一个不同寻常的,但非常酷的时钟:一个二进制时钟,中间用到了代码,但介绍地很详细,相信很值得大家学习
收藏 0 赞 0 分享

Flash动画特效制作技巧:制作超酷的文字炸开动画效果

本教程向大家介绍Flash动画特效制作技巧,本实例是制作文字炸开的动画效果,制作效果非常酷,制作过程也比较简单,喜欢的朋友可以过来学习一下这种制作方法
收藏 0 赞 0 分享
查看更多