Flash 3D Wall

2009年6月18日 Flash小猪 1 条评论

最近新写的一个flash3d效果
用的是pv3d 加上了缓动 发上来聊以自娱..
下面是效果图片

demo222

分类: ActionScript3.0 标签:

Right Click in AS3

2009年6月3日 Flash小猪 1 条评论

A day or two ago polyGeek has revived an old and challenging idea that one could make use of custom right-click functionality in Flash (AS3 + Javascript).

Why would anyone want to do this? Well, there are several very important reasons:

1) Games – the power of AS3 has brought Flash to the world of digital entertainment. At last it is possible to focus on the idea of your game rather than on how to improve the laggy experience. One thing that is still missing – right click functionality. We had this forever in desktop games, now it is time to let your casual RTS, RPG and FPS creations conquer the web.

2) User Experience – 2 buttons are better than 1. Every experimentalist’s dream is to be able to have more input options, not just one button. I can bet someone would soon create a stunning interface using this new functionality and we would see that on no less than FWA.

3) RIA – Rich Internet Applications. My clients are often asking if it is possible to remove embeded Flash Player menus from their applications and replace them with their company’s branding stuff.

***

AND THE ANSWER IS – YES! It is now possible to use custom right-click functionality in Flash and even Flex.

After long hours of searching through Microsoft’s documentation I came up with a universal solution that works nicely at least on 3 major browsers – Firefox 2, IE 7 and Safari. (IE6 has not been tested but I can bet it works OK).

***

Here you can see the * DEMO of right click * functionality (click the grey area to draw transparent dots)

Javascript source code looks like this:

/**
*
* Copyright 2007
*
* Paulius Uza
* http://www.uza.lt
*
* Dan Florio
* http://www.polygeek.com
*
* Project website:
* http://code.google.com/p/custom-context-menu/
*
* --
* RightClick for Flash Player.
* Version 0.6.2
*
*/

var RightClick = {
    /**
     *  Constructor
     */
    init: function () {
        this.FlashObjectID = "customRightClick";
        this.FlashContainerID = "flashcontent";
        this.Cache = this.FlashObjectID;
        if(window.addEventListener){
             window.addEventListener("mousedown", this.onGeckoMouse(), true);
        } else {
            document.getElementById(this.FlashContainerID).onmouseup = function() { document.getElementById(RightClick.FlashContainerID).releaseCapture(); }
            document.oncontextmenu = function(){ if(window.event.srcElement.id == RightClick.FlashObjectID) { return false; } else { RightClick.Cache = "nan"; }}
            document.getElementById(this.FlashContainerID).onmousedown = RightClick.onIEMouse;
        }
    },
    /**
     * GECKO / WEBKIT event overkill
     * @param {Object} eventObject
     */
    killEvents: function(eventObject) {
        if(eventObject) {
            if (eventObject.stopPropagation) eventObject.stopPropagation();
            if (eventObject.preventDefault) eventObject.preventDefault();
            if (eventObject.preventCapture) eventObject.preventCapture();
         if (eventObject.preventBubble) eventObject.preventBubble();
        }
    },
    /**
     * GECKO / WEBKIT call right click
     * @param {Object} ev
     */
    onGeckoMouse: function(ev) {
        return function(ev) {
        if (ev.button != 0) {
            RightClick.killEvents(ev);
            if(ev.target.id == RightClick.FlashObjectID && RightClick.Cache == RightClick.FlashObjectID) {
                RightClick.call();
            }
            RightClick.Cache = ev.target.id;
        }
      }
    },
    /**
     * IE call right click
     * @param {Object} ev
     */
    onIEMouse: function() {
        if (event.button> 1) {
            if(window.event.srcElement.id == RightClick.FlashObjectID && RightClick.Cache == RightClick.FlashObjectID) {
                RightClick.call();
            }
            document.getElementById(RightClick.FlashContainerID).setCapture();
            if(window.event.srcElement.id)
            RightClick.Cache = window.event.srcElement.id;
        }
    },
    /**
     * Main call to Flash External Interface
     */
    call: function() {
        document.getElementById(this.FlashObjectID).rightClick();
    }
}

