Playing sounds on Actionscript - actionscript-3

I have a simple drag and drop game started in flash and mostly working.
I have added my animals and you can drag and drop them in the right place.I have also added sound so that when the animal is dropped in the right spot , that is working however each time I add a new animal to the right spot it plays that sound and the last animal sound as well.
e.g. place pig in pig space , it plays pig sound
place cow in cow space , it plays cow sound and pig sound
place duck in duck space , it plays duck sound and cow sound and pig sound.
Obviously I only want to play the sound when the animal is placed in the right place - on drop ( not on next animal drop also )
I'm not sure what I have done wrong
/* Drag and Drop
Makes the specified symbol instance moveable with drag and drop.
*/
import flash.media.Sound;
var offset:int = 10;
var pigStartX:int = 196.80;
var pigStartY:int = 292.10;
var pigEndX:int = 578.40;
var pigEndY:int = 208.50;
Pig.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event:MouseEvent):void
{
Pig.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
function fl_ReleaseToDrop(event:MouseEvent):void
{
Pig.stopDrag();
// dragging and dropping the pieces while checking for correct location
if(Pig.x < pigEndX - offset || Pig.x > pigEndX + offset || Pig.y < pigEndY - offset ||Pig.y > pigEndY + offset){
Pig.x = pigStartX;
Pig.y = pigStartY;
}
else{
//set piece back to original position
Pig.x = pigEndX;
Pig.y = pigEndY;
var oink:PigOink = new PigOink();
var channel:SoundChannel = oink.play();
//checkGame();
}
}
/* Drag and Drop
Makes the specified symbol instance moveable with drag and drop.
*/
var cowStartX:int = 324;
var cowStartY:int = 317.95;
var cowEndX:int = 411.50;
var cowEndY:int = 140.95;
Cow.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag_2);
function fl_ClickToDrag_2(event:MouseEvent):void
{
Cow.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_2);
function fl_ReleaseToDrop_2(event:MouseEvent):void
{
Cow.stopDrag();
// dragging and dropping the pieces while checking for correct location
if(Cow.x < cowEndX - offset || Cow.x > cowEndX + offset || Cow.y < cowEndY - offset ||Cow.y > cowEndY + offset){
Cow.x = cowStartX;
Cow.y = cowStartY;
}
else{
//set piece back to original position
Cow.x = cowEndX;
Cow.y = cowEndY;
var moo:CowMoo = new CowMoo();
var channel:SoundChannel = moo.play();
//checkGame();
}
}
/* Drag and Drop
Makes the specified symbol instance moveable with drag and drop.
*/
var duckStartX:int = 209.45;
var duckStartY:int = 402.05;
var duckEndX:int = 56.45;
var duckEndY:int = 225.05;
Duck.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag_3);
function fl_ClickToDrag_3(event:MouseEvent):void
{
Duck.startDrag();
}
stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_3);
function fl_ReleaseToDrop_3(event:MouseEvent):void
{
Duck.stopDrag();
// dragging and dropping the pieces while checking for correct location
if(Duck.x < duckEndX - offset || Duck.x > duckEndX + offset || Duck.y < duckEndY - offset ||Duck.y > duckEndY + offset){
//set piece back to original position
Duck.x = duckStartX;
Duck.y = duckStartY;
}
else{
Duck.x = duckEndX;
Duck.y = duckEndY;
var quack:DuckQuack = new DuckQuack();
var channel:SoundChannel = quack.play();
//checkGame();
}
}

#Neal Davis is right about what is causing the problem, however I suggest to remove event listener once the animal is its destination position instead of listening MOUSE_UP event on the animal itself in release function:
function fl_ReleaseToDrop_3(event:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop_3);
Pig.stopDrag();
//...
}
Aditional suggestion.
Also as #Organis pointed out. It's much simpler to have more generic code.
Consider having something like this:
Document class:
package
{
import flash.display.Sprite;
import flash.geom.Point;
public class Main extends Sprite
{
private var animals:Vector.<Animal> = Vector.<Animal>([]);
public function Main() {
animals.push(new Animal("pig", pigMc, 578, 208, "oink.mp3"));
animals.push(new Animal("cow", cowMc, 411, 140, "moo.mp3"));
animals.push(new Animal("duck", duckMc, 56, 225, "quack.mp3"));
}
}
}
And simple Animal class:
package
{
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.media.Sound;
import flash.net.URLRequest;
public class Animal
{
private var _name:String;
private var _dropMargin:Number = 10;
private var _startPos:Point = new Point();
private var _endPos:Point = new Point();
private var _sound:Sound;
private var _view:Sprite;
public function Animal(name:String, view:Sprite, endX:Number = 0, endY:Number = 0, sound:String = null) {
_name = name;
_view = view;
_startPos.x = _view.x; _startPos.y = _view.y;
_endPos.x = endX; _endPos.y = endY;
_sound = new Sound(new URLRequest(sound));
view.addEventListener(MouseEvent.MOUSE_DOWN, onMDown);
}
private function onMDown(e:MouseEvent):void{
_view.stage.addEventListener(MouseEvent.MOUSE_UP, onMUp);
_view.startDrag();
}
private function onMUp(e:MouseEvent):void {
_view.stage.removeEventListener(MouseEvent.MOUSE_UP, onMUp);
_view.stopDrag();
//Distance to destination point
var dd:Number = Point.distance(pos, _endPos);
if (dd > dropMargin) pos = _startPos;
else {
pos = _endPos;
_sound.play();
}
}
public function get view():Sprite{return _view;}
public function get dropMargin():Number{return _dropMargin;}
public function set dropMargin(value:Number):void{_dropMargin = value;}
public function get pos():Point{return new Point(_view.x, _view.y);}
public function set pos(value:Point):void{
_view.x = value.x;
_view.y = value.y;
}
}
}

