making a symbol move by keyboard not showing result and when published it not reads stop(); but replays it again and again - actionscript-3

I am new to actionscript ,
My document class is ,
package
{
//list of our imports these are classes we need in order to
//run our application.
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class engine extends MovieClip
{
// moved ourShip to a class variable.
private var Circle:circle = new circle()
//our constructor function. This runs when an object of
//the class is created
public function engine()
{
addFrameScript(0, frame1);
addFrameScript(1, frame2);
}
// frame 1 layer 1 --------------------------------------------------
public function frame1()
{
stop();
}
//-------------------------------------------------------------------
// frame 2 layer 1 --------------------------------------------------
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
//-------------------------------------------------------------------
}
}
i made two frames first contains button and the other circle which i want to move but it not moves and it stays in the middle on second frame
My button class is
package
{
//imports
import flash.events.MouseEvent;
import flash.display.SimpleButton;
import flash.display.MovieClip;
//-------
public class start extends SimpleButton
{
public function start()
{
addEventListener(MouseEvent.CLICK, onTopClick);
addEventListener(MouseEvent.MOUSE_OVER, onBottomOver);
}
function onTopClick(e:MouseEvent):void
{
MovieClip(root).gotoAndStop(2)
}
function onBottomOver(e:MouseEvent):void
{
}
}
}
And my as of circle movieclip is
package
{
//imports
import flash.display.MovieClip;
import flash.display.Stage;
import flash.ui.Keyboard;
import flash.events.Event;
import flash.events.KeyboardEvent;
public class circle extends MovieClip
{
private var speed:Number = 0.5;
private var vx:Number = 0;
private var vy:Number = 0;
private var friction:Number = 0.93;
private var maxspeed:Number = 8;
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
function keyHit(event:KeyboardEvent):void {
switch (event.keyCode) {
case Keyboard.RIGHT :
vx+=speed;
break;
case Keyboard.LEFT :
vx-=speed;
break;
case Keyboard.UP :
vy-=speed;
break;
case Keyboard.DOWN :
vy+=speed;
break;
}
}
}
}
I am sorry to post so much for you guys to read but stackoverflow is the only website where anyone helps me !

You have made several major errors. First, addFrameScript() isn't a proper way to place code on frames, use Flash's editor to place code on timeline. (IIRC you will have to make a single call out of your two in order to have all the code you add to function) And, whatever code you added to a frame of a MC is executed each frame if the MC's currentFrame is the frame with code. Thus, you are adding a function "frame2()" that places the Circle in the center of the stage each frame! You should instead place it at design time (link it to a property) into the second frame, or in a constructor, or you can use one single frame and Sprite instead of MovieClip, and instead of using frames you can use container sprites, adding and removing them at will, or at an action.
The other major mistake is adding an event listener inside an enterframe listener - these accumulate, not overwrite each other, so you can have multiple functions be designated as listeners for a particular event, or even one function several times. The latter happens for you, so each frame another instance of a listening keyHit function is added as a listener. The proper way to assign listeners is either in constructor, or in any function that listens for manually triggered event (say, MouseEvent.CLICK), but then you have to take precautions about listening for more than once with each function, and listening only with those functions you need right now.
EDIT:
Okay. Your code was:
addFrameScript(0, frame1);
addFrameScript(1, frame2);
The more correct way should be:
addFrameScript(0,frame1,1,frame2);
The reason is, the call to addFrameScript replaces all the timeline code with what you supply within here. The function is undocumented, perhaps by the reason of its affects on the stage and AS3 environment. The closest thing to the documentation on addFrameScript() so far is this link.
Next: Your code is:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
public function loop(e:Event) : void
{
addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
x+=vx;
y+=vy
}
The correct way of writing this is as follows:
public function circle()
{
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
if (stage) init();
else addEventListener(Event.ADDED_TO_STAGE,init);
}
private function init(e:Event=null):void
{
removeEventListener(Event.ADDED_TO_STAGE,init);
stage.addEventListener(KeyboardEvent.KEY_DOWN, keyHit);
}
public function loop(e:Event) : void
{
x+=vx;
y+=vy
}
The listeners should be assigned in constructor, if they are permanent or you want them to be active as soon as you create an object. The KeyboardEvent listeners are separate case, as in order for them to function you have to assign them to stage, which is not available right at the time of creating the object, so you need an intermediate layer - the init() function, that is only called when the object is added to stage. At this point stage is no longer null, and you can assign an event listener there. Note, if you want to make your circles eventually disappear, you have to remove the listener you assigned to stage at some point of your removal handling code.
Next: Your code:
public function frame2()
{
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
Correct code should be:
public function frame2():void
{
if (Circle.parent) return; // we have added Circle to stage already!
Circle.x = stage.stageWidth / 2;
Circle.y = stage.stageHeight / 2;
addChild(Circle);
}
See, you are calling this every time your MC is stopped at second frame, thus you constantly reset Circle's coordinates to stage center, so you just cannot see if it moves (it doesn't, as you have assigned the keyboard listener not to stage).
Perhaps there are more mistakes, but fixing these will make your MC tick a little bit.

