Audio seek bar control on flash - actionscript-3

I have a scenario , I am developing a audio player and want to write code for audio track seek bar.
Any help is appreciated.

Assuming you have a Sound object and a SoundChannel object to play the Sound object, you can do something like this:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.media.Sound;
import flash.media.SoundChannel;
import flash.net.URLRequest;
public class Main extends Sprite
{
private var _trackBar:Sprite;
private var _sound:Sound;
private var _soundChannel:SoundChannel;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_trackBar = new Sprite();
_trackBar.graphics.beginFill(0);
_trackBar.graphics.drawRect(-10, 0, 20, 40);
_trackBar.graphics.endFill();
addChild(_trackBar);
graphics.lineStyle(2);
graphics.moveTo(_trackBar.x - 10, _trackBar.y);
graphics.lineTo(_trackBar.x - 10, _trackBar.y +_trackBar.height);
graphics.moveTo(_trackBar.x + 200, _trackBar.y);
graphics.lineTo(_trackBar.x + 200, _trackBar.y + _trackBar.height);
_sound = new Sound();
_sound.addEventListener(Event.COMPLETE, onLoaded);
_sound.load(new URLRequest("[mp3 url goes here].mp3"));
}
private function onLoaded(e:Event):void
{
_soundChannel = _sound.play();
stage.addEventListener(Event.ENTER_FRAME, onTick);
_trackBar.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
_trackBar.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
private function onTick(e:Event):void
{
if (!_soundChannel)
{
return;
}
_trackBar.x = 200 * (_soundChannel.position / _sound.length);
}
private function onMouseUp(e:MouseEvent):void
{
_trackBar.stopDrag();
_soundChannel = _sound.play(_sound.length * (_trackBar.x / 200));
}
private function onMouseDown(e:MouseEvent):void
{
_soundChannel.stop();
_soundChannel = null;
_trackBar.startDrag(false, new Rectangle(0, 0, 200, 0));
}
}
}
Please note: this is very rough and can definitely be optimized. It's just something thrown together to show you how you would accomplish such a task.

Related

Correct method of incorporating Starling with Preloader

Hi would like to know the best method of adding a preloader. Then when the content is loaded create an instance of Starling framework. Here is what I have:
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import loaders.Preloader;
import starling.core.Starling;
//main class container
public class Game extends Sprite
{
//preloader class
private var _loader:Preloader;
//starling instance
private var _starling:Starling;
//constructor to initialise game
public function Game():void
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage)
}
private function onAddedToStage(e:Event):void
{
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
_loader = new Preloader();
addChild(_loader);
_loader.addEventListener("loaded_game", onGameLoaded);
}
private function onGameLoaded(e:Event):void
{
trace("game loaded");
_starling = new Starling(Game,stage,null,null,"auto","baseline");
_starling.start();
}
}
This is the Preloader class:
package loaders
{
import flash.events.Event;
import flash.display.Sprite;
import flash.text.TextField;
import flash.text.TextFieldAutoSize;
public class Preloader extends Sprite
{
private var textLoaded:TextField;
public function Preloader()
{
this.addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(event:Event):void
{
// remove added to stage listener
this.removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
textLoaded = new TextField();
textLoaded.x = 300;
textLoaded.y = 300;
textLoaded.border = true;
textLoaded.autoSize = "center";
addChild(textLoaded);
//loop current load state
this.addEventListener(Event.ENTER_FRAME, loadGame);
this.addEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}
private function onRemovedFromStage(event:Event):void {
this.removeEventListener(Event.ENTER_FRAME, loadGame);
this.removeEventListener(Event.REMOVED_FROM_STAGE, onRemovedFromStage);
}
private function loadGame(e:Event):void
{
//vars
var total:Number = parent.stage.loaderInfo.bytesTotal;
var loaded:Number = parent.stage.loaderInfo.bytesLoaded;
textLoaded.text = Math.floor((loaded/total)* 100) + "%";
if (total == loaded)
{
this.removeEventListener(Event.ENTER_FRAME, loadGame);
dispatchEvent(new Event("loaded_game", true));
}
}
}//end of class
}
Is this the best way of doing it or is there a more efficient, practical option? As you can see I am making use of Flash classes before I instantiate Starling? The Preloader is simply a textfield listing what is loaded, this should allow the application to load up faster.
Don't you think that it would make more sense to create an external SWF that preloads your game? It is always a better solution than incorporating a preloader into your main game file.

AS3 Keyboard events

How would one go about adding event listeners for multiple keystrokes, for example if the up and right buttons are pressed player goes diagonally in that direction.
Check out the following code, I store the pressed key in a object and then animated a sprite using the object :
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.KeyboardEvent;
import flash.ui.Keyboard;
public class Main extends Sprite
{
private var _keys:Object = { };
private var _sprite:Sprite = new Sprite;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
_sprite.graphics.beginFill(0xff0000, 1);
_sprite.graphics.drawRect(0, 0, 40, 40);
_sprite.graphics.endFill();
_sprite.x = 100;
_sprite.y = 100;
addChild(_sprite);
stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
stage.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
stage.addEventListener(Event.ENTER_FRAME, onEnterFrame);
}
private function onKeyDown(e:KeyboardEvent):void
{
_keys[e.keyCode] = true;
}
private function onKeyUp(e:KeyboardEvent):void
{
_keys[e.keyCode] = false;
}
private function onEnterFrame(e:Event):void
{
if (_keys[Keyboard.UP])
{
_sprite.y --;
}
if (_keys[Keyboard.DOWN])
{
_sprite.y ++;
}
if (_keys[Keyboard.RIGHT])
{
_sprite.x++;
}
if (_keys[Keyboard.LEFT])
{
_sprite.x--;
}
}
}
}

AS3 Preloader Timing

I did the following
package classes
{
// imports removed
public class Main extends MovieClip {
// vars removed
public function Main():void {
trace('--> Main Function started ...');
/**************************************
Preloader
**************************************/
var preLoader:PreLoader = new PreLoader(); // init
stage.addChild(preLoader); // to Stage
stage.loaderInfo.addEventListener(ProgressEvent.PROGRESS, preLoader.preloaderProgress); // calling the function
doThis();
}
}
With the PreLoader Class looking like this:
package classes {
// imports removed
public class PreLoader extends MovieClip {
public var totalBytes:uint;
public var loadedBytes:uint;
public function PreLoader() {
trace('--> PRELOADER Started ...');
this.addEventListener(Event.ADDED_TO_STAGE, addedHandler);
this.loaderBar.scaleX = 0;
}
private function addedHandler(e:Event):void {
trace('Adding Preloader ...');
totalBytes = this.stage.loaderInfo.bytesTotal;
trace('PL: Total ' + totalBytes + ' / ' + loadedBytes);
this.removeEventListener(Event.ADDED_TO_STAGE, addedHandler);
preloaderProgress(e);
}
public function preloaderProgress(e:Event):void {
trace('Progress...');
loadedBytes = this.stage.loaderInfo.bytesLoaded;
this.loaderBar.scaleX = loadedBytes / totalBytes;
this.loaderBar.alpha = 1 - this.loaderBar.scaleX;
if (totalBytes == loadedBytes) {
trace('Removing PreLoader ...');
this.parent.removeChild(this);
}
}
}
}
The Problem: The Preloader is not displayed BEFORE the inital SWF-file has finished loading. Even all the tracing outputs start when the main movie is finished - i did some profiling on 'slow connections'.
If you wonder: doThis() is loading data from a xml-file, from here everything is fine, tracing outputs are at the right time (but too late at all :D)
Thank you in advance!
Edit: Maybe the question is: Is there a way to determine when the main movie is starting to load?
Make sure that you don't have any content other than the preloader on stage in the first frame. Otherwise all that content will have to load before the preloader starts up.
If you are working in FlashIDE you have to put your preloader into the first frame. If you prefer to use another IDE you should use Frame metatag. Example:
Main.as
package com.sample.preloader
{
import flash.display.Sprite;
import flash.events.Event;
/**
* ...
* #author Author
*/
[Frame(factoryClass="com.sample.preloader.Preloader")]
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
}
}
}
Preloader.as
package com.sample.preloader
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.utils.getDefinitionByName;
/**
* ...
* #author Author
*/
public class Preloader extends MovieClip
{
public function Preloader()
{
if (stage) {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
}
addEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
// TODO show loader
}
private function ioError(e:IOErrorEvent):void
{
trace(e.text);
}
private function progress(e:ProgressEvent):void
{
// TODO update loader
}
private function checkFrame(e:Event):void
{
if (currentFrame == totalFrames)
{
stop();
loadingFinished();
}
}
private function loadingFinished():void
{
removeEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
// TODO hide loader
startup();
}
private function startup():void
{
var mainClass:Class = getDefinitionByName("com.sample.preloader.Main") as Class;
addChild(new mainClass() as DisplayObject);
}
}
}

As3 project with Preloader

I want to use the Preloader provided by FlashDevelop but it does not react as it should.
My loader tells me 100% when no file has been downloaded.
The code should display a trace() containing the percent intermediary but does not
Could you help me?
Mains.as
package
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.net.URLRequest;
[Frame(factoryClass="Preloader")]
public class Main extends Sprite
{
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
// entry point
var imgRequest:URLRequest = new URLRequest("http://next-web.be/actionscript/0.jpg");
var img:Loader = new Loader();
img.load(imgRequest);
addChild(img);
}
}
}
Preloader.as
package
{
import flash.display.DisplayObject;
import flash.display.MovieClip;
import flash.display.StageAlign;
import flash.display.StageScaleMode;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.utils.getDefinitionByName;
import flash.display.Sprite;
public class Preloader extends MovieClip
{
private var bar:Sprite;
public function Preloader()
{
if (stage) {
stage.scaleMode = StageScaleMode.NO_SCALE;
stage.align = StageAlign.TOP_LEFT;
}
addEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioError);
// TODO show loader
bar = new Sprite();
bar.graphics.lineStyle(1, 0x4444ff, 1, true);
bar.graphics.drawRect(0, 0, 100, 6);
bar.x = stage.stageWidth / 2 - bar.width / 2;
bar.y = stage.stageHeight / 2 - bar.height / 2;
addChild(bar);
}
private function ioError(e:IOErrorEvent):void
{
trace(e.text);
}
private function progress(e:ProgressEvent):void
{
// TODO update loader
bar.graphics.lineStyle(0, 0, 0);
bar.graphics.beginFill(0x8888ff);
bar.graphics.drawRect(1, 1, (e.bytesLoaded / e.bytesTotal) * 98 , 4);
bar.graphics.endFill();
trace( "loading:" + (e.bytesLoaded / e.bytesTotal) * 100 );
}
private function checkFrame(e:Event):void
{
if (currentFrame == totalFrames)
{
stop();
loadingFinished();
}
}
private function loadingFinished():void
{
removeEventListener(Event.ENTER_FRAME, checkFrame);
loaderInfo.removeEventListener(ProgressEvent.PROGRESS, progress);
loaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioError);
// TODO hide loader
removeChild(bar);
bar = null;
startup();
//stop();
}
private function startup():void
{
var mainClass:Class = getDefinitionByName("Main") as Class;
addChild(new mainClass() as DisplayObject);
}
}
}
You need to register your listener on the contentLoaderInfo property of the Loader you use to download the data (in your case img.contentLoaderInfo).
In your code, you register progress on loaderInfo, which is a field of your Preloader class (inherited from MovieCLip), and will give you the progress on loading the SWF that contains the Preloader class.
public class Preloader extends MovieClip
{
public function Preloader()
{
// This is wrong.
loaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
// Function `progress` will show the progress of loading your SWF file,
// *not* the JPEG you're loading in class Main.
}
}
You need to register your listener on the contentLoaderInfo property of the Loader you use to download the data (in your case img.contentLoaderInfo).
img.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, progress);
Of course, then it will show only the progress of loading the JPEG file.
You'll also need to either pass the Loader object (or just the contentLoaderLinfo) to the Preloader somehow, or include the event handler in your Main class.
After a continued search, I realized my mistake.
Until now, I always use "loader" but this function does not include my pictures to swf file. So I use a library swc allowing me to generate a complete swf.

AS3 ActionScript 3 - Instantiating Objects With A Timer?

I'm making a vertical (constantly) scrolling shooter & am trying to instantiate objects based on a timer. For example: At 30 seconds, place a building # x, y.
My problem is that the "building" is instantiated when the game starts and then again at the 30 second mark - instead of only # the 30 second mark.
If anyone could steer me in the correct direction, it would be greatly appreciated.
package com.gamecherry.gunslinger
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
import flash.utils.Timer;
import flash.events.TimerEvent;
public class ObjectPlacer extends MovieClip
{
private var Build01Timer:Timer;
private var canPlace:Boolean = true;
private var stageRef:Stage;
private var startX:Number;
private var startY:Number;
private var time:int = 5000;
public function ObjectPlacer(stageRef:Stage) : void
{
this.stageRef = stageRef;
var Build01Timer = new Timer(time, 1);
Build01Timer.addEventListener(TimerEvent.TIMER, placeTimerHandler, false, 0, true);
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
Build01Timer.start();
}
private function loop(e:Event): void
{
if (canPlace)
{
var BuildingsLeft01:BuildingsLeft = new BuildingsLeft(stage, 720, -540);
BuildingsLeft01.scaleX = -1;
stageRef.addChildAt((BuildingsLeft01), 2);
canPlace = false;
}
}
private function placeTimerHandler(e: TimerEvent) : void
{
canPlace = true;
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
Where am I going wrong?
Thank you for looking.
Here's the first of your class:
public class ObjectPlacer extends MovieClip
{
private var Build01Timer:Timer;
**private var canPlace:Boolean = true;**
You're setting it to TRUE at the start, set it to false, and that would solve your problem :)