Set rotation flash tween to shortest distance as3? - actionscript-3

I am working on an adobe air interactive table project and I'm trying to tween some rotations. For the most part it works fine, but occasionally it spins aaall the way around version just spinning a little to the other direction. Does anyone of a good way to prevent this in the flash tweens?
A snippet of my code:
var rotatePos:Number;
if (event.rotation > 180) { rotatePos = event.rotation - 360; } else { rotatePos = event.rotation; }
var rotateDifference:Number = Math.abs(Math.abs(rotatePos) - Math.abs(Number(rotationCurrent[tempCircleNumber])));
if ( rotateDifference > 4 && rotateDifference < 60) {
rotateTheFiducial();
} else if ( rotateDifference > 100 ) {
trace("too far, ignore : " + rotateDifference);
}
function rotateTheFiducial():void
{
try
{
var cardTweenRotation:Tween = new Tween(MovieClip(fiducialArray[tempCircleNumber]), "rotation", Regular.easeOut, Number(rotationCurrent[tempCircleNumber]), rotatePos, .2, true);
rotationCurrent[tempCircleNumber] = rotatePos;
}
catch (e:Error)
{
trace(fiducialId + " : Rotate Error : " + e);
}
}

Regular.easeOut is supposed to perform the above behavior.
Sometimes, while having multiple tweens with easing, flash even misses out the final point.
So if you do have to use easeout, add a tween complete event wherein you set the final point manually.
Else use None.easeNone

You really should avoid using Flash built-in Tween engine. Its slow, bloated, and is lacking a lot of really useful things.
Try using TweenLite/TweenMax or better, eaze that both have built-in functions for short rotations like you are facing.
They are waaaay faster than using the default Tween engine ! (as you can see here)
Not only you will be able to sort that kind of short-rotation problems, but your app will gets faster with one of them :-)

Related

Could somebody help me out by telling me how to convert Actionscript 2 to actionscript3?

I devised a simple game that is at mice using actionscript 3. I do not understand how to change the code of actionscript 2 to actionscript 3, please help me.
Could somebody help me out by telling me how to convert Actionscript 2 to actionscript3 ?
jumlah = 0;
waktu_muncul = 0;
function buat_tikus()
{
nomor = random(3)+1;
tikus=attachMovie("tikus","tikus",2{_x:_root["lingkaran"+nomor]._x,_y:_root["lingkaran"+nomor]._y});
tikus.onEnterFrame = function()
{
waktu_muncul++;
if (waktu_muncul == 0)
{
this.gotoAndStop(4);
}
if (waktu_muncul == 20)
{
removeMovieClip(this);
buat_tikus();
waktu_muncul = 2;
}
tikus.onPress = function()
{
sound1 = new Sound();
sound1.attachSound("Suaratikus");
sound1.start(0,1);
var tikus:MovieClip;
if (jumlah == 90)
{
stop();
nextFrame();
}
if (this._currentframe == 1)
{
jumlah += 10;
this.gotoAndPlay(2);
}
};
};
}
onEnterFrame = function ()
{
fps++;
if (fps == 20)
{
timer_txt--;
fps=0
if (timer_txt==0)
{
stop();
gotoAndStop(6);
}
}
palu.swapDepths(_root.getNextHighestDepth());
palu._x = _xmouse;
palu._y = _ymouse;
};
onMouseDown = function ()
{
if (palu._currentframe == 1)
{
palu.gotoAndPlay(2);
}
};
buat_tikus();
var fps : Number = 0;
var timer_txt : Number = 20;
BotMaster's response to this question is right on the money; not to belabor the point, but I have been in this person's shoes, and I can understand the frustration of migrating from AS2 to AS3. Long term: Learn AS3. Short Term: if you have this game, and somehow you need to make it work ASAP (learning AS3 will take some time), one thing you might try is to create an empty AS3 swf that loads your complete game. That might work (but like I said, long term AS3 is more powerful).
Also, depending on how you created the game, you might try the Google Swiffy extension which might convert some basic AS2 games. Note that it WONT convert as2 to as3 but it might make the game accessible on the web. Best of luck
To be clear on AS2/AS3 conversion. This is not possible, those are 2 different languages and their keywords/global methods/properties/event system/display list, etc ... do not match and for that reason are incompatible. That is why for example there's no tool that exist that can convert in one click of a button a AS2 code to a AS3 code.
There are similarities though in those 2 languages and some pieces of AS2 code can sometimes work as is in AS3, other pieces of code can sometimes be converted quite easily, and of course other pieces of code cannot at all be converted and a new AS3 code has to replace the old AS2 code.
All in all only a translation can be done between the two languages and this has to be done line by line. Evaluating if the line is compatible and if it's not replacing it with something that will work in AS3, etc ...
To add to the difficulty some AS2 projects can have code placed inside symbols all over the place. In that case a translation to AS3 will be very unlikely to achieve.

