Tag Archives: flashdevelop

ActionScript 3 Minimal Comps for Quick Prototyping

Recently, Keith Peters has been putting overtime into his Minimal Comps library. It’s an ActionScript 3 library that offers a large number of typical user interface components. Easily and quickly you can construct basic user interfaces in ActionScript. When Flex is a little too heavy, this is a really neat solution.

Continue reading ActionScript 3 Minimal Comps for Quick Prototyping

Sandy 3D Tutorial: Getting Started with Sandy and FlashDevelop

Over the last year or two, developing 3D applications in Flash has become increasingly feasible, for almost any ActionScript developers. A number of open source 3D engines, like Sandy 3D, have popped up. Combined with the incredible FlashDevelop, any one can get started, right away. However, because FlashDevelop does not have the authoring tools of Adobe’s Flash tools, you need to know a few differences that you won’t find in many tutorials, but I will explain them in this post.

This is a refreshed version of my previous tutorial, where I explained the important differences you need to know to get started with FlashDevelop and Sandy 3D. I won’t go into setting up FlashDevelop, all details mentioned in the previous post are still valid.

But the Sandy 3D Engine has changed slightly (for the better, mind you). I’ll point out what’s new and give some additional examples. But first, lets look at the result:

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

The code consists of 4 main parts, I’ve split them up, but if you want, you can go right ahead and download the entire FlashDevelop workspace:

downloaddownload the full source and FlashDevelop project

1. Using bitmaps

I’ve gone over this a few times, but it bears repeating as this is something you won’t use in CS3. In FlashDevelop, you add a bitmap in the lib directory. With this done, you put an embed tag in your code (or double click, FD can usually do this for you) and on the next line you put the class name you want to assign to this embedded resource. As a final step, you need to instantiate the object.

It sounds much more complicated then it is, just look at the code:

[Embed(source = '../../../../lib/aqua.png')]
private var aquaClass:Class;
private var aquaBitmap:Bitmap = new aquaClass();

2. Creating and texturing the 3D objects

With the bitmaps imported, we can use them to texture objects. This is done by setting the objects appearance. The appearance has a few options, but for now, we’ll only set one material on it. The material is the object that actually contains the texture.

For instance, the background image when you move over the cube is a Plane3D object on which we set an appearance that consists of a BitmapMaterial:

plane = new Plane3D( "thePlane", 200, 200);
material = new BitmapMaterial(beamsBitmap.bitmapData);
material.lightingEnable = true;
plane.appearance = new Appearance(material);

More complicated objects can contain multiple surfaces. If you want to set them all alike, just use the code above, but you can also address them individually. You use the “aPolygons” collection for that. Depending on the object and the parameters you choose, you might need to experiment a little to find the correct polygons.

For instance, this code sets the front and back side of the box in the example:

var material:Material = new BitmapMaterial(logoBitmap.bitmapData);
material.lightingEnable = true;
var app:Appearance = new Appearance( material );
var i:int;
for (i = 0; i < 4; i++ )
    myBox.aPolygons[i].appearance = app;

3. Listening to events

While the way you handle events hasn’t changed since previous versions of Sandy, the MOUSE_MOVE event was removed. It is no longer handled, probably because of performance reasons, but I’m not entirely clear on the reasons.

The official tutorials also now suggest to put the event handling on the container, this is part of your object that is actually displayed. If you can, I would suggest to use this, because it’s probably a lot quicker.

There are cases where you might like to obtain the Shape3DEvent. Take a look at the tutorial on the Sandy site to decide if you’d need that. But to reiterate, the Sandy event system no longer supports the MOUSE_MOVE event.

In the example, the event listener for the mouse over event looks like this:

    myBox.container.addEventListener(MouseEvent.MOUSE_OVER, overHandler);
private function overHandler(event:MouseEvent):void {
    if(!zoomedIn)
        g.addChild(plane);
}

4. Setting up the scene and camera

New in Sandy3D (although it’s not that new any longer) is the removal of World3D. World3D was a singleton class, which meant that you could have only one in your program. It has now been replaced by Scene3D, of which you can create and render multiple in your program.

So if you want, you can have different scenes or different cameras in your program. Cool, but don’t overdo it, keep in mind that every scene you add will also add to the processing power required.

