I would like to change the volume of a soundchannel, instead of turning it off/ starting it from the beginning.
Here is a bit of my code dealing with the soundchannel, musicIcon toggles the sound.
function musicToggle(e:TouchEvent){
if(musicIcon.alpha != 1){
Chn_musicLoop = musicLoop.play(0,int.MAX_VALUE);
//Instead of restarting the music, I would like to set the volume to it's max (1)
musicIcon.alpha *= 2;
}
else{
musicIcon.alpha *= .5;
Chn_musicLoop.stop();
//Instead of stopping the music, I would like to set the volume to 0.
}}
What code would I need to do this?
I believe you are looking for SoundTransform class.
Basically:
var st:SoundTransform = new SoundTransform(0.5, 0);
Chn_musicLoop.soundTransform = st;
The SoundTransform parameter of 0.5 would put your "volume" at halfway. The parameter is a range from 0 to 1.
Here's a reference in AS3 from adobe:
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7d1f.html
Related
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
}
}
im working on as3 adobe flash, the FLA is a catching game and seems to work fine but i want to tweak it. i currently got :
trying to implement random speed per ball, i tried this:
var speed:Number = 7;
var RandomSpeed:Number = Math.random() * 7;
var ymov:Number = RandomSpeed + speed;
and in the function i put this:
bgame[j].y += ymov;
(its [ j ] because i had to make another array to get the ball to drop)
its currently randomising all the balls in the game to the same speed but i want it to do it to individual balls.
there's also one more problem, when the game is finish (once player gets a score of 2 the game takes you back to home screen) the ball sprites that were on the screen and not caught still remain on the screen,
You need to assign different ymov speeds to each ball. As it is now you assign the value at the top level scope, then use it to update each ball's position. This is why they are all the same speed.
You can assign a new random ymov property to each ball in your addBall() function:
bgame[i].ymov = 7 + Math.random() * 7;
Then in your Ballgame() update function move the ball based on that property:
bgame[j].y += bgame[j].ymov;
BTW as a style note, classes usually are UpperCase while variables and functions are lowerCase.
Your issue is that you are only "rolling the dice" once and using that result for the speed of every ball. Make ymov into a function it will produce a different result every time. IE:
function ymov():Number
{
var speed:Number = 7;
var RandomSpeed:Number = Math.random() * 7;
return RandomSpeed + speed;
}
I have animation with 5 frames. I want to make pause for x seconds every time one animation cycle ends
1,2,3,4,5 (pause) 1,2,3,4,5 (pause) ...
Array<AtlasRegion> regions = atlas.findRegions("coin");
animGoldCoin = new Animation(1.0f / 20.0f, regions, PlayMode.LOOP);
I can't find way to do this.
Thanks
I don't really like the animation class, you can make your own.
float pauseTime=5f; // lets say that you want to pause your animation for x seconds after each cicle
float stateTime=0f; // this variable will keep the time, is our timer
float frameTime=1/20f; //amount of time from frame to frame
int frame=0; // your frame index
boolean waiting=false; // where this is true, you wait for that x seconds to pass
void Update()
{
stateTime+=Gdx.graphics.getDeltaTime();
if(!waiting && stateTime>frameTime) // that frame time passed
{
stateTime=0f; // reset our 'timer'
frame++; // increment the frame
}
if(waiting && stateTime>=0)
{
frame=0;
waiting=false;
}
if(frame>=NUMBER_OF_FRAMES)
{
frame--;
waiting=true;
stateTime=-pauseTime;
}
}
}
I think this will work, do you understand what I did?
I just had a similar problem but managed to come up with a solution. It works well for me but may not be the best way to go about it.. I'm still learning.
I created a new animation from the old animation's frames but with a speed of 0. It stops on the frame its at until the player speed changes.
if(speedX == 0f && speedY == 0f){
playerIdle = new Animation(0f,playerAnim.getKeyFrames());
playerAnim = playerIdle;
}
I know its an old question, but hopefully this will be useful to someone.
I made a quick solution in my search to pause a Libgdx animation.
I wanted an animation to pause when I pressed the spacebar.
I did try the above method of instantiating a new object and it did work. So I tried to just set the frame duration to 0, but that didn't work for some reason. This a less expensive method w/o instantiation.
If you want to pause an animation simply create three variables two are Boolean variables named toStop and hasLaunched another is a TextureRegion named launchFrame. Haslaunched is used to tell me when the spacebar is pressed.
if (InputHandler.hasLaunched && toStop ) {
launchFrame = launchBarAnimation.getKeyFrame(runTime);
toStop = false;
} else if (InputHandler.hasLaunched && !toStop){
batcher.draw(launchFrame, 90, 20, 50, 37);
} else {
batcher.draw(launchBarAnimation.getKeyFrame(runTime), 90, 20, 50, 37);
}
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
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.