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

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
}
}

Related

Collision detection: TypeError: Error #1009: Cannot access a property or method of a null object reference

I'm trying to make a game but I'm stuck at this point:
in my game you are supposed to evade balls who come in from the right and disappear left. When you hit a ball you'll be redirected to another screen.
Here's the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at Evader/cleanUpObjects()
at Evader/update()
This is my code:
Evader.as (lines with the hyphens are the erroneous lines):
public class Evader extends MovieClip
{
public var penguin:Penguin;
private var objects:Array;
public function Evader()
{
initGame();
Mouse.hide();
objects = new Array();
addEventListener( Event.ENTER_FRAME, update );
//addEventListener( Event.ENTER_FRAME, hitObject );
}
private function initGame():void
{
penguin = new Penguin();
addChild( penguin );
}
private function update( event:Event ):void
{
if( Math.random() < 0.04 )
{
spawnObject();
}
//--------------------->cleanUpObjects();
}
private function cleanUpObjects():void
{
var currentObject:Object1;
for( var i:int = objects.length-1; i >= 0; i-- )
{
currentObject = objects[ i ];
//----------------------------->if( currentObject.x > stage.stageWidth )
{
removeChild( currentObject );
objects.splice( i, 1 );
}
}
}
private function spawnObject():void
{
var object1:Object1 = new Object1(penguin);
addChild( object1 );
objects.push( object1 );
}
/**
*private function hitObject(event:Event)
*{
* if (penguin.hitTestObject(object1))
* {
* Mouse.show();
* trace("geraakt!");
* removeEventListener( Event.ADDED_TO_STAGE, init );
* removeEventListener( Event.ENTER_FRAME, update );
* removeEventListener( Event.ENTER_FRAME, hitObject );
* Project.instance.switchScreen( "vierde" );
* }
}*/
}
}
Object1.as:
public class Object1 extends MovieClip
{
private var speed:Number;
private var penguin;
public function Object1(aPenguin: Penguin)
{
penguin = aPenguin;
addEventListener( Event.ADDED_TO_STAGE, init );
addEventListener( Event.ENTER_FRAME, hitObject );
}
private function init( event:Event ):void
{
removeEventListener( Event.ADDED_TO_STAGE, init );
addEventListener( Event.REMOVED_FROM_STAGE, unInit );
addEventListener( Event.ENTER_FRAME, move );
speed = -(1 + Math.random() * 2);
x = stage.stageWidth;
y = Math.random() * stage.stageHeight;
}
private function unInit( event:Event ):void
{
removeEventListener( Event.REMOVED_FROM_STAGE, unInit );
removeEventListener( Event.ENTER_FRAME, move );
}
private function move( event:Event ):void
{
this.x += speed;
}
private function hitObject(event:Event)
{
if (penguin.hitTestObject(this))
{
Mouse.show();
trace("geraakt!");
removeEventListener( Event.ADDED_TO_STAGE, init );
removeEventListener( Event.ENTER_FRAME, hitObject );
Project.instance.switchScreen( "vierde" );
}
}
}
}
The thing is, I need to have the hitTestObject function work for all the balls, so that it checks for collisions with all the appearing balls. Penguin is my character who is supposed to evade the balls.
If I comment the hitObject code in Object1.as and uncomment it at Evader.as, I don't know what to put in if (penguin.hitTestObject(???))
Using Objects doesn't work because it will give error #1067: Implicit coercion of a value of type Array to an unrelated type Function.
Could someone help me in getting it work?
Thanks in advance!
Evader is a DisplayObject, specifically type MovielCip. Each display object has a stage field, but the stage field is null until the display object (Evader) gets added to the stage display list (using addChild, eg. stage.addChild( myEvaderInstance) ).
So just from looking at the code you provided, it's possible you haven't added Evader to the display list, therefore its stage is null in the line:
if( currentObject.x > stage.stageWidth )
In which case you wouldn't want to add the event frame listener in its constructor. You'd want to add that listener after it's been added to the stage. So, here's how you can do that. In the Evador constructor:
public function Evader()
{
initGame();
Mouse.hide();
objects = new Array();
//don't update yet, we haven't been added to the display list
//addEventListener( Event.ENTER_FRAME, update );
addEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
}
private function onAddedToStage( e:Event ):void {
removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage );
//add the update listener!
addEventListener( Event.ENTER_FRAME, update );
}
That should do it. We wait till Evader has been added to the display list, then add the event frame listener.

Text displays on mouse release in as3

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
}

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();
}

MOUSE_DOWN trigger every frame, ActionScript 3

