Thursday, December 29, 2016

CLOCZ.com Custom Wall Clock Design Site

An interesting new business has sprung up at CLOCZ.com where you can order a Custom Image Wall Clock by choosing the clock background, style and colours. It's a really neat e-commerce site! Check it out if you're in the market for new clock to fit your home decoration motif. I went with the baby monkey yawning wall clock which looks great in my den. Personally, I love the website experience itself and I look forward to designing my next wall clock for my kitchen.

Wednesday, November 2, 2011

Dynamic Asset Loading And SWF Packaging in FlashDevelop

I've just recorded a detailed solution tutorial at 2dflashgamedev.blogspot.com.

Be sure to check it out as it applies even more so to loading large 3D assets like models and textures:

http://2dflashgamedev.blogspot.com/2011/11/dynamic-asset-resource-loading-flixel.html

The tutorial explains using BulkLoader to load asset individually into Flixel or through a SWF Class file with embedded assets.

Thursday, February 17, 2011

Compile FFmpeg Alpha Channel Images & Embed FLV In Flash AS3

The battle with flash video alpha channels has resulted in victory. Three days of trying every angle to get alpha channels on the cheap and I broke down and downloaded a trial version of Sorenson Squeeze to compress the video in the proprietary VP6a (A for Alpha) codec. That was just the beginning of the end of solving the transparent background.

The general idea is that we use FFmpeg to compile JPG to video with alpha then Sorenson Squeeze export to the vp6a codec and then use flash to export to the Flash 9 flv container. The VP6a codec is offered in Sorenson Squeeze for Flash 8 only. When you attempt to load the Flash 8 FLV into a movieclip for easy control it will bug out and say it can't deal with AVM1 files as Flash 10 is now using AVM2. Big deal right? Should get sorted out in Flash 11 more clearly how to do all this stuff but at the moment FLV transparent background video can a tough issue to tackle. Although you can download ffmpeg and many features and codecs are immediately available it is impossible to create transparency-supported embedded flash video formats.

You need a paid solution like Sorenson Squeeze so go ahead and download the trial version. My example exports the correct video format to preserve the alpha channel present in the PNG files (could as well be JPG) by using the flags "-vcodec rawvideo". If your output video comes out upside down then the flags '-vf "vflip"' are needed for you to unflip it. Even though these instructions are for converting still frames to video you should be able to use these settings to convert from video to video if your format isn't supported in Squeeze somehow.

1. Compress the image series with rawvideo codec which uses bgra pixel format by default:
ffmpeg -i "D:\animations\DemoFiles1\Animation1\Animation1.%d.png" -vcodec rawvideo -vf "vflip" testPNGtoRAW.avi
2. Compress to FLV with on2's codec VP6a in Sorenson Squeeze (Codec only available for Flash 8 AVM1 format).
3. Embed in Flash 9 AVM2 video swf container using Flash IDE. (This step is optional and only to use SWF movieclip functionality in code instead of netstream.)

All told over a week spent in the video encoding department (w/ alpha and w/o alpha) reading, testing and learning... Now I can get back to coding ^_^

To embed this flv alpha channel video into our flash movie you may use the following:
[Embed(source = "../data/playeranims/Player1/playerDefend.swf", mimeType = "application/octet-stream")] private var PlayerDefend:Class;
 Nevermind the parent folder notation in the example but make sure to include the correct mime type. I have embedded the video in the object class for each player character.

Now in my code I have different player objects each with their own videos and so each has functionality to access the embedded video with the next code example:
public function getDefendVideo():ByteArray { return new PlayerDefend(); }
 Now we can play the flv video with alpha channel functionality. This function loads the video's bytes from the character object and gets ready for the completion event which will fire soon as the video is embedded. This makes things kind of easy. ^_^
private function playVideo():void
{
_loader.loadBytes(playerCharacter.getDefenseVideoOne()); _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete);
}

The request to load the embedded video's bytes completes with the ability to easily use a movieclip to control the playback of the transparent flv video in flash. Without the proper version of Flash flv container it is not quite so easy to dynamically load and play your videos. As mentioned before you will get an AVM1 error as being an "outdated" video FLV container.

I have also implemented an EnterFrame event that checks the position of the video every cycle to determine what to do which is in this case unload the video after fading out:

private function onLoadComplete(event:Event):void {_loader.content.addEventListener(Event.ENTER_FRAME, onMovieEnter);}