On the Flash side is as simple as this code (AS3):

package {

    import flash.display.*;
    import flash.external.ExternalInterface;

    public class RightClick extends Sprite
    {

        public function RightClick()
        {
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;

            var methodName:String = "rightClick";
            var method:Function = onRightClick;
            ExternalInterface.addCallback(methodName, method);
        }

        private function onRightClick():void {

            var mx:int = stage.mouseX;
            var my:int = stage.mouseY;

            if(my> 0 && my  0 && mx < stage.stageWidth) {
                // YOUR CODE HERE
            }
        }
    }
} 

This demo has been tested and confirmed working on:

WINDOWS VISTA

  • Internet Explorer 7.0.6001 (16549)
  • Firefox 2.0.0.6 (with mouse gestures disabled)
  • Maxthon 2 (with mouse gestures disabled)
  • Safari 3.0.3 (522.15.5)

Windows XP SP2

  • Internet Explorer 6
  • Internet Explorer 7
  • Maxthon 2 (with mouse gestures disabled)
  • FireFox 2 (with mouse gestures disabled)
  • Safari 3
  • Netscape 8

Mac OSX 10.4.10 (Intel)

  • Firefox 2
  • Safari 3.0.3

Thank you all for testing!

Opera will not work, the browser forces the context menu to appear and blocks mouse events by default.

If you manage to get the demo working, please post the OS and Browser build number in the comments. Please also leave a comment if you experience any problems with the demo.

分类: ActionScript3.0 标签:

as3 格子小游戏

2009年5月22日 Flash小猪 没有评论

新做的一个flashas3 小游戏

数据结构用的Hashmap 性能和Array 比起来提高不少

分类: ActionScript3.0 标签:

XML控制页面的flash电子书

2009年5月18日 Flash小猪 没有评论

特征:

+ 可以加载img,swf,jpg,flv格式;

+ 可以扩展后加载视频格式;

+ 书大小可以通过xml调节

demo

分类: ActionScript3.0 标签:

Papervision3D GreatWhite 2.0基础教程:第八篇 - 动画

2009年5月14日 Flash小猪 没有评论

时间隔了很久了,终于更新了。这篇文章将继续介绍Papervision3D 中如何进行其他材质的贴图,在之前的系列中主要以增加3D场景的真实性为目的,这篇文章则要把重点放在如何给场景添加更多的动态可能性。

首先,抱歉这篇文章可能有点长,这篇里要讲的主要是MovieMaterials 动画贴图材质和VideoStreamMaterial 影片贴图材质,它们能通过使用Flash movies 或者 Flash video streams 来给3D物体表面提供动动画效果和增加交互可能性。其实把这些内容总结成几条来描述Papervision3D 能提供的可能性也许不公平,所以我试着描述的更广泛一点,但是即使这样做了我想仍然会丢失很多东西。可能性更多取决于使用人的创造力。

MovieMaterial 动画贴图材质允许我们使用一个已经存在的flash动画文件或者任何在库中导出过的MovieClip、Sprite 为贴图材质。Papervision3D 能将他们映射到3D物体的表面,并且允许我们直接在3D 场景上和动画里的内容进行交互,比如鼠标点击,移动这类的。

VideoStreamMaterial 影片贴图材质则就像他的名字描述的那样,允许我们使用一段flv 影片贴图在3D 物体的表面。
下面的例子会包含3种可行性的应用:一是使用一个2D flash movie为贴图材质并允许和里面进行交互,二是使用一段影片为贴图材质,三是使用另一个Papervision3D flash movie为贴图材质并允许和里面的3D 内容进行交互。
所以这篇文章会涉及到3个Actionscript classes:一个3D主场景,一个2D flash movie 和另一个Papervision3D flash movie,这里会讨论第一个并在文章结尾处付上其他源文件。

下面的源代码会实现3个被不同材质贴过图后的平板围绕的y轴转动,这些平板能通过双击使其固定并进行放大,以便你更方便和平板上的内容进行交互,再双击可以使其归位。整个场景可以通过背景上按住鼠标左键后移动鼠标来调整摄象机位置角度。整段代码有点长,但是我仍然会对每一段进行解释。虽然看上去长,但是相信我其实一点也不复杂。这个例子里仍然使用Tweener 来获得更好的运动效果,之前介绍过Tweener 的。

