Welcome to the JActionScripters.com

Who we are

JActionScripters.com is driven by more than 20 top-notch Japanese Flash developers. Including not just coders, but art directors, designers, and productions, too.

What it is for?

JActionScripters was born to introduce Japanese ActionScript tips, code snippets, open source libraries, and cutting-edge Flash showcases for the Flash geeks all over the world – yup, I mean, YOU!

What you can get from here?

JActionScripters provides you not just ActionScript open source codes, libraries, frameworks, and Flash showcases, but the coolest news about “what’s going on in the Japanese Flash world”, Japanese creative concepts and philosophies, and of course, the zen to everything above.
As we believe, Japan rules. You must already know, as you are already here.

Here is the feed

Correction of a sample code in “Using the Text Layout Framework” of the CS5 help

Using the Text Layout Framework” in “ActionScript 3.0 Developer’s Guide” on the Flash CS5 help includes some example codes to show how to use the Text Layout Framework. However, the second example in the section “The Text Layout Framework View” yields errors. The following two corrections should be made.

First, insert the xmlns attribute into the Flow element of the XML data (markup).

// var markup:XML = <TextFlow><p><span>Hello, World</span></p></TextFlow>;
var markup:XML = <TextFlow xmlns=’http://ns.adobe.com/textLayout/2008′><p><span>Hello, World</span></p></TextFlow>;

Second, the method updateAllContainers() is not implemented in the IFlowComposer interface. Use the updateAllControllers() method instead.

// myFlow.flowComposer.updateAllContainers();
myFlow.flowComposer.updateAllControllers();

The corrected frame action below works and shows the text in the top left corner of the stage.

// import necessary classes
import flashx.textLayout.container.*;
import flashx.textLayout.compose.*;
import flashx.textLayout.elements.TextFlow;
import flashx.textLayout.conversion.TextConverter;

// first, create a TextFlow instance named myFlow
// var markup:XML = <TextFlow><p><span>Hello, World</span></p></TextFlow>;
var markup:XML = <TextFlow xmlns='http://ns.adobe.com/textLayout/2008'><p><span>Hello, World</span></p></TextFlow>;
var myFlow:TextFlow = TextConverter.importToFlow(markup, TextConverter.TEXT_LAYOUT_FORMAT);

// second, create a controller
// the first parameter, this, must point to a DisplayObjectContainer
// the last two parameters set the initial size of the container in pixels
var contr:ContainerController = new ContainerController(this, 600, 600);

// third, associate it with the flowComposer property
myFlow.flowComposer.addController(contr);

// fourth, update the display list ;
// myFlow.flowComposer.updateAllContainers();
myFlow.flowComposer.updateAllControllers();

Using a class in flashx.textLayout package prevents the constructor from accessing Stage

Text Layout Framework example: News layout” in the [Help] yields the run-time error #1009. Because using a class in flashx.textLayout package prevents the constructor from accessing the Stage instance.

Note: The code has already been fixed. But it is good to know how to access the Stage object when classes in flashx.textLayout package are used. (2010/06/20)

As the test script below shows, the Stage object is available after the DisplayObject.addedToStage event, which is dispatched twice.

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flashx.textLayout.elements.TextFlow;
	public class TextLayoutFormatTest extends Sprite {
		public function TextLayoutFormatTest() {
			var my_fmt:TextFlow;
			trace("constructor", stage, parent);
			addEventListener(Event.ADDED_TO_STAGE, onAdded);
		}
		private function onAdded(eventObject:Event):void {
			trace(stage, parent);
		}
	}
}

// [Output]:
constructor null null
[object Stage] [object Loader]
[object Stage] [object Stage]

As for the prior example in the [Help], TLFNewsLayout class, the statements in the constructor should be moved into a listener method of the DisplayObject.addedToStage event as follows:

package {
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.geom.Rectangle;

	import flashx.textLayout.compose.StandardFlowComposer;
	import flashx.textLayout.container.ContainerController;
	import flashx.textLayout.container.ScrollPolicy;
	import flashx.textLayout.conversion.TextConverter;
	import flashx.textLayout.elements.TextFlow;
	import flashx.textLayout.formats.TextLayoutFormat;

	public class TLFNewsLayout extends Sprite {
		private var hTextFlow:TextFlow;
		private var headContainer:Sprite;
		private var headlineController:ContainerController;
		private var hContainerFormat:TextLayoutFormat;

		private var bTextFlow:TextFlow;
		private var bodyTextContainer:Sprite;
		private var bodyController:ContainerController;
		private var bodyTextContainerFormat:TextLayoutFormat;

		private const headlineMarkup:String = "TLF News Layout ExampleThis example formats text like a newspaper page with a headline, a subtitle, and multiple columns";

		private const bodyMarkup:String = "There are many such lime-kilns in that tract of country, for the purpose of burning the white marble which composes a large part of the substance of the hills. Some of them, built years ago, and long deserted, with weeds growing in the vacant round of the interior, which is open to the sky, and grass and wild-flowers rooting themselves into the chinks of the stones, look already like relics of antiquity, and may yet be overspread with the lichens of centuries to come. Others, where the lime-burner still feeds his daily and nightlong fire, afford points of interest to the wanderer among the hills, who seats himself on a log of wood or a fragment of marble, to hold a chat with the solitary man. It is a lonesome, and, when the character is inclined to thought, may be an intensely thoughtful occupation; as it proved in the case of Ethan Brand, who had mused to such strange purpose, in days gone by, while the fire in this very kiln was burning.The man who now watched the fire was of a different order, and troubled himself with no thoughts save the very few that were requisite to his business. At frequent intervals, he flung back the clashing weight of the iron door, and, turning his face from the insufferable glare, thrust in huge logs of oak, or stirred the immense brands with a long pole. Within the furnace were seen the curling and riotous flames, and the burning marble, almost molten with the intensity of heat; while without, the reflection of the fire quivered on the dark intricacy of the surrounding forest, and showed in the foreground a bright and ruddy little picture of the hut, the spring beside its door, the athletic and coal-begrimed figure of the lime-burner, and the half-frightened child, shrinking into the protection of his father's shadow. And when again the iron door was closed, then reappeared the tender light of the half-full moon, which vainly strove to trace out the indistinct shapes of the neighboring mountains; and, in the upper sky, there was a flitting congregation of clouds, still faintly tinged with the rosy sunset, though thus far down into the valley the sunshine had vanished long and long ago.";

		public function TLFNewsLayout() {
			addEventListener(Event.ADDED_TO_STAGE, initialize);
		}
		function initialize(eventObject:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, initialize);
			stage.scaleMode = StageScaleMode.NO_SCALE;
			stage.align = StageAlign.TOP_LEFT;

			// Headline text flow and flow composer
			hTextFlow = TextConverter.importToFlow(headlineMarkup,TextConverter.TEXT_LAYOUT_FORMAT);
			hTextFlow.flowComposer = new StandardFlowComposer();

			// initialize the headline container and controller objects
			headContainer = new Sprite();
			headlineController = new ContainerController(headContainer);
			headlineController.verticalScrollPolicy = ScrollPolicy.OFF;
			hContainerFormat = new TextLayoutFormat();
			hContainerFormat.paddingTop = 4;
			hContainerFormat.paddingRight = 4;
			hContainerFormat.paddingBottom = 4;
			hContainerFormat.paddingLeft = 4;

			headlineController.format = hContainerFormat;
			hTextFlow.flowComposer.addController(headlineController);
			addChild(headContainer);
			stage.addEventListener(flash.events.Event.RESIZE, resizeHandler);

			// Body text TextFlow and flow composer
			bTextFlow = TextConverter.importToFlow(bodyMarkup,TextConverter.TEXT_LAYOUT_FORMAT);
			bTextFlow.flowComposer = new StandardFlowComposer();

			// The body text container is below, and has three columns
			bodyTextContainer = new Sprite();
			bodyController = new ContainerController(bodyTextContainer);
			bodyTextContainerFormat = new TextLayoutFormat();
			bodyTextContainerFormat.columnCount = 3;
			bodyTextContainerFormat.columnGap = 30;

			bodyController.format = bodyTextContainerFormat;
			bTextFlow.flowComposer.addController(bodyController);
			addChild(bodyTextContainer);
			resizeHandler(null);
		}

		private function resizeHandler(event:Event):void {
			const verticalGap:Number = 25;
			const stagePadding:Number = 16;
			var stageWidth:Number = stage.stageWidth - stagePadding;
			var stageHeight:Number = stage.stageHeight - stagePadding;
			var headlineWidth:Number = stageWidth;
			var headlineContainerHeight:Number = stageHeight;

			// Initial compose to get height of headline after resize
			headlineController.setCompositionSize(headlineWidth, headlineContainerHeight);
			hTextFlow.flowComposer.compose();
			var rect:Rectangle = headlineController.getContentBounds();
			headlineContainerHeight = rect.height;

			// Resize and place headline text container
			// Call setCompositionSize() again with updated headline height
			headlineController.setCompositionSize(headlineWidth, headlineContainerHeight );
			headlineController.container.x = stagePadding / 2;
			headlineController.container.y = stagePadding / 2;
			hTextFlow.flowComposer.updateAllControllers();

			// Resize and place body text container ;
			var bodyContainerHeight:Number = (stageHeight - verticalGap - headlineContainerHeight);
			bodyController.format = bodyTextContainerFormat;
			bodyController.setCompositionSize(stageWidth, bodyContainerHeight );
			bodyController.container.x = (stagePadding/2);
			bodyController.container.y = (stagePadding/2) + headlineContainerHeight + verticalGap;
			bTextFlow.flowComposer.updateAllControllers();
		}
	}
}