AS3: repeating function in sigle frame timeline

I'm very new in action script. I have single frame timeline and there is function that moves movie clip verticaly. i want to repeat this only three times.
The code works, I'm just not sure if this is the correct way or if it's too complicated.
var pocet:Number = 0;
pruh.addEventListener(Event.ENTER_FRAME, fl_AnimateVertically);
function fl_AnimateVertically(event:Event)
{
if (pruh.y >= stage.stageHeight) {
pocet++;
}
if (pruh.y < stage.stageHeight) {
pruh.y += 3;
}
else {
pruh.y = 0 - pruh.y;
}
if (pocet == 3) {
pruh.removeEventListener(Event.ENTER_FRAME, fl_AnimateVertically);
}
}
thanx
Congratulations on achieving your goal.
Your code could be improved in terms of readability. You have fl_AnimateVertically as a descriptive name, but other than that it's kind of hard to figure out what's going on exactly. I mean sure it adds 3 to y which probably results in movement, but it's not trivial to understand the exact behaviour.
That's why you want to use abstraction or more of a top down approach as it often called..
What you are doing at the moment is adding a value to the coordinate, which as a result creates an animation. What you actually want is to create an animation, without going into details what that actually means.
And sure enough, people created animations with code before. That's why you can create an animation in the abstract sense: An animation is the change of a property of an object over time. In the realm of flash an animation is called a tween and there's a class doing exactly that..
Let's take the example code there:
var myTween:Tween = new Tween(myObject, "x", Elastic.easeOut, 0, 300, 3, true);
And apply it to your situation.
var verticalAnimation:Tween = new Tween(pruh, "y", Elastic.easeOut, pruh.y, stage.stageHeight, 3, true);
You have to adjust the duration to your liking. I hope you see how this is easier to read and maintain, because you specify properties of the animation like duration. You can also specify easing, which makes the motion more interesting.
Ok, this is only one animation, but you want 3, right?
More precisely, you want to do that same animation again, when it finished.
And you can do exactly that:
var animationCount:uint = 0;
var verticalAnimation:Tween = new Tween(pruh, "y", Elastic.easeOut, pruh.y, stage.stageHeight, 3, true);
verticalAnimation.addEventListener(TweenEvent.MOTION_FINISH, onMotionFinish); // wait for the animation to be finished
function onMotionFinish(e:TweenEvent):void
{
animationCount++; // add 1 to the counter
if(animationCount >= 3) // check how many times the animation finished so far
{
// if it was the last one, remove the listener
verticalAnimation.removeEventListener(TweenEvent.MOTION_FINISH, onMotionFinish);
}
else
{
// otherwise rewind and start again
verticalAnimation.rewind();
verticalAnimation.start();
}
}
There are other libraries than this built in Tween class that are far more powerful.
The one from greensock is very popular and easy to use you can find the documentation for the flash version here
Try this
var pocet:Number = 0;
pruh.addEventListener(Event.ENTER_FRAME, fl_AnimateVertically);
var startY:int=pruh.y;
function fl_AnimateVertically(event:Event)
{
if (pruh.y >= stage.stageHeight) {
pocet++;
pruh.y=startY;
}
if (pruh.y < stage.stageHeight) {
pruh.y += 3;
}
else {
pruh.y = 0 - pruh.y;
}
if (pocet ==3) {
pruh.removeEventListener(Event.ENTER_FRAME, fl_AnimateVertically);
trace("done");
}
}

How do I show the save progress of a FileStream in Flex?