Look at your MouseUp event handlers.
You are adding the event listener to the stage. So they are all getting called whenever the stage hears a mouse up event.
Add those listeners to the cow, pig etc just as you did for the mouse down listeners.
That should solve it.
Pig.addEventListener(MouseEvent.MOUSE_DOWN, fl_ClickToDrag);
function fl_ClickToDrag(event:MouseEvent):void
{
Pig.startDrag();
}
//stage.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);
// change to this
Pig.addEventListener(MouseEvent.MOUSE_UP, fl_ReleaseToDrop);

Related

AS3: Why is a line created with .graphics appearing in two different places and when removed with parent.visible = false, only one goes?

Nobody seems to have this question already so I asked it because I've spent a few hours trying to debug this and can't find a solution;
Essentially, I have a function called draw, which is declared in my document class:
public function draw(Target: MovieClip,mX: int,mY: int,lX: int,lY: int):void {
Target.graphics.clear();
Target.graphics.lineStyle(1,0x000000,1);
Target.graphics.moveTo(mX,mY);
Target.graphics.lineTo(lX,lY);
}
I call it later to draw two lines, on two different MovieClips:
draw(Line,Line.mX,Line.mY,Mirror.x + (Mirror.width / 2),Line.lY);
draw(nextLine,(Mirror.x + (Mirror.width / 2)),200,(Mirror.x + (Mirror.width / 2)),0);
where
var Line: MovieClip = new MovieClip();
var Mirror: MovieClip = new mirror();
and Mirror is draggable, so Mirror.x changes whenever it is dragged.
Line is a line made using .graphics and Line.mX is equal to the Line.graphics.moveTo X value last time it was modified. Line.mY is the same, but for the Y coordinate. I set these values by doing this:
Line.mX = 0;
Line.mY = 200;
Line.lX = 550;
Line.lY = 200;
But with whatever values I want to draw the line, with lX and lY being equal to the X and Y coordinates of Line.graphics.lineTo. Then I draw Line using my draw function like this:
draw(Line,Line.mX,Line.mY,Line.lX,Line.lY);
Then it gets more complex because, actually, Line is just one line in an array of lines, created like this:
public var lines = [line0,line1,line2,line3,line4,line5,line6,line7,line8];
and each of those lines is created like this (with 0 being replaced by the line's number, respectively):
public var line0: MovieClip = new MovieClip();
then I give each line a number and a name, add them to the stage and hide them like this:
for each(var setupLine:MovieClip in lines) {
setupLine.num = (lines.indexOf(setupLine));
setupLine.name = ('line' + setupLine.num);
addChild(setupLine);
setupLine.visible = false;
}
Then, after making line0 visible, because I need to see it at the start, I loop through each line in a function that runs on ENTER_FRAME, and set the value of nextLine to a different value each time I run the loop like this:
for each(var Line:MovieClip in lines) {
nextLine = this['line' + (Line.num + 1)];
}
Within that loop, I then loop through a few other arrays, then check for a collision with the selected Line and another selected MovieClip from another array, which I wont go into or this question will be longer than the code for node.js.
So essentially, if the collision with the two MovieClips is present, I draw the line that I mentioned at the top of my question. But for some reason, although Line draws correctly, nextLine draws correctly, but a duplicate of it is drawn across the Y axis at 0, and stops where nextLine is on the Y axis (nextLine is vertical, so it has the same Y value at the start as at the end).
Even stranger, when I try to hide nextLine if the collision with the two MovieClips is no longer present, using this code:
nextLine.visible = false;
it only hides the version of nextLine that runs along the top of the stage, which I didn't even intend to create in the start.
EDIT
here is a link to the current source code
Here is a link to the entire project files with the original source code
copy/paste the new source code from the pastebin link to get the new version
Thanks in advance,
-Raph
I figured out how to do this, code is
package {
import flash.events.*;
import flash.utils.*;
import flash.display.*;
[SWF(backgroundColor="0xbdc3c7")]
public class LightStage extends MovieClip {
//import classes
public var globeClass:Globe = new Globe();
public var mirrorClass:Mirror = new Mirror();
public var lineClass:Line = new Line();
//create all stage objects
public var curLine:Line
public var nextLine:Line;
public var curMirror:Mirror;
//create containers
public var mirrors:Vector.<Mirror> = new Vector.<Mirror>(); //a vector is an array, but every member has to be (or subclass) the specified class
public var globes:Vector.<Globe> = new Vector.<Globe>();
public var lines:Vector.<Line> = new Vector.<Line>();
trace('lightstage: working');
//create level object
public var curLevel:int = -1;
//create dependent variables
public var kill: Boolean = true;
//init function
public function LightStage() {
//setup MovieClips
var i:int = 0;
for (i = 0; i < 4; i++) {
mirrors.push(new Mirror());
}
for (i = 0; i < 4;i++ ) {
globes.push(new Globe());
}
var tmpLine:Line;
for (i = 0; i < 10; i++) {
tmpLine = new Line();
lines.push(tmpLine);
addChild(tmpLine);
tmpLine.visible = false;
}
//create ENTER_FRAME listener
stage.addEventListener(Event.ENTER_FRAME,enterFrame);
//start the game
levelUp();
}
//levelUp function
public function levelUp() {
curLevel++;
curLine = lines[curLevel]; //set line to the current level
curLine.curX = 0;
curLine.curY = 200;
curLine.draw(550, 200);
curLine.visible = true;
//show and position mirrors and globes
curMirror = mirrors[curLevel];
addChild(curMirror);
curMirror.x = 250;
curMirror.y = 350;
var curGlobe:Globe = globes[curLevel];
addChild(curGlobe);
curGlobe.x = 100;
curGlobe.y = 50;
//set mirror types
curMirror.gotoAndStop(2);
trace("you are now on level " + (curLevel + 1) + "!");
}
//ENTER_FRAME function
public function enterFrame(event:Event) {
//line1.visible = true;
for (var i:int = 0; i < lines.length;i++){
if (i < lines.length - 1) nextLine = lines[i + 1]; //check for out of bounds before assignment next line
if (lines[i].visible == true) {
kill = true;
for each(var mirror:Mirror in mirrors) {
if (lines[i].visible && mirror.stage && mirror.hitTestObject(lines[i])) { //for efficiency, do the hit test last in the if statement
for each(var globe:Globe in globes) {
//Looped through Mirrors and Lines and checked for collision - if collision is present, we loop through globes here
if (nextLine && nextLine.stage) {
addChild(nextLine);
}
//check for active globes
if (lines[i].visible && lines[i].hitTestObject(globe)) {
//check if the selected line touches the selected globe - if it does then we will start the timer for that globe
if (!globe.running){
globe.start();
//trace('timing');
kill = false;
}
}
else {
globe.reset();
}
switch(mirror.currentFrame) {
case 1:
break;
case 2:
//trace('live a life you will remember' + Math.random());
if(nextLine) nextLine.visible = true;
lines[i].draw(mirror.x + (mirror.width / 2),lines[i].curY);
if (nextLine) {
nextLine.curX = mirror.x + (mirror.width / 2);
nextLine.curY = 200;
nextLine.draw(mirror.x + (mirror.width / 2), 0);
}
kill = false;
break;
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
trace(mirror.currentFrame);
kill = false;
break;
}
}
}
else if (lines[i].visible && mirror.stage && lines[i].stage){
if (kill && nextLine){
nextLine.graphics.clear();
nextLine.visible = false;
}
}
}
}
}
}
}
}
//MIRROR CLASS DECLARATION
import flash.events.MouseEvent;
class Mirror extends MovieClip {
trace('mirror: working');
public function Mirror() {
this.addEventListener(MouseEvent.MOUSE_DOWN,onDown,false,0,true);
}
private function onDown(e:MouseEvent):void {
//add the mouse up listener on the stage, that way it's consistent even if the user drags so fast that the mouse leaves the bounds of the mirror
stage.addEventListener(MouseEvent.MOUSE_UP, onUp, false, 0, true);
this.startDrag();
}
private function onUp(e:MouseEvent):void {
//we need to remove the listener from the stage now
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp, false);
this.stopDrag();
}
}
//LINE CLASS DECLARATION
import flash.display.Graphics;
class Line extends MovieClip {
trace('line: working');
public var curX:int;
public var curY:int;
public function Line():void {
}
public function draw(toX:int,toY:int):void {
graphics.clear();
graphics.lineStyle(1,0x000000,1);
graphics.moveTo(curX,curY);
graphics.lineTo(toX, toY);
curX = toX;
curY = toY;
}
}
//GLOBE CLASS DECLARATION
import flash.display.MovieClip;
import flash.events.TimerEvent;
import flash.utils.Timer;
class Globe extends MovieClip {
trace('globe: working');
private var timer:Timer = new Timer(3 * 100, 5);
public function Globe():void {
timer = new Timer(300, 5);
timer.addEventListener(TimerEvent.TIMER, repeatShine, false, 0, true);
}
public function reset():void {
timer.reset();
}
public function start():void {
timer.start();
}
public function get running():Boolean { return timer.running; };
private function repeatShine(e:TimerEvent):void {
}
}