package {

  import caurina.transitions.Tweener;

  import flash.display.MovieClip;
  import flash.events.Event;
  import flash.events.MouseEvent;
  import flash.media.Video;
  import flash.net.NetConnection;
  import flash.net.NetStream;

  import org.papervision3d.core.proto.MaterialObject3D;
  import org.papervision3d.events.InteractiveScene3DEvent;
  import org.papervision3d.lights.PointLight3D;
  import org.papervision3d.materials.MovieMaterial;
  import org.papervision3d.materials.VideoStreamMaterial;
  import org.papervision3d.materials.shadematerials.FlatShadeMaterial;
  import org.papervision3d.materials.utils.MaterialsList;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.primitives.Cube;
  import org.papervision3d.view.BasicView;

  [SWF(backgroundColor="#222222")]

  public class Example008 extends BasicView {

    private static const ORBITAL_RADIUS:Number = 400;

    [Embed(source="/../assets/DrawTool.swf")]
    private var DrawTool:Class;

    private var exampleMovie:MovieClip;

     private var videoURL:String = "http://www.tartiflop.com/pv3d/FirstSteps/Radiohead_HOC.flv";

    private var video:Video;
    private var stream:NetStream;
    private var connection:NetConnection;

    private var objectGroup:DisplayObject3D;
    private var light:PointLight3D;
    private var currentActiveObject:DisplayObject3D = null;

    private var projectors:Array = new Array();

    private var doRotation:Boolean = false;
    private var canRotate:Boolean = true;
    private var lastMouseX:int;
    private var lastMouseY:int;
    private var cameraPitch:Number = 60;
    private var cameraYaw:Number = -60;

    public function Example008() {
      super(0, 0, true, true);

      // Initialise Papervision3D
      init3D();

      // create video stream for VideoStreamMaterial
      createVideoStream();

      // create the 3D Objects
      createScene();

      // Listen to mouse up and down events on the stage
      stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);

      // Start rendering the scene
      startRendering();
    }

    private function init3D():void {
      // position the camera
      camera.z = -1000;
      camera.fov = 60;
      camera.orbit(cameraPitch, cameraYaw);
    }

    private function createVideoStream():void {
      // Create a NetConnection. 2-way connection not necessary: connect to null
      connection = new NetConnection();
      connection.connect(null);

      // Create a new NetStream to obtain the flv stream. Ignore client messages so use a simple Object
      stream = new NetStream(connection);
      stream.client = new Object();

      // create a new video player
      video = new Video();

      // start streaming the video from the given URL and play it on the video player
      stream.play(videoURL);
      video.attachNetStream(stream);
    }

    private function createScene():void {
      // Specify a point light source and its location
      light = new PointLight3D();
      light.x = 400;
      light.y = 1000;
      light.z = -400;

      // Create a 3D object to group the projectors
      objectGroup = new DisplayObject3D();

      // Create a new video stream material with precise rendering.
      var videoMaterial:VideoStreamMaterial = new VideoStreamMaterial(video, stream, true);
      addProjector(videoMaterial);

      // Create a new flash movie material from an actionscript class (not transparent, animated and precise rendering)
      var movieMaterial1:MovieMaterial = new MovieMaterial(new Example006b(), false, true, true);
      addProjector(movieMaterial1);

      // Create a new flash movie material from an embedded flash movie (not transparent, animated and precise rendering)
      var movieMaterial2:MovieMaterial = new MovieMaterial(new DrawTool(), false, true, true);
      addProjector(movieMaterial2);

      // add the object group and light
      scene.addChild(objectGroup);
      scene.addChild(light);

      // set up the projector positions in the scene
      organiseProjectors();
    }

    private function addProjector(material:MovieMaterial):void {
      // materials are smooth rendred, interactive and resize to the 3D object.
      material.smooth = true;
      material.interactive = true;
      material.allowAutoResize = true;

      // simple flat shaded material as default for the projector
      var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterial(light, 0x554D33, 0x1A120C);
      flatShadedMaterial.interactive = true;

      // Material list with MovieMaterial used on the front, the rest being flat shaded
      var materialList:MaterialsList = new MaterialsList({"all":flatShadedMaterial, "front":material});

      // create a new interactive projector
      var projector:Cube = new Cube(materialList, 320, 10, 240);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_DOUBLE_CLICK, onMouseDoubleClickOnObject);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, onMouseOverObject);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, onMouseOutObject);

      // add the projector to the scene, being part of the object group
      objectGroup.addChild(projector);

      // store projector in an array
      projectors.push(projector);
    }

    private function organiseProjectors():void {
      // calculate angle between projectors
      var theta:Number = 360 / projectors.length;

      // set up each projector so that they are distributed in a circle and facing outwards
      for (var i:int = 0; i < projectors.length; i++) {
        var projector:Cube = projectors[i];

        // specifc angle for projector
        var angle:Number = i * theta - 180;
        var angleRadians:Number = angle * 2 * Math.PI / 360.;

        // position of projector
        var x:Number = Math.sin(angleRadians) * ORBITAL_RADIUS;
        var z:Number = Math.cos(angleRadians) * ORBITAL_RADIUS;

        // create tween to position, rotate and scale projector smoothly over 1 second
        Tweener.addTween(projector, {x:x, y:-150, z:z, rotationY:angle, scale:0.8, time:1, transition:"linear" });
      }
    }

    override protected function onRenderTick(event:Event=null):void {
      // rotate the object group: angle kept between 0 and 360 degrees
      objectGroup.rotationY += 1;
      if (objectGroup.rotationY > 360) {
        objectGroup.rotationY -= 360;
      }

      // if an object is active (double clicked) rotate it in the opposite direction
      // to the group so that it is stationary
      if (currentActiveObject != null) {
        currentActiveObject.rotationY -=1;
        if (currentActiveObject.rotationY < 0) {
          currentActiveObject.rotationY += 360;
        }
      }

      // If the mouse button has been clicked then update the camera position
      if (doRotation && canRotate) {
        // convert the change in mouse position into a change in camera angle
        var dPitch:Number = (mouseY - lastMouseY) / 2;
        var dYaw:Number = (mouseX - lastMouseX) / 2;

        // update the camera angles
        cameraPitch -= dPitch;
        cameraYaw -= dYaw;
        // limit the pitch of the camera
        if (cameraPitch <= 0) {
          cameraPitch = 0.1;
        } else if (cameraPitch >= 180) {
          cameraPitch = 179.9;
        }

        // reset the last mouse position
        lastMouseX = mouseX;
        lastMouseY = mouseY;

        // reposition the camera
        camera.orbit(cameraPitch, cameraYaw);
      }

      // call the renderer
      super.onRenderTick(event);
    }

    // called when mouse down on stage
    private function onMouseDown(event:MouseEvent):void {
      doRotation = true;
      lastMouseX = event.stageX;
      lastMouseY = event.stageY;
    }

    // called when mouse up on stage
    private function onMouseUp(event:MouseEvent):void {
      doRotation = false;
    }

    // called when mouse double clicked on a projector
    private function onMouseDoubleClickOnObject(event:InteractiveScene3DEvent):void {
      var object:DisplayObject3D = event.displayObject3D;

      // determine if the object is to be activated (placed in center) or deactivated
      if (object == currentActiveObject) {
        deactivate(object);
      } else {
        activate(object);
      }
    }

    // disable camera rotation when mouse is over a projector
    private function onMouseOverObject(event:InteractiveScene3DEvent):void {
      canRotate = false;
    }

    // re-enable camera rotation when mouse is out of a projector
    private function onMouseOutObject(event:InteractiveScene3DEvent):void {
      canRotate = true;
    }

    // places a projector in the center
    private function activate(object:DisplayObject3D):void {
      // remove projector from rotating projectors array
      projectors.splice(projectors.indexOf(object), 1);

      // if a projector is active already, put it back in the array of rotating projectors
      if (currentActiveObject != null) {
        projectors.push(currentActiveObject);
      }

      // create a tween to place selected projector in the center
      Tweener.addTween(object, {y:100, x:0, z:0, rotationY:-objectGroup.rotationY, scale:2, time:1, transition:"linear" });
      currentActiveObject = object;

      // re-organise the other projectors
      organiseProjectors();
    }

    // puts an activated projector back into the main pack of rotating projectors
    private function deactivate(object:DisplayObject3D):void {
      // put the projector back into the rotating projectors array
      projectors.push(currentActiveObject);
      currentActiveObject = null; 

      // re-organise all projectors
      organiseProjectors();
    }

  }
}