The result of the TLFNewsLayout class

The result of the TLFNewsLayout class

NTT DoCoMo SH-07B Standby Widgets

Today, the NTT DoCoMo has released some new products and services for this summer. One of them, “SH-07B” which is released from SHARP Corporation, has new function called “Standby Widgets” that was implemented by Yoshihiro Shindo (BeInteractive!, it’s me) and Yusuke Nakahara who belongs to the CD-IM. It was directed by Naoki Mima who belongs to the Rightninc, Inc. What I mentioned in my presentation at the FITC Toronto 2010 is about this.

“Standby Widgets” is a function that enables you to customize your standby screen. You can add, remove, or lay out built-in widgets as you like. There are some built-in widgets like bookmarks, calendar, and manner mode switch. Also you can change widget’s color to your favorite color. For phone and mail, it has a list that you can access recent calls or mails easily.

In all honesty, it’s not an amazing new function. However, a point is why the team has invited me. Can you make sense? Yes, it’s written by Flash (FlashLite). A special customized FlashLite engine has been provided by the device team, and all of “Standby Widgets” is running on it. This is our first answer of a question “Can we make better UI if we could use Flash?”.

Many Japanese mobile phone is high-spec actually, but its UI ruins the value of it, I think. In my view, this project is to improve it. Also I feel this project provides fun future to not only users of device but also Flash developers in the world.

TETRIS on the beat !

Tetrision

SiON TETRISizer – wonderfl build flash online

This is new demonstration of my AS3 software synthesize ‘SiON’. This work may remind someone of ‘LUMINES’ (of cause this is one of my favorite games). The SiON can bring its feeling to your flash.
In this flash, I also use various libraries, betweenas3, froce55ing, minimalcomps and papervision3d.
I would like to say thank you for all authors of these useful libraries.

Enjoy !

AS3 software synthesizer SiON Development Center in spark project

Decrement versus Increment in Loop 2

Adobe’s “Optimizing Performance for the Flash Platform” recommends that “Use reverse order for while loops” in its “Miscellaneous optimizations” section. And in my last post, decrement was not explicitly faster than increment with the following code to compare them:

while (--i > -1)

while (++i < MAX_NUMBER)  // MAX_NUMBER is a constant

Difference was very little in my Mac OS environment. But in Internet Explorer 7 and Firefox 3/Flash Player 10/Windows Vista, decrement was faster up to twenty percent than increment. After several trials, speed of operation between decrement and increment seems to be almost the same. The condition of loop does not care if expression is decrement or increment.

