Drag & Drop Function Not Working - Flash - actionscript-3

I am trying to create a function in ActionScript that shall trigger an event when a drag-gable object is dropped over another object.
var hits = 0;
// Register mouse event functions
answer_j.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_j.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_e.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_e.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_m.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_m.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_b.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_b.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_a1.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_a1.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_t.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_t.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_a2.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_a2.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
answer_n.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
answer_n.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
// Define a mouse down handler (user is dragging)
function mouseDownHandler(evt:MouseEvent):void
{
var object = evt.target;
// limit dragging to the area inside the canvas
object.startDrag();
}
function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
// obj.dropTarget will give us the reference to the shape of
// the object over which we dropped the circle.
var target = obj.dropTarget;
// If the target object exists the we ask the test_match function
// to compare moved obj and target where it was dropped.
if (target != null)
{
test_match(target, obj);
}
obj.stopDrag();
}
function test_match(target,obj) {
// test if either one of the four pairs match
if ( (target == box_j && obj == answer_j) ||
(target == box_e && obj == answer_e) ||
(target == box_m && obj == answer_m) ||
(target == box_b && obj == answer_b) ||
(target == box_a1 && obj == answer_a1) ||
(target == box_t && obj == answer_t) ||
(target == box_a2 && obj == answer_a2) ||
(target == box_n && obj == answer_n) )
{ // we got a hit
hits = hits+1;
textField.text = "Yes ! You got one !";
// make the object transparent
obj.alpha = 0.5;
// kill its event listeners - object can't be moved anymore
obj.removeEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
obj.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
// Test if we are done
if (hits == 8) {
textField.text = "Made it !!";
}
} else {
textField.text = "Missed :(";
}
}
box_j - box_n are the objects that shall be the target for the drag-gable objects.
However, for certain unknown reasons the above code won't work. Kindly please advise if you know how to resolve it.
All object are in "movie clip" type.

Just change the order inside your mouseUpHandler function.
Stop the drag before you reference the dropTarget when this don't work you should add .parent to the dropTarget:
function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
obj.stopDrag();
// obj.dropTarget will give us the reference to the shape of
// the object over which we dropped the circle.
var target = obj.dropTarget;
//var target = obj.dropTarget.parent;
// If the target object exists the we ask the test_match function
// to compare moved obj and target where it was dropped.
if (target != null) {
test_match(target, obj);
}
}
EDIT:
This is why you have to use .parent sometimes:
When you put the target on the stage in the authoring mode and not
through AS then the dropTarget property will reference the Shape. To
get the instance of the MovieClip or Sprite that contains the
Shape you need to use the parent parameter.

Related

why doesn't (if) work with no mistakes in code

my code is with AS3 ,( if-else) when i run it doesn't give me a mistake,but also doesn't give me the result of (if) that i want.
the ( tom) object has to be unvisible if touched another object called (food )else (tom) go back to ot's place
the idea is with ( drag and drop )
var hits = 0;
tom.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
tom.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(evt:MouseEvent):void {
var object = evt.target;
// we should limit dragging to the area inside the canvas
object.startDrag();
}
function mouseUpHandler(evt:MouseEvent):void {
var obj = evt.target;
var target = obj.dropTarget;
if (target == food && obj == tom) {
obj.visible=false;
} else {
obj.x=1051.05;
obj.y=135.05;
obj.stopDrag();
}
}
"When I run it doesn't give me a mistake, but also doesn't give me the result of if that I want."
That's because there is no error. You don't get a result because your IF condition is never reached. Think about example: if (obj == tom) Here what would ever make var obj be equal to var tom?
Solution:
I suspect food and tom are names, right? Try code to check by instance name...
function mouseUpHandler (evt:MouseEvent) :void
{
var obj = evt.target;
var target = obj.dropTarget;
if (target.name == "food" && obj.name == "tom")
{
obj.visible = false;
}
else
{
obj.x = 1051.05;
obj.y = 135.05;
obj.stopDrag();
}
}

AS3 : EventListener won't be removed in an [IF]