Setting up the camera is exactly the same as before:

private function init(e:Event = null):void
{
    removeEventListener(Event.ADDED_TO_STAGE, init);
    // entry point
    camera = new Camera3D( 300, 300 );
    camera.x = 0;
    camera.y = 50;
    camera.z = -200;
    camera.lookAt(0,0,0);

    var root:Group = createScene();

    scene = new Scene3D( "scene", this, camera, root );

    addEventListener( Event.ENTER_FRAME, enterFrameHandler );
}

I haven’t discussed the tweening used to move the cube in the program. If you’re interested, please let me know and I’ll write another blogpost. Otherwise, you now have all parts to get started with 3D development in FlashDevelop.

Good luck and don’t forget to show those results!

downloaddownload the full source and FlashDevelop project

Tutorial: Applying and Manipulating a Mask in ActionScript 3

Flash has become the de-facto standard for all kinds of web animations. One of the main reasons, is that it offers an impressive array of bitmap manipulation functions. Out of the box it probably has one of the richest API’s to manipulate bitmaps, vectors and even animation. One of those possibilities is masking, which I will explain in this post.

downloaddownload the full source and FlashDevelop project right here

As you will learn in this small tutorial, applying a mask to any Flash object is incredibly easy. However, if you search for more information on Google, you’ll only find ActionScript 2 tutorials. This one is specific for ActionScript 3 and furthermore it is a pure ActionScript solution, so you don’t need to buy anything. FlashDevelop will do just fine. They have just released a new version.

Applying a mask is just as easy as it used to be in AS2:

background.mask = myMask;

The mask itself is a Sprite on which I drew a rectangle. You could make it pretty much any shape. I put the rectangle in the top left corner and moved the sprite. This will make it a lot easier to move and rescale the sprite later on.

myMask = new Sprite();
myMask.graphics.beginFill(0x00FF00);
myMask.graphics.drawRect(0, 0, myMaskSize, myMaskSize);
myMask.x = 350;
myMask.y = 250;
addChild(myMask);

This is all pretty straightforward, however I was a bit stumped when I wanted to let the user move the mask with his mouse. Apparently it’s not possible to attach an event listener to a Sprite once it is a mask. According to all the AS2 demos I found, this used to be possible. But no problem, I attached them to the stage. If you only want to register clicks on the displayed area, you might want to do a little processing of the mouse coordinates in the mouseDown method, but I didn’t bother.

Just for kicks I also added a mouse wheel listener, so that you can change the size of the masked area. This is the result:

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

You might notice that Flash still forwards the scroll event to the browser, so the browser window also scrolls. Apparently there isn’t a good solution for this problem. So beware if you want to use the scroll event in a real application.

downloaddownload the full source and FlashDevelop project right here

Image credit

Obsession in Flash – Physics and 3D

If I’d like to learn something new, certainly some new technology, I always like to learn by example. Having a goal to create something specific is, for me, much more motivating than leaving through a book one page at a time.

Wallpaper for Revista De2ign (www.revistadesign.com.br)
Creative Commons License photo credit: dudutorres

For instance, Timo has a nice example of Papervision 3D and the WOW physics engine. It gives both a very short introduction to Papervision 3D, which is probably the leading 3D engine for Flash, and the WOW engine, a great free ActionScript 3 physics engine that plugs in pretty much any framework available.

There are a few issues with Timo’s code if you download it. For instance, it is missing an important Flash resource. A small movie that has a game timer in there that shows you how well you are doing. I got rid of it and replaced it with a simple texture, so no more game time. There are also a bunch of warning, which I just choose to ignore (turned of AS3 warnings in FlashDevelop’s compiler options).

Apart from that, you’ll also need to download the libraries. To ease your work a little, I’ve done all the hard work for you. I’ve put everything into a FlashDevelop project and got the libraries from their Subversion repositories. So here’s a truly cutting edge workspace to get your started:

Interactive Plane Demo FlashDevelop workspace (about 14MB)

The Lazy ActionScript Developer’s Way to Stream Flash Video

In this final installment of my tutorial on YouTube hacking, I’m going to show how to build the FLV URL for YouTube videos and start streaming the FLV in your ActionScript application. As you will notice, this is very little work, because it is based on the streaming example in the AS3 language reference. I’m being lazy.