Related

Unable to addChild on MouseCoordinations

What i am trying to do is, to place a new tower each time on MouseX and MouseY. but it seems it isn't working Any Idea guys?
or if you can create a tileMap array and add new child of PrototypeTower each time when we click on the Tower (on x=50, y=400) to select and place wherever we want. When i click the the box at x=50, y=400, the startDrag() doesn't work.
Main.as
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.ui.Mouse;
public class Main extends Sprite
{
private var pTower:PrototypeTower = new PrototypeTower;
private var zTower:PrototypeTower = new PrototypeTower;
private var fTower:PrototypeTower = new PrototypeTower;
public function Main()
{
pTower.x = 50;
pTower.y = 400;
addChild(pTower);
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(e:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
pTower.addEventListener(MouseEvent.CLICK, onClicked);
}
private function onClicked(e:Event):void
{
removeEventListener(MouseEvent.CLICK, onClicked);
zTower.x = mouseX;
zTower.y = mouseY;
addChild(zTower);
zTower.startDrag();
addEventListener(MouseEvent.CLICK, onPlaced);
}
private function onPlaced(e:Event):void
{
removeEventListener(MouseEvent.CLICK, onPlaced);
zTower.stopDrag();
fTower.x = mouseX
fTower.y = mouseY;
addChild(fTower);
}
}
}
PrototypeTower.as
package
{
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class PrototypeTower extends MovieClip
{
public function PrototypeTower()
{
this.graphics.beginFill(0x00FF00);
this.graphics.drawRect(this.x, this.y, 20, 20);
this.graphics.endFill();
}
}
}
Thank you, i am totally noob, wondering around from days!
Sorry this is just a schematic for now. I'll try to refine it later if you need. Hopefully this clears some things up for you though
When you click the tower, add a new tower at the x,y of the mouse and do some sort of startDrag(tower) on the new tower you just added. Then when you click on the stage, stop the drag and set the new X,y
edit
You might try getting rid of all your removeEventListener calls
I think your problem is you are removing the event listener that gets added in your main function. Keep in mind that the main function (class constructor) for the document class only gets called once, so you add an event listener for ADDED_TO_STAGE only once, and then you remove it the first time you try to add anything to the stage, and you never put it back. Just don't remove it in the first place.
You are calling zTower.startDrag() before you add it to the stage. Do addChild(zTower) and then zTower.startDrag()

Test collision between two movie clips in two different classes AS3