I have searched how to pass arguments through EventListeners, and I used the method without calling an anonymous function to remove the EventListener later.
The issue is that the EventListener will be removed if out the IF function, but not if it is in the IF function.
How could I do that ?
The code :
function dragShip(m:MouseEvent):void
{
var func:Function = dispositionShip(m.target);
if (isDragging == false)
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, func);
m.target.startDrag(true);
isDragging = true;
}
else
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, func);
isDragging = false;
placeShip(m.target , mouseX , mouseY , m.target.rotation);
}
// if the EventListener is put here, it gets removed, but not if put just in the else
}
NOTE : dispositionShip()returns a function.
Edit : Here is the following part of the code :
function dispositionShip(shipTarg):Function
{
return function(k:KeyboardEvent):void
{
rotateShip(k,shipTarg);
};
}
function rotateShip(k:KeyboardEvent,ship:Object):void
{
if (k.keyCode == 39)
{
ship.rotation += 90;
}
else if (k.keyCode == 37)
{
ship.rotation -= 90;
}
}
Moreover, if I replace rotateShip(k,shipTarg); by a simple trace, it also does not work.
Everytime you call
function dispositionShip(shipTarg):Function
{
return function(k:KeyboardEvent):void
{
rotateShip(k,shipTarg);
};
}
You're creating a new anonymous Object of type Function that calls rotateShip(), so when you call stage.removeEventListener(KeyboardEvent.KEY_DOWN, func); your func is a different Object to the func you passed into addEventListener(), so it doesn't match the orginal listener and doesn't get removed.
A better way to do this would be to store the current mouse target in a member var. IE:
var currentShip:Object;
function dragShip(m:MouseEvent):void
{
if (isDragging == false)
{
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyPress);
m.target.startDrag(true);
isDragging = true;
currentShip = m.target;
}
else
{
stage.removeEventListener(KeyboardEvent.KEY_DOWN, keyPress);
isDragging = false;
placeShip(m.target , mouseX , mouseY , m.target.rotation);
currentShip = null;
}
}
function keyPress(k:KeyboardEvent):void
{
rotateShip(k,currentShip);
}

AS3 Object Bin and Reset Button

I am trying to create a game for kids where they can drag letters on to a stage to make words.
I want to add a 'trash can' where users can drag letters they no longer need to dispose of them. I have created the movie clip but am totally unsure how to make it function using AS3.
I would also like to add a reset button so that the stage reverts to it's original state. Again, I have drawn it up and added the little as3 that I am aware of (to make it a button) but if anyone could assist with how to actually make this happen, I would be grateful.
The files are here: SWF | FLA and the code for the game is as follows:
import flash.display.MovieClip;
for (var i=1; i<27; i++)
{
this["object" + i].addEventListener(MouseEvent.MOUSE_DOWN, onStart);
this["object" + i].addEventListener(MouseEvent.MOUSE_UP, onStop);
}
var sx = 0,sy = 0;
function onStart(e)
{
sx = e.currentTarget.x;
sy = e.currentTarget.y;
e.currentTarget.startDrag();
}
function onStop(e)
{
if ( e.target.dropTarget != null &&
e.target.dropTarget.parent == dest &&
e.currentTarget.name != "copy" )
{
var objectClass:Class =
getDefinitionByName(getQualifiedClassName(e.currentTarget)) as Class;
var copy:MovieClip = new objectClass();
copy.name = "copy";
this.addChild(copy);
copy.x = e.currentTarget.x;
copy.y = e.currentTarget.y;
e.currentTarget.x = sx;
e.currentTarget.y = sy;
copy.addEventListener(MouseEvent.MOUSE_DOWN, onStart);
copy.addEventListener(MouseEvent.MOUSE_UP, onStop);
}
e.currentTarget.stopDrag();
}
resetButton.addEventListener(MouseEvent.CLICK, reset);
resetButton.buttonMode = true;
function reset(event:MouseEvent):void
{
//Not sure what AS3 to add here to reset to original state
}
I have already gave you the solution here Flash AS3 Clone, Drag and Drop
Here, I am providing a detail solution on how to drag objects inside a bin and remove them.
For dropping copied objects inside a bin, after dragging is stopped, check collision with bin object. for more info see,
copiedObject.hitTestObject(binObject)
For e.g.
First create trash-can MovieClip on the stage and give it an instance name 'trashCan' and add following lines to your onStop()(below e.currentTarget.stopDrag();)function like so:
UPDATE:
var copiedObjsArr:Array = [];
function onStop(e)
{
if ( e.target.dropTarget != null &&
e.target.dropTarget.parent == dest &&
e.currentTarget.name != "copy" )
{
//Code here remains same
//.......
//Keep collecting copied letters for further access in `reset()` function
copiedObjsArr.push(copy);
}
else if(e.currentTarget.name == "copy") //this is 'else if' (newly added)
{
var tarObject:MovieClip = e.currentTarget;
// These detects collision of dragged object with the trashCan
if(tarObject.hitTestObject(trashCan)) {
//These removes dragged object from the display list (not from the memory)
removeChild(tarObject);
tarObject = null; //to garbage
}
}
e.currentTarget.stopDrag();
}
And your reset() becomes like so:
function reset(event:MouseEvent):void
{
if(copiedObjsArr.length > 0)
{
//Traverse through all copied letters
for(var i:int = 0; i<copiedObjsArr.length; i++)
{
var objToRemove:MovieClip = copiedObjsArr[i];
removeChild(objToRemove);
objToRemove = null;
}
//Finally empty the array
copiedObjsArr = [];
}
}

Making an object or layer transparent when another object passes over it. (Flash Actionscript 3.0)

