How can I set the draggin box mc 50px from the bottom - actionscript-3

I Have a mc called box.
All I want is when dragging up I want the bottom of box mc 50px from the bottom of the stage.
Now it's in the middle of the stage.
Here is my code.
var topY:int = stage.stageHeight - box.height;
var botY:int = 0;
box.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
box.addEventListener(MouseEvent.MOUSE_UP, onUp);
var constrainY:Rectangle = new Rectangle(box.x, topY ,0, box.y+ (box.height-stage.stageHeight) );
var dragxy:String = "";
function onDown(e:MouseEvent):void
{
dragxy = mouseX + "_" + mouseY;
e.currentTarget.startDrag(false, constrainY);
}
function onUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
}

One bad thing I'm seeing is you are adding an eventListener every frame that the mouse button is down ( I think ). To not do that, just call start drag once when Mouse Down is true and then stop listening for mouse down. When mouse goes back up, start listening for down again.
function onDown(e:MouseEvent):void
{
dragxy = mouseX + "_" + mouseY;
e.currentTarget.startDrag(false, constrainY);
removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
addEventListener(MouseEvent.MOUSE_DOWN, onDown);
removeEventListener(MouseEvent.MOUSE_UP, onUp);
}

Related

How can I use "ease" for smoother dragging?

I have dragging mc called "box" but the dragging is not smooth at all.
So how can I make it smoother by using "ease" var.
I'm trying to use "/ease" anywhere but not work.
var topY:int = stage.stageHeight - box.height;
var botY:int = 0;
box.addEventListener(MouseEvent.MOUSE_DOWN, onDown);
box.addEventListener(MouseEvent.MOUSE_UP, onUp);
var constrainY:Rectangle = new Rectangle(box.x, topY ,0, box.y+ (box.height-stage.stageHeight) );
var dragxy:String = "";
function onDown(e:MouseEvent):void
{
dragxy = mouseX + "_" + mouseY;
e.currentTarget.startDrag(false, constrainY);
removeEventListener(MouseEvent.MOUSE_DOWN, onDown);
addEventListener(MouseEvent.MOUSE_UP, onUp);
}
function onUp(e:MouseEvent):void
{
e.currentTarget.stopDrag();
addEventListener(MouseEvent.MOUSE_DOWN, onDown);
removeEventListener(MouseEvent.MOUSE_UP, onUp);
}
a simple example of an easing function would be:
private function easeTo(obj:MovieClip,currentGoalx:Number,currentGoaly:Number,easeFac:Number):void{
obj.x += (currentGoalx-obj.x)/easeFac;
obj.y += (currentGoaly-obj.y)/easeFac;
}
first you will need a timer or enter frame loop such as this added to the stage:
addEventListener(Event.ENTER_FRAME,enterFrame);
then in your enterFrame function do this:
private function enterFrame(e:Event):void{
easeTo(box,stage.mouseX,stage.mouseY,3);
}
an easeFac of 3 is a slower and smoother ease-in than an easeFac of 2, and 4 is even smoother and buttery-er.
or something like that. The idea is that the obj goes half the distance to the goal on each function call. So if this function is getting called on every frame, you'll get a smooth "ease in" effect. If you set currentGoal as the mouse position, then the obj will follow the mouse wherever it goes, but not in a 1:1 matching, rather it will trail behind and smoothly catch up.

AS3 Works but I get a ReferenceError: Error #1069 Property startDrag not found