I'm making a simple tool that will let the user eventually save a image to the disk.
To make this, I'm using the FileStream class and its writeBytes() method.
This is working nicelly. The problem occurrs when I tried to show the save progress with a simple mx:ProgressBar. I've tried some approaches, but none seems to work.
Here is the ActionScript piece of code:
private function save(file:File, image:MyImageClass):void {
var data:BitmapData = new BitmapData(width, height, true, 0x000000);
image.draw(data, _cols);
var bytes:ByteArray = new PNGEncoder().encode(data);
fileStream = new FileStream();
fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onProgress);
fileStream.addEventListener(Event.CLOSE, onClose);
try {
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(bytes);
} catch (e:Error) {
Alert.show("Error trying to save the image: " + e.message);
} finally {
fileStream.close();
}
}
private function onProgress(event:OutputProgressEvent):void {
var progressRatio:Number = (1 - (event.bytesPending / event.bytesTotal));
progressBar.setProgress(progressRatio, 1);
trace(progressRatio);
if (event.bytesPending == 0)
event.target.close();
}
private function onClose(event:Event):void {
trace("closed");
}
And the mxml for the progress bar:
<mx:ProgressBar id="progressBar" mode="manual"/>
Executing this I got a frozen interface that is released when the file is totally saved and on the console I get all the traces at the same time. The progress bar stays on 0% until the interface is unfrozed and it goes to 100%.
I know that Flash is single thread, but I thought that the FileStream.openAsync() method should do the dirty work to make my interface responsible. It shouldn't be that hard to do this simple and (I think) common task.
The question is: what I'm doing wrong?
Thanks in advance
How big is the file being saved?
You code seems fine, in terms of saving the file. However, what I suspect is actually taking a long time is encoding the file to PNG format. Unfortunately, the PNGEncoder doesn't dispatch any progress events. But you should check out this project from Lee Burrows, or consider using Actionscript Workers to do the encoding in a different thread.
Quick way to prove it: add trace statements before/after you encode to PNG. Does the big delay correspond to this phase, or to the actual save?
If that doesn't help, please specify how big your file is, and whether you getting 0, 1, or multiple OUTPUT_PROGRESS events.
I agree with Sunil, but I'd like to add a thing or two.
First of all I'd suggest using the new method of the BitmapData class for encoding an image, because it's faster and easier. So your code would change to something like this:
var data:BitmapData = new BitmapData(width, height, true, 0x000000);
image.draw(data, _cols);
var bytes:ByteArray = data.encode(data.rect, new PNGEncoderOptions());
You can track the progress of the writing the file (although I suspect this isn't taking much time, like Sunil said) like this:
bytes.position = 0;
while(bytes.bytesAvailable > 0) {
fileStream.writeByte(bytes.readByte());
trace("progress:", bytes.position / bytes.length * 100); // multiply by 100 for percentage
}
Please note that you'll need a worker for this approach, else the progress will only update visually when the save is done.
Sunil is correct. Writing the file hardly takes a moment. It's decoding the byte array that's blocking the application. I implemented the following code to test it out.
private function save(file:File):void
{
var bytes:ByteArray = new ByteArray();
//233348 - very fast (requires 6000 x 10000 bitmap pixels)
//252790 - very fast (requires 6500 x 10000 bitmap pixels)
//2488990 - need a whole magnitude more of data in order to show the progress messages
for (var i:int = 0; i < 2488990; i++)
{
bytes.writeByte(1);
}
var fileStream:FileStream = new FileStream();
fileStream.addEventListener(OutputProgressEvent.OUTPUT_PROGRESS, onProgress);
fileStream.addEventListener(Event.CLOSE, onClose);
try {
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeBytes(bytes);
} catch (e:Error) {
//Alert.show("Error trying to save the image: " + e.message);
} finally {
fileStream.close();
}
}
You're going to need a progress indicator on the decoding task rather than on the file writing task. Workers seem like the best solution to this, but it depends upon which version of the runtime you need to target.

how to stop / pause geolocation on android

Im experimenting with flashbuilder 4.6 and am using this simple / bare-bones geolocation code I found online to do some testing as I try to learn more about it and how it might be used...
one thing I am curious to know is how to stop / interrupt the geolocation routine so that it STOPS polling for the location and waits for the user to 'start' the geolocation.
if I use clearInterval(interval); that can stop the loop I guess -- but geo2 continues to exist and use device resources, correct? what would the code look like to use a slideToggle to control it for example?
The geolocation code snippet Im experimenting with...
private function onMapReady(e:Event):void
{
if (Geolocation.isSupported)
{
var geo = new Geolocation();
geo.setRequestedUpdateInterval(100);
geo.addEventListener(GeolocationEvent.UPDATE, geolocationUpdateHandler);
}
else
{
trace("No geolocation support.");
}
}
private function geolocationUpdateHandler(event:GeolocationEvent):void
{
trace("lat:" + event.latitude.toString() + " - ");
trace("long:" + event.longitude.toString() + "° - ");
trace("Accuracy:" + event.horizontalAccuracy.toString() + " m");
}
If you want to stop reacting to polling updates, just remove the listener:
geo.removeEventListener(GeolocationEvent.UPDATE, geolocationUpdateHandler);
If you want to switch off polling completely, just nullify it:
geo = null;
(and make sure you also remove any listeners first)

Flash authoring environment strange Test Movie behavior (AS3)

I can't for the life of me figure out why this is happening. Let me describe what I'm experiencing.
I add everything dynamically via actionscript.
In the Flash authoring environment, when I test the movie, sometimes all of the movieclips on stage disappear and all I see is the color of the Stage.
The strange thing is that I can still rollover/rollout (I added trace statements to my rollover/rollout handlers).
I'm also tracing out the 'visible' and the 'alpha' property and visible=true and alpha=1.0 !!!
On thing that I am seeing is sometimes the rollover/rollout methods get called multiple times in quick succession. I.e. the method invocation order is rollover, rollout, rollover or rollout, rollover, rollout.
The actions that I have in my rollover and rollout methods are really simple. All they do is turn on/off other movieclips...imagine a map...when you rollover an icon, a path shows up on the map and when your rolloff, the path goes away.
However, if I adjust the window of the test movie window, everything appears again!
The crazy thing is that when I publish it, this behavior doesn't happen in the browser or as an app!
What's going on? Could it be a memory thing with the authoring environment?
Posting some code here:
private function rollOverUserListener ( e:MouseEvent ) {
trace(">>>>>>>> rollOverUserListener() e.currentTarget.name : " + e.currentTarget.name);
trace("e.currentTarget.alpha: " + e.currentTarget.alpha);
trace("e.currentTarget.visible: " + e.currentTarget.visible);
e.currentTarget.rollOverAction(); //just scales the icon a little
//fade up/down the appropriate path
worldMap.resetPaths(); //turns off all the paths
for (var i=0; i<users.length; i++){
if ( e.currentTarget == users[i] ) { //highlight the right path
worldMap.highlightPath(i);
}
}
}
private function rollOutUserListener ( e:MouseEvent ) {
trace("<<<<<<<< rollOutUserListener() e.currentTarget.name : " + e.currentTarget.name);
e.currentTarget.rollOutAction(); //scales down the icon to normal
worldMap.resetPaths();
}
I don't think it's efficient to try and solve this problem via posting the code you did.
But, my guess is that the difference in behavior that you are seeing is due to the flash player version.
CS5 or whatever version you have of flash, comes with the latest player at that time. But the flash player is constantly being upgraded, so when you are in your browser -- you most likely have the latest flash player. That could account for the differences you are seeing.
However, the code above doesn't help to much without seeing the highlightPaths and resetPaths functions. I see that you have a trace, but right after that -- there's code executed that could potentially easily change the state of anything you traced before rendering the frame.
Stick some traces after that code to see if you get what you expect.
Are you using any libraries that might have features only supported by a newer flash player ?
private function rollOverUserListener ( e:MouseEvent ) {
trace(">>>>>>>> rollOverUserListener() e.currentTarget.name : " + e.currentTarget.name);
trace("e.currentTarget.alpha: " + e.currentTarget.alpha);
trace("e.currentTarget.visible: " + e.currentTarget.visible);
e.currentTarget.rollOverAction(); //just scales the icon a little
//fade up/down the appropriate path
worldMap.resetPaths(); //turns off all the paths
for (var i=0; i<users.length; i++){
if ( e.currentTarget == users[i] ) { //highlight the right path
worldMap.highlightPath(i);
}
}
}
private function rollOutUserListener ( e:MouseEvent ) {
trace("<<<<<<<< rollOutUserListener() e.currentTarget.name : " + e.currentTarget.name);
e.currentTarget.rollOutAction(); //scales down the icon to normal
worldMap.resetPaths();
}