private function onMovieEnter(event:Event):void {

var swfTimeline:MovieClip = _loader.content as MovieClip;

if (swfTimeline.currentFrame == swfTimeline.totalFrames)

{

_loader.content.removeEventListener(Event.ENTER_FRAME, onMovieEnter);

swfTimeline.stop();

Tweener.addTween(_loader.content, { alpha:0.2, time:0.3, transition:"easeOutCirc"} );

Tweener.addTween(_loader.content, { alpha:0, time:0.3, delay:0.3, transition:"easeOutCirc" , onComplete:function():void { _loader.unloadAndStop(); }} );

}

}

The code example then goes on to tween the video in and out as well as unloading and stopping the transparent flv movie upon completion of the fade-out. As you can see I am using the Tweener library and format here in the example as3. Put simply, the second Tweener command fades the alpha to zero over 3 tenths of a second using circular outer easing and unloads the movie on completion.

You are going to need to declare the loader up top in your controlling code portion:
public var _loader:Loader;

Also your imports for this as3 transparent video tutorial are:
import flash.display.loader
import flash.events.Event

Saturday, February 12, 2011

Away3D & Groups: Object Containers with 3D Tank Game Development Tutorial

The tank flash game can be seen here: Two Tanks 3D Tank Flash Game


Calculating When To Blow Up

The bullet fired from a tank is checked for impact with another tank or the ground elevation's height level at the X,Y coordinate that it is at.

if (earth.y < elevationreader.getLevel(earth.x, -earth.z, -3500) || meshEnemy.distanceTo(earth) < 350) 

LOL: -3500 is just some offset that I'm using with the Away3D elevation reader. Sounds important though. I could do a tutorial on tinkering with the built-in terrain code to get what you want out of it but it's not That difficult... even though it is... I think I just need to figure it out better! I'm postponing any such thing in case better Away3D documentation comes out or the output of the terrain library is easier to guess in terms of scale, size, etc.


Tank Controls: Keyboard Input Code In Away3D

The following exposes a great deal of information to 3D video game developers on how a simple tank rig needs to be constructed with code in Away3D. Moving the mouse while the button is clicked down adjusts the object container group cannonMesh. With the way that the groups were setup, the rotation X property uses a range from 0 to 37 degrees for the range of movement in which the tank barrel is allowed to aim "up and down". There was some very tricky 3D coding needed to set this up which will be covered towards the end of the post. Turning the entire tank is provided for but not in the following code. So, the only movements left to explain are rotating the barrel around the tank. In this case the tank barrel turns freely all 360 degrees if it likes and so cannonMesh and bulletMarkerDummyRotationObject are rotated together. I am using bulletMarkerDummyRotationObject as an easy way to locate the end of the barrel when we need to fire a shot off in the code. When the player shoots the tank or the enemy fires upon the player, Away3D just grabs the position of bulletMarkerDummyRotationObject which thanks to the groups setup is already rotated right into place to take the correct x,z,y coordinates. Also, cameraMarkerDummyRotationObject is another "dummy object" used to track and tween the position of the camera around the tank:
if (move) 
{
cannonMesh.rotationX += (stage.mouseY - lastMouseY) * .01;
if(cannonMesh.rotationX < 0)
{cannonMesh.rotationX = 0; }
if(cannonMesh.rotationX > 37)
{cannonMesh.rotationX = 37; }
}

if (qispressed)
{
cannonMesh.rotationY -= 4;
bulletMarkerDummyRotationObject.rotationY -= 4;
}
if (eispressed)
{
cannonMesh.rotationY += 4;
bulletMarkerDummyRotationObject.rotationY += 4;
}
if (zispressed)
{
cameraMarkerDummyRotationObject.rotationY -= 3;
}
if (cispressed)
{
cameraMarkerDummyRotationObject.rotationY += 3;
}
mesh.rotationY = mesh.rotationY + (accelerationSideRate / 3);

At the end I had first come up with a little trick to fake the tank being level with the ground on uneven terrain like the side of a hill but I came up with the real thing a while later. It doesn't twitch as if it's matching the angle of the terrain but it actually matches the angle quite well and in terms of computation... inexpensively as well.


Health Bar With Rendered Text Status: Critical

I chose to use a health status display of pre-rendered image assets that need to switch based on tank's health percentage range. I am using a function called getStatus which returns the index number of the correct image in our array of images which corresponds to that tank's current class of health.