点击下面的图片可以flash 运行后的效果。
example008

OK,就像这个系列的前几篇文章一样,我们通常是拿前面的例子修改以便更容易理解,而在这个例子里修改主要来自为影片创建影片贴图和更改场景的交互方式,下面我们一步一步来看。

让我们从构造函数开始,可以发现唯一的不同就是新加了播放flv影片的初始化过程,而且在flash中播放flv影片可以是一个纯as工作,所以不需要借助任何其他东西。

private function createVideoStream():void {
      // Create a NetConnection. 2-way connection not necessary: connect to null
      connection = new NetConnection();
      connection.connect(null);

      // Create a new NetStream to obtain the flv stream. Ignore client messages so use a simple Object
      stream = new NetStream(connection);
      stream.client = new Object();

      // create a new video player
      video = new Video();

      // start streaming the video from the given URL and play it on the video player
      stream.play(localVideoURL);
      video.attachNetStream(stream);
    }

下面看场景构造方法createScene ,因为是用前面的例子修改而来,所以保留了光源,做了一个object group 把3个平板放在里面模拟转动。

    private function createScene():void {
      // Specify a point light source and its location
      light = new PointLight3D();
      light.x = 400;
      light.y = 1000;
      light.z = -400;

      // Create a 3D object to group the projectors
      objectGroup = new DisplayObject3D();

      // Create a new video stream material with precise rendering.
      var videoMaterial:VideoStreamMaterial = new VideoStreamMaterial(video, stream, true);
      addProjector(videoMaterial);

      // Create a new flash movie material from an actionscript class (not transparent, animated and precise rendering)
      var movieMaterial1:MovieMaterial = new MovieMaterial(new Example006b(), false, true, true);
      addProjector(movieMaterial1);

      // Create a new flash movie material from an embedded flash movie (not transparent, animated and precise rendering)
      var movieMaterial2:MovieMaterial = new MovieMaterial(new DrawTool(), false, true, true);
      addProjector(movieMaterial2);

      // add the object group and light
      scene.addChild(objectGroup);
      scene.addChild(light);

      // set up the projector positions in the scene
      organiseProjectors();
    }