A recap of the ActionScript 3.0 YouTube player series:

Constructing the YouTube video URL

There are several ways to get to this one. You could fire up FireBug and check the network logs, or you could check Shane’s code and open his Main.as class. Skip to line 67 and you’ll see:

case YouTube.VIDEOID :
	fvc.play(YouTube.FLVUrl + e.value.id + "&t=" + e.value.t);
	break;

What this means: to construct the full URL to a YouTube Flash video file, you take the base URL and add both the video id and the T-parameter as arguments. An example URL might look like this:

http://www.youtube.com/get_video?video_id=v6ICEpYEcD8&t=OEgsToPDskIltmXs7gZ89kc2a3Z1SRGN

(I have not linked the URL, as it probably won’t work, because the T-parameter changes over time)

Streaming the FLV

For this one I’m going to use the existing ActionScript 3 classes. In particular flash.net.NetConnection and flash.net.NetStream. In the following code I’m adding the language reference example to the already existing code.

What happens might not be clear when you look at the code. That’s because we use a lot of event handlers. But if you take your time and go over the code it will become clear. What goes on is this:

  1. We create a NetConnection.
  2. If this goes well the netStatusHandler is called with the event “NetConnection.Connect.Success”. This in turn will launch the YouTube query to locate a video and create the URL to play it.
  3. This part we’ve already discussed in previous posts:
    1. Create the YouTube object and add listeners.
    2. Get a list of videos for a tag.
    3. When that lists returns, select the first one and get the T-parameter from our PHP script
  4. We construct the YouTube FLV URL (see above) and call the play method.
  5. The play method creates a NetStream and Video object and starts the play the video.

Everything else you see is basically code to handle possible errors:

package
{
  import com.flashdynamix.events.CustomEvent;
  import com.flashdynamix.services.YouTube;
  import flash.display.Sprite;
  import flash.events.AsyncErrorEvent;
  import flash.events.ErrorEvent;
  import flash.events.Event;
  import flash.events.NetStatusEvent;
  import flash.events.SecurityErrorEvent;
  import flash.media.Video;
  import flash.net.NetConnection;
  import flash.net.NetStream;

  public class Main extends Sprite {
    private var connection : NetConnection;
    private var stream : NetStream;
    private var video : Video;
    private var yt : YouTube;

    public function Main():void {
      if (stage) init();
      else addEventListener(Event.ADDED_TO_STAGE, init);
    }

    private function init(e:Event = null):void {
      removeEventListener(Event.ADDED_TO_STAGE, init);

      trace("creating NetConnection");
      connection = new NetConnection();
      connection.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
      connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
      connection.connect(null);
    }

    private function netStatusHandler(event : NetStatusEvent):void {
      switch (event.info.code) {
        case "NetConnection.Connect.Success":
          connectStream();
          break;
        case "NetStream.Play.StreamNotFound":
          trace("Unable to locate video");
          break;
        case "NetStream.Play.Start":
          trace("start playing");
          break;
        case "NetStream.Play.Stop" :
          trace("stop playing");
          break;
      }
    }

    private function securityErrorHandler(event:SecurityErrorEvent):void {
      trace("securityErrorHandler: " + event);
    }

    private function connectStream():void {
      trace("start YouTube search");
      yt = new YouTube();
      yt.addEventListener(Event.COMPLETE, onLoaded);
      yt.addEventListener(ErrorEvent.ERROR, onError);
      yt.videosForTag("lego");
    }

    private function onLoaded(e:CustomEvent):void {
      switch (e.id) {
        case YouTube.SEARCH :
          trace("search finished");
          try {
            trace("first item : " + e.value.items[0].title + " - " + e.value.items[0].link);
          } catch (evt:ArgumentError) {
            trace("ERROR : No Videos For Tag");
          }
          trace("requesting the video id and t-parameter");
          yt.videoId(e.value.items[0].link);
          break;
        case YouTube.VIDEOID :
          trace("loaded: video id = " + e.value.id + " and T-parameter = " + e.value.t);
          play(YouTube.FLVUrl + e.value.id + "&t=" + e.value.t);
          break;
      }
    }

    private function onError(e:ErrorEvent):void {
      trace("IOError : " + e );
    }

    private function play(url:String):void {
      trace("playing: " + url);
      stream = new NetStream(connection);
      stream.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
      stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, asyncErrorHandler);
      video = new Video();
      video.attachNetStream(stream);
      stream.play(url);
      addChild(video);
    }

    private function asyncErrorHandler(event:AsyncErrorEvent):void {
      // ignore AsyncErrorEvent events.
    }
  }
}