I need to test the collision between 2 movie clips, using air for android action script 3.
Its a collision between an object and several obstacles.
My structure is the following :
The base FLA file, is linked to Action Script file called baseCode.as.
In this AS file, i create the obsctacles, using the following code :
baseCode.as :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.Point;
import Mc_MC; // Not strictly needed
public class baseCode extends flash.display.MovieClip
{
//private static var SYMBOLS:Array = new Array(MySymbol1, MySymbol2);
public var t:int = 0;
public function baseCode()
{
// Create five symbols:
for (var i:int = 0; i < 5; i++) {
trace(i);
makeSymbol();
}
}
function randomRange(minNum:Number, maxNum:Number):Number
{
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum);
}
public function makeSymbol():void
{
trace("IT entered makeSymbol");
// Pick a random symbol from the array:
// var symType:Class = SYMBOLS[0];
//trace(SYMBOLS[Math.random() * SYMBOLS.length]);
// Construct the new symbol:
//var Positi : Number = new Number(Math.random);
var loc:Point = new Point(randomRange(100,stage.stage.height),0);
var loc2:Point = new Point(randomRange(110,stage.stage.height),0);
//var loc:Point = new Point(10*randomRange(15, stage.width),100*randomRange(10 , stage.width));
trace("this is the starting point" , loc);
var sym:Mc_MC = new Mc_MC(1 + Math.random() *10, loc);
if( t % 2 == 0 ){
var sym2:Mc_MC2 = new Mc_MC2(15 + Math.random() *10, loc);
// Listen for the object hitting the left edge:
//sym2.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym2);
}
sym.addEventListener(Event.COMPLETE, remakeObject);
this.addChild(sym);
t ++;
}
public function remakeObject(e:Event):void
{
e.target.removeEventListener(Event.COMPLETE, remakeObject);
//e.removeChild(sym);
//e.parent.removeChild(this.child);
// removeChild(this);
// this.removeChild(sym);
// Replace the dead symbol:
makeSymbol();
}
}
}
Mc_MC and Mc_MC2 are two Action Script file in which the obstacles are called :
Mc_MC.as :
package {
import flash.display.MovieClip;
import flash.events.Event;
import flash.geom.*;
import flash.display.Screen;
import flash.system.Capabilities;
public class Mc_MC extends MovieClip
{
public var speed:Number; // Pixels moved per frame
var valuee:baseCode;
public function Mc_MC(speed:Number, startPosition:Point)
{
this.speed = speed;
this.addEventListener(Event.ENTER_FRAME, update);
this.x = startPosition.x;
this.y = startPosition.y;
}
public function update(speed:Number)
{
var screenWidth:Number = Capabilities.screenResolutionX;
var screenHeight:Number = Capabilities.screenResolutionY;
trace("this.y" , this.y);
trace("this is the stage height" , screenHeight);
trace("this.speed" , this.speed);
if (this.y >= screenHeight - 100) { // We're at the left edge
trace("Entered if");
trace("new Starting Pos" , this.y);
this.y = stage.height;
parent.removeChild(this);
this.removeEventListener(Event.ENTER_FRAME, update);
this.dispatchEvent(new Event(Event.COMPLETE));
}
else this.y += this.speed;
}
}
}
In the base FLA file, i create the main object that will collide with all the obstacles created using Mc_MC and Mc_MC2. I create it using the following code :
Home.fla
import flash.events.*
//import flash.events.EventDispatcher.addEventListener()
import flash.display.DisplayObject;
//import flash.events.MouseEvent;
import flashx.textLayout.events.UpdateCompleteEvent;
import flash.display.MovieClip;
var offsetX:Number;
var offsetY:Number;
//var draggedObject:DisplayObject;
var my_obj:OriginalObject = new OriginalObject();
//left.addEventListener(MouseEvent.MOUSE_MOVE, drag);
//The speed of the scroll movement.
var scrollSpeed:uint = 2;
//This adds two instances of the movie clip onto the stage.
var s1:ScrollBg = new ScrollBg();
var s2:ScrollBg = new ScrollBg();
left.addEventListener(MouseEvent.MOUSE_DOWN,mouseDown);
function mouseDown(e:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUp); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.
addEventListener(Event.ENTER_FRAME,myButtonClick); //while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp(e:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME,myButtonClick); //stop running the tick function every frame now that the mouse is up
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUp); //remove the listener for mouse up
}
right.addEventListener(MouseEvent.MOUSE_DOWN,mouseDown2);
function mouseDown2(e:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUp2); //listen for mouse up on the stage, in case the finger/mouse moved off of the button accidentally when they release.
addEventListener(Event.ENTER_FRAME,stopDragging); //while the mouse is down, run the tick function once every frame as per the project frame rate
}
function mouseUp2(e:MouseEvent):void {
removeEventListener(Event.ENTER_FRAME,stopDragging); //stop running the tick function every frame now that the mouse is up
stage.removeEventListener(MouseEvent.MOUSE_UP,mouseUp2); //remove the listener for mouse up
}
my_obj.x = stage.width / 2;
my_obj.y = stage.height - (stage.height / 3 );
stage.addChild(my_obj);
function myButtonClick(ev:Event):void
{
trace("UPPP");
if(my_obj.x > (my_obj.width*2)){
my_obj.x = my_obj.x - 10;
trace("In the limit");
}
else {
trace("out of bounds");
}
trace("myButton has been clicked.");
}
//// This function is called when the mouse button is released.
function stopDragging(ev2:Event):void
{
trace("Down");
if(my_obj.x <= right.x){
my_obj.x = my_obj.x + 10;
}
}
How can I test the collision of the moving Mc_MC / Mc_MC2 with my_obj considering that the come from different AS files?
I am new to AS, so any help would be appreciated!
If you want to be able to collision test objects from different classes / parentage, then you need to set up your project in a way that you can gain a reference to said objects.
From the looks of it, your two objects are actually in the same class already (as your main timeline code and document class code share the same scope, so what you declare in one should be available in the other).
The only thing you are missing, is a top-level reference to your obstacle/Mc_MC. As currently you assign it to a var that is scoped to the makeSymbol function (so you only have a reference to it inside that function).
Solution
In your document class (baseCode.as) , create a top-level var to hold a reference to that obstacle: (for reference, you have a top level var called t, put this line above or below that)
private var obstacle:Mc_MC;
later in your function that instantiates the new Mc_MC (makeSymbol), assign the instance to that top level var:
obstacle = new Mc_MC(1 + Math.random() *10, loc);
addChild(obstacle);
Now you can access that obstacle var anywhere else in the main timeline or document class.
if(my_obj.hitTest(obstacle)){
}
As an aside, if you have a document class, there is no point in having code on the first frame of your main timeline as that code would work the same in your document class (though it has to be contained in a function). Here is an example of where to move main timeline code:
public class Main extends MovieClip {
public function Main():void {
//listen for the added to stage event prior to do anything display oriented
this.addEventListener(Event.ADDED_TO_STAGE, init);
}
private function init(e:Event):void {
//this is the best place to put the equivalent of timeline code (not including vars or functions, put those in the class root NOT nested here)
}
}

