I have a movieClip with two buttons inside.
The problem is that when the mouse is over these two buttons, the code that manages the movieClip stops working, as if the mouse is not over the MC (the buttons are children of the MC, shouldn't it work regardless?).
Could you please share some advice?
Thanks
/*mc follows mouse. I can't click btns because when mouse rollover btns the mc moves*/
function showImgOptions (e:Event):void{
if (mc.hitTestPoint(mouseX,mouseY,false)){
mc.y = mc.y;
mc.x = mc.x;
}else{
var delayX:int = mc.x - mouseX;
var delayY:int = mc.y - mouseY;
mc.x -= delayX / 6;
mc.y -= delayY/6;
}
}
mc.btn1.addEventListener (MouseEvent.CLICK, closeClick);
mc.btn2.addEventListener (MouseEvent.CLICK, zoomClick);
function closeClick (e:MouseEvent):void{}
function zoomClick (e:MouseEvent):void{}
stage.addEventListener (Event.ENTER_FRAME, showImgOptions);
addChild (mc);
Changed the code to:
var mc:menuMC = new menuMC();
addChild(mc);
var p:Point = mc.localToGlobal(new Point(mc.mouseX,mc.mouseY));
/*mc follows mouse. I can't click btns because when mouse rollover btns the mc moves*/
function showImgOptions (e:Event):void
{
if (! mc.hitTestPoint(p.x,p.y,false))
{
mc.y = mc.y;
mc.x = mc.x;
}else{
//move mc towards mc.parent's mouseX and mouseY
var delayX:int = mc.x - mouseX;
var delayY:int = mc.y - mouseY;
mc.x -= delayX / 6;
mc.y-=delayY/6;
}
}
mc.btn1.addEventListener (MouseEvent.CLICK, closeClick);
mc.btn2.addEventListener (MouseEvent.CLICK, zoomClick);
function closeClick (e:MouseEvent):void
{
}
function zoomClick (e:MouseEvent):void
{
}
stage.addEventListener (Event.ENTER_FRAME, showImgOptions);
And now I get this error:
TypeError: Error #1010: A term is undefined and has no properties.
Here you can download an FLA. Test it and try to click on the buttons 1 and 2, inside the MC following the mouse
hitTestPoint expects stage coordinates:
The x and y parameters specify a point in the coordinate space of the Stage, not the display object container that contains the display object (unless that display object container is the Stage).
Use localToGlobal to get the stage coordinates:
var p:Point = mc.localToGlobal(new Point(mc.mouseX, mc.mouseY));
if(!mc.hitTestPoint(p.x, p.y,false))
{
//move mc towards mc.parent's mouseX and mouseY
}
Solved it!!
Changed the code. I don't know if this helps anybody, but I hope so. Thanks to you all.
stage.addEventListener(Event.ENTER_FRAME, moveMC);
var mc:menuMC = new menuMC();
addChild(mc);
function moveMC(e:Event):void {
if (mc.hitTestObject(big_mc)) {
mc.visible = true;
} else {
mc.visible = false;
}
if (mc.hitTestPoint(mouseX,mouseY,false)) {
mc.y = mc.y;
mc.x = mc.x;
} else {
var delayX:int = mc.x - mouseX;
var delayY:int = mc.y - mouseY;
mc.x -= delayX / 6;
mc.y-=delayY/6;
}
}
mc.btn1.addEventListener(MouseEvent.CLICK, onBtn1);
mc.btn2.addEventListener(MouseEvent.CLICK, onBtn2);
function onBtn1(e:MouseEvent):void {
trace("do something");
}
function onBtn2(e:MouseEvent):void {
trace("do something else");
}
Related
I am fairly new to actionscript 3 and I would like to know how can I make EventListener to work only once. Right now it works after every click, but I need to get it work only with first click.
After click it displays a ball on the stage where the click was made. I need to get to the point where only one ball appears and after that click should do nothing.
my code:
stage.addEventListener(MouseEvent.CLICK, onClick,false,0,true);
function onClick(evt:MouseEvent):void {
var ball:MovieClip = new Ball();
ball.x = stage.mouseX;
ball.y = stage.mouseY;
addChildAt(ball,0);
}
You need to call removeEventListener() as follows:
stage.addEventListener(MouseEvent.CLICK, onClick,false,0,true);
function onClick(evt:MouseEvent):void {
stage.removeEventListener(MouseEvent.CLICK, onClick);
var ball:MovieClip = new Ball();
ball.x = stage.mouseX;
ball.y = stage.mouseY;
addChildAt(ball,0);
}
One possible solution is to remove the EventListener.
stage.addEventListener(MouseEvent.CLICK, onClick,false,0,true);
function onClick(evt:MouseEvent):void {
stage.removeEventListener(MouseEvent.CLICK, onClick);
var ball:MovieClip = new Ball();
ball.x = stage.mouseX;
ball.y = stage.mouseY;
addChildAt(ball,0);
}
Another solution is a simple bool variable, in case you need the eventlistener for something else.
var clickedOnce:Boolean = false;
stage.addEventListener(MouseEvent.CLICK, onClick,false,0,true);
function onClick(evt:MouseEvent):void {
if(!clickedOnce){
clickedOnce = true;
var ball:MovieClip = new Ball();
ball.x = stage.mouseX;
ball.y = stage.mouseY;
addChildAt(ball,0);
}
}
How do I loaded MovieClips in the position of the mouse with a different name on each click? or I have to make several different MovieClips to laod?
please help me :)
Is this what you're trying to do?
var counter:int = 0;
stage.addEventListener(MouseEvent.CLICK, click);
function click(event:MouseEvent):void
{
var mc:MovieClip = new MovieClip(); // Or new YourExportedLibraryClip();
mc.name = 'mc_' + (counter++);
mc.x = stage.mouseX;
mc.y = stage.mouseY;
stage.addChild(mc);
}
I'm just trying to make a simple vertical shooter, one where the player's ship is controlled by the mouse and fires a laser when you click the mouse. However, when I try running the code, I keep getting the same error message:
"1046: Type was not found or was not a compile-time constant: MouseEvent."
The thing is, I declared the MouseEvent. I know I did. It is as follows:
--==--
package
{
import flash.display.MovieClip;
import flash.utils.Timer;
import flash.events.TimerEvent;
import flash.events.MouseEvent;
public class SpaceShooter_II extends MovieClip //The public class extends the class to a movie clip.
{
public var army:Array; //the Enemies will be part of this array.
///*
//Laser Shots and Mouse clicks:
import flash.events.MouseEvent;
public var playerShot:Array; //the player's laser shots will fill this array.
public var mouseClick:Boolean;
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseGoDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseGoUp);
stage.addEventListener(Event.ENTER_FRAME, onTick);
//*/
//Back to the rest of the code:
public var playerShip:PlayerShip; //This establishes a variable connected to the PlayerShip AS.
public var onScreen:GameScreen; //This establishes a variable that's connected to the GameScreen AS.
public var gameTimer:Timer; //This establishes a new variable known as gameTimer, connected to the timer utility.
///*
//Functions connected to Shooting via mouse-clicks:
public function mouseGoDown(event:MouseEvent):void
{
mouseClick = true;
}
public function mouseGoUp(event:MouseEvent):void
{
mouseClick = false;
}
//*/
//This function contains the bulk of the game's components.
public function SpaceShooter_II()
{
//This initiates the GameScreen.
onScreen = new GameScreen;
addChild ( onScreen );
//This sets up the enemy army.
army = new Array(); //sets the "army" as a NEW instance of array.
var newEnemy = new Enemy( 100, -15); //This will create new enemies. There's new var newEnemy statement, hence we call THIS a var.
army.push ( newEnemy ); //the new enemy is added to the army.
addChild( newEnemy ); //the new enemy is added to the game.
//This sets up the player's avatar, a spaceship.
playerShip = new PlayerShip(); //This invokes a new instance of the PlayerShip...
addChild( playerShip ); //...And this adds it to the game.
playerShip.x = mouseX; //These two variables place the "playerShip" on-screen...
playerShip.y = mouseY; //...at the position of the mouse.
///*
//This sets up the player's laser shots:
playerShot = new Array(); //sets the "army" as a NEW instance of array.
var goodShot = new goodLaser( playerShip.x, playerShip.y); //This will create new enemies. There's new var newEnemy statement, hence we call THIS a var.
playerShot.push ( goodShot ); //the new enemy is added to the army.
addChild( goodShot ); //the new enemy is added to the game.
//*/
//This sets up the gameTimer, where a lot of the action takes place.
gameTimer = new Timer( 25 );
gameTimer.addEventListener( TimerEvent.TIMER, onTick );
gameTimer.start();
}
//This function contains the things that happen during the game (player movement, enemy swarms, etc.)
public function onTick( timerEvent:TimerEvent ):void
{
//This "if" statement is where the array that contains the enemy ships is initialized.
if ( Math.random() < 0.05 ) //This sets the number of ships showing up at once.
{
var randomX:Number = Math.random() * 800 //Generates a random number between 0 and 1.
var newEnemy:Enemy = new Enemy ( randomX, -15 ); //This shows where the enemy starts out--at a random position on the X plane, but at a certain points on the Y plane.
army.push( newEnemy ); //This adds the new enemy to the "army" Array.
addChild( newEnemy ); //This makes the new enemy part of the game.
}
//This "for" statement sends the enemies downward on the screen.
for each (var enemy:Enemy in army) //Every time an enemy is added to the "army" array, it's sent downward.
{
enemy.moveDown(); //This is the part that sends the enemy downward.
//And now for the collision part--the part that establishes what happens if the enemy hits the player's spaceship:
if ( playerShip.hitTestObject ( enemy ) ) //If the playerShip makes contact with the enemy...
{
gameTimer.stop(); //This stops the game.
dispatchEvent( new PlayerEvent(PlayerEvent.BOOM) ); //This triggers the game over screen in the PlayerEvent AS
}
}
//This, incidentally, is the player's movement controls:
playerShip.x = mouseX;
playerShip.y = mouseY;
///*
//And this SHOULD be the shooting controls, if the mouse function would WORK...
if ( mouseClick = true )
{
var goodShot = new goodLaser( playerShip.x, playerShip.y); //This will create new lasers. There's new variable in the statement, hence we call THIS a variable.
playerShot.push ( goodShot ); //the new laser is added to the army.
addChild( goodShot ); //the new laser is added to the game.
}
for each (var goodlaser: goodLaser in goodShot)
{
goodlaser.beamGood();
}
//*/
}
}
}
--==--
Sorry if the brackets are coming in uneven, I just wanted to outline the code in its entirety, and show the parts I added where things started going wrong, so someone can tell me what I need to do to make this work.
Basically, everything else works...but when I work on the things connected to the mouse clicking and the array with the lasers, the program stops working. The error seems to be connected to the functions "mouseGoUp" and "mouseGoDown," but I'm not sure how to fix that.
This assignment is due March 8. Can someone help me, please?
Add this import flash.events.MouseEvent; to the top of your class and it should work. You need to import everything you use. That's why you get that error.
As well as importing MouseEvent, in the initialisation of your game, you should add event listeners to the stage which listen for the MOUSE_DOWN and MOUSE_UP events:
stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseGoDown);
stage.addEventListener(MouseEvent.MOUSE_UP, mouseGoUp);
What would be simpler, though, would be to do away with the 'mouseClick' variable and have just a single MouseEvent listener which listens for the MOUSE_DOWN event and trigger your missle launch from the handler.
I had a game like this if you want the entire source i can give it to you but the main parts are
var delayCounter:int = 0;
var mousePressed:Boolean = false;
var delayMax:int = 5;//How rapid the fire is
var playerSpeed:int = 5;
var bulletList:Array = [];
var bullet:Bullet;
var upPressed:Boolean = false;
var downPressed:Boolean = false;
var leftPressed:Boolean = false;
var rightPressed:Boolean = false;
stage.addEventListener(MouseEvent.MOUSE_DOWN,mouseDownHandler,false,0,true);
stage.addEventListener(MouseEvent.MOUSE_UP,mouseUpHandler,false,0,true);
stage.addEventListener(Event.ENTER_FRAME,loop,false,0,true);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_SetKeyPressed);
stage.addEventListener(KeyboardEvent.KEY_UP, fl_UnsetKeyPressed);
function loop(e:Event):void
{
player.rotation = Math.atan2(mouseY - player.y,mouseX - player.x) * 180 / Math.PI + 90;
if (bulletList.length > 0)
{
for each (bullet in bulletList)
{
bullet.bulletLoop();
}
}
if (mousePressed)
{
delayCounter++;
if ((delayCounter == delayMax))
{
shootBullet();
delayCounter = 0;
}
}
if (upPressed)
{
player.y -= playerSpeed;
}
if (downPressed)
{
player.y += playerSpeed;
}
if (leftPressed)
{
player.x -= playerSpeed;
}
if (rightPressed)
{
player.x += playerSpeed;
}
}
function mouseDownHandler(e:MouseEvent):void
{
mousePressed = true;
}
function mouseUpHandler(e:MouseEvent):void
{
mousePressed = false;
}
function shootBullet():void
{
var bullet:Bullet = new Bullet(stage,player.x,player.y,player.rotation - 90);
bulletList.push(bullet);
stage.addChildAt(bullet,1);
}
function fl_SetKeyPressed(event:KeyboardEvent):void
{
if (event.keyCode == 87)
{
upPressed = true;
}
if (event.keyCode == 83)
{
downPressed = true;
}
if (event.keyCode == 65)
{
leftPressed = true;
}
if (event.keyCode == 68)
{
rightPressed = true;
}
}
function fl_UnsetKeyPressed(event:KeyboardEvent):void
{
if (event.keyCode == 87)
{
upPressed = false;
}
if (event.keyCode == 83)
{
downPressed = false;
}
if (event.keyCode == 65)
{
leftPressed = false;
}
if (event.keyCode == 68)
{
rightPressed = false;
}
}
BULLET CLASS
package
{
import flash.display.Stage;
import flash.display.MovieClip;
import flash.events.Event;
public class Bullet extends MovieClip
{
private var stageRef:Stage;
private var speed:Number = 10;//speed that the bullet will travel at
private var xVel:Number = 5;
private var yVel:Number = 5;
private var rotationInRadians = 0;
public function Bullet(stageRef:Stage, X:int, Y:int, rotationInDegrees:Number):void
{
this.stageRef = stageRef;
this.x = X;
this.y = Y;
this.rotation = rotationInDegrees;
this.rotationInRadians = rotationInDegrees * Math.PI / 180;
}
public function bulletLoop():void
{
xVel = Math.cos(rotationInRadians) * speed;
yVel = Math.sin(rotationInRadians) * speed;
x += xVel;
y += yVel;
if (x > stageRef.stageWidth || x < 0 || y > stageRef.stageHeight || y < 0)
{
deleteBullet();
}
}
public function deleteBullet()
{
this.visible=false
this.x=9999
this.y=9999
}
}
}
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.
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.