I am trying to make a simple project when you click a button a draggable MovieClip is added to the stag and when you click it releases the MovieClip to the X/Y where you clicked, you can then pickup the MovieClip and drag it into a bin (MovieClip) where it destroys itself. The code is working great I can make multiple Movieclips with the button and they are all destroyed when I drag them in the bin however I don't like having "Error Codes".
import flash.events.MouseEvent;
var rubbish:my_mc = new my_mc();
btntest.addEventListener(MouseEvent.CLICK, makeRubbish);
function makeRubbish (event:MouseEvent):void {
addChild(rubbish);
rubbish.x = mouseX - 10;
rubbish.y = mouseY - 10;
rubbish.width = 50;
this.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
rubbish.buttonMode = true;
}
function stopDragging (event:MouseEvent):void {
rubbish.stopDrag()
event.target.addEventListener(MouseEvent.CLICK, startDragging);
rubbish.buttonMode = true;
if (event.target.hitTestObject(bin))
{
trace("hit");
event.target.name = "rubbish";
removeChild(getChildByName("rubbish"));
}
}
function startDragging (event:MouseEvent):void {
event.target.startDrag();
this.addEventListener(MouseEvent.CLICK, stopDragging);
}
Some Pointers:
The target property of an Event is not always what it seems. It actually refers to the current phase in the event bubbling process. Try using the currentTarget property.
I would also recommend tying the stopDragging method to the stage, as sometimes your mouse won't be over the drag as you're clicking.
I would use the MOUSE_UP event as opposed to a CLICK for standard dragging behaviour.
When dragging, keep a global reference to the drag in order to call the stopDrag method on the correct object.
Try This:
import flash.events.MouseEvent;
var rubbish:my_mc = new my_mc();
var dragging:my_mc;
btntest.addEventListener(MouseEvent.CLICK, makeRubbish);
function makeRubbish (event:MouseEvent):void {
addChild(rubbish);
rubbish.x = mouseX - 10;
rubbish.y = mouseY - 10;
rubbish.width = 50;
rubbish.addEventListener(MouseEvent.MOUSE_DOWN, startDragging);
rubbish.buttonMode = true;
}
function stopDragging (event:MouseEvent):void {
this.stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragging);
if(dragging !== null){
dragging.stopDrag();
if (event.currentTarget.hitTestObject(bin)){
removeChild(dragging);
}
dragging = null;
}
}
function startDragging (event:MouseEvent):void {
dragging = event.currentTarget as my_mc;
dragging.startDrag();
this.stage.addEventListener(MouseEvent.MOUSE_UP, stopDragging);
}

AS3: why does the MC "tremble" when selected?