Actionscript 3.0, error with hitTestObject

I'm getting an error I can't seem to fix. I think I know kind of what is going on but I'm not sure enough to be able to fix it. I keep getting error
"TypeError: Error #2007: Parameter hitTestObject must be non-null.
at flash.display::DisplayObject/_hitTest()
at flash.display::DisplayObject/hitTestObject()"
Basically I fire an attack in my game. It hits an enemy and he is killed just fine. BUT, he has an animation as he dies that takes a couple seconds. It seems if I fire another attack during his animation, my attack IMMEDIATELY gives this error (before striking anything, that is). Once the animation is over, everything is fine again. Also, the game was working 100% fine before I put in this animation.
Here is my document class
package com.classes
{
import flash.display.MovieClip;
import flash.display.Stage;
import flash.events.Event;
public class DocumentClass extends MovieClip
{
// we need to keep track of our enemies.
public static var enemyList1:Array = new Array();
// moved stickobject1 to a class variable.
private var stickobject1:Stickman2;
public function DocumentClass() : void
{
//removed the var stickobject1:Stickman2 because we declared it above.
var bg1:background1 = new background1();
stage.addChild(bg1);
stickobject1 = new Stickman2(stage);
stage.addChild(stickobject1);
stickobject1.x=50;
stickobject1.y=300;
//running a loop now.... so we can keep creating enemies randomly.
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
//our loop function
private function loop(e:Event) : void
{
//run if condition is met.
if (Math.floor(Math.random() * 90) == 5)
{
//create our enemyObj1
var enemyObj1:Enemy1 = new Enemy1(stage, stickobject1);
//listen for enemyObj1 being removed from stage
enemyObj1.addEventListener(Event.REMOVED_FROM_STAGE, removeEnemyObj1, false, 0, true);
//add our enemyObj1 to the enemyList1
enemyList1.push(enemyObj1);
stage.addChild(enemyObj1);
}
}
private function removeEnemyObj1(e:Event)
{
enemyList1.splice(enemyList1.indexOf(e.currentTarget), 1);
}
}
}
And here is my attack1 class
package com.classes {
import flash.display.MovieClip;
import flash.display.Stage;
import com.senocular.utils.KeyObject;
import flash.ui.Keyboard;
import flash.events.Event;
public class attack1 extends MovieClip {
private var stageRef:Stage;
private var bulletSpeed:Number = 16;
public function attack1 (stageRef:Stage, x:Number, y:Number) : void
{
this.stageRef = stageRef;
this.x = x;
this.y = y;
addEventListener(Event.ENTER_FRAME, loop, false, 0, true);
}
private function loop(e:Event) : void
{
//move bullet up
x += bulletSpeed;
if (x > stageRef.stageWidth)
removeSelf();
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++)
{
if (hitTestObject(DocumentClass.enemyList1[i].hit))
{
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
}
}
}
private function removeSelf() : void
{
removeEventListener(Event.ENTER_FRAME, loop);
if (stageRef.contains(this))
stageRef.removeChild(this);
}
}
}
Don't think you should need any other of my classes to figure out what's going on, but let me know if you do! Thanks very much =)
You don't want to do a hit test against any object that may have been removed from the scene (or from the enemyList array). The extra condition added to attack1.loop's for loop should get rid of your error. A better fix is to splice out the items you remove, so they are never tested against in the loop.
The break line will make it stop trying to hit other enemies after the bullet is removed. If the line "DocumentClass.enemyList1[i].takeHit();" removes the item from the enemyList1, you need to make sure you use "i--;" at the bottom of the loop as well, if you plan on looping through the remainder of the enemies. "i--" or "break", you will probably need one of them in that loop.
Double check the order in which you are executing your removal methods. Sometimes it's better to flag the items for removal and remove them in a separate loop than to remove an item that may be needed later in the same loop.
for (var i:int = 0; i < DocumentClass.enemyList1.length; i++){
if(DocumentClass.enemyList1[i] && DocumentClass.enemyList1[i].hit){
if (hitTestObject(DocumentClass.enemyList1[i].hit)){
trace("hitEnemy");
removeSelf();
DocumentClass.enemyList1[i].takeHit();
break;
}
}
}
Not the correct solution in this question. You can always do != null in a conditional statement.
if(object!=null){
party.drink();
}