看了上面3个MovieMaterial (VideoStreamMaterial 继承自MovieMaterial )的个实例化发现很简单吧。对于MovieMaterial 最后3个布尔值分别表示透明,播放动画和精确渲染。所以如果你需要贴图用的flash movie是动态的,就设置播放动画为true。

贴图材质做好了要将他贴给3D Object,在上面使用了addProjector 函数,因为每个贴图的使用步骤都一样,所以使用一个函数来做节省了多代码。

    private function addProjector(material:MovieMaterial):void {
      // materials are smooth rendred, interactive and resize to the 3D object.
      material.smooth = true;
      material.interactive = true;
      material.allowAutoResize = true;

      // simple flat shaded material as default for the projector
      var flatShadedMaterial:MaterialObject3D = new FlatShadeMaterial(light, 0x554D33, 0x1A120C);
      flatShadedMaterial.interactive = true;

      // Material list with MovieMaterial used on the front, the rest being flat shaded
      var materialList:MaterialsList = new MaterialsList({"all":flatShadedMaterial, "front":material});

      // create a new interactive projector
      var projector:Cube = new Cube(materialList, 320, 10, 240);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_DOUBLE_CLICK, onMouseDoubleClickOnObject);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_OVER, onMouseOverObject);
      projector.addEventListener(InteractiveScene3DEvent.OBJECT_OUT, onMouseOutObject);

      // add the projector to the scene, being part of the object group
      objectGroup.addChild(projector);

      // store projector in an array
      projectors.push(projector);
    }