I'm trying to make a simple function to select and drag a MovieClip, without using the startDrag() function.
I have a few MCs on the stage, when mouse down on a MC, I want the MC to move with the mouse. But when I hold the mouse down, the MC starts to "tremble" and I'm not sure why.
I have the code inside each MC for other reasons. Here is what I have so far:
var selectX:Number; //x coordinate of mouse click (to select right point on mc on mouse down)
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(e:MouseEvent):void {
selectX = this.x - mouseX;
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
function mouseUpHandler(e:MouseEvent):void {
mouseX2 = mouseX;
removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
function onEnterFrameHandler(e:Event):void {
this.x = mouseX + selectX + stage.x;
}
This is happening because you are using mouseX of the inside of the movieclip. but when you are trying to set the x of the movieClip it sets the x on the parent movieclip.
e.g.:
mainClip
|-- DragableButton
when you adding DragableButton.x = 100, it is x position insided of the mainClip.
and when your code is taking mouseX inside of the DragableButton, the real mouseX = x + mouseX. and since mouseX inside of the DragableButton is equals e.g. 20, and you adding: selectX = this.x - mouseX -> if you have selectX = 100 - 20. but not 100 - 120 as it should be.
so if you still want to keep to your code change it a bit:
var selectX:Number; //x coordinate of mouse click (to select right point on mc on mouse down)
var mouseX2:Number;
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(e:MouseEvent):void {
selectX = this.x - parent.mouseX;
// selectX = this.x - stage.mouseX;
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
function mouseUpHandler(e:MouseEvent):void {
mouseX2 = parent.mouseX;
removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
}
function onEnterFrameHandler(e:Event):void {
this.x = parent.mouseX + selectX;
// this.x = stage.mouseX + selectX;
}
p.s. stage.x = 0, it will be always. unless you change the property.
p.s.s. stage is only one and same instance no matter from which MC you are trying to get it.
my suggestion draging would be:
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(e:MouseEvent):void
{
this.startDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
function mouseUpHandler(e:MouseEvent):void
{
this.stopDrag();
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
I think the movieclip is trembling because during your drag, your application keeps calling mouseDownHandler, changing the selectX.
Try removing the MOUSE_DOWN event listener. In mouseDownHandler, make that the first thing you do (this is also a good practice for preventing memory leaks). You can add the listener back when you mouse up (and then remove the mouse up listener).
why are you using Event.ENTER_FRAME event (costly), try to use MouseEvent.MOUSE_MOVE like this.
function mouse_move(e:Event)
{
this.x = mouseX + selectX + stage.x;
}
and remove this event handler on mouse up.

AS3 How to set boundries to Mouse Down drag?

I'm new to AS3 and I have a square(1200w) that's bigger than the stage(200w). Right now you can keep dragging it left and right as far as you possibly can. How can I set a limit/boundry to how much of the square you can drag? So that it can't be dragged beyond it's maximum width?
Here's an image
this.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
this.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(e:MouseEvent) {
this.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
function mouseMoveHandler(e:MouseEvent) {
square_mc.x = mouseX;
}
function mouseUpHandler(e:MouseEvent) {
removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
Please note I do not want to use the startdrag() method.
Based on your image, assume that mc refers to the blue box.
var ox:Number = 0;
mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(e:MouseEvent):void
{
ox = mc.mouseX;
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
function mouseUpHandler(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
function mouseMoveHandler(e:MouseEvent):void
{
mc.x = mc.parent.mouseX - ox;
if(mc.x > 0) mc.x = 0;
if(mc.x + mc.width < stage.stageWidth) mc.x = stage.stageWidth - mc.width;
}
Hopefully this is what you were after.

startDrag - stop diagonal movement

Is there a way to have a MovieClip with startDrag, but to force only horizontal and vertical (i.e. not diagonal) movement?
Here is my solution. It tracks the mouseX and mouseY on click and compares it to last position. Finds out which direction the mouse is mainly moving then moves the object there. You may want to add some extra logic to lock the object to the nearest 10th unit or whatever unit size you want to form a snap grid for use in games or organized placement of the object.
Update: I went ahead and added a snapNearest function to help control the movement.
import flash.events.MouseEvent;
import flash.events.Event;
dragObj.addEventListener(MouseEvent.MOUSE_DOWN, dragIt);
var curX:Number = 0;
var curY:Number = 0;
var oldX:Number = 0;
var oldY:Number = 0;
var gridUnit:Number = 25;
function dragIt(e:MouseEvent):void
{
// set x,y on down
oldX = mouseX;
oldY = mouseY;
// add mouse up listener so you know when it is released
stage.addEventListener(MouseEvent.MOUSE_UP, dropIt);
stage.addEventListener(Event.ENTER_FRAME, moveIt);
trace("Start Drag")
}
function moveIt(e:Event):void
{
// figure out what the main drag direction is and move the object.
curX = mouseX;
curY = mouseY;
// figure out which is the larger number and subtract the smaller to get diff
var xDiff:Number = curX > oldX ? curX - oldX : oldX - curX;
var yDiff:Number = curY > oldY ? curY - oldY : oldY - curY;
if(xDiff > yDiff) {
dragObj.x = snapNearest(mouseX, gridUnit);
}else{
dragObj.y = snapNearest(mouseY, gridUnit);
}
oldX = mouseX;
oldY = mouseY;
}
function dropIt(e:MouseEvent):void
{
//remove mouse up event
stage.removeEventListener(MouseEvent.MOUSE_UP, dropIt);
stage.removeEventListener(Event.ENTER_FRAME, moveIt);
trace("Stop Drag")
}
// snap to grid
function snapNearest(n:Number, units:Number):Number
{
var num:Number = n/units ;
num = Math.round(num);
num *= units;
return num;
}
yes. there are a few options.
A. you can choose to use the startDrag() function and supply it's 2nd parameter with a bounds rectangle for your draggable object. something like;
dragSprite.startDrag(false, new Rectangle(0, 0, 20, stage.stageHeight));
B. you can set your draggable object to listen for mouse events, moving it according to the mouse movements. something like:
dragSprite.addEventListener(MouseEvent.MOUSE_DOWN, mouseDownEventHandler);
function mouseDownEventHandler(evt:MouseEvent):void
{
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEventHandler);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
}
function mouseMoveEventHandler(evt:MouseEvent):void
{
//only move dragSprite horizontally
//dragSprite.y = evt.stageY;
dragSprite.x = evt.stageX;
}
function mouseUpEventHandler(evt:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveEventHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpEventHandler);
}
You could use a modifier key, for instance normal behavior would be horizontal & press down the shift key to move vertically.
function mouseMoveEventHandler(evt:MouseEvent):void
{
if(!evt.shiftKey)
dragSprite.x = evt.stageX;
else
dragSprite.y = evt.stageY;
}
You can only constrain to one axis or the other (using a constraint rectangle) But diagonal movement would be possible in the method you propose, unless you also define some other limits... for example a grid.