Need info on how to solve a function - function

What am i doing wrong? The program is meant to move a picture of a plane over the screen. The speed of the plane is increasing over time. The stage has a timer that runs the function 10 times per second
private function myTimer(e) {
var speed:int = 0;
plane.x = plane.x + speed
speed = speed + 10
}

You are defining the speed variable inside the function, this causes it to be initialized to 0 on every call, and since you only add to the speed after changing the x of the plane it never moves.
If you move the var speed:int = 0; definition outside of the function the changes will not be overwritten on each call.

Related

How to Adjust Volume in an Audio loop?

How would someone change sound levels of a music playing in a loop? For example, I'm making a game and at a certain frame I want the music level (music.wav) to be decreased to half of its volume.
How could someone do this in AS3?
You are using the word "loop" in a confusing way. In programming, a loop usually refers to one of the "for" loops that looks like this:
for (var i:int = 0; i < 10; i++)
{
//do stuff 10 times
}
I surmise that this is not what you mean by loop, but rather that you would like a MovieClip or the main timeline to decrease the volume of a Sound object at the end of n frames. Or do you just mean the music itself is looping? Hopefully you see the value of asking well written questions. That being said..
Mind you, I haven't tried this, but according to my reference book (ActionScript 3.0 Cookbook by Lott, Schall & Peters) you need to use a SoundTransform object which specifies the volume at which you want the sound to be set. Try this:
var _sound:Sound = new Sound(music.wav); // creates a Sound object which has no internal volume control
var channel:SoundChannel = _sound.play(); // creates a SoundChannel which has a soundTransform property
var transform:SoundTransform = new SoundTransform(); // SoundTransform objects have a property called "volume". This is what you need to change volume.
Now in your loop (or on the frame event that you are using) do this:
transform.volume *= 0.9; // or whatever factor you want to have it decrease
//transform.volume /= 1.1; // or this if you prefer.
channel.soundTransform = transform; //
So anytime you want the volume to decrease by this incremental amount, run this bit of code. Of course, you need to make sure that any variables you set are accessible in the code that is referencing them. One way that comes to mind to do this is with a function.
private function soundDiminish(st:SoundTransform, c:SoundChannel, factor:Number = 0.9):void
{
st.volume *= factor;
c.soundTransform = st;
}
Now, whenever you want to diminish the volume just call the soundDiminish function.
Maybe your frame event looks like this:
function onLoadFrame(fe:Event):void
{
soundDiminish(transform, channel); // 3rd parameter optional
}
If you only want this function to be called every 20 frames then:
function onLoadFrame(fe:Event):void
{
// this is a counter that will count up each time this frame event happens
frameCount ++;
if (frameCount >= 20)
{
soundDiminish(transform, channel); // 3rd parameter optional
frameCount = 0; // reset the frame counter
}
}

AS 3 simple ease

How can I move an object and be able to physically see it when it is moving? Not just disappear and appear on a different location like it would be using the following code.
buttonL2_btn.addEventListener(MouseEvent.CLICK, left);
function left(event:Event):void{
box_mc.x =241.5;
}
This is going to move myObject to any location specified, but again I want to be able to see it when moving.
In your example you are just setting it's X position when some button is pressed, when you need to change X into an EnterFrame event, like this:
this.addEventListener(Event.ENTER_FRAME, move);
function move(event:Event):void{
box_mc.x -= 5
}
Your box_mc should move left 5 pixels accordingly with your framerate.
You can use a easing library to that easily. I strongly recommend TweenMax.
Okay I am getting a bit sick of people constantly suggesting some tweening engine. Sure they rock, but it won't help the OP to understand what he is doing.
Kircho to move an object with a really easy tween I suggest the following code in an onEnterFrame event for your object to move:
addEventListener(Event.ENTER_FRAME, onEnterFrame);
var xGoal:Number = 100; //:: The target X destination for your object
var yGoal:Number = 100; //:: The target Y destination for your object
var smothness:Number = 10; //:: Smoothness factor for movement. The lower the value the faster the movement.
function onEnterFrame(e:Event):void
{
box_mc.x += (xGoal - box_mc.x) / smothness;
box_mc.y += (yGoal - box_mc.y) / smothness;
}
Will move/ease your box object to the desired location with a set smoothness.
You can install any of the 437 available tweening engines
or you can add a few lines of code
set up a variable that holds the destination value
var dest:Number = 241.5; // this is what gets updated on mouse click
on enterframe event for box:
function onBoxEnterFrame(e:MouseEvent):void{
if (dest != box_mc.x){
var easeNum:Number = 0.4 // between 0 and 1, the higher the number, the slower the transition
box_mc.x = box_mc.x * easeNum + dest * (1-easeNum);
}
}
you can add a few more lines to snap the position when it is close (less than 0.1 difference) or use a more linear change where you adjust incrementally like box_mc.x += 5; until it matches the dest number

Faster way to tell if a sprite is near another sprite?

When one of my sprites is being dragged (moved around), I'm cycling through other sprites on the canvas, checking whether they are in range, and if they are, I set a background glow on them. Here is how I'm doing it now:
//Sprite is made somewhere else
public var circle:Sprite;
//Array of 25 sprites
public var sprites:Array;
public function init():void {
circle.addEventListener(MouseEvent.MOUSE_DOWN, startDrag);
}
private function startDrag(event:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, glowNearbySprites);
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrag);
circle.startDrag();
}
private function stopDrag(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, glowNearbySprites);
stage.removeEventListener(MouseEvent.MOUSE_UP, stopDrag);
circle.stopDrag();
}
private function glowNearbySprites(event:MouseEvent):void {
for (var i = 0; i < sprites.length; i++) {
var tSprite = sprites.getItemAt(i) as Sprite;
if (Math.abs(tSprite.x - circle.x) < 30 &&
Math.abs(tSprite.y - circle.y) < 30) {
tSprite.filters = [new GlowFilter(0xFFFFFF)];
}
else {
tSprite.filters = null;
}
}
}
Basically I'm cycling through each sprite every time a MOUSE_MOVE event is triggered. This works fine, but the lag when dragging the sprite around is pretty noticeable. Is there a way to do this that is more efficient, with no or less lag?
Well, depending on the size of the amount of sprites you have, it may be trivial. However, if you're dealing with over 1k sprites -- use a data structure to help you reduce the amount of checks. Look at this QuadTree Demo
Basically you have to create indexes for all the sprites, so that you're not checking against ALL of them. Since your threshold is 30, when a sprite moves, you could place it into a row/column index of int(x / 30), int(y / 30). Then you can check just the sprites that exist in 9 columns around the row/column index of the mouse position.
While this would seem more cumbersome, it actually it way more efficient if you have more items -- the number of checks stays consistent even as you add more sprites. With this method I'm assuming you could run 10k sprites without any hiccup.
Other performance optimizations would be:
use an vector/array of sprites rather than getChildAt
preincrement i (++i)
store a static single instance glowfilter, so it's only one array, rather creating a separate filter for all the sprites.
GlowFilter is pretty CPU intensive. Might make sense to draw all the sprites together in one shot, and then apply GlowFilter once to it -- (this of course depends on how you have things set up -- might even be more cumbersome to blit your own bitmap).
Make your variable declaration var sprite:Sprite = .... If you're not hard typing it, it has to do the "filters" variable lookup by string, and not by the much faster getlex opcode.
I'd incorporate all the improvements that The_asMan suggested. Additionally, this line:
tSprite.filters = [new GlowFilter(0xFFFFFF)];
is probably really bad, since you're just creating the same GlowFilter over and over again, and creating new objects is always expensive (and you're doing this in a for loop every time a mouse_move fires!). Instead create it once when you create this class and assign it to a variable:
var whiteGlow:GlowFilter = new GlowFilter(0xFFFFFF);
...
tSprite.filters = [whiteGlow];
If you're still having performance issues after this, consider only checking half (or even less) of the objects every time you call glowNearbySprites (set some type of flag that will let it know where to continue on the next call (first half of array or second half). You probably won't notice any difference visually, and you should be able to almost double performance.
Attempting to compile the suggestions by others into a solution based on your original code, so far I've created the GlowFilter only once and re-used, secondly I've changed the loop to use a for each instead of the iterant based loop, third I've updated to use ENTER_FRAME event instead of MOUSE_MOVE. The only thing I've left out that's been suggested so far that I see is using a Vector, my knowledge there is pretty much nil so I'm not going to suggest it or attempt until I do some self education. Another Edit
Just changed the declaration of sprites to type Vector no code here for how it's populated but article below says you can basically treat like an Array as it has all the same method implemented but has a couple of caveats you should be aware of, namely that you cannot have empty spots in a Vector and so if that is a possibility you have to declare it with a size. Given it knows the type of the object this probably gets a performance gain from being able to compute the exact position of any element in the array in constant time (sizeOfObject*index + baseOffset = offset of item). The exact performance implications aren't entirely clear but it would seem this will always result in at least as good as Array times if not better.
http://www.mikechambers.com/blog/2008/08/19/using-vectors-in-actionscript-3-and-flash-player-10/
//Array of 25 sprites
public var sprites:Vector.<Sprite>;
private var theGlowFilterArray:Array;
public function init():void
{
theGlowFilterArray = [new GlowFilter(0xFFFFFF)];
circle.addEventListener(MouseEvent.MOUSE_DOWN, startDrag);
}
private function startDrag(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, stopDrag);
addEventListener(Event.ENTER_FRAME, glowNearbySprites);
circle.startDrag();
}
private function stopDrag(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, stopDrag);
removeEventListener(Event.ENTER_FRAME, glowNearbySprites);
circle.stopDrag();
}
private function glowNearbySprites(event:Event):void
{
var circleX:Number = circle.x;
var circleY:Number = circle.y;
for each(var tSprite:Sprite in sprites) {
if (Math.abs(tSprite.x - circleX) < 30 && Math.abs(tSprite.y - circleY) < 30)
tSprite.filters = theGlowFilterArray;
else
tSprite.filters = null;
}
}
You problem is that making calculations that are at least linear O(n) on every mouse change event is terribly inefficient.
One simple heuristic to bring down the amount of times that you make your calculations is to save the distance to the closest sprite and only after mouse moved that distance would you recalculate the potential crash. This can be calculated in constant time O(1).
Notice that this works only when one sprite moves at a time.

AS3 - How much time until next frame / screen draw

I have a generative art app, and I'd like it to draw as many cycles as possible each frame without reducing the framerate. Is there a way to tell how much time is left until the screen updates/refreshes?
I figure if I can approximate how many milliseconds each cycle takes, then I can run cycles until the amount of time left is less than the average or the peak cycle time, then let the screen refresh, then run another set of cycles.
If you want your app to run at N frames per second, then you can draw in a loop for 1/N seconds*, where N is typically the stage framerate (which you can get and set):
import flash.utils.getTimer;
import flash.events.Event;
private var _time_per_frame:uint;
... Somewhere in your main constructor:
stage.frameRate = 30;
_time_per_frame = 1000 / stage.frameRate;
addEventListener(Event.ENTER_FRAME, handle_enter_frame);
...
private function handle_enter_frame(e:Event):void
{
var t0:uint = getTimer();
while (getTimer()-t0 < _time_per_frame) {
// ... draw some stuff
}
}
Note that this is somewhat of a simplification, and may cause a slower resultant framerate than specified by stage.frameRate, because Flash needs some time to perform the rendering in between frames. But if you're blitting (drawing to a Bitmap on screen) as opposed to drawing in vector or adding Shapes to the screen, then I think the above should actually be pretty accurate.
If the code results in slower-than-desired framerates, you could try something as simple as only taking half the allotted time for a frame, leaving the other half for Flash to render:
_time_per_frame = 500 / stage.frameRate;
There are also FPS monitors around that you could use to monitor your framerate while drawing. Google as3 framerate monitor.
Put this code to main object and check - it will trace time between each frame start .
addEventListener(Event.ENTER_FRAME , oef);
var step:Number = 0;
var last:Number = Date.getTime();
function oef(e:Event):void{
var time:Number = Date.getTime();
step = time - last;
last = time;
trace(step);
}

How to make smooth moving using as3?

I have loaded some images through XML and attached into dynamically created MovieClips named mc0,mc1,mc2...etc.
_loader.removeEventListener(ProgressEvent.PROGRESS, onLoadingAction);
count++;
var img:Bitmap = Bitmap(e.target.content);
img.cacheAsBitmap = true;
img.smoothing = true;
img.alpha = 0;
TweenLite.to(MovieClip(my_mc.getChildByName("mc"+count)).addChild(img),1, {alpha:1,ease:Quint.easeIn});
and within ENTER_FRAME handler
for (i=0; i < mc.numChildren; i++)
{
my_mc.getChildAt(i).x -= Math.round((mouseX-stage.stageWidth/2)*.006);
}
Everthing works fine. But it is shaking so that it was not looking good.
How do I achieve smooth movement?
One solution I've used is to round the (x,y) position to the closest integer. No matter that you've added smoothing to your bitmap and cached it, rounding could make it feel less choppy and way smoother.
Another thing you need to be careful is the dimensions of the images. Images that have an odd dimension won't be smoothed the same way as images with even dimensions. Check how to workaround this in my blog post Flash Smoothing Issue.
Since Flash has a variable frame rate (in the sense that it will drop frames), one shouldn't depend on the entering of a frame as a unit of action. Rather, it would be wiser to calculate the elapsed time explicitly.
For instance, in the enter frame handler:
var currentTime:Number = (new Date()).time;
for (i=0; i < mc.numChildren; i++)
{
my_mc.getChildAt(i).x -= speed * (currentTime - lastTime); // speed is in px/ms
}
lastTime = currentTime;
where you have the variable lastTime declared somewhere in a persistent scope:
var lastTime:Number = (new Date()).time;
I don't know if this addresses what you are calling "shaking", but it's at least something to consider.