Make three MovieClips appear and disappear inside a snowglobe when shaken

I used a creative cow tutorial to create my own snow globe that moves and snow reactivates - it really is a great tutorial.
What I'm trying to do is Change between 3 Movie clips in the ActionScript - But each time I add my movie clip names - Or try and add a simple visibility code I break my snow globe actions.
I have my MovieClip instances named friendsSceneThree, BuddiesSceneTwo and HatsOffSceneOne. I would think they'd be good but somewhere I'm missing something. Right now I can't get the code to even SEE The movieclips I'm getting a simple:
TypeError: Error #1006: value is not a function.at SnowGlobeContainer/update()
Down in the 'if drag' Update is where I'd like to Change from One MClip to the Next.
What Am I Not Seeing?!?! Any help would be greatly appreciated! Thanks
Here is the ActionScript:
package {
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.geom.Rectangle;
import flash.geom.Point;
public class SnowGlobeContainer extends Sprite {
public var snowForeground:SnowGeneratorCircle;
public var snowBackground:SnowGeneratorCircle;
public var friendsSceneThree:MovieClip;
public var buddiesSceneTwo:MovieClip;
public var hatsOffSceneOne:MovieClip;
public var drag:Boolean = false;
public var over:Boolean = false;
public var startPos:Point = new Point;
public var mouseDownOffset:Point = new Point;
public var bounds:Rectangle = new Rectangle;
public var vel:Point = new Point(0,0);
public var pos:Point = new Point(x,y);
public var old:Point = new Point(x,y);
public var gravity:Number = 5+(Math.random()*1);
public var restitution:Number = 0.5;
public var friction:Number = 0.9;
public function SnowGlobeContainer() {
// save some initial persistant properties
startPos.x = this.x;
startPos.y = this.y;
old.x = this.x;
old.y = this.y;
bounds.x = 0;
bounds.y = 0;
bounds.width = 600;
bounds.height = startPos.y;
// add mouse interaction listeners and show the cursor on rollover
this.mouseChildren = false;
this.useHandCursor = true;
this.buttonMode = true;
this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
this.addEventListener(Event.ENTER_FRAME, update);
}
protected function onMouseOver(e:MouseEvent=null):void { over = true; }
protected function onMouseOut(e:MouseEvent=null):void { over = false; }
protected function onMouseDown(e:MouseEvent=null):void {
// Save the offset of your mouse when you first start dragging. Same functionality as startDrag(false)
mouseDownOffset.x = mouseX;
mouseDownOffset.y = mouseY;
drag = true;
}
protected function onMouseUp(e:MouseEvent=null):void {
vel.x = vel.y = 0;
pos.x = x;
pos.y = y;
drag = false;
}
public function update(e:Event):void {
// this if/else statement controls the mouse over and out instead of using event listeners
if(mouseY < -175 || mouseY > 175 || mouseX < -175 || mouseX > 175){
if(over) onMouseOut();
}else{
if(!over) onMouseOver();
}
if(drag){
// drag around..
this.x = parent.mouseX - mouseDownOffset.x;
this.y = parent.mouseY - mouseDownOffset.y;
// keep this thing on the table :)
if(y >= bounds.height) y = bounds.height;
// if you "shake" or move the mouse quickly, we are going to reset the snow particles
var d:Point = new Point(Math.abs(old.x - x), Math.abs(old.y - y));
if(d.x > 50 || d.y > 50 ){
snowForeground.reset();
snowBackground.reset();
friendsSceneThree.visible = false;
}
// update the history position
old.x = x;
old.y = y;
vel.y = (y-old.y)/2;
}else{
// if you drop this object it should have a bit of realistic falling..
vel.y += gravity;
pos.y += vel.y;
// bounce
if(pos.y > bounds.height){
pos.y = bounds.height;
vel.y *= -(Math.random()*restitution);
}
y = pos.y;
}
}
}
}
I appreciate the help -- If you haven't noticed I'm new to all of this scripting. I'm looking in on lynda.com and other forums. the SnowGeneratorCircle.as is:
package {
import flash.display.Sprite;
import flash.events.Event;
public class SnowGeneratorCircle extends Sprite {
var totalFlakes:int = 500;
var flakes:Array = new Array();
public function SnowGeneratorCircle() {
addSnowFlakes();
addEventListener(Event.ENTER_FRAME, update);
}
protected function addSnowFlakes():void{
for(var i:int=0; i<totalFlakes; i++){
var f:SnowFlake = new SnowFlake();
addChild(f);
flakes.push(f);
}
}
public function reset():void{
for(var i:int=0; i<totalFlakes; i++){
var f:SnowFlake = flakes[i];
f.reset();
}
}
public function update(e:Event=null):void {
for(var i:int=0; i<totalFlakes; i++){
var f:SnowFlake = flakes[i];
f.update(0);
}
}
}
}
I debugged - didn't clean up the code, because every time I did - it broke the actions. So I left the code with the double spacing. That's how it went in when I copied and pasted from the tutorial anyway.
Here's the error on line 173 - which is the MovieClip I'd like to have change.
Attempting to launch and connect to Player using URL /Volumes/Lacie Biggest S2S/GRaid/Veronica
/V/Rubio/Work/SUBARU/SnowGlobe Subaru/SnowGlobeAnima/snowGlobeShakev3.swf
[SWF] Volumes:Lacie Biggest S2S:GRaid:Veronica:V:Rubio:Work:SUBARU:SnowGlobe >Subaru:SnowGlobeAnima:snowGlobeShakev3.swf - 468081 bytes after decompression
TypeError: Error #1006: value is not a function.
at SnowGlobeContainer/update()[/Volumes/Lacie Biggest S2S/GRaid/Veronica/V/Rubio/Work/SUBARU
/SnowGlobe Subaru/SnowGlobeAnima/SnowGlobeContainer.as:173]
I just don't know how to get the actionscript to find my MovieClips and then swap them out wt each shake of the globe.

ScrollPane and ScrollBar not working

I have an application I'm trying to build where it will display a large map image (1920x1040 which is set as the base layer of frame one, then all my AS is on the layer above on the first frame too), then draw lines to it by reading in their coordinates from an external file (lines.txt) and associate a particular image with each line.
When a user clicks on a line, a ScrollPane should open, showing the image associated with the line they clicked on. These images are 1040 in height, and at least 4000px wide, so I want the image to fill the screen height, and then allow the user to use a scroll bar along the bottom to scroll left and right to see the full image.
Right now, I have it working where it reads in my lines.txt file, and draws the lines correctly. Then when I click on a line, it will load the corresponding image in the ScrollPane (along with a button to click that will remove the scroll pane and allow them to select a new line).
However, I can't get a horizontal scroll bar to work. I have it so that the space shows up at the bottom where a scroll bar should be, but there's no bar to drag left/right, and no way to scroll around.
I saw that it's possible to use dragging to scroll, which would be nice, but that hasn't worked either (it' now commented out), and when I have it turned on, when I click my Back Button and attempt to click another line, it throws an error saying,
"TypeError: Error #1009: Cannot access a property or method of a null object reference.
at fl.containers::ScrollPane/endDrag()"
Anybody able to help me clean this up and get it figured out what's going wrong here?
My code:
import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import fl.containers.ScrollPane;
import fl.events.ScrollEvent;
import fl.controls.ScrollPolicy;
import fl.controls.DataGrid;
import fl.data.DataProvider;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.net.URLLoader;
import fl.controls.UIScrollBar;
import flash.events.Event;
import fl.controls.ScrollBar;
var worldLines:Array = new Array();
var lineSprites:Array = new Array();
var lineSpritesLength:int;
var basicColorTransform:ColorTransform = new ColorTransform();
basicColorTransform.color = 0x00FF00;
var hoverColorTransform:ColorTransform = new ColorTransform();
hoverColorTransform.color = 0xFFFF00;
populateWorldLines();
function populateWorldLines():void
{
var textFile:File = File.applicationDirectory.resolvePath("lines.txt");
var fileContents:String = getFileData(textFile);
var contentsLength:int = fileContents.split("$").length;
for(var i:int = 0; i < contentsLength; i++)
{
trace(i);
worldLines[i] = new Object();
worldLines[i]["x1"] = fileContents.slice(0, fileContents.indexOf(","));
fileContents = fileContents.slice(fileContents.indexOf(",") + 1, fileContents.length);
worldLines[i]["y1"] = fileContents.slice(0, fileContents.indexOf(","));
fileContents = fileContents.slice(fileContents.indexOf(",") + 1, fileContents.length);
worldLines[i]["x2"] = fileContents.slice(0, fileContents.indexOf(","));
fileContents = fileContents.slice(fileContents.indexOf(",") + 1, fileContents.length);
worldLines[i]["y2"] = fileContents.slice(0, fileContents.indexOf(","));
fileContents = fileContents.slice(fileContents.indexOf(",") + 1, fileContents.length);
worldLines[i]["image"] = fileContents.slice(0, fileContents.indexOf(";"));
fileContents = fileContents.slice(fileContents.indexOf("$") + 1, fileContents.length);
}
drawLines(worldLines);
}
function drawLines(lines:Array):void
{
for(var i:int = 0; i < lines.length; i++)
{
var line:Sprite = new Sprite;
line.graphics.moveTo(lines[i]["x1"], lines[i]["y1"]);
line.graphics.lineStyle(3, basicColorTransform.color);
line.graphics.lineTo(lines[i]["x2"], lines[i]["y2"]);
lineSprites.push(line);
addChild(line);
}
lineSpritesLength = lineSprites.length;
this.addEventListener(MouseEvent.MOUSE_OVER, checkLines);
}
function checkLines(e:MouseEvent):void
{
var targetSprite:* = e.target;
for(var i:int = 0; i < lineSpritesLength; i++)
{
if(targetSprite == lineSprites[i])
{
targetSprite.transform.colorTransform = hoverColorTransform;
targetSprite.addEventListener(MouseEvent.CLICK, lineClicked);
targetSprite.addEventListener(MouseEvent.MOUSE_OUT, resetColorTransform);
}
}
}
function lineClicked(e:MouseEvent):void
{
var targetSprite:* = e.target;
for(var i:int = 0; i < lineSpritesLength; i++)
{
if(targetSprite == lineSprites[i])
{
showImage(worldLines[i]["x1"], worldLines[i]["y1"], worldLines[i]["image"]);
}
}
//e.target.removeEventListener(e.type, lineClicked);
}
function showImage(xPos:int, yPos:int, imageName:String):void
{
var aSp:ScrollPane = new ScrollPane();
var aBox:MovieClip = new MovieClip();
drawBox(aBox, imageName);
aSp.source = aBox;
aSp.setSize(1920, 1040);
aSp.move(0, 0);
aSp.name = "scrollyPaneThing";
//aSp.scrollDrag = true;
aSp.horizontalScrollPolicy=ScrollPolicy.ON;
aSp.addEventListener(ScrollEvent.SCROLL, scrollListener);
addChild(aSp);
}
function scrollListener(event:ScrollEvent):void {
var mySP:ScrollPane = event.currentTarget as ScrollPane;
trace("scrolling");
trace("\t" + "direction:", event.direction);
trace("\t" + "position:", event.position);
trace("\t" + "horizontalScrollPosition:", mySP.horizontalScrollPosition, "of", mySP.maxHorizontalScrollPosition);
trace("\t" + "verticalScrollPosition:", mySP.verticalScrollPosition, "of", mySP.maxVerticalScrollPosition);
};
function drawBox(box:MovieClip,imageName:String):void {
trace(imageName + ":imageName");
var file:File = File.applicationDirectory.resolvePath("dataImages/"+imageName);
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest(file.url);
imageLoader.load(image);
imageLoader.x = 1;
imageLoader.y = 1;
box.addChild (imageLoader);
trace("backButton.png:imageName");
var file2:File = File.applicationDirectory.resolvePath("backButton.png");
var imageLoader2:Loader = new Loader();
var image2:URLRequest = new URLRequest(file2.url);
imageLoader2.load(image2);
imageLoader2.x = 10;
imageLoader2.y = 950;
box.addChild (imageLoader2);
imageLoader2.addEventListener(MouseEvent.CLICK, removeScrollyPaneThing);
}
function removeScrollyPaneThing(MouseEvent):void
{
removeChild(getChildByName("scrollyPaneThing"));
}
function resetColorTransform(e:MouseEvent):void
{
e.target.transform.colorTransform = basicColorTransform;
e.target.removeEventListener(e.type, resetColorTransform);
}
function getFileData(file:File):String
{
var fDataStream:FileStream;
var sContent:String;
fDataStream = new FileStream();
fDataStream.open(file, FileMode.READ);
sContent = fDataStream.readUTFBytes(fDataStream.bytesAvailable);
fDataStream.close();
return sContent;
}
Your Loader Object has a scrollRect property that is built in.
It is MUCH easier to use a simple ScrollBar than a ScrollPane,
but mouse dragging is much cleaner:
see: http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/DisplayObject.html#scrollRect
To mouse drag:
private var scrollyThingy:Rectangle;
private var map:Loader;
// holders for the location of the view
//(to allow for cancelling the drag):
private var _cx:int = 0;
private var _cy:int = 0;
private var downpoint:Point = null;
public function init():void{
// Load your image:
/* I prefer to use embeded png files
or draw simple line images, but
Loader objects also have a scrollRect property
From this point I will assume your main image ('map') is loaded,
and 'scrollyThingy' is the part you want diplayed
I could not follow the code once you added the
loader to the stage very well...
*/
// to enable mouse dragging:
map.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
var w:int = 100;
var h:int = 100;
scrollyThingy = new Rectangle(_cx, _cy, w, h);
map.scrollRect = scrollyThingy;
AddChild(map);
}
private function onMouseDown(event:MouseEvent):void{
_downpoint = new Point(event.stageX, event.stageY);
map.removeEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
map.addEventListener(MouseEvent.MOUSE_DRAG, onMouseDrag);
map.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
map.addEventListener(MouseEvent.RELEASE_OUTSIDE , onReleaseOutside);
}
private function onMouseDrag(event:MouseEvent):void{
if (_downpoint == null)
return;
// the movement delta:
_dx = int((event.stageX - _downpoint.x));
_dy = int((event.stageY - _downpoint.y));
// (if the movement is backwards, use scrollyThingy.x -= _dx)
scrollyThingy.x += _dx;
scrollyThingy.y += _dy;
Loader.scrollRect = scrollyThingy;
}
private function onMouseUp(event:MouseEvent):void{
if (_downpoint == null)
return;
// new corner coords
_cx += int((event.stageX - _downpoint.x));
_cy += int((event.stageY - _downpoint.y));
resetListeners();
}
private function onReleaseOutside(event:MouseEvent):void{
// put it back where it was
resetListeners();
}
private function resetListeners():void{
scrollyThingy.x = _cx;
scrollyThingy.y = _cy;
Loader.scrollRect = scrollyThingy;
_downpoint = null;
if(!map.hasEventListener(MouseEvent.MOUSE_DOWN)
map.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
//(if it has one, it has them all!)
if(map.hasEventListener(MouseEvent.MOUSE_DRAG){
map.removeEventListener(MouseEvent.MOUSE_DRAG, onMouseDrag);
map.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp);
map.removeEventListener(MouseEvent.RELEASE_OUTSIDE , onReleaseOutside);
}
}
if you still want a ScrollBar, just scale it to your Loader dimensions less the
size of the viewport (xScrollBar.maximum = loader.content.width - scrollyThingy.width,
yScrollbar.maximum = loader.content.height - scrollyThingy.height) then you can use the
same listener for both bars:
function onScrollBarChange(e:event):void{
scrollyThingy.x = xScrollBar.value;
scrollyThingy.y = yScrollBar.value;
}
listen for a change Event and set the Loader.scrollRect.x and Loader.scrollRect.y
properties to the scrollBarx.value & scrollBary.value.
Note also that I did not include any value checking.
You should check the values before moving the scrollRect
to avoid rangeErrors
i.e. if (_cx > loader.width - loader.scrollRect.width)
_cx = Loader.width - Loader.scrollRect.width;

Correct usage of addtoStage when loading external swf

I am loading an external swf file into a parent swf file.
Previously, I was getting error 1009 and fixed that by using a listener event to add the swf to the stage before running any scripts.
The swf however fails to load completely when embedded into a parent swf as seen in this URL
http://viewer.zmags.com/publication/06b68a69?viewType=pubPreview#/06b68a69/1
Here is the code I am using.
Thank you for any input.
package
{
import com.greensock.TweenLite;
import flash.display.DisplayObject;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.SpreadMethod;
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.events.TimerEvent;
import flash.utils.Timer;
import flash.utils.getDefinitionByName;
public class slider5 extends Sprite
{
public var thumbPath:String = "Trailchair_thumb";
public var featPath:String = "Trailchair";
public var sliderIndex:Number = 1;
public var currBg:Bitmap = new Bitmap();
public var thumbCount:Number = 8;
public var thumbHolder:Sprite = new Sprite();
public var thumbMask:Sprite = new Sprite();
public var thumbX:Number = 0;
public var thmPadding:Number = 10;
public var thmWidth:Number;
public var navLeft:Sprite = new Sprite();
public var navRight:Sprite = new Sprite();
public var timer:Timer = new Timer(5000,0);
public var sliderDir:String = "fwd";
public function slider5()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
public function onAddedToStage(e:Event):void{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
//THE BACKGROUND IMAGE
currBg.alpha = 1;
stage.addChildAt(currBg, 0);
changeBg(sliderIndex);
//The thumbMask a sprite with graphic rectangle
thumbMask.x = 87;
thumbMask.y = 572;
thumbMask.graphics.beginFill(0xFFFFFF);
thumbMask.graphics.drawRect(0,0, 406, 181);
stage.addChildAt(thumbMask, 2);
//The thumbSlider
thumbHolder.x = 228;
thumbHolder.y = 573;
stage.addChildAt(thumbHolder, 1);
thumbHolder.mask = thumbMask;
buildThumbs();
//add the nav
navLeft.x = 100;
navLeft.y = 609;
navRight.x = 496;
navRight.y = 609;
stage.addChildAt(navLeft, 4);
stage.addChildAt(navRight, 4);
var navBmp:Bitmap = new Bitmap();
navBmp.bitmapData = new navarrow(109,109);
var navBmp_Rt:Bitmap = new Bitmap();
navBmp_Rt.bitmapData = new navarrow(109,109);
navLeft.addChild(navBmp);
navLeft.scaleX *= -1;
navRight.addChild(navBmp_Rt);
navLeft.useHandCursor = true;
navLeft.buttonMode = true;
navRight.useHandCursor = true;
navRight.buttonMode = true;
navLeft.name = "left";
navRight.name = "right";
navLeft.addEventListener(MouseEvent.CLICK, navClick);
navRight.addEventListener(MouseEvent.CLICK, navClick);
//add the active item frame
var frame:Sprite = new Sprite();
frame.x = 226;
frame.y = 570;
frame.graphics.lineStyle(10, 0x000000);
frame.graphics.drawRect(0,0,131, 181);
stage.addChildAt(frame, 6);
timer.addEventListener(TimerEvent.TIMER, timeEvt);
timer.start();
}
public function changeBg(index):void
{
//set the first slide from our library and add to the stage
var currBg_Class:Class = getDefinitionByName( featPath + index ) as Class;
currBg.bitmapData = new currBg_Class(597,842);
//fade it in
TweenLite.from(currBg, 0.5, {alpha:0});
}
public function buildThumbs():void
{
var currThm:Class;
for (var i:uint = 1; i<=thumbCount; i++)
{
currThm = getDefinitionByName( thumbPath + i ) as Class;
var thmBmp:Bitmap = new Bitmap();
thmBmp.bitmapData = new currThm(126,176);
thmBmp.x = thumbX;
thumbHolder.addChild(thmBmp);
thumbX += thmBmp.width + thmPadding;
}
thmWidth = thmBmp.width + thmPadding;
}
public function navClick(e):void
{
timer.reset();
timer.start();
var dir:String = e.currentTarget.name;
if (dir=="left" && thumbHolder.x < 228 )
{
sliderIndex--;
TweenLite.to(thumbHolder, 0.5, {x:thumbHolder.x + thmWidth});
//thumbHolder.x = thumbHolder.x + thmWidth;
}
else if (dir=="right" && thumbHolder.x > - 724 )
{
sliderIndex++;
TweenLite.to(thumbHolder, 0.5, {x:thumbHolder.x - thmWidth});
//thumbHolder.x = thumbHolder.x - thmWidth;
}
if (sliderIndex == thumbCount)
{
sliderDir = "bk";
}
if (sliderIndex == 1)
{
sliderDir = "fwd";
}
changeBg(sliderIndex);
}
public function timeEvt(e):void
{
if (sliderDir == "fwd")
{
navRight.dispatchEvent(new Event(MouseEvent.CLICK));
}
else if (sliderDir == "bk")
{
navLeft.dispatchEvent(new Event(MouseEvent.CLICK));
}
}
}
}
If you still need it you can try these two suggestions. Note I didnt know about Zmags and initially assumed that it was your own domain name. That's why I suggested you use the Loader class. It worked for me when I did a test version of a parent.swf' that loaded a test 'child.swf' containing your code. It actually loaded the child swf without problems.
Change from extending Sprite to extending MovieClip
Avoid checking for added to stage in this project
Explanations:
Extending MovieClip instead of Sprite
I Long story short Flash wont like your swf extending Sprite then being opened by a parent loader that extends Movieclip. The ZMag player will be extending MovieClip. It's logical and the docs do confirm this in a way. Whether it fixes your issue or not just keep it MovieClip when using ZMags.
Avoiding Stage referencing in your code..
Looking at this Zmags Q&A documentaion:
http://community.zmags.com/articles/Knowledgebase/Common-questions-on-flash-integration
Looking at Question 4.. In their answer these two stand out.
Reference of the stage parameter in the uploaded SWF conflicting with the publication
Badly or locally referenced resources in the SWF you uploaded which cannot be found
Is it really necessary to have an added_to_stage check in this? If it wont hurt then I suggest dropping the stage_added checking from function slider5() and instead cut/paste in there the code you have from the function onAddedToStage(e:Event).
Hope it helps.

How to change the pixels in an image

i actually try to do the following: I have loaded an external image in a bitmapdata object and create a bitmap from it which i attach it to a sprite/MovieClip in order to have mouse events on it. Now under the previous logic i loaded two images (let's say circles) of the same size one that has a particular color and is covered by its black foreground circle. When i press left mouse button and hold it down i want while the mouse is moved to erase the foreground circle's pixels and so the background image starting to appear. I tried this to achieve but had no luck. In my best attempt i achieve to draw a line in the foreground image but i cannot reveal the background!
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Loader;
import flash.net.URLRequest;
import flash.display.BitmapData;
import flash.display.Bitmap;
import flash.display.BlendMode;
public class Test2 extends MovieClip
{
// properties - state
// to attach the image and have mouse events
private var frontImage:Sprite;
private var backImage:Sprite;
// to load the image
private var myLoader:Loader;
// to get the bitmap data of the image
private var frontBitmapData:BitmapData;
private var frontBitmap:Bitmap;
// test
private var frontMask:Bitmap;
// constructor
function Test2():void
{
// load the background image
backImage = new Sprite();
attachImageToSprite1(new URLRequest("btest.jpg"));
backImage.mouseEnabled = false;
this.addChild( backImage );
// load the front image
frontImage = new Sprite();
attachImageToSprite2(new URLRequest("test.jpg"));
frontImage.mouseEnabled = true; // enable mouse
frontImage.buttonMode = true; // set button mode
this.addChild(frontImage); // load to stage
this.frontImage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
this.frontImage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
// methods
private function attachImageToSprite1(Name:URLRequest):void
{
this.myLoader = new Loader();
this.myLoader.load(Name);
this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete1);
}
private function attachImageToSprite2(Name:URLRequest):void
{
this.myLoader = new Loader();
this.myLoader.load(Name);
this.myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoadComplete2);
}
private function getImageBitmapDataFromSprite(srcImage:Sprite):BitmapData
{
var tmpBitmapData:BitmapData = new BitmapData(frontImage.width, frontImage.height, true, 0xFFCCCCCC);
tmpBitmapData.lock();
tmpBitmapData.draw(frontImage);
tmpBitmapData.unlock();
return tmpBitmapData;
}
private function isPixelAlpha(bitmapdata:BitmapData):Boolean
{
var pixelValue:uint = bitmapdata.getPixel32(mouseX, mouseY);
var alphaValue:uint = pixelValue >> 24 & 0xFF;
//var red:uint = pixelValue >> 16 & 0xFF;
//var green:uint = pixelValue >> 8 & 0xFF;
//var blue:uint = pixelValue & 0xFF;
return (alphaValue == 0x00) ? true : false;
}
private function deletePixelUnderMouse(bitmapdata:BitmapData, bitmap:Bitmap):void
{
bitmapdata.lock();
if ( !isPixelAlpha(bitmapdata) ) {
bitmapdata.setPixel32(mouseX, mouseY, 0xFF << 24); // how to make the current pixel's alpha
} // equal to zero.
bitmap = new Bitmap(bitmapdata);
bitmap.x = frontImage.x;
bitmap.y = frontImage.y;
this.frontImage.addChild(bitmap);
bitmapdata.unlock();
}
// events
public function onLoadComplete1(e:Event):void
{
frontImage.addChild(this.myLoader.content);
}
public function onLoadComplete2(e:Event):void
{
backImage.addChild(this.myLoader.content);
}
public function onMouseDown(e:MouseEvent):void
{
// delete a pixel from the sprite under the mouse
frontBitmapData = getImageBitmapDataFromSprite(frontImage);
deletePixelUnderMouse(frontBitmapData, frontBitmap);
frontImage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
trace("start");
}
public function onMouseUp(e:MouseEvent):void
{
frontImage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseDown);
trace("stop")
}
}
}
Not sure if I got it right, but if you want a 'reveal' effect, as in you draw a mask to display a hidden image for example, this could be achieved slightly easier:
var bitmapToReveal:BitmapData = new BitmapToReveal(0,0);
var brush:BitmapData = new Brush(0,0);
var canvasData:BitmapData = new BitmapData(bitmapToReveal.width,bitmapToReveal.height,true,0x00FFFFFF);
var cursor:Point = new Point();//used as destination point when painting
var zero:Point = new Point();//reused for painting
var reveal:Bitmap = new Bitmap(bitmapToReveal);
var canvas:Bitmap = new Bitmap(canvasData);
reveal.cacheAsBitmap = canvas.cacheAsBitmap = true;
addChild(reveal);
addChild(canvas);
reveal.mask = canvas;
stage.addEventListener(MouseEvent.MOUSE_DOWN, brushDown);
stage.addEventListener(MouseEvent.MOUSE_UP, brushUp);
function brushDown(event:MouseEvent):void {
this.addEventListener(Event.ENTER_FRAME, paint);
}
function brushUp(event:MouseEvent):void {
this.removeEventListener(Event.ENTER_FRAME, paint);
}
function paint(event:Event):void {
cursor.x = mouseX-brush.width*.5;
cursor.y = mouseY-brush.height*.5;
canvasData.copyPixels(brush,brush.rect,cursor,brush,zero,true);
}
I'm using two Bitmaps form the library(bitmapToReveal and brush).
The main thing to look at is the copyPixels() method. I copy
the brush bitmap into the canvas(an empty transparent bitmap data),
using the offset cursor position(so the brush centered), and using the
alpha channel to do that. Note that I've set cacheAsBitmap to true
for both mask and maskee. You need to do that to get a transparent mask,
which is key to the effect.
Here is the result:
You can 'paint' the mask here. CS4 Source is here.
HTH,
George