The difference came from value to be compared with a counter variable. The new sample script for increment below does not use a constant in the condition. Then its speed seems to be almost identical to the decrement's.

while (++i < <the literal number>)

AS3/Flash10 software synthesizer SiON goes to version 0.6

SiON goes to version 0.60

Now, the ActionScript software synthesizer “SiON” is updated to version 0.6. You can get the newest version from following link.

SiON Development Center in spark project
SiON version 0.60 ASDoc

In the SiON version 0.6, the interfaces are basically same as previous, but it suggests one new feature “SoundObject”. Here’s the example on wonderfl.

SiON SoundObject Quartet

The Arpeggiator, BassSequencer, ChordPad and DrumMachine are the inheritances of SiON SoundObject. The SoundObject brings an feeling of ‘DisplayObject’ to the operations of SiON’s synthesizer.

Let us explore a tidbit of sample’s source code. The concept of SiON SoundObject consists of 4 modules, the SiONDriver, SoundObjects, Synthesizers and Effectors (shown in line 16~54).

The SiONDriver is the centeral processing unit of all SiON’s sound, you have to create one new SiONDriver and call play() method. And you might access some SiONDriver’s properties and methods to set up general settings (BPM, effector and so on) (shown in line 76~83).
driver = new SiONDriver(); (line 65)
...
driver.autoStop = true; // set auto stop after fade out
driver.bpm = 132; // BPM = 132
driver.effector.slot0 = [equaliser]; // The equaliser is applied to slot0 (master effector)
driver.effector.slot1 = [delay]; // The delay effector is applied to slot1 (global effector)
driver.effector.slot2 = [chorus]; // The chorus effector is applied to slot2 (global effector)
driver.addEventListener(SiONTrackEvent.BEAT, _onBeat); // handler for each beat
driver.addEventListener(SiONEvent.STREAM_START, _onStartStream); // handler when streaming starts
driver.addEventListener(SiONEvent.STREAM_STOP, _onStopStream); // handler when streaming stopped
...
driver.play(null, false); (line 193)

The SoundObjects provides a sequence controler. You can control the sounding patterns in real time by properties (following code is from Arpeggiator’s setting line 91~101). In this exapmle, you can feel the SoundObject’s sound controling especially in the Arpeggiator’s large square pad. All SoundObject classes belong to org.si.sound package.
Ar = new Arpeggiator();
Ar.scaleName = "o6Emp"; // scaled in E minor pentatonic on octave 6
Ar.pattern = [0,1,2,3,4,2,3,1]; // basic pattern is "egababg" in MML
Ar.noteLength = 1; // note langth = 16th
Ar.gateTime = 0.2; // gate time = 0.2
Ar.effectors = [autopan]; // apply auto-panning effector to Arpeggiator (local effector)
Ar.volume = 0.3; // dry volume = 0.3
Ar.effectSend1 = Ar.volume * 0.4; // effect send for slot1 = 0.3 * 0.4 = 0.12
Ar.effectSend2 = Ar.volume * 0.5; // effect send for slot2 = 0.3 * 0.4 = 0.15
...
Ar.play(); (line 198)

The Synthesizers provides a voice controler. This class simplifys the SiONVoice’s settings, and supports a real-time voice charactor chagings on a SoundObject. In this example, some components are connected to the synthesizer’s properties (especially in BassSequencer’s envelop controls) and you may feel the voice character changing on it. (following code is from Arpeggiator’s WaveTableSynth line 106~109). All synthesizer classes belong to org.si.sound.synthesizers package.
waveTableSynth = new WaveTableSynth();
waveTableSynth.color = 0x1203acff; // wavecolor value
waveTableSynth.releaseTime = 0.2; // release time
Ar.synthesizer = waveTableSynth; // apply synthesizer

The Effectors represents the sound effector units. You can apply effectors to the SoundObject like filters to the DisplayObject (please refer above code).
One remarkable point on effectors is that there are 3 types of connections, master, global and local effector. The master effector preocesses the final output of all SiON’s sound, the global effector preocesses the effect send pipe and the local effector processes only one SoundObject’s output. The arrow diagram of effector connection is as shown in below figure. All effector classes belong to org.si.sion.effector package.