public function recalculateHealthBar():void
{
//cgg edit: this was causing error now that its in flash 10 debugger and not flash 9 which worked previously
removeChild(currentHealthBar);
var playerStatus:int = getStatus(tankhealth);
var enemyStatus:int = getStatus(tankhealthEnemy);
currentHealthBar = bitmapArray[playerStatus][enemyStatus];
addChild(bitmapArray[playerStatus][enemyStatus]);
}


The getStatus function simply sorts out which range the player's health is in and returns the appropriate integer:

public function getStatus( health:uint ):uint
{
if (health == 100) return 0;
if (health < 100 && health >= 80) return 1;
if (health < 80 && health >= 40) return 2;
if (health < 40 && health >= 0) return 3;
return 0;
}


Enjoy Away3D! I have really appreciated all of the work that the Away3D team is doing with Away3DLite. Even more exciting is Adobe's Molehill release of Flash 11 and the 3D card support coming into the works as we speak.

Monday, February 7, 2011

Skybox Textures Free Tutorial - Make Your Own Performance Skybox In Away3D

First thing you need is a proper skybox generator like Terragen.

How to script the camera settings in a text file with a TGS extension is shown here.

Alternatively, you can set the camera up by hand to render each frame by setting zoom to one and taking renders of 0, 90, -90, 180 degrees rotation as well as up and down with 90 and -90 whilst the other rotation value is zero.

Now, once we have the textures ready we can import them into the actionscript:

        [Embed(source='skybox5/up.jpg')]
        private var EarthUp:Class;
        [Embed(source='skybox5/front.jpg')]
        private var EarthFront:Class;
        [Embed(source='skybox5/left.jpg')]
        private var EarthLeft:Class;
        [Embed(source='skybox5/right.jpg')]
        private var EarthRight:Class;
        [Embed(source='skybox5/back.jpg')]
        private var EarthBack:Class;
 In this tutorial I will present a skybox with only five sides. I have eliminated the bottom face from the away3d skybox class to make a new class skybox5 as opposed to skybox6 where away3d provides a method of including all six images in one texture file.

The use of only 5 faces is for performance as the bottom face is never seen underneath the map's terrain. We just need to make sure the camera doesn't ever look over the edge of our 3D terrain!


In this next code in our game initialisation we need to turn each included file into a corresponding BitmapMaterial for our skybox class in away3D to accept out textures:
           var earthBackBmp:Bitmap = new EarthBack() as Bitmap;
            var back:BitmapMaterial = new BitmapMaterial(earthBackBmp.bitmapData);
            var earthFrontBmp:Bitmap = new EarthFront() as Bitmap;
            var front:BitmapMaterial = new BitmapMaterial(earthFrontBmp.bitmapData);
            var earthLeftBmp:Bitmap = new EarthLeft() as Bitmap;
            var left:BitmapMaterial = new BitmapMaterial(earthLeftBmp.bitmapData);
            var earthRightBmp:Bitmap = new EarthRight() as Bitmap;
            var right:BitmapMaterial = new BitmapMaterial(earthRightBmp.bitmapData);
            var earthUpBmp:Bitmap = new EarthUp() as Bitmap;
            var up:BitmapMaterial = new BitmapMaterial(earthUpBmp.bitmapData);
           
            skybox = new Skybox5( front, left, back, right, up );
            skybox.quarterFaces();
            scene.addChild( skybox );

Of course, the variable "skybox" of type Skybox5 was declared up top with the skybox texture image includes.

I will go ahead and display the the altered Away3D class file:

package away3d.primitives
{
    import away3d.core.base.*;
    import away3d.materials.*;

    /**
    * QTVR-style 360 panorama renderer that is initialized with six images.
    * A skybox contains six sides that are arranged like the inside of a cube.
    */
    public class Skybox5 extends Mesh
    {
        public function Skybox5(front:ITriangleMaterial, left:ITriangleMaterial, back:ITriangleMaterial, right:ITriangleMaterial, up:ITriangleMaterial)
        {
            super();

            var width:Number = 800000;
            var height:Number = 800000;
            var depth:Number = 800000;

            var v000:Vertex = new Vertex(-width/2, -height/2, -depth/2);
            var v001:Vertex = new Vertex(-width/2, -height/2, +depth/2);
            var v010:Vertex = new Vertex(-width/2, +height/2, -depth/2);
            var v011:Vertex = new Vertex(-width/2, +height/2, +depth/2);
            var v100:Vertex = new Vertex(+width/2, -height/2, -depth/2);
            var v101:Vertex = new Vertex(+width/2, -height/2, +depth/2);
            var v110:Vertex = new Vertex(+width/2, +height/2, -depth/2);
            var v111:Vertex = new Vertex(+width/2, +height/2, +depth/2);

            var uva:UV = new UV(1, 0);
            var uvb:UV = new UV(0, 0);
            var uvc:UV = new UV(0, 1);
            var uvd:UV = new UV(1, 1);

            addFace(new Face(v000, v001, v010, back, uva, uvb, uvd));
            addFace(new Face(v010, v001, v011, back, uvd, uvb, uvc));
                                          
            addFace(new Face(v100, v110, v101, front, uvb, uvc, uva));
            addFace(new Face(v110, v111, v101, front, uvc, uvd, uva));
                                          
            //addFace(new Face(v000, v100, v001, down, uvb, uvc, uva));
            //addFace(new Face(v001, v100, v101, down, uva, uvc, uvd));
                                                
            addFace(new Face(v010, v011, v110,  up, uvc, uvd, uvb));
            addFace(new Face(v011, v111, v110,  up, uvd, uva, uvb));

            addFace(new Face(v000, v010, v100, left, uvb, uvc, uva));
            addFace(new Face(v100, v010, v110, left, uva, uvc, uvd));
                                                               
            addFace(new Face(v011, v001, v101, right, uvd, uva, uvb));
            addFace(new Face(v011, v101, v111, right, uvd, uvb, uvc));

            quarterFaces();
            quarterFaces();

            mouseEnabled = false;
           
            type = "Skybox";
            url = "primitive";
        }
    }
   
}
 See I've only commented out the face creation which is as far as we need to go for this "3D sky box" performance increase. I've also removed the down skybox texture file parameter from the constructor method's input.

This should save us a fair bit of memory and processing time as the sixth image does not need to embedded or used and the sixth face which is never seen... is never created and therefore never rendered. :P

Here are some generated skybox textures download them directly for use in your own flash games. These images are 512x512 and compressed with JPEG to 80% quality.

Away3d skybox example.

Use a five sided skybox instead of the away3d skybox6.

Away3d skybox tutorial for performance boost. Remember to keep the zoom at exactly 1 when rendering skybox textures or else the images will not line up correctly with each other and the collection will not match.

A good skybox generator can do wonders in simplifying complex sky simulations.

This is the last texture file so I hope you've enjoyed this 3d skybox tutorial and good luck with your AS3 projects!

Wednesday, June 30, 2010

Tracking Vertices In Away3D Animated 3D Models

Tracking Vertex Positions In Away3D MovieMesh Class For Animated Models In Away3dLite (Jan. 28th 2010 )

**Useful for interchangeable handheld weapons for models to find attachment points**

Add MovieMesh Variable Declaration:
public var leftHandx:Number;

public var leftHandy:Number;

public var leftHandz:Number;


MovieMesh.onEnterFrame:

Place after "while(i--)" update of all vertices:

var tempOffset:int = 100;

leftHandx = _vertices[(tempOffset*3)];

leftHandy = _vertices[(tempOffset*3) + 1];

leftHandz = _vertices[(tempOffset*3) + 2];


Added to MyProject code:

mySphere = new Sphere();
mySphere.radius = 10;
mySphere.x = mySphere.y = mySphere.z = 0;
scene.addChild(mySphere);


MyProject.onEnterFrame:

//trace(mesh.leftHandx);
mySphere.x = mesh.leftHandx;
mySphere.y = mesh.leftHandy;
mySphere.z = mesh.leftHandz;

Fixing MD2 Model Animation Play In Away3dLite

Fixing MD2 Model Animation Play ( Away3dLite - Jan. 28th 2010 )

I made a note of this fix early in development of a project where the MD2 animation kept playing in entirety initially and then played the desired loop.

I haven't verified this %100 as an issue as I was using certain test models at the time and attempting proper Md2 generation simultaneously. The following code is my modification to correct this MovieMesh play error in AS3:

In class MovieMesh.onEnterFrame:

//CGG - January 28th 2010 - 11:31 pm

//Added this check and set to stop animation from

//playing through from beginning before finally

//entering desired loop animation


if(_otime == 0){

_otime = getTimer();

}

//end of CGG edit above

NOTE: I checked this out again and I can't see any differences with or without it... was it a frame name problem???

NOTE: I think I just confirmed that this actually is a problem but the best test case is with two animations each with a sizable length like 70 frames. I could barely notice the issue but I uncommented the hack and the problem went away.

The version of Away3DLite should have been the most current as of Jan. 28th 2010.

I wonder if anyone else saw this?