I’ve put all files we used in the tutorials in a handy zip file. Just expand and open in FlashDevelop.

Conclusion

In this 5th and final post of the series I have shown how to actually stream the YouTube FLV. It was particularly easy because Flash already has everything you need. It’s a matter of finding the right classes and using them.

That wraps up the 5 part tutorial. Feel free to leave a comment if you found this useful or not. I’m also open for suggestions for improvements or other subjects for future tutorials.

Image credit.

What Every Flash Developer Ought to Know About flash.display.StageScaleMode

While this post is only cursory related to using YouTube, it is important knowledge if you want to create fullscreen Flash applets and/or make sure they resize properly. So I have made it part of the series. In this post I’ll explain the StageScaleMode, which is a property that sometimes causes, what appears to be, weird behavior.

A recap of the ActionScript 3.0 YouTube player series:

If you are an experienced Flash developer, you might want to skip this section, but it got me puzzled for a while. If you want to use the fullscreen mode of Flash, you’ll probably need a little knowledge of how a Flash applet can be resized. You could fix everything, so that images stay the same size, no matter how large your window is, but that would result in empty borders around the picture. It will look better if the video scales with the size of the applet. However, the interface elements usually don’t scale, or else you’d get giant play and pause buttons. To obtain this, you need to handle resizing yourself.

First I’d suggest to try out this basic applet. It’s not user friendly, but it should give you an idea of how this thing works. Open it in a new window and resize away. Then change the scaleMode attribute to see how Flash handles resizing (click on the text to change it):

The full code is available, but the important part is actually only a few lines:

private var modes:Array = new Array(StageScaleMode.EXACT_FIT,
				StageScaleMode.NO_BORDER,
				StageScaleMode.NO_SCALE,
				StageScaleMode.SHOW_ALL);
private var current:Number = 0;
private function changeMode(event:MouseEvent):void {
	stage.scaleMode = modes[++current % 4];
	modeText.text = "current stage scale mode: " + stage.scaleMode;
	event.stopPropagation();
}

Setting the stage.scaleMode attribute makes all the difference when resizing. Everytime you click on the text, the program will rotate over the 4 different possible values for the scaleMode:

  • StageScaleMode.EXACT_FIT: This stretches the image to fit the entire screen. Thus the image is deformed. You’re probably never going to need this mode, unless in very special circumstances.
  • StageScaleMode.NO_BORDER: Makes sure that the application fills the entire screen without deforming. No borders will be visible (unlike SHOW_ALL), but some parts of the application might drop of the screen. When using this mode, take extra care that user interface elements do not fall of the screen. In example applet, if you resize it just right, you can no longer change the mode. This is not exactly what you’d want in a finished application.
  • StageScaleMode.NO_SCALE: This is the easiest mode: just leave everything as is. This is the mode you want if you need complete control.
  • StageScaleMode.SHOW_ALL: Always show the entire applet, and keep the aspect ratio fixed (no stretching). In many cases this will be the best choice. It might however cause borders to appear alongside your applet.

Once you got that working, the Flash fullscreen mode is really a piece of cake. You need to do two things to make it happen:

  • In the ActionScript code change the display state of the stage:
stage.displayState = StageDisplayState.FULL_SCREEN;
  • If you run the applet now, you will get a security exception. On the page where you use the applet, you must explicitly specify that the applet is allowed to go fullscreen. If you use the index.html that FlashDevelop generates for you, you need to add the “allowFullScreen” parameter to the JavaScript loader:
var params = {
	menu: "false",
	scale: "noScale",
	allowFullScreen: "true"
};

Note:

Conclusion

In this post I’ve shown you that the StageDisplayState could be important to your Flash applet and how to use it. I have also demonstrated how easy it is to go full screen in Flash. I hope you enjoyed this post and let me know if you create anything based on it.