SiON SoundObject's Effector connection arrow diagram

SiON SoundObject's Effector connection arrow diagram

The SiON’s SoundObject brings the simple interactive synthesizers to your flash contents. Enjoy it !

Decrement versus Increment in Loop

Adobe’s “Optimizing Performance for the Flash Platform” recommends that “Use reverse order for while loops” in its “Miscellaneous optimizations” section.

while (--i > -1)

But according to my test significant difference could not be found between decrement and increment. In other language they said that decrement and increment are identical.

The pre-increment/decrement is a little faster than post, which is included in my test, though.

Quaternion notation of Vector3D

The [Help] of the Vecror3D.w property mentions about the quaternion notation as follows:

Quaternion notation employs an angle as the fourth element in its calculation of three-dimensional rotation. The w property can be used to define the angle of rotation about the Vector3D object.

But this sounds like explanation of the axis angle (see Orientation3D .AXIS_ANGLE Constant). The axis angle uses a combination of an axis and an angle to determine the rotation. For an argument of the Matrix3D.decompose() or Matrix3D.recompose() method Orientation3D.AXIS_ANGLE can be specified as the orientation style used for the matrix transformation.

Try to rotate a Matrix3D object 180 degrees (π) around the axis (1/√2, 1/√2, 0).

The axis of rotation

var myMatrix3D:Matrix3D = new Matrix3D();
var axis:Vector3D = new Vector3D(Math.SQRT1_2, Math.SQRT1_2,0);
myMatrix3D.prependRotation(180, axis);
var axisAngle:Vector3D = myMatrix3D.decompose(Orientation3D.AXIS_ANGLE)[1];
trace(axisAngle, axisAngle.w);

The frame action above outputs as follows:

Vector3D(0.7071067094802856, 0.7071068286895752, -2.339619844353034e-24) 3.1415927410125732

[Note]: 0.707… = 1/√2 and 3.14… = π radians = 180 degrees.

The (x, y, z) coordinates represents the axis and Vector3D.w property is an angle of the rotation. This result seems to fit the explanation of the [Help] quoted above.

But the quaternion notation determine the rotation by the four value. The following expression of the quaternion Q represents the rotation of θ around the vector U.

U = (x, y, z) and |U| = 1
Q = (cos(θ/2); sin(θ/2)U)

Then try to rotate a Matrix3D object 60 degrees around the y axis (0, 1, 0).

var myMatrix3D:Matrix3D = new Matrix3D();
myMatrix3D.prependRotation(60, Vector3D.Y_AXIS);
var quaternion:Vector3D = myMatrix3D.decompose(Orientation3D.QUATERNION)[1];
trace(quaternion.w, quaternion);

The frame action above outputs as follows:

0.8660253882408142 Vector3D(0, 0.4999999701976776, 0)

These numbers represent the quaternion of 60 degrees’ rotation.

0.866… = cos(60/2) = cos(30)
(0, 0.5, 0) = sin(60/2) (0, 1, 0)

Return value of Matrix3D.recompose() method

The [Help] of the Matrix3D.recompose() method tells about its return value as follows:

Returns false if any of the scale elements are zero.

But this is not true. Try the code below, in the 7th statement of which the third element, the z coordinate, of the scale Vector3D instance is set to zero.

var myMatrix3D:Matrix3D = new Matrix3D();
trace(myMatrix3D.decompose());
// Output: Vector3D(0, 0, 0),Vector3D(0, 0, 0),Vector3D(1, 1, 1)
var myVector:Vector.<Vector3D> = new Vector.<Vector3D>();
myVector.push(new Vector3D());  // translation
myVector.push(new Vector3D());  // rotation
myVector.push(new Vector3D(1, 1, 0));  // scale
trace(myMatrix3D.recompose(myVector));
// Output: true
trace(myMatrix3D.decompose());
// Output: Vector3D(0, -1.9986319541931152, 0),Vector3D(-1.5707963705062866, NaN, 0),Vector3D(7.667765755019554e-19, -1.998608112335205, 1.9719639421382673e-19)