(AS3) Functions

I managed to fix the whole null stage error by following MJW's guide on debugging Error #1009. But now the function that initializes the bullets doesn't get called.
Snippets:
if (stage) {
 init();
} else {
addEventListener(Event.ADDED_TO_STAGE, init);
}
...
private function init(event:Event = null) {
removeEventListener(Event.ADDED_TO_STAGE, init);
stage.addEventListener(Event.ENTER_FRAME, shoot);
}
...
private function shoot(event:Event) {
var bullet:EnemyBullet = new EnemyBullet();
stage.addChild(bullet);
bullet.x = enemy.x;
bullet.y = enemy.y;
bullet.theta = Math.random() * 360;
bManager.bulletVector.push(bullet);
}
Note that when I put trace() within the second two functions, nothing happens, but the addEventListener() in the first snippet does get called (or so I think).
As a general practice, stage should not be referenced - especially in your case, where your reference is solely to add instances of your bullet class. If it's a matter of z-index, you could instead have a layer in which bullets are placed on top of other display objects on the display list.
Besides complexities loading multiple SWFs on a single stage, your code would become nice isolated functional units by adding display objects to their own hierarchy of the display list. Or, you could leverage a MVC pattern whereby a controller manipulated views.
In order for your code to work, that class must either be the main function of the SWF or added to stage.
If it's the main function of the SWF, init() will be called.
Otherwise, assure it's getting added to the display list via an addChild().
Do you really intend to fire a bullet every frame? That could be 24 to 60 bullets a second. You might want to throttle that with some probability whether a bullet with fire.
Say this was a battlefield, and your battlefield class was added to stage, it could be implemented as this:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
if (stage)
init();
else
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
init();
}
protected function init():void
{
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Which would output:
Skip... Odds were: 0.3539872486144304
Skip... Odds were: 0.742108017206192
Fire! Odds were: 0.025597115512937307
Skip... Odds were: 0.7608889108523726
Fire! Odds were: 0.08514392375946045
Skip... Odds were: 0.27881692815572023
Beyond Stage3D, I've never been fond of this initialization pattern, as you could just as easily rely on stage events, as in:
package
{
import flash.display.Sprite;
import flash.events.Event;
[SWF(percentWidth = 100, percentHeight = 100, backgroundColor = 0x0, frameRate = 30)]
public class Battlefield extends Sprite
{
public function Battlefield()
{
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function addedToStageHandler(event:Event):void
{
removeEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ENTER_FRAME, frameHandler);
}
protected function removedFromStageHandler(event:Event):void
{
removeEventListener(Event.ENTER_FRAME, frameHandler);
removeEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler);
addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler);
}
protected function frameHandler(event:Event):void
{
var odds:Number = Math.random();
trace((odds < 0.1 ? "Fire! " : "Skip...") + "Odds were: " + odds);
}
}
}
Therefore, upon added to stage the class initiates its actions, and upon removed from stage the class terminates its actions.
I think the issue is in the first block.
you are checking for stage, if stage is not null, then use a added to stage listener.
you should only be using addEventListener(Event.ADDED_TO_STAGE, init);
however, this is assuming that the class is DisplayObject subclass, objects that do not get added to stage cannot call the ADDED_TO_STAGE listener

