Text displays on mouse release in as3 - actionscript-3

Ok, I have a question about drag/drop, hittest and some text.
I have two objects, one of them is draggable. I want to display some text, when colission is detected, but only when mouse is UP (mouse is released).
How to do that?
This is part of the code that handles collision:
this.addEventListener( Event.ENTER_FRAME, handleCollision)
function handleCollision( e:Event ):void
{
if(zuto.hitTestObject(tabla) && crveno.hitTestObject(tabla))
{
tekst.text = "GAME OVER"
} else {
tekst.text = ""
}
}

Should check if the mouse is down or not:
var mouseDown:Boolean;
stage.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
stage.addEventListener(MouseEvent.MOUSE_Up, onMouseUp);
function onMouseDown(e:MouseEvent):void {
mouseDown = true;
}
function onMouseUp(e:MouseEvent):void {
mouseDown = false;
}
function handleCollision( e:Event ):void {
if (mouseDown) { // mouse is still down, stop collision check
return;
}
// ..rest of your code here
}

Related

change keyboard event to mouse event as3

I am a new new person who learn action script 3.
i have problem when i convert keyboard event to mouse event when i moving a walking character.
when use the keyboard event i have no problem. this is my code
import flash.ui.Keyboard;
var speed:Number=2;
stage.addEventListener(KeyboardEvent.KEY_DOWN, stikman);
function stikman(e:KeyboardEvent)
{
if (e.keyCode==Keyboard.LEFT)
{
stik.x-=speed;
stik.scaleX=-1;
stik.stik2.play();
}
else if (e.keyCode==Keyboard.RIGHT)
{
stik.x+=speed;
stik.scaleX=1;
stik.stik2.play();
}
}
and then i try to change keyboard event to mouse event when moving character with button it should press click, click and click. i want to hold the click when moving the character and when mouse up the character stop. but i still don't know how. this my code when i try to change to mouse event
var speed:Number=2;
mundur.addEventListener(MouseEvent.MOUSE_DOWN, stikman);
function stikman(e:MouseEvent)
{
stik.x-=speed;
stik.scaleX=-1;
stik.stik2.play();
}
maju.addEventListener(MouseEvent.CLICK, stikman2);
function stikman2(e:MouseEvent)
{
stik.x+=speed;
stik.scaleX=1;
stik.stik2.play();
}
Because keyboard produces KeyboardEvent.KEY_DOWN event repeatedly as long as key is pressed, while MouseEvent.CLICK as well as MouseEvent.MOUSE_DOWN are dispatched only once per user action.
With mouse you need to change the logic.
// Subscribe both buttons.
ButtonRight.addEventListener(MouseEvent.MOUSE_DOWN, onButton);
ButtonLeft.addEventListener(MouseEvent.MOUSE_DOWN, onButton);
var currentSpeed:Number = 0;
var isPlaying:Boolean = false;
function onButton(e:MouseEvent):void
{
// Set up the directions and start the animation.
switch (e.currentTarget)
{
case ButtonLeft:
currentSpeed = -speed;
stik.stik2.play();
stik.scaleX = -1;
break;
case ButtonRight:
currentSpeed = speed;
stik.stik2.play();
stik.scaleX = 1;
break;
}
isPlaying = true;
// Call repeatedly to move character.
addEventListener(Event.ENTER_FRAME, onFrame);
// Hook the MOUSE_UP even even if it is outside the button or even stage.
stage.addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onFrame(e:Even):void
{
// Move character by the designated offset each frame.
stik.x += currentSpeed;
if (!isPlaying)
{
// Stop at last frame.
// if (stik.stik2.currentFrame == stik.stik2.totalFrames)
// Stop at frame 1.
if (stik.stik2.currentFrame == 1)
{
// Stop the animation.
stik.stik2.stop();
// Stop moving.
removeEventListener(Event.ENTER_FRAME, onFrame);
}
}
}
function onUp(e:MouseEvent):void
{
// Indicate to stop when the animation ends.
isPlaying = false;
// Unhook the MOUSE_UP event.
stage.removeEventListener(MouseEvent.MOUSE_UP, onUp);
}

How to prevent a drag action to affect the childrens of a MovieClip

My problem is: I have a MovieClip (obj) that users can drag to both sides to navigate, the code I use for this:
import flash.events.MouseEvent;
import flash.geom.Point;
import flash.events.Event;
import flash.geom.Rectangle;
var destination: Point = new Point();
var dragging: Boolean = false;
var speed: Number = 10;
var offset: Point = new Point();
var bounds: Rectangle = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight);
obj.addEventListener(MouseEvent.MOUSE_DOWN, startdrag);
stage.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
obj.addEventListener(Event.ENTER_FRAME, followmouse);
function startdrag(e: MouseEvent): void {
offset.x = obj.mouseX * obj.scaleX;
dragging = true;
}
function stopdrag(e: MouseEvent): void {
dragging = false;
}
function followmouse(e: Event): void {
if (obj) {
if (dragging) {
destination.x = mouseX;
}
obj.x -= (obj.x - (destination.x - offset.x)) / speed;
if (obj.x > bounds.left) {
obj.x = bounds.left;
}
if (obj.x < -obj.width + bounds.right) {
obj.x = -obj.width + bounds.right;
}
}
}
So far so good, the problem comes up when I put some clickable elements inside that MovieClip (obj), here are the code for the clickable elements:
objA.addEventListener(MouseEvent.CLICK, objATrigger);
objB.addEventListener(MouseEvent.CLICK, objBTrigger);
objC.addEventListener(MouseEvent.CLICK, objCTrigger);
function objATrigger(event: MouseEvent): void {
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
function objBTrigger(event: MouseEvent): void {
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
function objCTrigger(event: MouseEvent): void {
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
The problem is: When I drag the MovieClip (obj) there is a conflict with the event, when release the mouse after the drag, the event Click of MovieClips inside the MovieClip (obj) is fired, how can I fix this? They should only be triggered when there is no drag action.
This is how I handle dragging a parent that has clickable children. The benefit of this method, is that you don't need to do anything to the children (no extra conditions in their click handlers etc), the click event simply doesn't reach them.
You can also hopefully gleam some efficiency tips from the code/comments below:
var wasDragged:Boolean = false;
var dragThreshold:Point = new Point(10,10);
// ^ how many pixels does it need to move before it's considered a drag
//this is good especially on touchscreens as it's easy to accidentally drag the item a couple pixels when clicking.
var dragStartPos:Point = new Point(); //to store drag origin point to calculate whether a drag occured
var dragOffset:Point = new Point(); //to track the gap between the mouse down point and object's top left corner
obj.addEventListener(MouseEvent.MOUSE_DOWN, startdrag);
obj.addEventListener(MouseEvent.CLICK, dragClick, true); //listen on the capture phase of the event.
//the only reason we listen for click on the draggable object, is to cancel the click event so it's children don't get it
function dragClick(e:Event):void {
//if we deemed it a drag, stop the click event from reaching any children of obj
if(wasDragged) e.stopImmediatePropagation();
}
function startdrag(e: MouseEvent): void {
//reset all dragging vars
wasDragged = false;
dragStartPos.x = obj.x;
dragStartPos.y = obj.y;
//set the offset so the object doesn't jump when first clicked
dragOffset.x = stage.mouseX - obj.x;
dragOffset.y = stage.mouseY - obj.y;
//only add the mouse up listener AFTER the mouse down
stage.addEventListener(MouseEvent.MOUSE_UP, stopdrag);
//mouse_move is more efficient that enter_frame, and only listen for it when dragging
stage.addEventListener(MouseEvent.MOUSE_MOVE, followmouse);
}
function stopdrag(e:MouseEvent = null): void {
//remove the dragging specific listeners
stage.removeEventListener(MouseEvent.MOUSE_UP, stopdrag);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, followmouse);
}
function followmouse(e:MouseEvent): void {
if (obj) {
//do what you need to move the object
obj.x = stage.mouseX - dragOffset.x;
obj.y = stage.mouseY - dragOffset.y;
//check if the obj moved far enough from the original position to be considered a drag
if(!wasDragged
&& (Math.abs(obj.x - dragStartPos.x) > dragThreshold.x
|| Math.abs(obj.y - dragStartPos.y) > dragThreshold.y)
){
wasDragged = true;
}
}
}
I don`t know if this is the best approach, but it was possible to check using the code below:
stage.addEventListener(MouseEvent.MOUSE_DOWN, setmousepos);
brose_trigger.addEventListener(MouseEvent.MOUSE_UP, broseTrigger);
denso_trigger.addEventListener(MouseEvent.MOUSE_UP, densoTrigger);
honda_trigger.addEventListener(MouseEvent.MOUSE_UP, hondaTrigger);
var mousePos: Point = new Point();
function setmousepos(e:MouseEvent): void {
mousePos.x = mouseX;
}
function broseTrigger(e:MouseEvent): void {
if(mousePos.x == mouseX){
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
}
function densoTrigger(event:MouseEvent): void {
if(mousePos.x == mouseX){
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
}
function hondaTrigger(event:MouseEvent): void {
if(mousePos.x == mouseX){
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
}
When MOUSE_DOWN event is triggered, I store the mouse.x position in a variable, after that in the MOUSE_UP event, I compare the stored position with the actual position, if equals, TÃDÃ!
Do add condition in objATrigger function to check if dragging is false
function objATrigger(event: MouseEvent): void {
if(!MovieClip(root).dragging){
MovieClip(this.parent).gotoAndPlay(1, "Main");
}
}

Flash Game ArgumentError: Error #2025 removeChild

I'm trying to get the bat character to remove the jack/2/3 child(s) in my game here, but I keep getting the ArgumentError: Error #2025. I understand that I may be removing a child twice, perhaps? I'm looking around and I'm not really experienced in this stuff so I'm having a hard time understanding what needs to be done to fix this issue. Can someone tell me what needs to be done with my code specifically, please?
var jack:pumpkin = new pumpkin();
var jack2:pumpkin = new pumpkin();
var jack3:pumpkin = new pumpkin();
var score:Number = 0;
scoreBox.text = String(score);
addChild(jack);
jack.x = 125;
jack.y = 285;
addChild(jack2);
jack2.x = 270;
jack2.y = 310;
addChild(jack3);
jack3.x = 445;
jack3.y = 285;
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveLeft);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveRight);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveDown);
stage.addEventListener(KeyboardEvent.KEY_DOWN, moveUp);
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function moveLeft(e:KeyboardEvent):void {
if (e.keyCode == 37) {
bat.x -= 5;
}
}
function moveRight(e:KeyboardEvent):void {
if (e.keyCode == 39) {
bat.x += 5;
}
}
function moveDown(e:KeyboardEvent):void {
if (e.keyCode == 40) {
bat.y += 5;
}
}
function moveUp(e:KeyboardEvent):void {
if (e.keyCode == 38) {
bat.y -= 5;
}
}
function bump(e:KeyboardEvent):void {
stage.addEventListener(Event.ENTER_FRAME, bumpIt);
function bumpIt(e:Event):void {
if (bat.hitTestObject(jack)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack);
score++;
scoreBox.text = String(score);
}
if (bat.hitTestObject(jack2)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack2);
score++;
scoreBox.text = String(score);
}
if (bat.hitTestObject(jack3)) {
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
removeChild(jack3);
score++;
scoreBox.text = String(score);
}
}
}
Due to the nested bumpit() event handler, on every key up you're adding another enter frame event if your hit-test has no collision.
On KeyboardEvent.KEY_UP, event handler calls bump() which adds an Event.ENTER_FRAME listener that will call bumpIt().
If bat.hitTestObject() is true, you remove Event.ENTER_FRAME.
If not, you still have the Event.ENTER_FRAME listener firing bumpIt() every frame.
So, every key up you're potentially adding another frame handler.
If ten key up events occurred and none of them hit test your objects, you are now calling bumpIt ten times a frame.
If you need to hit test on key up, just put the logic there:
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function bump(e:KeyboardEvent):void {
if (bat.hitTestObject(jack)) { /* ... */ }
}
Or, if you're tracking an animation sequence after key up, maybe add some state variable, such as:
var isFlying:Boolean = false;
stage.addEventListener(KeyboardEvent.KEY_UP, bump);
function bump(e:KeyboardEvent):void {
// If bat is already flying, don't add another frame handler
if (isFlying)
return;
// Otherwise, indicate bat is now flying and add frame handler
isFlying = true;
stage.addEventListener(Event.ENTER_FRAME, bumpIt);
}
Then, if your hit-test works and you remove your frame handler, reset the state variable:
stage.removeEventListener(Event.ENTER_FRAME, bumpIt);
isFlying = false;
Another solution is to remove the nested handlers. Because you have nested bumpIt() inside bump(), you are seeing cumulative firing of callbacks due to scope:
function bump():void {
function bumpIt():void { /* ... */ }
}
Simply promote bumpIt():
function bump():void { /* ... */ }
function bumpIt():void { /* ... */ }

click tap or touch begin and drag an object on the same time as3

i am creating a buttons bar that can be dragged however when i lift my finger after dragging the buttons the button is getting pushed, i would like to cancel the click/tap when dragging the buttons any suggestions?
Thank you
You'll either need to remove/add your listeners as necessary, or have a property on your buttons. Something like:
public class DragButton extends Sprite
{
public var isDragging:Boolean = false;
public function DragButton()
{
// add our listeners
this.addEventListener( MouseEvent.MOUSE_DOWN, this._onMouseDown );
this.addEventListener( MouseEvent.MOUSE_UP, this._onMouseUp );
this.addEventListener( MouseEvent.CLICK, this._onMouseClick );
}
private function _onMouseDown( e:MouseEvent ):void
{
// add our move listener for dragging
this.addEventListener( MouseEvent.MOUSE_MOVE, this._onMouseMove );
}
private function _onMouseUp( e:MouseEvent ):void
{
// remove our dragging listener
this.removeEventListener( MouseEvent.MOUSE_MOVE, this._onMouseMove );
}
private function _onMouseMove( e:MouseEvent ):void
{
// drag us
this.x = e.stageX;
this.y = e.stageY;
this.isDragging = true;
}
private function _onMouseClick( e:MouseEvent ):void
{
// if we're dragging, ignore
if( this.isDragging )
{
this.isDragging = false;
return;
}
// do our click stuff
}
}

Flash AS3 hit test go to next frame

I have a object that can be dragged into another object. I have set up a hit test for the collision. When the collision occurs I would like to progress to the next frame however, I have to click on the draggable object for it to do so. I would like it to move to the next frame right away without clicking. Is there anyway to fix this?
I mean after I have dragged the objected to create the collision I need to click on the object again to progress to the next frame. I do not want to have to click on the object again I want it to go to the next frame as the collision occurs.
This is my code
bottle.buttonMode = true;
bottle.addEventListener(MouseEvent.MOUSE_DOWN, drag);
bottle.addEventListener(MouseEvent.MOUSE_UP, drop);
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
collision();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
}
You should be checking for collisions after the drop, not at the start of the drag:
function collision():void{
if(bottle.hitTestObject(hit)){
nextFrame();
}
}
function drag(e:MouseEvent):void{
bottle.startDrag();
}
function drop(e:MouseEvent):void{
bottle.stopDrag();
collision();
}
Change collision() into an event listener and attach it to bottle.
Try this one ( adapted from Gary Rosenzweig ) :
bottle.buttonMode = true;
bottle.addEventListener( MouseEvent.MOUSE_DOWN, startBottleDrag );
stage.addEventListener( MouseEvent.MOUSE_UP, stopBottleDrag );
function collision():void {
if( bottle.hitTestObject( hit ) ) {
stopBottleDrag();
nextFrame();
}
}
// to keep bottle location as it is when clicked
var clickOffset:Point = null;
function startBottleDrag( e:MouseEvent ) {
clickOffset = new Point( e.localX, e.localY );
bottle.addEventListener( Event.ENTER_FRAME, dragBottle );
}
function stopBottleDrag( e:MouseEvent = null ) {
clickOffset = null;
bottle.removeEventListener( Event.ENTER_FRAME, dragBottle );
}
function dragBottle( e:Event ) {
bottle.x = mouseX - clickOffset.x;
bottle.y = mouseY - clickOffset.y;
collision();
}