AS3: How to make this mouse position detection work properly? - actionscript-3

I'm new to AS3 so please bare with my basic questions.
What I want to do is have a left arrow MC on the left side of the stage and right arrow MC on the right side of stage. When the mouse is over the left 1/3 of the stage, the left arrow appears, on the right 1/3 of the stage, the right arrow appears, but the middle 1/3 the arrows fade out.
I do NOT want to make large invisible MCs and detect the mouse movement that way. I just want it to be relative to the mouse position on the stage.
I thought it would be very easy, but the eventListener fires everytime the mouse moves, so the left and right arrow MC animation is constantly being triggered, and they look like they are "shaking" for a lack of a better word.
What I have so far is the following. Could someone please give me some help with this?
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
}
}

if...else seem to be ok. The only thing which may couse the problem is mc.gotoAndPlay. Try to use alpha property instead:
var stagePos:int = stage.width/3;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent) {
var mouseArrow:int = mouseX;
if (mouseArrow<stagePos) {
arrowLeft_mc.alpha = 1; //alpha is 1, arrow is shown
trace ("left arrow show");
} else if (mouseArrow>stagePos && mouseArrow<stagePos*2) {
arrowLeft_mc.alpha = 0; //alpha is 0, arrow is hidden
arrowRight_mc.alpha = 0;
trace ("nothing happens");
} else if (mouseArrow>stagePos*2) {
arrowRight_mc.alpha = 1;
trace ("right arrow show");
}
}

The trouble is the speed with which your code is getting called repeatedly.
If you you are listening to MouseEvent.MOUSE_MOVE then it will happen way too fast for any 'gotoAndPlay' business to finish.
Since you don't want to do the invisible MovieClips ( which gives you the very handy MouseEvent.ROLL_OVER and MouseEvent.ROLL_OUT events ) then you are left polling to evaluate coordinates like you have in your code.
You need to remember the last 'answer' your code gave and then ignore the case that is already true next time. You'll have to bear with my preference for switch statements.
var stagePos:int = stage.width/3;
var _arrowShowing : int = 0;
addEventListener(MouseEvent.MOUSE_MOVE, arrowDetectHandler);
function arrowDetectHandler(e:MouseEvent)
{
var mouseArrow:int = mouseX;
switch( true )
{
case ( !_arrowShowing == 1 && mouseArrow < stagePos ) :
_arrowShowing = 1;
arrowLeft_mc.gotoAndPlay("Show");
trace ("left arrow show");
break;
case ( !_arrowShowing == 0 && mouseArrow > stagePos && mouseArrow < stagePos * 2 ) :
_arrowShowing = 0;
arrowLeft_mc.gotoAndPlay("Hide");
arrowRight_mc.gotoAndPlay("Hide");
trace ("nothing happens");
break;
case ( !_arrowShowing == 2 && mouseArrow>stagePos*2 ) :
_arrowShowing = 2;
arrowRight_mc.gotoAndPlay("Show");
trace ("right arrow show");
break;
}
}

Related

Need an object to become 'unclickable' behind certain objects. As3 Flash Cs4