Own drag function in AS3

I need to develop my own drag function in AS3 (instead of using startDrag) because I'm resizing a MovieClip.
I'm doing this:
public class resizeBR extends MovieClip {
var initialScaleX, initialScaleY;
public function resizeBR() {
this.addEventListener(MouseEvent.MOUSE_DOWN, initResize);
this.addEventListener(MouseEvent.MOUSE_UP, stopResize);
}
public function initResize(e:MouseEvent):void
{
initialScaleX = e.target.scaleX;
initialScaleY = e.target.scaleY;
e.target.addEventListener(MouseEvent.MOUSE_MOVE, startResize);
}
public function startResize(e:MouseEvent):void
{
e.target.x += e.localX;
e.target.y += e.localY;
e.target.parent.parent.width += mouseX;
e.target.parent.parent.height += mouseY;
// Keep its own scale
e.target.scaleX = initialScaleX;
e.target.scaleY = initialScaleY;
}
public function stopResize(e:MouseEvent):void
{
e.target.removeEventListener(MouseEvent.MOUSE_MOVE, startResize);
}
}
But the drag feature is not working fluently. I mean, when I drag a MovieClip from class resizeBR I need to move slowly my mouse cursor or it's not going to work propertly.
resizeBR is a MovieClip as a child of another MovieClip; the second one is which I have to resize.
What am I doing wrong?
Thanks!
Thanks all for your answers, but I found a great classes to do what I want.
http://www.senocular.com/index.php?id=1.372
http://www.quietless.com/kitchen/transform-tool-drag-scale-and-rotate-at-runtime/
I'm not really sure if I completely understand what you mean. But I think your problem lies with your MOUSE_MOVE handler.
In your current example you're resizing your target only when moving your mouse over the target. When you're moving your mouse fast enough it's possible your mouse leaves the target, casuing it to stop resizing. When I'm writing my own drag handlers I usually set the MOUSE_MOVE and MOUSE_UP listeners to the stage.
Your class would end up looking something like this:
public class resizeBR extends MovieClip
{
var initialScaleX, initialScaleY;
public function resizeBR()
{
addEventListener(MouseEvent.MOUSE_DOWN, initResize);
addEventListener(MouseEvent.MOUSE_UP, stopResize);
}
public function initResize(e:MouseEvent):void
{
initialScaleX = scaleX;
initialScaleY = scaleY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, startResize);
}
public function startResize(e:MouseEvent):void
{
x += e.localX;
y += e.localY;
parent.parent.width += mouseX;
parent.parent.height += mouseY;
// Keep its own scale
scaleX = initialScaleX;
scaleY = initialScaleY;
}
public function stopResize(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, startResize);
}
}
There are a couple reasons the resizing is jumpy. First, like rvmook points out, you'll need to make sure you support the mouse rolling off of the clip while its being resized. Since there is not an onReleaseOutside type of event in AS3, you have to set listeners to the stage, or some other parent clip. If you have access to the stage, that is best. If not, you can use the root property of your resizable clip, which will reference the highest level display object you have security access to. Setting mouse events to the root is a little wonky, because for them to fire, the mouse needs to be on one of the root's child assets - whereas the stage can fire mouse events when the mouse is over nothing but the stage itself.
Another reason you might be seeing some strange resizing behavior is because of using the localX/Y properties. These values reflect the mouseX/mouseY coordinates to the object being rolled over - which might not necessarily be your clip's direct parent.
I tend to avoid having classes access their parent chain. You might want to consider placing the resizing logic in the clip you want resized, and not in one of its children. Here is simple self resizing example:
package {
import flash.display.MovieClip;
import flash.events.MouseEvent;
import flash.events.Event;
public class ResizableBox extends MovieClip {
public function ResizableBox() {
addEventListener(MouseEvent.MOUSE_DOWN, startResize);
}
private function startResize(evt:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, handleResize);
stage.addEventListener(MouseEvent.MOUSE_UP, stopResize);
}
private function stopResize(evt:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleResize);
stage.removeEventListener(MouseEvent.MOUSE_UP, stopResize);
}
private function handleResize(evt:MouseEvent):void {
this.scaleX = this.scaleY = 1;
this.width = this.mouseX;
this.height = this.mouseY;
}
}
}
ResizableBox is set as the base class of a MC in the library.