The method returns true as long as the argument of Vector instance has three Vector3D elements. Therefore, the explanation in the [Help] should be rewritten as follows:

Returns false if any of the Vector3D elements of the Vector instance as the argument don’t exist or are null.

Note: The coordinates of Vector3D elements come to be invalid values if any of the scale elements are zero.

Calculation in the Utils3D.projectVectors() method

The Utils3D.projectVectors() method projects a Vector of three-dimensional space coordinates to a Vector of two-dimensional space coordinates. And the method also sets the t value of the uvt data.

Calculation in the Utils3D.projectVectors() method

Values for the calculation in the Utils3D.projectVectors() method

The Utils3D.projectVectors() method calculates t value of the uvt data by the following formula:

t value = 1 / (Distance to the origin + z coordinate value)

Also, the method calculates projected x and y values by the following formula:

Projected x or y value = Three-dimensional space x or y coordinate * Focal length * t value

The frame action below compares the results of calculation by the formulas above with the methods’. And [Output] is as follows:

0,0,0.0004 // uvt data
0.0004 // Calculated t value
20,20 // Projected x and y coordinates
20 // Calculated two-dimensional space x or y coordinate

var myPerspective:PerspectiveProjection = new PerspectiveProjection();
var myMatrix3D:Matrix3D = new Matrix3D();
var nDistance:Number = 1000;  // Distance to the origin
var nX:Number = 100;  // Three-dimensional space x or y coordinate
var nZ:Number = 1500;  // Three-dimensional z coordinate
var vertices3D:Vector.<Number> = Vector.<Number>([nX, nX, nZ]);
var vertices2D:Vector.<Number> = new Vector.<Number>();
var uvtData:Vector.<Number> = Vector.<Number>([0, 0, 0]);
var nT:Number = 1/(nDistance + nZ);  // t value
myPerspective.focalLength = 500;  // Focal length 
myMatrix3D.appendTranslation(0, 0, nDistance);
myMatrix3D.append(myPerspective.toMatrix3D());
Utils3D.projectVectors(myMatrix3D, vertices3D, vertices2D, uvtData);
trace(uvtData);  // uvt data
trace(nT);  // Calculated t value
trace(vertices2D);  // Projected x and y coordinates
trace(nX * myPerspective.focalLength * nT);  // Calculated two-dimensional space x or y coordinate

iPhone Metronome app built with Flash CS5

simplemetronome_js

I released Simple Metronome app that runs with Package for iPhone technology, CS5’s new feature. I just got permission to talk about the app.

Seems this is the first Flash made iPhone app from Japan.

This app is originally made for technical research, to understand animation speed and interactivity of flash for iPhone. The reason why I made metronome is simply it needs accurate and smooth frame rate. Version 1.00 is minimum implementation, it will be updated step by step.

Some people said that flash is too slow for iPhone, however as far as I see this app, Flash is enough fast for actual project. It may be not for 3d game, but for utility app. Flash CS5 is still under development and I believe it will be much much faster when it is actually shipped.

The biggest advantage of Flash made iPhone app is that you can easily build both iPhone app and online demo. In iPhone app market, many people looking for the way to promote their application, however only flash developer can promote their app with working demo on the web site!!. It’s quite strong feature, isn’t it?

This is sample project and I will make the source code open. It will be available when Flash CS5 is released. :-)

Rotating an instance with the y axis

Try to rotate a MovieClip instance named my_mc 80 degrees with the y axis. The trace() function in the code below displays information in the [Output] panel as follows:

80.00003182368921 1.3962639570236206

var nRotationY:Number = 80;
my_mc.rotationY = 0;
var myMatrix3D:Matrix3D = my_mc.transform.matrix3D;
myMatrix3D.prependRotation(nRotationY, Vector3D.Y_AXIS);
trace(my_mc.rotationY, myMatrix3D.decompose()[1].y);

Rotating an instance 80 degrees

Then change the number of degrees in the variable, nRotationY, to 100. The code seems to rotate an instance 100 degrees. However, the number of degrees shown in the [Output] panel is still 80.

80.00003182368921 1.3962639570236206