每一个MovieMaterial 都设置允许平滑,允许交互,允许自动适应尺寸。然后实例化一个MaterialsList 来给Cube(平板是用cube模拟的) 贴图,Cube 5个面都使用FlatShadeMaterial ,front面则使用MovieMaterial 。然后给Cube 加上监听函数,这样就可是响应在Cube 身上的双击事件之类的了。这3个平板之后都加入objectGroup群组,再储存在projectors数组里,以便后面访问时调用。

在上面场景构造最后看到一个organiseProjectors 函数是用来设置这3个平板的坐标位置的。

    private function organiseProjectors():void {
      // calculate angle between projectors
      var theta:Number = 360 / projectors.length;

      // set up each projector so that they are distributed in a circle and facing outwards
      for (var i:int = 0; i < projectors.length; i++) {
        var projector:Cube = projectors[i];

        // specifc angle for projector
        var angle:Number = i * theta - 180;
        var angleRadians:Number = angle * 2 * Math.PI / 360.;

        // position of projector
        var x:Number = Math.sin(angleRadians) * ORBITAL_RADIUS;
        var z:Number = Math.cos(angleRadians) * ORBITAL_RADIUS;

        // create tween to position, rotate and scale projector smoothly over 1 second
        Tweener.addTween(projector, {x:x, y:-150, z:z, rotationY:angle, scale:0.8, time:1, transition:"linear" });
      }
    }

这个函数通过一个for循环给每个平板计算分配了自己的角度和位置,并使用了Tweener 让这些平板在开始的时候运动到自己该处的位置。

下面的onRenderTick 则用来描述整个flash在每个frame该做什么事情。

override protected function onRenderTick(event:Event=null):void {
      // rotate the object group: angle kept between 0 and 360 degrees
      objectGroup.rotationY += 1;
      if (objectGroup.rotationY > 360) {
        objectGroup.rotationY -= 360;
      }

      // if an object is active (double clicked) rotate it in the opposite direction
      // to the group so that it is stationary
      if (currentActiveObject != null) {
        currentActiveObject.rotationY -=1;
        if (currentActiveObject.rotationY < 0) {
          currentActiveObject.rotationY += 360;
        }
      }

      // If the mouse button has been clicked then update the camera position
      if (doRotation && canRotate) {
        // convert the change in mouse position into a change in camera angle
        var dPitch:Number = (mouseY - lastMouseY) / 2;
        var dYaw:Number = (mouseX - lastMouseX) / 2;

        // update the camera angles
        cameraPitch -= dPitch;
        cameraYaw -= dYaw;
        // limit the pitch of the camera
        if (cameraPitch <= 0) {
          cameraPitch = 0.1;
        } else if (cameraPitch >= 180) {
          cameraPitch = 179.9;
        }

        // reset the last mouse position
        lastMouseX = mouseX;
        lastMouseY = mouseY;

        // reposition the camera
        camera.orbit(cameraPitch, cameraYaw);
      }

      // call the renderer
      super.onRenderTick(event);
    }

这里的object group群组转动在前面的例子中也使用过,但是这次我用了控制rotationY 属性的方式而不是使用yaw 函数,因为这样做对位置的精确控制会更加方便。

再下面的代码就是定义onMouseDown, onMouseUp 事件了。这些是用来配合鼠标控制摄象机的,和之前的例子一样就不多将了。新加的onMouseOverObject 和 onMouseOutObject 也是配合控制摄象机的。

主要讲一讲onMouseDoubleClickOnObject 双击事件。

    // called when mouse double clicked on a projector
    private function onMouseDoubleClickOnObject(event:InteractiveScene3DEvent):void {
      var object:DisplayObject3D = event.displayObject3D;

      // determine if the object is to be activated (placed in center) or deactivated
      if (object == currentActiveObject) {
        deactivate(object);
      } else {
        activate(object);
      }
    }