The Secret of Reading Mouse Input in Flash Sandy3D – part 2

This posts is a continuation of the previous post and goes into more detail on how to greatly speed up the 2D > 3D mapping by analyzing what actually happens. Usually I’d let Sandy3D do everything for me, but in this case, it turns out it is too slow and the calculation is not complicated at all.

What actually happens in part 1 is this:

  • We have a camera with a viewport of 300 by 300 pixels looking at (0,0,0)
  • There is a plane centered at (0,0,0) and perpendicular to the z-axis. So it faces us.
  • This means the plane will be projected perfectly onto the screen. As is shown in the following figure.

Because of this, it is really simple to calculate the mouse coordinate in the 3D space. The top left corner (0,0) maps to the “plane”-coordinate (-150, 150) and the bottom right corner (300,300) maps to (150,-150). The necessary calculation is easy and can be found in the event handler in the following code:

package  {

	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import sandy.core.Scene3D;
	import sandy.core.scenegraph.Camera3D;
	import sandy.core.scenegraph.Group;
	import sandy.core.scenegraph.Shape3D;
	import sandy.materials.Appearance;
	import sandy.materials.BitmapMaterial;
	import sandy.primitive.Plane3D;

	public class MappingOurown extends Sprite {

		[Embed(source = 'library/capoeira.jpg')]
		private var capoeira:Class;

		private var scene:Scene3D;
		private var camera:Camera3D;
		private var shape:Shape3D;
		private var dir:int = 1;

		public function MappingOurown()
		{
			camera = new Camera3D (300, 300);

			var root:Group = createScene();
			scene = new Scene3D("scene", this, camera, root);

			addEventListener (Event.ENTER_FRAME, enterFrameHandler);
			stage.addEventListener (MouseEvent.MOUSE_MOVE, stageMoveHandler);
		}

		private function createScene () : Group
		{
			var g:Group = new Group ('scene');
			shape = new Plane3D ('plane', 10, 15);
			shape.tilt = 45;

			shape.appearance = new Appearance (new BitmapMaterial (new capoeira ().bitmapData));

			g.addChild (shape);

			return g;
		}

		private function enterFrameHandler (event : Event) : void
		{
			if (shape.pan > 60) {
				dir = -1;
			} else if (shape.pan < -60) {
				dir = 1;
			}
			shape.pan += dir*3;
			scene.render();
		}

		private function stageMoveHandler (event : MouseEvent) : void
		{
			var x:Number = event.localX - 145;
			var y:Number = -1 * (event.localY - 145);
			shape.x = x;
			shape.y = y;
		}
	}
}

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Notes:

  • The dimensions of the Flash applet are put at 300 x 300. In FlashDevelop you can do this in the Project > Properties dialog.
  • The mouse move handler is attached to the stage, so it no longer receives 3D events, but just the ordinary MouseEvent.
  • I've left out the "camera.z = -300;" statement, because -300 is the default z-value for the camera in Sandy 3D
  • I have replaced the "*" import statements with specific classes. This is not required, but it does have the advantage to clearly show which dependencies exist in your program.
  • You'll notice that the 3D object does not follow the mouse exactly. I could just hide the cursor and be done with it (few people will notice). But it is nagging me and I have no idea why that is. I'll ask around and see if any one can explain this to me.

And that's really all there is to it. This really only works because the playing field is exactly the same as the screen. You might be tempted to rotate the field for cool perspective effects, but as soon as you do that, the calculation becomes more complicated.

Now it's about time to introduce some interesting 3D objects and get some real action going. But that's for a next post.

The Secret of Reading Mouse Input in Flash Sandy3D – part 1

Previously, I’ve shown you a few random Flash tidbits. The ultimate goal is to create a small arcade action game in a 3 dimensions. I’m taking this opportunity to learn Sandy 3D, one of the better Flash 3D engines. In this two part feature, I will be going into the details of how to get mouse information into a 3D world.

Although this might seem easy, the underlying problem is that the mouse position is in 2 dimensions: an X and Y coordinate. Your screen is flat after all. However, the game world has 3 dimensions. So how do we map the cursor 2D position on the screen onto a 3D position in the game world?