as I am new to as3, I want to implement a MachineGun, that fires while has ammo, and the trigger is pulled, In my case, the MouseEvent.MOUSE_DOWN.
The problem is that this event fires only once.
The closest I get is to this is MouseEvent.MOUSE_MOVE, but it fails my purpose when the mouse position is sustained
EDIT:
I need the updated mouse cursor every frame
When your MouseEvent.MOUSE_DOWN event handler you can create an event listener that listens for the Event.ENTER_FRAME event to be dispatched. Using the Event.ENTER_FRAME event handler you can repeatedly call a method that handles shooting the bullet. The following is an example I modeled after an example at http://www.benoitfreslon.com/actionscript-throw-bullets-to-mouse-direction:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
[SWF(width="500", height="500", frameRate="24", backgroundColor="0xFFFFFF")]
public class Main extends Sprite
{
private var _gun:Gun;
private var _interval:int;
public function Main():void
{
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE, init);
}// end function
private function init(e:Event = null):void
{
removeEventListener(Event.ADDED_TO_STAGE, init);
_gun = new Gun();
_gun.x = stage.stageWidth / 2 - _gun.width / 2;
_gun.y = stage.stageHeight / 2 - _gun.height / 2;
addChild(_gun);
stage.addEventListener(MouseEvent.MOUSE_DOWN, onStageMouseDown);
}// end function
private function onStageMouseDown(e:MouseEvent):void
{
stage.addEventListener(Event.ENTER_FRAME, onStageEnterFrame);
stage.addEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
}// end function
private function onStageEnterFrame(e:Event):void
{
shootBullet();
}// end function
private function shootBullet():void
{
if (_interval > 5)
{
var bullet:Bullet = new Bullet();
bullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
bullet.x = _gun.x;
bullet.y = _gun.y;
bullet.angleRadian = Math.atan2(stage.mouseY - _gun.y, stage.mouseX - _gun.x);
bullet.addEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
addChild(bullet);
_interval = 0; // reset
}// end if
_interval++;
}// end function
private function onBulletEnterFrame(e:Event):void
{
var bullet:Bullet = Bullet(e.target);
bullet.x += Math.cos(bullet.angleRadian) * bullet.SPEED;
bullet.y += Math.sin(bullet.angleRadian) * bullet.SPEED;
if ( bullet.x < 0 || bullet.x > 500 || bullet.y < 0 || bullet.y > 500)
{
removeChild(bullet);
bullet.removeEventListener(Event.ENTER_FRAME, onBulletEnterFrame);
}// end if
}// end function
private function onStageMouseUp(e:MouseEvent):void
{
stage.removeEventListener(Event.ENTER_FRAME, onStageEnterFrame);
stage.removeEventListener(MouseEvent.MOUSE_UP, onStageMouseUp);
_interval = 0;
}// end function
}// end class
}// end package
import flash.display.Sprite;
internal class Gun extends Sprite
{
public function Gun()
{
graphics.beginFill(0x000000);
graphics.drawCircle(0, 0, 10);
graphics.endFill();
}// end function
}// end class
internal class Bullet extends Sprite
{
public var angleRadian:Number;
public const SPEED:Number = 10;
public function Bullet()
{
graphics.lineStyle(1, 0x000000);
graphics.drawCircle(0, 0, 10);
graphics.endFill();
}// end function
}// end class
The point of interest is in the onStageEnterFrame() method. There's an if statement that checks whether the _interval property's value is greater than 5, if so, a new bullet is created and shot otherwise the _interval property's value is incremented. The purpose of the _interval property is to space out the bullets being shot.
[UPDATE]
Here is an image of the example flash application running:
The mouse button is being held down in the top right corner hence the bullets being shot in that direction.
On receiving a MouseEvent.MOUSE_DOWN event, run a while loop making the machine gun fire. The loop breaks on receiving a MouseEvent.MOUSE_UP event. Something like this
private function handleMouseDown( event:Event ):void
{
this.addEventListener( MouseEvent.MOUSE_UP , handleMouseUp );
startFiring();
}
private function handleMouseUp( event:Event ):void
{
this.removeEventListener( MouseEvent.MOUSE_UP , handleMouseUp );
this.addEventListener( MouseEvent.MOUSE_DOWN , handleMouseDown);
stopFiring();
}
EDIT: For clarification, the stop and start firing functions are functions that run a loop to keep the machine gun firing animation going however that may be.
add firing action to ENTER_FRAME event when mouse is pressed and remove when mouse is up
this.addEventListener( MouseEvent.MOUSE_DOWN, this.handler_down );
this.addEventListener( MouseEvent.MOUSE_UP, this.handler_up );
private function handler_down(event:Event):void {
super.addEventListener( Event.ENTER_FRAME, this.handler_frame );
}
private function handler_up(event:Event):void {
super.removeEventListener( Event.ENTER_FRAME, this.handler_frame );
}
private function handler_frame(event:Event):void {
this.fire();
}
I have to do this regularly, and instead of using an enter_frame listener, I opt for a Timer() and TimerEvent.Timer listener. That way I have more control over how often the repeat is fired without accounting for frame rate and what not.
private var fireRepeat:Timer;
private function triggerDown(e:MouseEvent):void {
if (!this.fireRepeat) { // create the repeater
this.fireRepeat = new Timer(500, 0);
this.fireRepeat.addEventListener(TimerEvent.TIMER, this.fire);
}
fire(); // fire the first bullet
this.fireRepeat.reset(); // reset the repeater
this.fireRepeat.start(); // start the repeater
}
private function triggerUp(e:MouseEvent):void {
if (this.fireRepeat) { this.fireRepeat.stop(); }
}
public function fire(e:* = null):void {
trace('fire!');
}

Convert AS2 por AS3...please

oranja.onPress = function(){
this.startDrag(true);
}
oranja.onRelease = function(){
this.stopDrag();
if(this.hitTest(this._parent.trash)){
trace("trash");
this.unloadMovie();
} else {
trace("no trash");
}
}
I think you're looking for an AS3 version of this? Something like this should work:
oranja.addEventListener( MouseEvent.MOUSE_DOWN, this._onPress );
oranja.addEventListener( MouseEvent.MOUSE_UP, this._onRelease );
// called when we mouse down on the oranja clip
private function _onPress( e:MouseEvent ):void
{
oranja.startDrag( true )
}
// called when we mouse up on the oranja clip
private function _onRelease( e:MouseEvent ):void
{
oranja.stopDrag();
if( oranja.hitTest( oranja.parent.trash ) )
{
trace( "trash" );
// remove the event listeners
oranja.removeEventListener( MouseEvent.MOUSE_DOWN, this._onPress );
oranja.removeEventListener( MouseEvent.MOUSE_UP, this._onRelease );
// remove the oranja clip
oranja.parent.removeChild( oranja );
oranja = null;
}
else
trace( "not trash" );
}
You should probably replace the oranja calls in _onPress() and _onRelease() with e.target or e.currentTarget