如何我们双击一个物体则将它设置为currentActiveObject,如果再双击她则取消设置。

    // places a projector in the center
    private function activate(object:DisplayObject3D):void {
      // remove projector from rotating projectors array
      projectors.splice(projectors.indexOf(object), 1);

      // if a projector is active already, put it back in the array of rotating projectors
      if (currentActiveObject != null) {
        projectors.push(currentActiveObject);
      }

      // create a tween to place selected projector in the center
      Tweener.addTween(object, {y:100, x:0, z:0, rotationY:-objectGroup.rotationY, scale:2, time:1, transition:"linear" });
      currentActiveObject = object;

      // re-organise the other projectors
      organiseProjectors();
    }

    // puts an activated projector back into the main pack of rotating projectors
    private function deactivate(object:DisplayObject3D):void {
      // put the projector back into the rotating projectors array
      projectors.push(currentActiveObject);
      currentActiveObject = null; 

      // re-organise all projectors
      organiseProjectors();
    }

这里的activate 和deactivate 函数,用来设置平板处于双击放大状态和再次双击归位时候的位置设置。

这篇文章到这里就结束了,在这里例子可是发现当使用了Papervision3D 和 Tweener 在一起工作时候,生成了效果很棒3D动画。再配合了movie materials 发现这个世界又不可思义了,而这一切我们所做的工作并不多,Papervision3D 给我们安排好了一些。其实很感谢Papervision3D 作者们的工作。

最后 drawTool.as :

package {
  import flash.display.Sprite;
  import flash.events.MouseEvent;
  import flash.text.TextField;
  import flash.text.TextFieldAutoSize;
  import flash.text.TextFormat;

  public class DrawTool extends Sprite {

    private var isDrawing:Boolean = false;

    public function DrawTool() {

      // create a drawing surface
      graphics.beginFill(0xEEEEEE);
      graphics.moveTo(0, 0);
      graphics.lineTo(320, 0);
      graphics.lineTo(320, 240);
      graphics.lineTo(0, 240);
      graphics.endFill();

      // create text and format
      var textFormat:TextFormat = new TextFormat();
      textFormat.size = 30;
      textFormat.font = "Arial";

      var text:TextField = new TextField();
      text.x = 50;
      text.y = 100;
      text.textColor = 0x222222;
      text.text = "click to draw!";
      text.setTextFormat(textFormat);
      text.autoSize = TextFieldAutoSize.LEFT;
      text.selectable = false;
      addChild(text);

      // listen to mouse events
      this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
      this.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);

    }

    // start drawing circles
    private function onMouseDown(event:MouseEvent):void {
      isDrawing = true;
      drawCircle(event.stageX, event.stageY);
    }

    // stop drawing circles
    private function onMouseUp(event:MouseEvent):void {
      isDrawing = false;
    }

    // draw a circle
    private function onMouseMove(event:MouseEvent):void {
      if (isDrawing) {
        drawCircle(event.stageX, event.stageY);
      }
    }

    // circle drawing function
    private function drawCircle(x:int, y:int):void {
      graphics.beginFill(Math.random() * 0xFFFFFF, 0.5);
      graphics.drawCircle(x, y, 5);
      graphics.endFill();
    }

  }
}

还有Example006b.as :