var nRotationY:Number = 100;  // 80;
my_mc.rotationY = 0;
var myMatrix3D:Matrix3D = my_mc.transform.matrix3D;
myMatrix3D.prependRotation(nRotationY, Vector3D.Y_AXIS);
trace(my_mc.rotationY, myMatrix3D.decompose()[1].y);

Rotating an instance 100 degrees

The following code reveals the reason.

0 80.00003182368921 0
Vector3D(0, 1.3962639570236206, 0)
180.00000500895632 80.00003182368921 180.00000500895632
Vector3D(3.1415927410125732, 1.3962639570236206, 3.1415927410125732)

var mySprite:Sprite = new Sprite();
var axis:Vector3D = Vector3D.Y_AXIS;  // Vector3D.X_AXIS  // Try to change this
mySprite.rotationY = 0;
var myMatrix3D:Matrix3D = mySprite.transform.matrix3D;
myMatrix3D.prependRotation(80, axis);
xTrace(mySprite);
myMatrix3D.prependRotation(20, axis);
xTrace(mySprite);
function xTrace(targetSprite:Sprite):void {
	trace(targetSprite.rotationX, targetSprite.rotationY, targetSprite.rotationZ);
	trace(targetSprite.transform.matrix3D.decompose()[1]);
}

When the Matrix3D.prependRotation() method rotates an instance 100 degrees with y axis, it is only rotated 80 degrees but is flipped with x and z axes.

The appearance of the instance is all right. But the number of degrees is not good. Besides, 100 degrees can be set with x or z axis. It means that the result of y axis is not consistent. Therefore, I suspect that this is a bug.

Three types of transformation objects in the Transform class

The Transform class has several kinds of transformation objects as its properties.

The Transform class provides access to color adjustment properties and two- or three-dimensional transformation objects that can be applied to a display object.

I noticed three types of properties from the point of view of getting and seting their values.

The first example is the Transform.matrix property. It does not provide its Matrix object reference but its copy. It means that operations to the copy will not affect to the property’s Matrix object. To set a Matrix object to the Transform.matrix property, the object should be assigned to the property.

var mySprite:Sprite = new Sprite();
var myMatrix:Matrix = new Matrix();
mySprite.transform.matrix = myMatrix;
myMatrix.translate(100, 50);
trace(mySprite.transform.matrix);
// Output: (a=1, b=0, c=0, d=1, tx=0, ty=0)
mySprite.transform.matrix = myMatrix;
trace(mySprite.transform.matrix);
// Output: (a=1, b=0, c=0, d=1, tx=100, ty=50)
myMatrix = mySprite.transform.matrix;
myMatrix.scale(2, 1.5);
trace(mySprite.transform.matrix);
// Output: (a=1, b=0, c=0, d=1, tx=100, ty=50)
trace(mySprite.transform.matrix == myMatrix);  // Output: false

The second example is the Transform.matrix3D property. Unlike to the Transform.matrix property, a Matrix3D object’s reference is obtained from the property. Therefore, once its reference is gotten, operations to the reference affects to the Transform.matrix3D property.

var mySprite:Sprite = new Sprite();
var myMatrix3D:Matrix3D = new Matrix3D();
mySprite.transform.matrix3D = myMatrix3D;
myMatrix3D.prependTranslation(100, 50, 0);
trace(mySprite.transform.matrix3D.position);
// Output: Vector3D(100, 50, 0)
trace(mySprite.transform.matrix3D == myMatrix3D);  // Output: true

The third one is the Transform.perspectiveProjection property. When a new PerspectiveProjection instance is assigned to the property, operations to the instance do not affect to the property as well as the Transform.matrix property. Then, try to get the object from the property and set it to a variable again. You can operate the variable as if it was the object reference of the property. However the variable’s object is not evaluated to be equal to the property’s value. It is a mysterious property, isn’t it.

