Increasing and decreasing the volume of a jukebox(Actionscript 3) - actionscript-3

So I've been working on this jukebox assignment for some time now. And I've stumbled upon a problem related to changing the volume of the jukebox while playing the animation.
Here's the code I was trying to use:
var st:SoundTransform = new SoundTransform();
st.volume = 0.3;
SoundMixer.soundTransform = st;
And while this code in itself works perfectly fine, when I try to add it to my script, it has no effect on the volume level. (The code above is not added to the code below, as it didn't work)
Here is my script:
import flash.media.Sound;
import flash.net.URLRequest;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.media.SoundTransform;
//Equalizer
var _sound1 :Sound = null;
var _sound2 :Sound = null;
var _sound3 :Sound = null;
var _sound4 :Sound = null;
var _sound5 :Sound = null;
var _sound6 :Sound = null;
var _sound7 :Sound = null;
var _sound8 :Sound = null;
//Volume
var _soundChannel :SoundChannel = null;
_soundChannel = new SoundChannel();
//Sanger
_sound1 = new Sound(new URLRequest("lyd1.mp3"));
_sound2 = new Sound(new URLRequest("lyd2.mp3"));
_sound3 = new Sound(new URLRequest("lyd3.mp3"));
_sound4 = new Sound(new URLRequest("lyd4.mp3"));
_sound5 = new Sound(new URLRequest("lyd5.mp3"));
_sound6 = new Sound(new URLRequest("lyd6.mp3"));
_sound7 = new Sound(new URLRequest("lyd7.mp3"));
_sound8 = new Sound(new URLRequest("lyd8.mp3"));
//Spille sanger
knapp1.addEventListener(MouseEvent.CLICK, spill1);
knapp2.addEventListener(MouseEvent.CLICK, spill2);
knapp3.addEventListener(MouseEvent.CLICK, spill3);
knapp4.addEventListener(MouseEvent.CLICK, spill4);
knapp5.addEventListener(MouseEvent.CLICK, spill5);
knapp6.addEventListener(MouseEvent.CLICK, spill6);
knapp7.addEventListener(MouseEvent.CLICK, spill7);
knapp8.addEventListener(MouseEvent.CLICK, spill8);
function spill1(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound1.play();
skjermTekst.text = "Miami Nights - Ocean Drive";
}
function spill2(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound2.play();
skjermTekst.text = "Likelike - So Electric";
}
function spill3(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound3.play();
skjermTekst.text = "LazerHawk - Disco Planet";
}
function spill4(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound4.play();
skjermTekst.text = "Garth Knight - Silent Strike";
}
function spill5(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound5.play();
skjermTekst.text = "Mitch Murder - Terminator Theme";
}
function spill6(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound6.play();
skjermTekst.text = "Dynatron - Stars of the Night";
}
function spill7(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound7.play();
skjermTekst.text = "Electric Youth - The Best Thing";
}
function spill8(event:MouseEvent)
{
SoundMixer.stopAll();
_soundChannel = _sound8.play();
skjermTekst.text = "Borgeoisie - Neon Black";
}
//Equalizer
addEventListener(Event.ENTER_FRAME, Update, false, 0, true)
function Update($e:Event):void
{
_equalizer._eq1.gotoAndStop (Math.round(_soundChannel.leftPeak * 3) );
_equalizer._eq2.gotoAndStop (Math.round(_soundChannel.rightPeak * 5) );
_equalizer._eq3.gotoAndStop (Math.round(_soundChannel.leftPeak * 7) );
_equalizer._eq4.gotoAndStop (Math.round(_soundChannel.rightPeak * 9) );
_equalizer._eq5.gotoAndStop (Math.round(_soundChannel.leftPeak * 11) );
_equalizer._eq6.gotoAndStop (Math.round(_soundChannel.rightPeak * 13) );
_equalizer._eq7.gotoAndStop (Math.round(_soundChannel.leftPeak * 15) );
_equalizer._eq8.gotoAndStop (Math.round(_soundChannel.rightPeak * 17) );
_equalizer._eq9.gotoAndStop (Math.round(_soundChannel.leftPeak * 17) );
_equalizer._eq10.gotoAndStop (Math.round(_soundChannel.rightPeak * 15) );
_equalizer._eq11.gotoAndStop (Math.round(_soundChannel.leftPeak * 13) );
_equalizer._eq12.gotoAndStop (Math.round(_soundChannel.rightPeak * 11) );
_equalizer._eq13.gotoAndStop (Math.round(_soundChannel.leftPeak * 9) );
_equalizer._eq14.gotoAndStop (Math.round(_soundChannel.rightPeak * 7) );
_equalizer._eq15.gotoAndStop (Math.round(_soundChannel.leftPeak * 5) );
_equalizer._eq16.gotoAndStop (Math.round(_soundChannel.rightPeak * 3) );
}
Now, with the volume snippet added the volume of the jukebox stays the same. Even if I change the st.volume = 0.3 to any other number between 0 and 1.

You could optimise your code greatly, and for this task you don't need SoundMixer, your sounds and SoundChannels are easily accessible. Main idea is to manage one at time SoundChannel:
const soundKey:String = "sound";
const soundNameKey:String = "soundName";
var sounds:Dictionary = new Dictionary();
var mainChannel:SoundChannel;
var volume:SoundTransform = new SoundTransform(1);
//"Bind" your buttons to the corresponding Sound description
sounds[knapp1] = {"sound": new Sound(new URLRequest("path")), "soundName": "Miami Nights - Ocean Drive"};
//Add all your sounds
//sounds[knapp8] = ...;
//Add all knapp buttons to the one container
//myKnappContainer.addChild(knapp1); ...
myKnappContainer.addEventListener(MouseEvent.CLICK, onClick);
function onClick(e:MouseEvent):void {
var soundInfo:Object = sounds[e.target];
if (soundInfo != null) {
if (mainChannel != null) {
//Stop previous sound
mainChannel.stop();
}
//Start a new
mainChannel = Sound(soundInfo[soundKey]).play();
//Apply current volume
mainChannel.soundTransform = volume;
//Display sound name
skjermTekst.text = soundInfo[soundNameKey];
}
}

Related

"is MovieClip" is true, yet compiler insists it is not and throws Error #1034: Type Coercion failed? (AS3)

I have in my library, various food icons converted and linked as MovieClips which i add to the scene dynamically. I'm trying to move them from one container to another. Containers are also dynamically added MovieClips.
I've been trying to move these icons who are "MovieClip extended class" instances to another MovieClip as child, by drag and drop, yet currentTarget in drop(it is fine in drag) is not recognised as MovieClip even with "currentTarget as MovieClip" and compiler throws error. Every trace indicates that it is indeed a MovieClip though. I'm at my wits end.
The "plate.addChild(mc);" is causing the error during dropping into the "plate" from "shelves".
The .fla file: https://1drv.ms/u/s!ApqQOqYhGvWHget1A4YRqyzT3a9BEQ?e=9UJB0R
import flash.display.Sprite;
import flash.display.MovieClip;
/*;
choValues = {
"apple": 15,
"bakedBeans": 15,
"chickenLeg": 0,
"chickenNuggets": 15,
"cornOnTheCob": 15,
"egg": 0,
"grapes": 5,
"hamburger": 30,
"milkFull": 24,
"juiceFull": 30,
"juiceHalf": 15,
"saltineCrackers": 5,
"orange": 15,
"tomato": 5
}*/
var foodNames:Array = new Array();
var choValues:Array = new Array();
var options:Array = new Array();
var index:Array = new Array();
var shelves:MovieClip = new Shelves();
var plate:MovieClip = new Plate();
var plateSlots:Array = [0,0,0,0];
var iconSize:Array = new Array();
trace(stage.stageWidth);
trace(stage.stageHeight);
var relativeWidth:Number = stage.stageWidth/32;
var relativeHeight:Number = stage.stageHeight/32;
trace("shelves");
trace(shelves.x = relativeWidth*4 );
trace(shelves.y = relativeHeight*8);
trace(shelves.width = relativeWidth*10);
trace(shelves.height = relativeHeight*14);
stage.addChildAt(shelves,1);
trace("plate");
plate.instanceName = "plate";
trace(plate.x = relativeWidth*15 );
trace(plate.y = relativeHeight*8);
trace(plate.width = relativeWidth*10);
trace(plate.height = relativeHeight*14);
plate.name = "plate";
stage.addChildAt(plate,0);
trace("plate.name "+ plate.name);
/*var fruit = new orange;
trace("fruit");
trace(fruit.x = plate.width/2);
trace(fruit.y = plate.height/2);
//trace(plateSlots.width = plate.width/2);
//trace(plateSlots.height = plate.height/2);*/
//plate.addChild(fruit);
function drag (e:MouseEvent):void //find the slot
{
e.currentTarget.startDrag();
trace("drag "+e.currentTarget.name);
trace("Classname "+ getQualifiedClassName(e.currentTarget));
}
function drop (e:MouseEvent):void
{
e.currentTarget.stopDrag();
trace("drop Classname "+ getQualifiedClassName(e.currentTarget));
trace("drop name "+ (e.currentTarget.name));
//if(e.currentTarget.dropTarget !=null)
//if(e.currentTarget.dropTarget.parent !=null)
//if(e.currentTarget.dropTarget.parent.parent != null)
try{if (e.currentTarget.dropTarget.parent.parent.name == "plate")
{
trace("currentTarget is "+e.currentTarget);
var mc:MovieClip = MovieClip(e.currentTarget);
trace(mc);
trace("mc is movieClip?" + (mc is MovieClip));
trace("is plate");
for (var i=0; i<4; i++)
{
if (plateSlots[i] == 0)
{
trace(mc);
//shelves.removeChild(mc);
plate.addChild(mc);
//e.currentTarget.width = iconSize[0];
//e.currentTarget.height = iconSize[1];
trace(mc.x = plate.width/6 + ((i%2)*plate.width/8));
trace(mc.y = plate.height/6 + ((i<2 ? 0:1)*plate.height/4));
plateSlots[i] = 1;
mc.slot = i;
return;
}
}
}
else{
shelves.addChild(e.currentTarget as MovieClip);
e.currentTarget.x = e.currentTarget.oldX;
e.currentTarget.y = e.currentTarget.oldY;
}
}
catch(e:Error){}
shelves.addChild(e.currentTarget as MovieClip);
e.currentTarget.x = e.currentTarget.oldX;
e.currentTarget.y = e.currentTarget.oldY;
}
function randomize ( a : *, b : * ) : int {
return ( Math.random() > .5 ) ? 1 : -1;
}
foodNames.push(
"apple","bakedBeans","chickenLeg",
"chickenNuggets","cornOnTheCob","egg",
"grapes","hamburger","milkFull",
"juiceFull","juiceHalf","saltineCrackers",
"orange","tomato"
)
choValues.push(
15,15,0,
15,15,0,
5,30,24,
30,15,5,
15,5
)
for (var i:int=1; i<foodNames.length; i++)
{
index.push(i);
}
index.sort(randomize);
trace(index);
for(i=0; i<8; i++)
{
options[index[i]] = new (getDefinitionByName(foodNames[index[i]]));
trace("class "+getDefinitionByName(foodNames[index[i]]));
options[index[i]].addEventListener(MouseEvent.MOUSE_DOWN, drag);
options[index[i]].addEventListener(MouseEvent.MOUSE_UP, drop);
options[index[i]].CHO = choValues[i];
options[index[i]].x += ( (2*(i%4)) +1 ) *(shelves.width /10);
options[index[i]].y = ( ( i<4 ) ? 17 : 37 )*(shelves.height/64);
options[index[i]].oldX = options[index[i]].x;
options[index[i]].oldY = options[index[i]].y;
shelves.addChild(options[index[i]]);
}
//iconSize[0] = options[index[0]].width;
//iconSize[1] = options[index[0]].height;
stop();

How to scale GraphicsPathCommand data?

Context: For a legacy Flex/Actionscript drawing app, I need to add scaling of simple symbols. The app uses the Graffiti lib for drawing and the resulting shape data is stored as GraphicsPathCommands serialized to XML using the Degrafa lib for save and reload. I need to enable the user to scale these graphics and then get updated path data which can be serialized. The symbols are simple but more complicated than simple geometry. For example:
Question: I converted the SVG data for this symbol to Actionscript GraphicsPathCommands and am able to draw it, and of course translation is easy – but I don't know how I would scale it, given a bounding box defined by a user dragging out a marquee rectangle in the app.
Does anyone know of either an Actionscript way of transforming the command data, or a Javascript snippet for scaling SVG which I can port to Actionscript?
For reference, an example of the Actionscript GraphicsPathCommands for drawing a star is below.
public function DrawPathExample()
{
var star_commands:Vector.<int> = new Vector.<int>(5, true);
star_commands[0] = GraphicsPathCommand.MOVE_TO;
star_commands[1] = GraphicsPathCommand.LINE_TO;
star_commands[2] = GraphicsPathCommand.LINE_TO;
star_commands[3] = GraphicsPathCommand.LINE_TO;
star_commands[4] = GraphicsPathCommand.LINE_TO;
var star_coord:Vector.<Number> = new Vector.<Number>(10, true);
star_coord[0] = 66; //x
star_coord[1] = 10; //y
star_coord[2] = 23;
star_coord[3] = 127;
star_coord[4] = 122;
star_coord[5] = 50;
star_coord[6] = 10;
star_coord[7] = 49;
star_coord[8] = 109;
star_coord[9] = 127;
graphics.beginFill(0x003366);
graphics.drawPath(star_commands, star_coord);
}
Solution
A full solution for interactively scaling GraphicsPathCommand data is below. The path data was derived from an SVG put through this SVGParser. It generates path drawing commands in the form of graphics.lineTo(28.4,16.8);. A couple of utility functions separate the data from the commands and store them in Vectors so the data can be serialized. I don't need to use arbitrary SWGs so I just hardcoded the data.
package classes
{
import flash.display.GraphicsPathCommand;
import flash.display.Shape;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.geom.Rectangle;
public class DrawSVG extends Sprite
{
private var startPt:Point = new Point();
private var selectRect:Rectangle = new Rectangle();
private var viewBox:Rectangle = new Rectangle();
protected var commands:Vector.<int> = new Vector.<int>();
protected var drawingData:Vector.<Number> = new Vector.<Number>();
protected var sourceDrawingData:Vector.<Number> = new Vector.<Number>();
public function DrawSVG()
{
super();
this.addEventListener(Event.ADDED_TO_STAGE, setup);
setupWomanData();
}
private function setup(event:Event):void
{
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
private function onMouseDown(event:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
this.graphics.clear();
// offset so graphic draws centered on click point
startPt = new Point(event.stageX - (viewBox.width /2), event.stageY - (viewBox.height /2));
selectRect = new Rectangle(startPt.x, startPt.y, viewBox.width, viewBox.height);
var kx:Number = selectRect.width / (viewBox.width);
var ky:Number = selectRect.height / (viewBox.height);
var scaleFactor:Number = kx < ky ? kx : ky;
drawSymbol(scaleFactor);
this.graphics.lineStyle(1, 0x000000);
this.graphics.drawRect(selectRect.x, selectRect.y, selectRect.width, selectRect.height);
}
private function onMouseMove(event:MouseEvent):void
{
selectRect.width = Math.max(viewBox.width, Math.abs(event.stageX - startPt.x));
selectRect.height = Math.max(viewBox.height, Math.abs(event.stageY - startPt.y));
var kx:Number = selectRect.width / (viewBox.width);
var ky:Number = selectRect.height / (viewBox.height);
var scaleFactor:Number = kx < ky ? kx : ky;
this.graphics.clear();
drawSymbol(scaleFactor);
this.graphics.lineStyle(1, 0x000000);
this.graphics.drawRect(selectRect.x, selectRect.y, viewBox.width * scaleFactor, viewBox.height * scaleFactor);
}
private function onMouseUp(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
this.graphics.clear();
createSprite(commands, drawingData);
}
private function drawSymbol(toScale:Number):void
{
drawingData.length = 0;
for (var i:int = 0; i < sourceDrawingData.length; i++) {
drawingData[i] = Math.max(sourceDrawingData[i], sourceDrawingData[i] * toScale);
drawingData[i] += i % 2 == 0 ? startPt.x : startPt.y ;
}
this.graphics.clear();
this.graphics.lineStyle();
this.graphics.beginFill(0xff0000);
this.graphics.drawPath(commands, drawingData);
this.graphics.endFill();
}
private function createSprite(command:Vector.<int>, coord:Vector.<Number>):Shape{
var s:Shape = new Shape();
addChild(s);
s.graphics.beginFill(0xff);
s.graphics.drawPath(command, coord);
s.graphics.endFill();
return s;
}
private function setupWomanData():void
{
commands = new Vector.<int>();
drawingData = new Vector.<Number>();
viewBox= new Rectangle(0, 0, 24.629, 52.336);
addMoveToCmd(12.31,10.3);
addCurveToCmd(13.37,10.3,14.3,9.89);
addCurveToCmd(15.24,9.48,15.94,8.78);
addCurveToCmd(16.64,8.08,17.05,7.14);
addCurveToCmd(17.46,6.2,17.46,5.15);
addCurveToCmd(17.46,4.1,17.05,3.16);
addCurveToCmd(16.64,2.23,15.94,1.52);
addCurveToCmd(15.24,0.82,14.3,0.41);
addCurveToCmd(13.37,0,12.31,0);
addCurveToCmd(11.26,0,10.33,0.41);
addCurveToCmd(9.39,0.82,8.69,1.52);
addCurveToCmd(7.98,2.23,7.57,3.16);
addCurveToCmd(7.16,4.1,7.16,5.15);
addCurveToCmd(7.16,6.2,7.57,7.14);
addCurveToCmd(7.98,8.08,8.69,8.78);
addCurveToCmd(9.39,9.48,10.33,9.89);
addCurveToCmd(11.26,10.3,12.31,10.3);
addLineToCmd(12.314,10.304);
addMoveToCmd(24.6,26.36);
addLineToCmd(20.7,12.77);
addCurveToCmd(20.62,12.3,20.39,11.91);
addCurveToCmd(20.15,11.51,19.81,11.23);
addCurveToCmd(19.47,10.94,19.04,10.78);
addCurveToCmd(18.61,10.62,18.14,10.62);
addLineToCmd(6.49,10.62);
addCurveToCmd(6.02,10.62,5.59,10.78);
addCurveToCmd(5.16,10.94,4.82,11.23);
addCurveToCmd(4.48,11.51,4.24,11.91);
addCurveToCmd(4.01,12.3,3.93,12.77);
addLineToCmd(0.03,26.36);
addCurveToCmd(0.01,26.4,0.01,26.45);
addCurveToCmd(-0.01,26.5,-0.01,26.55);
addCurveToCmd(0.01,26.6,0.01,26.65);
addCurveToCmd(0.02,26.69,0.03,26.74);
addCurveToCmd(-0.15,27.95,0.55,28.69);
addCurveToCmd(1.25,29.44,2.2,29.6);
addCurveToCmd(3.15,29.77,4.05,29.3);
addCurveToCmd(4.95,28.84,5.17,27.63);
addLineToCmd(6.85,21.37);
addLineToCmd(4.07,34.88);
addCurveToCmd(3.81,35.51,3.91,36.15);
addCurveToCmd(4,36.78,4.35,37.3);
addCurveToCmd(4.7,37.81,5.26,38.13);
addCurveToCmd(5.81,38.45,6.49,38.45);
addLineToCmd(6.78,38.45);
addLineToCmd(6.78,49.72);
addCurveToCmd(6.78,50.99,7.59,51.62);
addCurveToCmd(8.41,52.25,9.39,52.25);
addCurveToCmd(10.37,52.25,11.19,51.62);
addCurveToCmd(12,50.99,12,49.72);
addLineToCmd(12,38.45);
addLineToCmd(12.63,38.45);
addLineToCmd(12.63,49.72);
addCurveToCmd(12.63,50.99,13.44,51.62);
addCurveToCmd(14.26,52.25,15.24,52.25);
addCurveToCmd(16.22,52.25,17.04,51.62);
addCurveToCmd(17.85,50.99,17.85,49.72);
addLineToCmd(17.85,38.45);
addLineToCmd(18.14,38.45);
addCurveToCmd(18.82,38.45,19.38,38.13);
addCurveToCmd(19.93,37.81,20.28,37.3);
addCurveToCmd(20.63,36.78,20.72,36.14);
addCurveToCmd(20.81,35.51,20.56,34.87);
addLineToCmd(17.78,21.37);
addLineToCmd(19.45,27.58);
addCurveToCmd(19.67,28.79,20.57,29.27);
addCurveToCmd(21.47,29.75,22.43,29.6);
addCurveToCmd(23.38,29.45,24.08,28.7);
addCurveToCmd(24.78,27.96,24.6,26.74);
addCurveToCmd(24.61,26.69,24.62,26.65);
addCurveToCmd(24.63,26.6,24.63,26.55);
addCurveToCmd(24.63,26.5,24.62,26.45);
addCurveToCmd(24.62,26.4,24.6,26.36);
addLineToCmd(24.601,26.356);
}
protected function addCurveToCmd(p1:Number, p2:Number, p3:Number, p4:Number):void
{
commands.push(GraphicsPathCommand.CURVE_TO);
sourceDrawingData.push(p1);
sourceDrawingData.push(p2);
sourceDrawingData.push(p3);
sourceDrawingData.push(p4);
}
protected function addMoveToCmd(p1:Number, p2:Number):void
{
commands.push(GraphicsPathCommand.MOVE_TO);
sourceDrawingData.push(p1);
sourceDrawingData.push(p2);
}
protected function addLineToCmd(p1:Number, p2:Number):void
{
commands.push(GraphicsPathCommand.LINE_TO);
sourceDrawingData.push(p1);
sourceDrawingData.push(p2);
}
}
}
Seems like there is a pretty straightforward way to do this. It looks like the only thing to scale are the coordinates themselves, so you may just apply a scale factor.
Based on your example:
public function ASEntryPoint() {
var star_commands:Vector.<int> = new Vector.<int>(5, true);
star_commands[0] = GraphicsPathCommand.MOVE_TO;
star_commands[1] = GraphicsPathCommand.LINE_TO;
star_commands[2] = GraphicsPathCommand.LINE_TO;
star_commands[3] = GraphicsPathCommand.LINE_TO;
star_commands[4] = GraphicsPathCommand.LINE_TO;
var star_coord:Vector.<Number> = new Vector.<Number>(10, true);
star_coord[0] = 66; //x
star_coord[1] = 10; //y
star_coord[2] = 23;
star_coord[3] = 127;
star_coord[4] = 122;
star_coord[5] = 50;
star_coord[6] = 10;
star_coord[7] = 49;
star_coord[8] = 109;
star_coord[9] = 127;
//reference shape to detect initial size
var s:Shape = shapeInRect(star_commands, star_coord);
var bounds:Rectangle = s.getBounds(s);
s.graphics.lineStyle(1);
s.graphics.drawRect(bounds.x, bounds.y, bounds.width, bounds.height);
addChild(s);
//fit to target
var targetSize:Rectangle = new Rectangle(150, 100, 75, 60);
//detect lesser factor - assuming you need to preserve proportions
var kx:Number = targetSize.width / (bounds.width);
var ky:Number = targetSize.height / (bounds.height);
var toUse:Number = kx < ky ? kx : ky;
//apply to coords
for (var i:int = 0; i < star_coord.length; i++) {
//size
star_coord[i] *= toUse;
//fix initial offset
star_coord[i] -= i % 2 == 0 ? bounds.x * toUse : bounds.y * toUse;
}
//draw
addChild(shapeInRect(star_commands, star_coord, targetSize));
}
private function shapeInRect(command:Vector.<int>, coord:Vector.<Number>, rect:Rectangle = null):Shape{
var s:Shape = new Shape();
addChild(s);
s.graphics.beginFill(0x003366);
s.graphics.drawPath(command, coord);
s.graphics.endFill();
if (rect){
s.graphics.lineStyle(1);
s.graphics.drawRect(0, 0, rect.width, rect.height);
s.x = rect.x;
s.y = rect.y;
}
return s;
}

User interaction with Leapmotion AS3 library

I can connect the device and attach a custom cursor to one finger, but I can´t use any of the gestures to over/click a button or drag a sprite around, etc.
I´m using Starling in the project. To run this sample just create a Main.as, setup it with Starling and call this class.
My basic code:
package
{
import com.leapmotion.leap.Controller;
import com.leapmotion.leap.events.LeapEvent;
import com.leapmotion.leap.Finger;
import com.leapmotion.leap.Frame;
import com.leapmotion.leap.Gesture;
import com.leapmotion.leap.Hand;
import com.leapmotion.leap.InteractionBox;
import com.leapmotion.leap.Pointable;
import com.leapmotion.leap.ScreenTapGesture;
import com.leapmotion.leap.Vector3;
import starling.display.Shape;
import starling.display.Sprite;
import starling.events.Event;
import starling.events.TouchEvent;
/**
* ...
* #author miau
*/
public class LeapController extends Sprite
{
private var _controller:Controller;
private var _cursor:Shape;
private var _screenTap:ScreenTapGesture;
private var _displayWidth:uint = 800;
private var _displayHeight:uint = 600;
public function LeapController()
{
addEventListener(Event.ADDED_TO_STAGE, _startController);
}
private function _startController(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, _startController);
//adding controller
_controller = new Controller();
_controller.addEventListener( LeapEvent.LEAPMOTION_INIT, onInit );
_controller.addEventListener( LeapEvent.LEAPMOTION_CONNECTED, onConnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_DISCONNECTED, onDisconnect );
_controller.addEventListener( LeapEvent.LEAPMOTION_EXIT, onExit );
_controller.addEventListener( LeapEvent.LEAPMOTION_FRAME, onFrame );
//add test button
_testButton.x = stage.stageWidth / 2 - _testButton.width / 2;
_testButton.y = stage.stageHeight / 2 - _testButton.height / 2;
addChild(_testButton);
_testButton.touchable = true;
_testButton.addEventListener(TouchEvent.TOUCH, doSomething);
//draw ellipse as a cursor
_cursor = new Shape();
_cursor.graphics.lineStyle(6, 0xFFE24F);
_cursor.graphics.drawEllipse(0, 0, 80, 80);
addChild(_cursor);
}
private function onFrame(e:LeapEvent):void
{
trace("ON FRAME STARTED");
var frame:Frame = e.frame;
var interactionBox:InteractionBox = frame.interactionBox;
// Get the first hand
if(frame.hands.length > 0){
var hand:Hand = frame.hands[0];
var numpointables:int = e.frame.pointables.length;
var pointablesArray:Array = new Array();
if(frame.pointables.length > 0 && frame.pointables.length < 2){
//trace("number of pointables: "+frame.pointables[0]);
for(var j:int = 0; j < frame.pointables.length; j++){
//var pointer:DisplayObject = pointablesArray[j];
if(j < numpointables){
var pointable:Pointable = frame.pointables[j];
var normal:Vector3 = pointable.tipPosition;
var normalized:Vector3 = interactionBox.normalizePoint(normal);
//pointable.isFinger = true;
_cursor.x = normalized.x * _displayWidth;
_cursor.y = _displayHeight - (normalized.y * _displayHeight);
_cursor.visible = true;
}else if (j == 0) {
_cursor.visible = false;
}
}
}
}
}
private function onExit(e:LeapEvent):void
{
trace("ON EXIT STARTED");
}
private function onDisconnect(e:LeapEvent):void
{
trace("ON DISCONNECT STARTED");
}
private function onConnect(e:LeapEvent):void
{
trace("ON CONNECT STARTED");
_controller.enableGesture( Gesture.TYPE_SWIPE );
_controller.enableGesture( Gesture.TYPE_CIRCLE );
_controller.enableGesture( Gesture.TYPE_SCREEN_TAP );
_controller.enableGesture( Gesture.TYPE_KEY_TAP );
}
private function onInit(e:LeapEvent):void
{
trace("ON INIT STARTED");
}
private function doSomething(e:TouchEvent):void
{
trace("I WAS TOUCHED!!!");
}
}
}
If a good code Samaritan can update this code to perform a screen tap gesture (or any interacion with any object), I will really appreciate this a lot.
Regards!
controller.enableGesture(Gesture.TYPE_SWIPE);
controller.enableGesture(Gesture.TYPE_SCREEN_TAP);
if(controller.config().setFloat("Gesture.Swipe.MinLength", 200.0) && controller.config().setFloat("Gesture.Swipe.MinVelocity", 500)) controller.config().save();
if(controller.config().setFloat("Gesture.ScreenTap.MinForwardVelocity", 30.0) && controller.config().setFloat("Gesture.ScreenTap.HistorySeconds", .5) && controller.config().setFloat("Gesture.ScreenTap.MinDistance", 1.0)) controller.config().save();
//etc...
Then catch it in the frame event listener:
private function onFrame( event:LeapEvent ):void
{
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
for ( var i:int = 0; i < gestures.length; i++ )
{
var gesture:Gesture = gestures[ i ];
switch ( gesture.type )
{
case Gesture.TYPE_SCREEN_TAP:
var screentap:ScreenTapGesture = ScreenTapGesture ( gesture);
trace ("ScreenTapGesture-> x: " + Math.round(screentap.position.x ) + ", y: "+ Math.round( screentap.position.y));
break;
case Gesture.TYPE_SWIPE:
var screenSwipe:SwipeGesture = SwipeGesture(gesture);
if(gesture.state == Gesture.STATE_START) {
//
}
else if(gesture.state == Gesture.STATE_STOP) {
//
trace("SwipeGesture-> direction: "+screenSwipe.direction + ", duration: " + screenSwipe.duration);
}
break;
default:
trace( "Unknown gesture type." )
}
}
}
When the event occurs, check the coordinates translated to the stage/screen and whether a hit test returns true.
EDIT: Considering I have no idea how to reliable get the touch point x/y (or better: how to translate them to the correct screen coordinates), I would probably do something like this in my onFrame event:
private function onFrame(event:LeapEvent):void {
var frame:Frame = event.frame;
var gestures:Vector.<Gesture> = frame.gestures();
var posX:Number;
var posY:Number;
var s:Shape;
if(frame.pointables.length > 0) {
var currentVector:Vector3 = screen.intersectPointable(frame.pointables[0], true); //get normalized vector
posX = 1920 * currentVector.x - stage.x; //NOTE: I hardcoded the screen res value, you can get it like var w:int = leap.locatedScreens()[0].widthPixels();
posY = 1080 * ( 1 - currentVector.y ) - stage.y; //NOTE: I hardcoded the screen res value, you can get it like var h:int = leap.locatedScreens()[0].heightPixels();
}
for(var i:int = 0; i < gestures.length; i++) {
var gesture:Gesture = gestures[i];
if(gesture.type == Gesture.TYPE_SCREEN_TAP) {
if(posX >= _button1.x &&
posX <= _button1.x + _button1.width &&
posY >= _button1.y &&
posY <= _button1.y + _button1.height) {
s = new Shape();
s.graphics.beginFill(0x00FF00);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Lisa tocada!");
}
else {
s = new Shape();
s.graphics.beginFill(0xFF0000);
s.graphics.drawCircle(0, 0, 10);
s.graphics.endFill();
s.x = posX;
s.y = posY;
stage.addChild(s);
trace("Fallaste! Intentalo otra vez, tiempo: "+new Date().getTime());
}
}
}
}

Netstream audio playing twice

I am new to flash (this is the first time I've ever used it or actionscript) and I'm trying to make a video player. The video player gets params from the embed code and pulls the videos from a folder on the server.
I've got the following code (I've removed everything that I'm 100% sure isn't causing my problem):
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.media.Video;
import flash.events.NetStatusEvent;
import flash.events.MouseEvent;
import flash.events.FullScreenEvent;
import flash.events.Event;
import flash.ui.Mouse;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.text.TextFormat;
import flash.media.SoundTransform;
var nc:NetConnection;
var ns:NetStream;
var ns2:NetStream;
var video:Video;
var video2:Video;
//get filename parameters from embed code
var filename:String = root.loaderInfo.parameters.filename;
var filename2:String = root.loaderInfo.parameters.filename2;
var t:Timer = new Timer(5000);
var duration;
var currentPosition:Number;
var st:Number;
var started:Boolean;
Object(this).mcPlay.buttonMode = true;
Object(this).mcPause.buttonMode = true;
Object(this).ScreenClick.buttonMode = true;
Object(this).mcMax.buttonMode = true;
Object(this).mcSwitcher.buttonMode = true;
Object(this).mcPause.addEventListener(MouseEvent.CLICK,PlayPause);
Object(this).mcPlay.addEventListener(MouseEvent.CLICK,PlayPause);
Object(this).ScreenClick.addEventListener(MouseEvent.CLICK,PlayPause);
Object(this).mcMax.addEventListener(MouseEvent.CLICK,Maximize);
Object(this).slideVolume.addEventListener(Event.CHANGE, ChangeVolume);
Object(this).mcSwitcher.addEventListener(MouseEvent.CLICK, ToggleSwitcher);
t.addEventListener(TimerEvent.TIMER, TimerComplete);
stage.addEventListener(MouseEvent.MOUSE_MOVE, resetTimer);
stage.addEventListener(MouseEvent.MOUSE_DOWN, resetTimer);
stage.addEventListener(MouseEvent.MOUSE_UP, resetTimer);
stage.addEventListener(Event.ENTER_FRAME, videoTimer);
if (!nc) start();
var IsPaused:String;
function start():void
{
Object(this).slideVolume.maximum = 100;
Object(this).slideVolume.value = 100;
started = false;
var tf:TextFormat = new TextFormat();
tf.color = 0xFFFFFF;
tf.bold = true;
this.lblTime.setStyle("textFormat", tf);
connect();
t.start();
}
function connect():void
{
nc = new NetConnection();
nc.client = this;
nc.addEventListener(NetStatusEvent.NET_STATUS, OnNetStatus);
nc.connect(null);
}
function OnNetStatus(e:NetStatusEvent):void
{
switch(e.info.code)
{
case "NetConnection.Connect.Success":
if (!started)
{
started = true;
stream();
}
else
{
finish();
}
break;
default:
finish();
break;
}
}
function stream():void
{
ns = new NetStream(nc);
ns.client = this;
ns.bufferTime = 5; // set the buffer time to 5 seconds
if ((filename2 != null) && (filename2.length > 0))
{
ns2 = new NetStream(nc)
//ns2.client = this; //Uncomment to use ns2 vid for duration info
ns2.bufferTime = 5; // set the buffer time to 5 seconds
startVideo(2);
currentPosition = 1; //Default
ns.seek(0);
ns2.seek(0);
}
else
{
this.mcSwitcher.visible = false;
startVideo(1);
ns.seek(0);
}
}
function startVideo(num:Number):void
{
var startVolume:SoundTransform = new SoundTransform();
startVolume.volume = slideVolume.value / 100;
if (num == 2)
{
video = new Video(320,180);
video.x = 0;
video.y = 90;
addChild(video);
video.attachNetStream(ns);
ns.checkPolicyFile = false;
ns.play(filename); //path/filename
setChildIndex(video,1);
video2 = new Video(320,180);
video2.x = 320;
video2.y = 90;
addChild(video2);
video2.attachNetStream(ns2);
ns2.checkPolicyFile = false;
ns2.play(filename2); //path/filename
setChildIndex(video2,1);
ns.soundTransform = startVolume;
var videoVolumeTransform2:SoundTransform = new SoundTransform();
videoVolumeTransform2.volume = 0;
ns2.soundTransform = videoVolumeTransform2;
ns2.receiveAudio(false);
}
else if (num == 1)
{
video = new Video(640,360);
video.x = 0;
video.y = 0;
addChild(video);
video.attachNetStream(ns);
ns.checkPolicyFile = false;
ns.play(filename); //path/filename
setChildIndex(video,1);
ns.soundTransform = startVolume;
}
IsPaused = "playing";
this.removeChild(mcPlay);
setChildIndex(this.ScreenClick,0);
setChildIndex(this.mcTitleOverlay,2);
}
function ShowControls ():void
{
for (var i:int = 0; i < Object(root).numChildren; i++)
{
switch (Object(root).getChildAt(i))
{
case mcPause:
if (IsPaused != "paused")
Object(root).getChildAt(i).visible = true;
break;
case mcPlay:
if (IsPaused != "playing")
Object(root).getChildAt(i).visible = true;
break;
case mcSwitcher:
if ((filename2 != null) && (filename2.length > 0))
Object(root).getChildAt(i).visible = true;
break;
default:
Object(root).getChildAt(i).visible = true; //Bring back everything else
break;
}
ScreenClick.y = 154;
}
}
function videoTimer(e:Event):void
{
var curTime = ns.time; //Current time in seconds
var curMinutes = Math.floor(curTime / 60); //Get the minutes
var curSeconds = Math.floor(curTime % 60); //Get the leftover seconds
var durMinutes = Math.floor(duration / 60);
var durSeconds = Math.floor(duration % 60);
//Add the zeroes to the begining of the seconds if it is needed.
if (curSeconds < 10)
curSeconds = "0" + curSeconds;
if (durSeconds < 10)
durSeconds = "0" + durSeconds;
Object(this).lblTime.text = curMinutes + ":" + curSeconds + " / " + durMinutes + ":" + durSeconds;
}
function PlayPause (e:MouseEvent):void
{
switch (IsPaused)
{
case "playing":
IsPaused = "paused";
this.mcPlay.visible = true;
this.mcPause.visible = false;
ns.togglePause();
ns2.togglePause();
break;
case "paused":
IsPaused = "playing";
this.mcPause.visible = true;
this.mcPlay.visible = false;
ns.togglePause();
ns2.togglePause();
break;
default:
//
break;
}
}
The problem I have is small but frustrating (I've spend most of today trying to figure it out with zero progress made). It is thus: Everything works perfectly, except that when the videos load up and play, sound plays twice (for the video that has sound enabled). I am at my wits end trying to figure this out, any help would be greatly appreciated!
Thanks!
EDIT:
Ok, on further research (re-writing every function very simply and seeing if the problem goes away with the features) I've determined that the following function is the root of all evil (or at least my problems):
function startVideo(num:Number):void
{
var startVolume:SoundTransform = new SoundTransform();
startVolume.volume = Object(this).slideVolume.sldVol.value / 100;
if (num == 2)
{
video = new Video(320,180);
video.x = 0;
video.y = 90;
addChild(video);
video.attachNetStream(ns);
ns.checkPolicyFile = false;
ns.play(filename); //path/filename
this.removeChild(btnPlay);
setChildIndex(video,1);
video2 = new Video(320,180);
video2.x = 320;
video2.y = 90;
addChild(video2);
video2.attachNetStream(ns2);
ns2.checkPolicyFile = false;
ns2.play("test.mp4"); //path/filename
setChildIndex(video2,1);
ns.soundTransform = startVolume;
var videoVolumeTransform2:SoundTransform = new SoundTransform();
videoVolumeTransform2.volume = 0;
ns2.soundTransform = videoVolumeTransform2;
ns2.receiveAudio(false);
}
else if (num == 1)
{
video = new Video(640,360);
video.x = 0;
video.y = 0;
addChild(video);
video.attachNetStream(ns);
ns.checkPolicyFile = false;
ns.play("test.flv"); //path/filename
setChildIndex(video,1);
ns.soundTransform = startVolume;
}
IsPaused = "playing";
this.removeChild(btnPlay);
setChildIndex(this.ScreenClick,0);
//setChildIndex(this.mcTitleOverlay,2);
}
I shall persevere with my troubleshooting (I've isolated the problem, hopefully the next step is a solution!

actionscript: access now object instance

my problem is that after I create the new movie clips I don't know how to access them
var numOfBalls:int = 5;
var balls:Array = new Array();
import flash.utils.getDefinitionByName;
function addBall(instanceName:String) {
var mcIName:String = "ball";
var tMC:Class = getDefinitionByName(mcIName) as Class;
var newMc:MovieClip = new tMC() as MovieClip;
newMc.name = instanceName;
trace("added " + newMc.name);
newMc.x = randRange(10, 300);
newMc.y = randRange(10, 300);
addChild(newMc);
return this.newMc;
}
function randRange(start:Number, end:Number) : Number {
return Math.floor(start +(Math.random() * (end - start)));
}
var i = 0;
while ( i < numOfBalls) {
balls[i] = addBall("ball_" + i);
i++;
}
trace (this.balls[0]); // returnes error
trace (this.balls_0); //returnes error
function addBall(instanceName:String):MovieClip {
var mcIName:String = "ball";
var tMC:Class = getDefinitionByName(mcIName) as Class;
var newMc:MovieClip = new tMC() as MovieClip;
newMc.name = instanceName;
trace("added " + newMc.name);
newMc.x = randRange(10, 300);
newMc.y = randRange(10, 300);
addChild(newMc);
return newMc;
}
That should fixe it. return typed to MovieClip, and the fix bit,
return newMc instead of this.newMc;
newMC doesn't belong to this.
if you had this.newMc = newMC maybe.
you need to specify what the addBall function is returning
function addBall(instanceName:String):MovieClip {
and you may have to push the balls into the balls array, like
balls[i].push(addBall("ball_" + i));
try this, i'm not sure about your problem
The only thing i can see is the index i where you write the name of the new MovieClip, in ActionScript3 you can't pass a numeric value to a String without convert it with toString() method, try to fix it and see if it works
var numOfBalls:int = 5;
var balls:Array = new Array();
import flash.utils.getDefinitionByName;
function addBall(instanceName:String):MovieClip {
var mcIName:String = "ball";
var tMC:Class = getDefinitionByName(mcIName) as Class;
var newMc:MovieClip = new tMC() as MovieClip;
newMc.name = instanceName;
trace("added " + newMc.name);
newMc.x = randRange(10, 300);
newMc.y = randRange(10, 300);
addChild(newMc);
return this.newMc;
}
function randRange(start:Number, end:Number) : Number {
return Math.floor(start +(Math.random() * (end - start)));
}
var i = 0;
while ( i < numOfBalls) {
// convert i with toString() is requested in as3 or will return ERRORS
balls.push(addBall("ball_" + i.toString ()));
i++;
}
trace (MovieClip(this.balls[0]));