package {

  import flash.display.Bitmap;
  import flash.display.Sprite;
  import flash.events.Event;
  import flash.events.MouseEvent;

  import org.papervision3d.materials.BitmapMaterial;
  import org.papervision3d.materials.utils.MaterialsList;
  import org.papervision3d.objects.DisplayObject3D;
  import org.papervision3d.objects.primitives.Cube;
  import org.papervision3d.objects.primitives.Sphere;
  import org.papervision3d.view.BasicView;

  [SWF(backgroundColor="#FFFFFF")]

  public class Example006b extends BasicView {

    [Embed(source="/../assets/pv3d.png")] private var PV3D:Class;

    private static const ORBITAL_RADIUS:Number = 100;

    private var bitmap:Bitmap = new PV3D();

    private var cube1:Cube;
    private var cube2:Cube;
    private var sphere1:Sphere;
    private var sphere2:Sphere;
    private var objectGroup:DisplayObject3D;

    private var doRotation:Boolean = false;
    private var lastMouseX:int;
    private var lastMouseY:int;
    private var cameraPitch:Number = 60;
    private var cameraYaw:Number = -60;

    public function Example006b() {
      var background:Sprite = new Sprite();
      background.graphics.beginFill(0x000000);
      background.graphics.moveTo(0, 0);
      background.graphics.lineTo(320, 0);
      background.graphics.lineTo(320, 240);
      background.graphics.lineTo(0, 240);
      background.graphics.endFill();
      addChild(background);

      super(320, 240, true, false);

      // Initialise Papervision3D
      init3D();

      // Create the 3D objects
      createScene();

      // Listen to mouse up and down events on the stage
      background.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
      background.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
      background.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);

      // Start rendering the scene
      startRendering();
    }

    private function init3D():void {
      // position the camera
      camera.z = -500;
      camera.orbit(cameraPitch, cameraYaw);
    }

    private function createScene():void {

      // create interactive bitmap material
      var bitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, false);

      // create an interactive tiled bitmap material (bitmap tiled as 2 x 2)
      var tiledBitmapMaterial:BitmapMaterial = new BitmapMaterial(bitmap.bitmapData, false);
      tiledBitmapMaterial.tiled = true;
      tiledBitmapMaterial.maxU = 2;
      tiledBitmapMaterial.maxV = 2;

      // create cube with simple bitmap material
      cube1 = new Cube(getBitmapMaterials(bitmapMaterial), 50, 50, 50);
      cube1.x =  ORBITAL_RADIUS;

      // create cube with tiled bitmap material
      cube2 = new Cube(getBitmapMaterials(tiledBitmapMaterial), 50, 50, 50);
      cube2.x = -ORBITAL_RADIUS;

      // create sphere with simple bitmap material
      sphere1 = new Sphere(bitmapMaterial, 25, 10, 10);
      sphere1.z =  ORBITAL_RADIUS;

      // create sphere with tiled bitmap material
      sphere2 = new Sphere(tiledBitmapMaterial, 25, 10, 10);
      sphere2.z = -ORBITAL_RADIUS;

      // Create a 3D object to group the spheres
      objectGroup = new DisplayObject3D();
      objectGroup.addChild(cube1);
      objectGroup.addChild(cube2);
      objectGroup.addChild(sphere1);
      objectGroup.addChild(sphere2);

      // Add the light and spheres to the scene
      scene.addChild(objectGroup);
    }

    private function getBitmapMaterials(bitmapMaterial:BitmapMaterial):MaterialsList {
      // create list of materials for all faces of the cube,
      //    all with the same bitmap material
      var materials:MaterialsList = new MaterialsList();
      materials.addMaterial(bitmapMaterial, "all");

      return materials;
    }

    override protected function onRenderTick(event:Event=null):void {

      // rotate the objects
      cube1.yaw(-3);
      cube2.yaw(-3);
      sphere1.yaw(-3);
      sphere2.yaw(-3);

      // rotate the group of objects
      objectGroup.yaw(1);

      // call the renderer
      super.onRenderTick(event);
    }

    // called when mouse down on stage
    public function onMouseDown(event:MouseEvent):void {
      doRotation = true;
      lastMouseX = event.stageX;
      lastMouseY = event.stageY;
    }

    // called when mouse up on stage
    public function onMouseUp(event:MouseEvent):void {
      doRotation = false;
    }

    // called when the mouse moves over the stage
    public function onMouseMove(event:MouseEvent):void {
      // If the mouse button has been clicked then update the camera position
      if (doRotation) {

        // convert the change in mouse position into a change in camera angle
        var dPitch:Number = (event.stageY - lastMouseY) / 2;
        var dYaw:Number = (event.stageX - lastMouseX) / 2;

        // update the camera angles
        cameraPitch -= dPitch;
        cameraYaw -= dYaw;
        // limit the pitch of the camera
        if (cameraPitch < = 0) {
          cameraPitch = 0.1;
        } else if (cameraPitch >= 180) {
          cameraPitch = 179.9;
        }

        // reset the last mouse position
        lastMouseX = event.stageX;
        lastMouseY = event.stageY;

        // reposition the camera
        camera.orbit(cameraPitch, cameraYaw);
      }

    }

  }
}
分类: 杂谈 标签: