What code in as-3 to use to allow seekbar to be moved by user? - actionscript-3

I'm creating a simple music player which will play just one song. Stage timeline has got just one frame. There is main graphic for player which is movieClip_1 (it has 4 frames in it's own timeline) and that works ok. I've got button (button_2) which starts and pauses the song and the movieClip_1 (works ok). And i also have got a graphic (it's called tube - i have changed it to movie clip, it has got one frame inside it's timeline) as a seekbar component which I just want it to move correspondingly to channel.position of this song on the x axis which it does but gives me triple error of:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
Debug points at this line:
tube.x = (chan.position/song.length) * 83;
I would really appreciate a tip regarding error and also what method to use in order for user to be able to navigate (with mouse) through song by moving tube on x axis and going to different part of song. I read about .startDrag and .stopDrag would that be good idea with my present code?
My code so far:
movieClip_1.stop();
var itsstoped:Boolean;
var youpausedit:Boolean;
var counter:Timer = new Timer(100);
var chan:SoundChannel;
var song:Sound = new Sound();
song.load(new URLRequest("wmc2.mp3"));
song.addEventListener(Event.COMPLETE, soundloaded);
function soundloaded(event:Event)
{
trace("Song has been loaded.");
}
counter.addEventListener(TimerEvent.TIMER,countcounter);
itsstoped = true;
youpausedit = false;
button_2.addEventListener(MouseEvent.CLICK, presser);
function presser(event:MouseEvent):void
{
if(itsstoped == true && youpausedit == true)
{
movieClip_1.gotoAndPlay(1);
chan = song.play(chan.position);
itsstoped = false;
}
else if(itsstoped == false)
{
movieClip_1.gotoAndStop(1);
chan.stop();
itsstoped = true;
youpausedit = true;
}
else if(itsstoped == true && youpausedit == false)
{
movieClip_1.gotoAndPlay(1);
chan = song.play();
counter.start();
itsstoped = false;
}
}
function countcounter(e:TimerEvent):void
{
trace(chan.position/song.length);
var percentage:uint = 100 * (chan.position / song.length);
trace(percentage);
if(percentage == 100)
{
movieClip_1.gotoAndStop(1);
itsstoped = true;
youpausedit = false;
counter.stop();
}
}
tube.buttonMode = true;
tube.useHandCursor = true;
addEventListener(Event.ENTER_FRAME, movewhenplay);
function movewhenplay(e:Event):void
{
tube.x = (chan.position/song.length) * 83;
}

Regarding the error, you're accessing an object that has yet to be instantiated, i.e. there is no data to fetch as it does not exist.
As for the searchbar, I'm guessing you're using some kind of mask for the search bar, as you're using its x position to display the song position. I would suggest you instead use its width parameter, and set the center point to the far left.
To be able to then search through the song, you can add a copy of this searchbar, place it on top of the first one. Set its alpha to 0, to make it invisible, but still clickable. Add mouseEvent listeners to that, and when the user clicks it, you can set the song to play from the position which you can calculate using mouseX relevant to the invisible search bar.
I.e. if you want the clicked position in percents
percent = (mouseX - invisiSearchBar.x) / invisiSearchbar.width

Related

remove drag and drop objects when exit frame on button click