var mySprite:Sprite = new Sprite();
var myPerspective:PerspectiveProjection = new PerspectiveProjection();
mySprite.transform.perspectiveProjection = myPerspective;
myPerspective.fieldOfView = 20;
trace(mySprite.transform.perspectiveProjection.fieldOfView);  // Output: 55
myPerspective = mySprite.transform.perspectiveProjection;
myPerspective.fieldOfView = 100;
trace(mySprite.transform.perspectiveProjection.fieldOfView);  // Output: 100
trace(mySprite.transform.perspectiveProjection == myPerspective);
// Output: false

ActionScript3/Flash10 software synthesizer SiON released

SiON title

Hello all, I’m kei mesuda aka keim japanese free-game home brewer.

I just release completely new software synthesizer named “SiON” (pronounced as “scion”), so let me introduce my work.

The SiON library works on ActionScript3/Flash10. This provides a simple sound synchronization with DisplayObject and an easy dynamic sound generation. You can generate various sounds without any mp3 files and wave data. The musical sequence is represented as simple text data “Music Macro Language”. It makes your sounding SWF file very very small.

This library’s development center is here in spark project. You can get newest version’s swc file, asdoc and svn link.


- Demonstrations

You can use SiON in Wonderfl and I posted some demonstrations.

Other works using SiON are shown in tag [SiON] in Wonderfl. I plan to post some other works with SiON at wonderfl, please check my page if you want more.

And this is another demonstration for SiON. The MMLTalks is an MML hosting service powered by SiON. Here, you can listen many musics generated only by SiON software synthsizer without any mp3 files and wave data.


- Synthesizer specifications

The SiON software synthesizer is an extention of the sound chip YM2151s emulator. Currently, SiON includes 4 types of sound modules.

    • Extended Emulators of various Frequency Modulation synthesizing sound chips; The emulation code is based on the time-proven emulators, MAME, fmgen and x68sound.dll. And the outputs of various sound chips (OPM,OPNA,OPL3,OPX,MA3) are reproducible by giving same parameters of actual equipments.
      • Simulator of PSG and wave memory sound chips; The SiONs Extended FM synth can simulate various PSG chips (AY-3-8910, DCSG, 2A03, SSG) and wave memory sound chips(SCC, C15, GameBoy).
        • Physical Modeling Guitar synthesizer; SiON also includes Guitar Physical modeling synthesizer based on Karplus strong algorism.
          • PCM sound module; The SiON handles MP3 sound (Sound Class) as a PCM sound modules source wave. This means you can control the pitch of MP3 file by musical sequence.

            The SiON can modify the output from these sound modules by low-pass filter with ADSR envelop, ring modulation, pitch/amplitude modulation.


            - Sequencer specifications

            The SiON uses Music Macro Language (MML) as a musical score data. The MML is a simple powerful language to represent musical sequence. For example, “[ccggaag2 ffeeddc2 | [ggffeed2]]” represents “the ABC song” in MML. The reference manual is here, mml editor here, and you can refer MMLs of various great musics here in MMLTalks (and click rightmost button in song title).


            - Effector specifications

            SiON includes many sound effectors like reverb, chorus, delay, wave shaper, various filters, speaker simulator and so on. These effectors can be control from MML. Please see the discriptions in the MML reference manual.

            Now detail discription is under construction, please check my blog or development center. And if you have any questions or comments, please leave comment on this post or contact me by e-mail (but sorry for my poor English..).

            Sequencer specification.
            SiON uses Music Macro Language (MML) as a musical score data. The MML is a simple powerful language to represent musical sequence. For example, “[ccggaag2 ffeeddc2 | [ggffeed2]]” represents “the ABC song” in MML. Reference manual <a href=”http://mmltalks.appspot.com/document/siopm_mml_ref_05.html”>here</a> and you can try to play mml <a href=”http://mmltalks.appspot.com/labo/mmleditor.html”>here</a>.
            This site <a href=”http://mmltalks.appspot.com/”>MMLTalks</a> is the MML hosting service powered by SiON, you can refer many MMLs to represent grate musics.

            Genie effect with as3

            Here is a Mac OSX like Genie effect made with AS3.

            It’s basically made with Flash 10’s drawTriangles API & Yoshihiro Shindo’s betweenAS3 tween library.

            It’s just a initial sketch, but seems there is plenty of possibilities around the new bitmap drawing API.