How can I make a clickable movieclip 'hide' behind another object. Eg.. I have a rabbit movieclip - he is clickable - as he walks behind a tree(MC) he needs to hide behind that tree.
At the moment, if I click on the tree - the mouse click seems to ignore the tree completely and I can still click the unseen rabbit.
var HitCount:Number = 10;
var RabbitG1X:Number = 0;
var RabbitG1Y:Number = 0;
var RabbitG2X:Number = 0;
var RabbitG2Y:Number = 0;
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE, follow);
function follow(evt:MouseEvent)
{
Cursor_mc.x =mouseX;
Cursor_mc.y=mouseY;
}
stage.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void
{
if (Cursor_mc.hitTestObject(RabbitG1_mc))
{
trace ("you fed rabbit1 ");
RabbitG1_mc.x = RabbitG1X + 5000;
RabbitG1H_mc.x = RabbitG1X + 1271.85;
RabbitG1H_mc.y = RabbitG1Y + 184.05;
HitCount = HitCount -1;
Dec_txt.text = "" + HitCount + "";
}
if (Cursor_mc.hitTestObject(RabbitG2_mc))
{
trace ("you fed rabbit2 ");
RabbitG2_mc.x = RabbitG2X + 5000;
RabbitG2H_mc.x = RabbitG2X + 1271.85;
RabbitG2H_mc.y = RabbitG2Y + 184.05;
HitCount = HitCount -1;
Dec_txt.text = "" + HitCount + "";
}
if (HitCount ==0)
{
trace("You fed all the rabbits");
}
}
I tried adding this to the tree mc to see if I could kill the mouse when it moved over tree.
Tree2MC.addEventListener(MouseEvent.CLICK, solid);
function solid(e:MouseEvent):void{
Tree2MC.mouseEnabled = false;
}
However, it isn't ideal. I really need a clickable object to hide if it goes behind another object on the stage. So if he is half hidden and I click on the part of the MC still revealed, it will click.. And it didn't work.
First, there is no need to use the hitTest code to figure out what was clicked. You can use the mouse event's .target property to figure that out - that will also solve your issue of knowing if the tree was clicked or the rabbit.
For example:
function clickHandler(event:MouseEvent):void {
if (event.target == RabbitG1_mc){
//.....do you stuff
if (event.target == RabbitG2_mc){
Now, one thing to point out, is the .target of an event could also be a child object of a rabbit (if your rabbit MC had other objects inside it). So to make sure it's consistent, you can do something like this when you initialize your rabbits:
RabbitG1_mc.mouseChildren = false;
RabbitG2_mc.mouseChildren = false;
Alternatively, you could just add mouse event listeners to the rabbits directly instead of one listener on the stage that will catch everything. This way, if an object (tree) is in front of them (and is mouse enabled), the click event will dispatch on the tree instead of the rabbit and the clickHandler won't run.
RabbitG1_mc.addEventListener(MouseEvent.CLICK, clickHandler);
RabbitG2_mc.addEventListener(MouseEvent.CLICK, clickHandler);
function clickHandler(event:MouseEvent):void {
//event.currentTarget is a reference to what you attached the listener to
switch(event.currrentTarget){
case RabbitG1_mc:
//..do your code
break;
case RabbitG2_mc:
//..do your code
break;
}
}

libGDX bullet position logic

My game has a update method which handles the fire ability of my chracter.
my problem is the logic of my game, the bullet should fire from the position of my chracter, upon game start(not moving the character) fire bullet come from the position of the character, but when i move my character the start position of bullet is not same with the position of character.
The direction of the bullet depends on the direction of the player.
private void update() {
Vector2 direction = new Vector2(0, 0);
if (Gdx.input.isKeyPressed(Keys.D)) {
direction.x = 1f ;
}
if (Gdx.input.isKeyPressed(Keys.A)) {
direction.x = -1f ;
}
if (Gdx.input.isKeyPressed(Keys.W)) {
direction.y = 1f ;
}
if (Gdx.input.isKeyPressed(Keys.S)) {
direction.y = -1f;
}
if (direction.x != 0 || direction.y != 0) {
playerDirection.set(direction);
System.out.println("player x: " +playerDirection.x + "\t" +"player y:"+playerDirection.y);
}
if (Gdx.input.isKeyPressed(Keys.F)) {
bulletPos = new Vector2(startPos);
bulletDirection.set(playerDirection);
}
if (bulletPos != null) {
bulletPos.x += direction.x;
bulletPos.y +=direction.y;
if (bulletPos.x < 0 || bulletPos.x > mapPixelWidth
|| bulletPos.y < 0 || bulletPos.y > mapPixelHeight) {
bulletPos = null;
}
}
}
can anyone knows the logic error, or anyone there can provide simple logic of shooting that fire on a direction?
From what i see, you're always firing button from players start position (startPos), and then, when the bullet is moving, you update its position according to player direction (direction.x, .y)? But when player changes direction, bullet is starting to move other way as well. Thats wrong.
After its created, bullet should be always moved independent from your player. So when you create it, it has to have own start position (taken from current player position), and own direction (based on current player position). Your player movement cannot change bullet position anymore.
Something like:
if (Gdx.input.isKeyPressed(Keys.F)) {
bulletPos.set(currentPlayerPosition);
bulletDirection.set(currentPlayerDirection);
}
//and then in update()
bulletPos.x+=bulletDirection.x;
bulletPos.y+=bulletDirection.y;
//until it goes out of screen, or passes given distance,
//or new bullet is created, or whatever condition you like

Drag finger on X axis of mc, changes value - AS3

I have a rectangle mc. When the user swipes his finger slowly right on the mc, a value needs to increase, If moved left, it will decrease. 1 to 100 is the limit. How do I do that? i don't want a visible slider. It should not matter where the finger is on the mc, only which direction the finger is moving.
EDIT: I am currently looking into the touchEvent and am researching the web for solutions.
You'll want to keep track of whether or not a swipe is happening and, if so, where it started.
var dragging:Boolean = false;
var startX:Number = 0.0;
Then you'll use simple event listeners to keep track of this bool.
mc.addEventListener(MouseEvent.MOUSE_DOWN, mouseDown);
mc.addEventListener(MouseEvent.MOUSE_UP, mouseReleased);
function mouseDown(event:MouseEvent):void
{
dragging = true;
startX = event.localX;
}
function mouseReleased(event:MouseEvent):void
{
dragging = false;
}
Then you're MOUSE_MOVE touch event can handle all the logic:
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove); // Notice this event is on stage, not mc.
function mouseMove(event.MouseEvent):void
{
value += event.localX - startX;
if (value < 0) value = 0;
if (value > 100) value = 100;
}
Happy Holidays!

how to stop a movieclip on the Y-axis with buttons?

I have two buttons that moves a movieclip up/down the Y-axis. How do I get the movieclip to stop at a certain height, and still be able to move it in the opposite direction?
I need this to work like this:
When you press the down-button, the movieclip goes downwards, but not past Y=500.
When you press the up-button, the movieclip goes upwards, but not past Y= 300.
I get the movieclip to stop at the correct point (500), but when it reaches this point it's stuck..
so it won't go upwards again if I press the up-button.
can someone help me please?:)
here's my code so far:
1) decrease = the down-button
2) increase = up-button
3) stempel = the movieclip I want to stop on the Y-axis
var moveStempel = 0;
decrease.addEventListener(MouseEvent.MOUSE_DOWN, decreasePressed);
decrease.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
increase.addEventListener(MouseEvent.MOUSE_DOWN, increasePressed);
increase.addEventListener(MouseEvent.MOUSE_UP, removeEnterFrame);
function decreasePressed(e:MouseEvent):void
{
moveStempel = 2;
addEnterFrame();
}
function increasePressed(e:MouseEvent):void
{
moveStempel = -2;
addEnterFrame();
}
// ADD ENTER FRAME
function addEnterFrame():void
{
this.addEventListener(Event.ENTER_FRAME, update);
}
function removeEnterFrame(e:MouseEvent):void
{
this.removeEventListener(Event.ENTER_FRAME, update);
}
function update(e:Event):void
{
if (stempel.y < 500)
{
stempel.y += moveStempel;
trace("inside");
}
else if (stempel.y > 500)
{
stempel.stop();
trace("outside");
}
In your code right now, once stempel has a y value greater than 500, it will never be able to move again.
There are two conditions when stempel can move: if it's moving down, it can't be at the bottom of the allowed area, and if it's moving up, it can't be at the top of the allowed area.
if ((stempel.y < 500 && moveStempel == 2) || (stempel.y > 300 && moveStempel == -2))
{
stempel.y += moveStempel;
trace("inside");
}
else
{
stempel.stop();
trace("outside");
}

How to make carousel loop back to beginning

I have a 800w movieclip containing 4 panels next to each other, each with 200 width (See picture here). When I click and drag then mouse_out, it detects the direction of the mouse and move the panels by 200 either left or right depending on the direction.
My problem is I want this to loop, so when it gets to the very left panel, it'll continue on to the left, and visa versa when it gets to the very right panel, I should be able to continue with the click and drag motion.
I'm not sure if this is considered a carousel.
Anyhow this is what I have so far. I've made 2 comments "What happens now" toLeftTween() and toRightTween() to indicate where I'm stuck.
import com.greensock.*;
import com.greensock.easing.*;
var selectX:Number = 0;
var mouseX1:int = 0;
var mouseX2:int = 0;
var mcPosX:int = 0;
var contents:MovieClip = all_mc;
var draggable:Boolean = true;
contents.buttonMode = true;
contents.mouseChildren = false;
contents.x = 0;
contents.y = 70;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
function mouseDownHandler(e:MouseEvent):void {
//select the correct point on mc
selectX = contents.x - mouseX;
//for prediction direction later - mouse point 1
mouseX1 = stage.mouseX;
//trace("1: " + mouseX1);
// move mc with mouse
if (draggable) {
addEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
} else {
trace("unable to drag");
}
}
function mouseUpHandler(e:MouseEvent):void {
//for prediction direction later - mouse point 2
mouseX2 = stage.mouseX;
//trace("2: " + mouseX2);
//remove mc move with mouse
removeEventListener(Event.ENTER_FRAME, onEnterFrameHandler);
//check for direction of the mc based on mouseX1 and mouseX2
mouseDirection();
}
function onEnterFrameHandler(e:Event):void {
contents.x = parent.mouseX + selectX;
}
function mouseDirection():void {
if (mouseX1 > mouseX2) {
trace("to the left");
toLeftTween();
} else if (mouseX1 < mouseX2) {
trace("to the right");
toRightTween();
} else {
trace("nothing happened");
}
}
function toLeftTween():void {
if(contents.x<1 && contents.x>199) {
mcPosX = 0;
trace("to left - Panel 1");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = -200;
trace("to left - Panel 2");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -400;
trace("to left - Panel 3");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -600;
trace("to left - Panel 4");
} else if(contents.x>-600) {
//What happens now?
}
var toLeftTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}
function toRightTween():void {
if(contents.x<-601 && contents.x>-799) {
mcPosX = -600;
trace("to right - Panel 4");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -400;
trace("to right - Panel 3");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -200;
trace("to right - Panel 2");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = 0;
trace("to right - Panel 1");
} else if(contents.x<-2) {
//What happens now?
}
var toRightTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}
Good work. The solution is actually quite simple, when you see it.
You need to check the distance between your starting mouse point and your current mouse point, every frame, which it looks like you're doing with selectX and mouseX. Your problem is that when you go past a certain distance, you have no logic to handle your loop.
Because it's a loop, you want to check whether the distance between your starting point and current point is greater than the width of your carousel movieclip, which is 800. If so, you need the logic to loop back on itself. (However, I'm not sure why your toLeftTween and toRightTween functions check that contents.x is in a negative range....I suppose that's because of the registration point on the movieclip?)
(Edit: I see what you did - why you have the negative numbers. You're sliding the movieclip to the left as needed. Now that I'm looking at the way you did this, the modulus won't actually work because you're checking a range between -600 and 200, instead of a range between 0 and 800...)
You'll need something like this.
function toLeftTween():void {
// If contents.x is divisible by the width of the movieclip, it's greater than the mc width.
// We check this here, and grab the remainder.
if (contents.x > 800 || contents.x < -600)
contents.x = contents.x % 800; // Modulus operator. Returns remainder.
if(contents.x<1 && contents.x>199) {
mcPosX = 0;
trace("to left - Panel 1");
} else if(contents.x<-1 && contents.x>-199) {
mcPosX = -200;
trace("to left - Panel 2");
} else if(contents.x<-201 && contents.x>-399) {
mcPosX = -400;
trace("to left - Panel 3");
} else if(contents.x<-401 && contents.x>-599) {
mcPosX = -600;
trace("to left - Panel 4");
} else if(contents.x>-600) { // I think you flipped a sign here... -lunchmeat
//What happens now?
// Due to the modulus, we should never find ourselves in this situation!
}
var toLeftTween:TweenLite = new TweenLite(contents,0.25, {x:mcPosX});
}
That should do the trick, more or less. You'll need to add this to both tween functions. (It might need a little tweaking.) Let me know if you run into any problems. Good luck!
if you want something like
(Note:numbers stands for panels, and index 0 is initial point.)
for index 0
1 - 2 - 3 - 4
for index 1
2 - 3 - 4 - 1
for index -1
4 - 1 - 2 - 3
Seems like you heading wrong way.
First if u need continues loop you have to move movieclips that is out of view to the end. And you need a clone of first element at the end of items for continues look. I would prefer to use bitmapData of content so you wont need a clone of first element and it ll compute faster and the way is easier.