i want to make flash application that allowed users to match picture with the box containing its first letter of the word. the method is drag and drop with target. i'm really new to this.
drag and drop target is working so far but my problem is when i exit the frame after moving the object, the drag and drop object still visible.
how can i remove this object when leaving frame?
here is what i got:
import flash.events.MouseEvent;
import flash.display.DisplayObject;
var objectoriginalX:Number;
var objectoriginalY:Number;
a.buttonMode = true;
a.addEventListener(MouseEvent.MOUSE_DOWN, pickupObject);
a.addEventListener(MouseEvent.MOUSE_UP, dropObject);
function pickupObject(event:MouseEvent):void
{
event.target.startDrag();
event.target.parent.addChild(event.target);
objectoriginalX = event.target.x;
objectoriginalY = event.target.y;
}
function dropObject(event:MouseEvent):void
{
event.target.stopDrag();
var matchingTargetName:String = "target" + event.target.name;
var matchingTarget:DisplayObject = getChildByName(matchingTargetName);
if(event.target.dropTarget != null && event.target.dropTarget.parent == matchingTarget)
{
event.target.removeEventListener(MouseEvent.MOUSE_DOWN, pickupObject);
event.target.removeEventListener(MouseEvent.MOUSE_UP, dropObject);
event.target.buttonMode = false;
event.target.x = matchingTarget.x;
event.target.y = matchingTarget.y;
}
else
{
event.target.x = objectoriginalX;
event.target.y = objectoriginalY;
}
}
thanks before, any suggestion will be appreciated
edited: this is the code i use to move to other scene
HOME1.addEventListener(MouseEvent.CLICK, fl_ClickToGoToScene_15);
function fl_ClickToGoToScene_15(event:MouseEvent):void
{
MovieClip(this.root).gotoAndStop(2, "Scene 1");
}
When through code you do something to a timeline object that causes the parentage to change, that timeline object will no longer be controlled by the timeline.
So when you do this:
event.target.parent.addChild(event.target);
(presumably to bring the item being dragged to the front), you are inadvertently telling Flash that this object is controlled by code now.
The solution, is to manually remove the object(s) by code when done with them. This can be done with removeChild(childObject).
Since you are likely dealing with multiple objects that can be dragged around, it would likely be easiest to just clear all children manually prior to going to the next frame:
removeChildren(); //remove all children of the current context (timeline)
nextFrame(); //go to the next frame, or play(); or whatever you want to do
If you are targeting an older version of flash (less than 11 doesn't support the removeChildren method), you can do this in it's place:
var i:int = numChildren;
while(i--){
removeChildAt(i);
}
Alternatively, if you don't desire to clear all children of the current timeline, you could just keep track of what's being dragged around and remove those object:
var draggedObjs:Array = [];
function pickupObject(event:MouseEvent):void
{
draggedObjs.push(event.target);
...rest of code
Then do this when ready to move on:
for each(obj in draggedObjs){
removeChild(obj);
}
draggedObjs = [];
nextFrame(); //or whatever
Another option, would be to duplicate the item clicked, add it to stage, then drag the duplicate and match the originals position to it on mouse move. When the drag is done, remove the duplicate from stage.

Going from one scene to next and gettingType1009 Null object reference errors

Okay so in my main menu for my game, I have a glow effect so that when you hover over the invisible button 'startdesu', the script will make the whole menu glow, fading in and out. This code (from the event listener onwards) has been repeated for each button on the menu, with appropriate changes to the button instance name and the function names. The only problem is, when I click 'startdesu' and it takes me to the next scene, I start getting repetitive errors, "TypeError: Error #1009: Cannot access a property or method of a null object reference.
at bjvb_fla::MainTimeline/increaseGlow()". I've tried removing the glow event listeners when the buttons are clicked and everything but no luck. Please help! ;0;
Here is the essential code for brevity's sake, but I can post the whole thing if it helps.
(also, i get the same Null error for something else when i go from the game back to the start menu.
import flash.filters.*;
import flash.events.Event;
stop();
wow.alpha=0.5;
var menuGlow:GlowFilter = new GlowFilter();
menuGlow.color = 0xffffff;
menuGlow.blurX = 20;
menuGlow.blurY = 20;
menuGlow.alpha = 0;
menu.filters = [menuGlow];
var glow:Boolean = false;
startdesu.addEventListener(MouseEvent.MOUSE_OVER, addGlow);
startdesu.addEventListener(MouseEvent.MOUSE_OUT, removeGlow);
startdesu.addEventListener(Event.ENTER_FRAME, increaseGlow);
function addGlow(e:MouseEvent):void
{
glow = true;
}
function removeGlow(e:MouseEvent):void
{
glow = false;
}
function increaseGlow(e:Event):void
{
if(glow == true)
{
menuGlow.alpha = menuGlow.alpha + 0.02;
}
else if(glow == false)
{
menuGlow.alpha = menuGlow.alpha - 0.02;
}
menu.filters = [menuGlow];
}
This is the line that is likely causing the error:
menu.filters = [menuGlow];
There is probably no object with the instance name 'menu' in your second scene. You could fix the error by just adding a check if the object exists, like so:
function increaseGlow(e:Event):void
{
//if there's no menu object, return
if(!menu) return;
if(glow == true) {
menuGlow.alpha = menuGlow.alpha + 0.02;
} else {
menuGlow.alpha = menuGlow.alpha - 0.02;
}
menu.filters = [menuGlow];
}
But the correct solution would be to remove the event listeners. Not sure why it didn't work for you, but you should be able to just add this in the click event handler before you switch your scene.
startdesu.removeEventListener(Event.ENTER_FRAME, increaseGlow);
What errors do you get when you try to remove the event listener?

Actionscript 3 drag and drop on multiple specific targes and change alpa for the dropped objects as well as stack targets

I have been trying to achieve three things in the project without success. I am new at this and have relied on tutorials to get this far. Here we go!!
a. I want to be able to drop label_3 and label_4 on either or targetlabel_3 and targetlabel_4 but not effect the other labels and targets.
b. I want to be able to drop label_2 on top of label_1 once it has been dropped. I am finding that when label_1 has been dropped, it hides the targetlabel_2 and label_2 can't find it's target.
c. I want to change the Alpa of each of labels _1, _2, _3, _4 and _5 to zero when they are dropped on their targets and change the Apha for labels _11, _21, _31, _41 and _51 to 100. (I have changed the Apha to 25 on these for the sake of making it easier for someone to see what I am trying to do).
I have been mucking around for days on this and have hit a brick wall.
Can anyone help please?
import flash.display.DisplayObject;
import flash.geom.Rectangle;
/* Drag and Drop
Makes the specified symbol instance moveable with drag and drop.
*/
var startX:Number;
var startY:Number;
var counter = 0;
var attempts = 0;
var rect:Rectangle;
rect=new Rectangle(100,100,700,500);
correct_txt.text=counter;
attempts_txt.text=attempts;
label_1.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_1.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_2.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_2.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_3.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_3.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_4.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_4.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_5.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_5.addEventListener(MouseEvent.MOUSE_UP,Drop);
label_1.buttonMode = true;
label_2.buttonMode = true;
label_3.buttonMode = true;
label_4.buttonMode = true;
label_5.buttonMode = true;
function Drag(event:MouseEvent):void
{
event.target.startDrag(true,rect);
feedback_txt.text="";
event.target.parent.addChild(event.target);
startX=event.target.x;
startY=event.target.y;
}
function Drop(event:MouseEvent):void
{
event.target.stopDrag();
var myTargetName:String="target" + event.target.name;
var myTarget:DisplayObject=getChildByName(myTargetName);
if (event.target.dropTarget!=null&&event.target.dropTarget.parent==myTarget){
feedback_txt.text="Well done! You have selcted the correct label and placed it in the recommended position on the package.";
feedback_txt.textColor = 0xCC0000
event.target.removeEventListener(MouseEvent.MOUSE_UP,Drop);
event.target.removeEventListener(MouseEvent.MOUSE_DOWN,Drag);
event.target.buttonMode = false;
event.target.x=myTarget.x;
event.target.y=myTarget.y;
counter++;
correct_txt.text=counter;
correct_txt.textColor = 0x0000ff
attempts++;
attempts_txt.text=attempts;
attempts_txt.textColor = 0x0000ff
}else{
feedback_txt.text="Your attempt is not quite correct. You have either selected the incorrect label or placed it in the wrong position. Please try again.";
event.target.x = startX;
event.target.y = startY;
attempts++;
attempts_txt.text = attempts;
}
if (counter==5){
feedback_txt.text="Well done! You have correctly placed all 5 labels";
percentage_txt.text ="Based on your attempts, you have scored "+Math.round ((counter/attempts) *100)+" %";
percentage_txt.textColor = 0x0000ff
}
}
The easiest way to detect when a label is on another label is by using hittest in an enter frame event listener.
stage.addEventListener(Event.ENTER_FRAME, hit_test);
function hit_test(e:Event):void{
if (label_1.hitTestObject(targetLabel_1)) {
trace("Label_1 is hitting targetlabel_1");
label_hit();
}
if (label_2.hitTestObject(targetLabel_2)) {
trace("Label_2 is hitting targetlabel_2");
label_hit();
}
}
When the hittest is activated, the trace text is shown and the function is called. To change the alphas of the labels, use the function being called by the hittest. For example:
function label_hit()
{
label_1.alpha = 0;
label_2.alpha = 0;
label_3.alpha = 0;
}
If you are trying to have conditions to when things can be dragged, seen, or hit tested, that function is also where you can take care of them. For example, If you don't want a label to be visible until the hittest, you have the alpha set to 0 until the function sets it to 100. If you don't want a label to be drageable until then, you create the listener inside the function instead of earlier.
function label_hit()
{
label_1.alpha = 100;
label_1.addEventListener(MouseEvent.MOUSE_DOWN,Drag);
label_1.addEventListener(MouseEvent.MOUSE_UP,Drop);
}
If you want hittests to occur only after other hittests have already occured, place them in conditions and have the conditions met in the functions.
stage.addEventListener(Event.ENTER_FRAME, hit_test);
function hit_test(e:Event):void{
if (label_1.hitTestObject(targetLabel_1)) {
trace("Label_1 is hitting targetlabel_1");
label_hit();
}
if(condition)
{
if (label_2.hitTestObject(targetLabel_2)) {
trace("Label_2 is hitting targetlabel_2");
label_hit();
}
}
function label_hit()
{
var condition = true;
}

Make an item disapear when the player touch 2 times the touch screen

I'm trying to make a flash game for a touch screen (android). My player can take some items and put them in his inventory.
The player can, then, click on a item in his inventory and drag it where he wants on the scene.
But, I'd like to make the item disapear of the screen when the player double tap on the screen.
For the moment, my player need just to taps one. (and it's frustrating as, if he hasn't put the item into the correct space and wants to corrects it by dragging the item again, it's disappearing since he clicks on a wrong space).
I know that I have to change my "removeDraggedItem" function, but I can't figure it out how to tell it that I want this function only if the player ahs double tap on the screen (not just one click)
Here's my code. If someone has an idea....
public function itemClick(e:Event):void{
inv.draggingItem = false;
var nameofMC:String;
var tempMC;
var draggedName:String = draggedItem.displayName;
if (draggedItem.lookTag)
draggedName = draggedName + draggedItem.lookTag;
if (newFriend){
nameofMC = "action_"+draggedName+"_"+newFriend.displayName;
//trace ("Looking for "+nameofMC);
try {
tempMC = getDefinitionByName(nameofMC);
//trace ("MC found.");
removeDraggedItem();
if (speech)
speech.dispatchEvent(new Event("stopTalking"));
tempMC = new tempMC;
playerAction = new PlayerAction(stageRef, draggedItem, newFriend, tempMC, false);
}
catch(e){
//trace ("No MC found. Checking for dialog option...");
try {
var tempData = linesData.dialog[newFriend.displayName].useObject[draggedItem.displayName];
if (tempData != "" && tempData != null){
//trace ("Dialog option found.");
removeDraggedItem();
alignPlayer();
if (speech)
speech.dispatchEvent(new Event("stopTalking"));
dialog = new Dialog(stageRef, newFriend, draggedItem, false);
}
}
catch(e){
//trace ("No dialog option found. Defaulting to player line.");
alignPlayer();
if (speech)
speech.dispatchEvent(new Event("stopTalking"));
var actionName:String = "Use_"+newFriend.displayName;
if (newFriend.lookTag)
actionName = actionName+newFriend.lookTag;
speech = new Speech(stageRef, draggedItem, actionName);
}
}
} else {
removeDraggedItem();
}
}
private function removeDraggedItem():void{
stageRef.removeEventListener(MouseEvent.MOUSE_MOVE, dragItem);
stageRef.removeEventListener(Event.ENTER_FRAME, itemHitTest);
draggedItem.removeEventListener(MouseEvent.CLICK, itemClick);
stageRef.removeChild(draggedItem);
toolbar.useText.text = "";
if (stageRef.contains(this))
stageRef.removeChild(this);
Mouse.show();
Engine.playerControl = true;
}
On the first tap set a variable (eg screenTap) to true and set up a Timer for the maximum amount of milliseconds you will allow between taps in a double-tap. When the Timer expires reset screenTap to false.
Then, in your tap screen handler, check if screenTap is true. If so, remove the item.
Try to use MouseEvent.DOUBLE_CLICK instead of MouseEvent.CLICK.
Make sure double click is enabled for your stage :
stageRef.doubleClickEnabled=true;
then use :
stageRef.addEventListener(MouseEvent.DOUBLE_CLICK,removeDraggedItem);

Drag and Drop error 1010 part of the time?

I have a working drag and drop game, but it's not perfect. All my movieclips drag and drop to their targets when you are exactly lined up with the target.
However, if you let go of the mouse up when dragging the mc outside of the target zones, it will sometimes, but not always, throw the 1010 term undefined error and will not snap the mc back to its original start x/y coordinates (it just leaves the mc in the spot it was during mouse up). I ran the debugger and it deals with this line in my drop function:
if (event.currentTarget.dropTarget != null && MovieClip(event.currentTarget.dropTarget.parent).allowed.indexOf(event.currentTarget) >= 0){
FYI, allowed is a set of target arrays since I wanted "zones" for targets and not specific targets for some of the movieclips.
Any ideas?
Updated Code Below:
if (event.currentTarget.dropTarget != null) {
var mc:MovieClip=event.currentTarget.dropTarget as MovieClip;
if (mc==null) { // typecast fails. Say there's a Sprite below
reply_txt.textColor = 0xEE1212
reply_txt.text = "Oops! Try Again!";
event.currentTarget.alpha = 1;
event.currentTarget.x = startX;
event.currentTarget.y = startY;
return; // nothing to do here
}
mc=mc.parent;
if (mc && mc.allowed) {
// this MC has "allowed" property not "undefined" - we're in the grid
// so now we can check indexOf() safely
if (mc.allowed.indexOf(event.currentTarget)>=0){
reply_txt.textColor = 0x33BC10
reply_txt.text = "Good Job!";
event.currentTarget.alpha = 1;
event.currentTarget.removeEventListener(MouseEvent.MOUSE_DOWN, pickUp);
event.currentTarget.removeEventListener(MouseEvent.MOUSE_UP, dropIt);
event.currentTarget.buttonMode = false;
event.currentTarget.x = MovieClip(event.currentTarget.dropTarget.parent).x;
event.currentTarget.y = MovieClip(event.currentTarget.dropTarget.parent).y;
stored.push(event.currentTarget);
startXarray.push(startX);
startYarray.push(startY);
counter++;
}
}
}
Yes, when you stopDrag an object, it checks what kind of a DisplayObject is below the cursor, and that one is returned as dropTarget property in your event. So, if your object is dropped onto another MC that does not have allowed property, your 1010 error is thrown. You need to check this situation in a nested if statement like this:
if (event.currentTarget.dropTarget != null) {
var mc:MovieClip=event.currentTarget.dropTarget as MovieClip;
if (mc==null) { // typecast fails. Say there's a Sprite below
returnThisBack();
return; // nothing to do here
}
mc=mc.parent;
if (mc && mc.allowed) {
// this MC has "allowed" property not "undefined" - we're in the grid
// so now we can check indexOf() safely
if (mc.allowed.indexOf(event.currentTarget)>=0) snapThisToGrid();
} else returnThisBack();
} else returnThisBack();