I'm very new to coding and am having trouble finishing the last little bit of a mini game type project for school.
So this is a draft of what the program looks like so far: http://aaronmillard.com/dir/wp-content/uploads/2013/08/Google-Doodle_Roomba.swf
Now what I want the program to do is "vacuum" up the google when the roomba drives over it. The easiest way to achieve this (I think) is to have an exact replica of the carpet layer without the google logo beneath the carpet layer with the google logo. So I would need to code something like "when the object(roomba) passes over object(carpetwithgooglelogo) make object(carpetwithgooglelogo) have 0 opacity." I just can't figure out how to say that in code.
The code as of right now look like this:
// Assign 4 booleans for the 4 arrow keys
var keyUp = false;
var keyDown = false;
var keyLeft = false;
var keyRight = false;
// Add the keyboard event (KEY_DOWN) on the stage
stage.addEventListener(KeyboardEvent.KEY_DOWN, pressKey);
function pressKey(pEvent)
{
// If an arrow key is down, switch the value to true to the assigned variable
if (pEvent.keyCode == 38)
{
keyUp = true;
}
else if (pEvent.keyCode == 40)
{
keyDown = true;
}
else if (pEvent.keyCode == 37)
{
keyLeft = true;
}
else if (pEvent.keyCode == 39)
{
keyRight = true;
}
}
// Add the keyboard event (KEY_UP) on the stage
stage.addEventListener(KeyboardEvent.KEY_UP, releaseKey);
function releaseKey(pEvent)
{
// If the arrow key is up, switch the value to false to the assigned variable
if (pEvent.keyCode == 38)
{
keyUp = false;
}
else if (pEvent.keyCode == 40)
{
keyDown = false;
}
else if (pEvent.keyCode == 37)
{
keyLeft = false;
}
else if (pEvent.keyCode == 39)
{
keyRight = false;
}
}
// Set the velocity of the object
var speed = 4;
// And the rotation speed
var rotationSpeed = 6;
// Add an enter frame event on the moving object
myCircle.addEventListener(Event.ENTER_FRAME, circleEnterFrame);
function circleEnterFrame(pEvent)
{
// Set the default velocity to 0 if no key is pressed
var velocity = 0;
if (keyUp)
{
// If the key up is pressed set the new velocity to the speed value
velocity = speed;
}
if (keyDown)
{
// If the key down is pressed set the new velocity to the half speed value
velocity = -speed/2;
}
if (keyLeft)
{
// rotate the object
pEvent.currentTarget.rotation -= rotationSpeed;
}
if (keyRight)
{
// rotate the object
pEvent.currentTarget.rotation += rotationSpeed;
}
// Convert the degreeAngle to the radian angle
var angleRadian = pEvent.currentTarget.rotation / 180 * Math.PI;
// Move the object with the radian angle and the object speed
pEvent.currentTarget.x += Math.cos(angleRadian) * velocity;
pEvent.currentTarget.y += Math.sin(angleRadian) * velocity;
}
Any help would be very much appreciated! Thanks!
The easiest way is to do something like this:
if( roomba.hitTestObject(google)){
google.alpha = 0;
}
You'll have to check this on every frame using an ENTER_FRAME event.
If this is confusing tell me in the comments and I will clarify with more code.

Starling onClick method

I'm using starling framework, to simulate onclick method I use this code:
if(e.getTouch(this).phase == TouchPhase.ENDED){
//Some code
}
It's OK, but it also fires, if the mouse is not over the button anymore, however I'd like it to dispatch only if it's over. Is there any way to achieve this?
thanks
in the code, "this" is a Sprite, It's kinda irrelevant thougth
According to the docs the interactsWith(target:DisplayObject) method of the TouchEvent class should return true if the target is currently being touched. I have no way to test this theory, but the following should work:
if (e.getTouch(this).phase == TouchPhase.ENDED && e.interactsWith(this)) {
//The touch ended on the same DisplayObject as it originated at
}
How about this idea:
if ( e.getTouch( this ).phase == TouchPhase.ENDED ) {
if ( this.hitTestPoint( stage.mouseX, stage.mouseY, true ) ) {
// Some code
}
}
The easy way would be to use a starling.display.Button to do it. they dispatch TRIGGERED Events, which are basically what you want. The 'not so easy' way is to keep track of your touches, by replicating what is actually done in Button :
private function onTouch(event:TouchEvent):void
{
var touch:Touch = event.getTouch(this);
if (!mEnabled || touch == null) return;
if (touch.phase == TouchPhase.BEGAN && !mIsDown)
{
//equivalent to MOUSE_DOWN
mIsDown = true;
}
else if (touch.phase == TouchPhase.MOVED && mIsDown)
{
// reset button when user dragged too far away after pushing
var buttonRect:Rectangle = getBounds(stage);
if (touch.globalX < buttonRect.x - MAX_DRAG_DIST ||
touch.globalY < buttonRect.y - MAX_DRAG_DIST ||
touch.globalX > buttonRect.x + buttonRect.width + MAX_DRAG_DIST ||
touch.globalY > buttonRect.y + buttonRect.height + MAX_DRAG_DIST)
{
mIsDown = false;
}
}
else if (touch.phase == TouchPhase.ENDED && mIsDown)
{
mIsDown = false;
//this is a click
dispatchEventWith(Event.TRIGGERED, true);
}
}
you'l have to change the buttonRect code to reflect your sprite's shape, but basically here you are.