In this post and the next, I’ll show you two ways to get this working. First I’ll show you the solution, which I think is “the best” from a theoretical perspective. Sadly it is not workable in real life, as it is too slow. In a second post, I’ll present a possibility which is sort-of hacky, because it works perfectly in this example, but if you want a slightly different game, it probably won’t help you (or you’ll have to do some Maths yourself, which could be complicated, depending on the case in question).

The Right Way

The idea is to have the game playable on a 2D plane, but use 3D objects and effects to make it more interesting. So all objects and user interaction will happen only in 2 dimensions. It is not too well documented (there are a bunch of tutorials on the topic), but Sandy3D makes this very easy for you. In Sandy, you can add listeners to any 3D object. Basically any Flash event is supported and on top of that, it will return a Shape3DEvent, which contains the 3D position of the cursor on the object.

So easy enough, all I have to do is draw a “interactivity” plane in which I want the objects to move and attach a mouse listener. You’ll probably recognize a lot of this code:

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

	public class Demo1 extends Sprite
	{
		[Embed(source = 'library/capoeira.jpg')]
		private var capoeira:Class;

		private var scene:Scene3D;
		private var camera:Camera3D;
		private var shape:Shape3D;
		private var groundPlane:Shape3D;
		private var dir:int = 1;
		public function Demo1 ()
		{
			camera = new Camera3D (300, 300);
			camera.z = -300;

			var root:Group = createScene();
			scene = new Scene3D("scene", this, camera, root);

			addEventListener (Event.ENTER_FRAME, enterFrameHandler);
		}

		private function createScene () : Group
		{
			var g:Group = new Group ('scene');
			shape = new Plane3D ('plane', 10, 15);
			shape.tilt = 45;

			groundPlane = new Plane3D("ground", 300, 300, 10, 10);
			groundPlane.enableEvents = true;
			groundPlane.addEventListener( MouseEvent.MOUSE_MOVE, moveHandler);

			shape.appearance = new Appearance (new BitmapMaterial (new capoeira ().bitmapData));

			g.addChild (shape);
			g.addChild (groundPlane);

			return g;
		}

		private function enterFrameHandler (event : Event) : void
		{
			if (shape.pan > 60) {
				dir = -1;
			} else if (shape.pan < -60) {
				dir = 1;
			}
			shape.pan += dir*3;
			scene.render();
		}

		private function moveHandler (event : Shape3DEvent) : void
		{
			shape.x = event.point.x;
			shape.y = event.point.y;
		}
	}
}

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

A few notes:

  • I purposely kept the plane to which the event handler is connected visible, so that it would be clear what happened. In any real game this would be invisible.
  • On my machine, the animated object correctly follows the mouse, but it is very laggy. In fact, if this was an arcade game, it would be unplayable. Sometimes it doesn't even update at all. If you have a faster computer, you might not notice it that much. But if you'd start adding other objects, chances are high you'd run into the problem at some point.
  • An event handler attached to a Sandy object returns a Shape3DEvent. This contains many useful properties. Such as the "point" that we use to extra the cursor location on the plane. No Math needed.
  • Compared to the previous Sandy3D tutorials, I have replaced the (older) World3D with a (newer) Scene3D object. The Scene3D is preferable as it allows more flexibility. You can have multiple Scene3D objects in your application (for instance, if you want a picture-in-picture type of display, or if you want to switch between worlds)
  • Although this is a very very basic example, this event handling is very powerful. It will work on anything. Put a sphere in your scene and it will allow you to follow the cursor on the sphere. However, the downside of all this power is that it does not perform too well.
  • Make sure to take a look at the "User interaction" tutorials on the Sandy site to grasp all the possibilities in Sandy 3D.

Next week I'll show you what actually happens behind the scene of the position calculation. In case of this particular plane, this turns out to be deceptively simple. In fact, we can do it ourselves and save many CPU cycles.

Vector vs Bitmap side-by-side – SVG & PNG in Flash

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)

Looking back at my previous post and the comments, I don’t think the vector versus bitmap comparison was very clear, so I tried to show it differently with the applet above. In the meantime I also got some hands-on time with matrix transformations in Flash. It’s not really needed, but if you’re interested, you can do some reading up on matrix transformations on Wikipedia and many other sites.
Continue reading Vector vs Bitmap side-by-side – SVG & PNG in Flash