Only get mouse coordinates when it is on screen as3 - actionscript-3

So I have a character on a screen and I want it to be at the current mouse coordinates.
The problem I'm having is when the mouse is not on the screen the character will jump to some random location on the screen when what I want it to do is stay in the location the mouse was last in when it was on the screen.
Question:
How do I make it so my character stays in the last location the mouse was in on the screen?
import flash.ui.Mouse;
import flash.display.MovieClip;
import flash.events.*;
stage.addEventListener (Event.ENTER_FRAME,gameloop);
function gameloop(e:Event){
Mouse.hide();
Character.x = mouseX;
Character.y = mouseY;
}

You just have to put some conditions on your position assignments:
function gameloop(e:Event){
Mouse.hide();
if(mouseX > 0 && mouseX < stage.stageWidth - Character.width){
Character.x = mouseX;
}
if(mouseY > 0 && mouseY < stage.stageHeight - Character.height){
Character.y = mouseY;
}
}
There you are saying, only update the characters x value if the mouse position if greater than 0 and less than stage width (less the characters width which is helpful if you anchor point is 0,0 on your character). If the condition doesn't pass, the character will remain in it's previous position.
Your condition may be different depending on the bounds your characters needs to adhere to.
Though, if your mouse is off-screen (outside your application window), it should not update the mouseX/Y values at all, so perhaps there is another issue at play here?

So what was happening is when the mouse left the screen it would for some reason read the mouse values in a seemingly random spot on the screen. The new random location of the mouse seemed to always be 60-70+ or so pixels away from the last mouse value so my solution was this:
stage.addEventListener(MouseEvent.MOUSE_MOVE,screenExit);
function screenExit(e:MouseEvent){
if((mouseX > (lastX+50))||(mouseX < (lastX-50))){
lastX =mouseX;
lastY =mouseY;
}
else if((mouseY > (lastY+50))||(mouseY < (lastY-50))){
lastX =mouseX;
lastY =mouseY;
}
else{
Character.x = mouseX;
Character.y = mouseY;
}
lastX =mouseX;
lastY =mouseY;
trace(mouseX, mouseY);
}
whenever the mouse moves it will check the values of the mouse, if the values are drastically different (50) then it assumes the mouse is off the screen (which it is) and does not update the characters location until the mouse returns to the screen and it can track movement again.
also it is possible for someone to move the mouse faster than 50 pixels (in which case it will lag for the next movement) but given the game I am making going that fast would be unlikely.

Related

How to shoot on angles with rotating Movie Clip?

Hey everyone so I am having some trouble with this. So I have an Array of Barrel Movie clips that are added to the stage and a movie clip called Circle that when comes in contact with any of the barrels in the array the barrel that it is currently hittesting starts to rotate. It rotates on its registration point which is centered. So in my ENTER_FRAME event is where I have everything setup for the barrel to rotate and hit Test etc...
This is how the circle is added to the barrels:
if (!circleFired)
{
circle.x = globalFirePoint.x;
circle.y = globalFirePoint.y;
currentCannon.addChildAt(circle, 0);
}
Now what I am trying to accomplish is when the user taps the screen the circle Movie clip is shot from the Barrel. Right now I have the circle shooting from the barrel in the angle that its supposed to shoot but instead of going in a straight line from the angle it shoots it shoots and starts to curve really quickly in the clockwise position that the barrel is rotating in.
Here is the code I have that is sort of working besides that one problem:
var dX:Number = globalFirePoint.x;
var dY:Number = globalFirePoint.y;
var angle:Number = Math.atan2(dY, dX);
if (circleFired)
{
circle.x += Math.sin(deg2rad(angle -90)) * velocity;
circle.y += Math.cos(deg2rad(angle - 90)) * velocity;
}
so the globalFirePointis this:
globalFirePoint = localToGlobal(new Point(currentCannon.mcFirePoint.x, currentCannon.mcFirePoint.y));
Its the starting point I want the circle to shoot from.
Here is the deg2rad Function:
private function deg2rad(num:Number):Number
{
var radians:Number = num * (Math.PI / 180);
return radians;
}
I know that I need sin and cos to calculate the angle correct? Is the math wrong? Why is the circle curving when the circle shoots from the globalFirePoint? What can I do to make it go in a straight line?
Any help would be appreciated thanks!
Does globalFirePoint change on each ENTER_FRAME event? If so then the calculated angle is going to change as well, leading to the curve you are experiencing.
One way to fix this is to only calculate globalFirePoint when the user presses the screen. Then on every ENTER_FRAME event instead of re-calculating globalFirePoint, use the already calculated globalFirePoint that won't change unless the user presses the screen when the circle is in a barrel.
You should only calculate the angle when the user presses the screen as well. There is no need to calculate it on every ENTER_FRAME event, since the only time you're interested in the angle is when the circle is shot from a barrel.

How do I make smoother rotation for my objects in my game?

I am making a game where insects from the top of the screen come down. The object of the game is to kill these insects. I have made a code for these insects on how they move, but what seems to be the problem is that they seem to rotate in a non smooth pattern. They twitch!
This is the code:
else // Enemy is still alive and moving across the screen
{
//rotate the enemy between 10-5 degrees
tempEnemy.rotation += (Math.round(Math.random()*10-5));
//Find the rotation and move the x position that direction
tempEnemy.x -= (Math.sin((Math.PI/180)*tempEnemy.rotation))*tempEnemy.speed;
tempEnemy.y += (Math.cos((Math.PI/180)*tempEnemy.rotation))*tempEnemy.speed;
if (tempEnemy.x < 0)
{
tempEnemy.x = 0;
}
if (tempEnemy.x > stage.stageWidth)
{
tempEnemy.x = stage.stageWidth;
}
if (tempEnemy.y > stage.stageHeight)
{
removeEnemy(i);
lives--;
roachLevel.lives_txt.text = String(lives);
}
}
}
}
Another problem that I am experiencing is that some of the insects are going along the edge of the screen. The user can barely kill them because half of their bodies are on the screen, and the other half are off. Can I make them move a bit away from the edge, like an offset? Thank you!
From your code, it looks like they are twitching because you're changing the rotation by a large amount right away:
tempEnemy.rotation += (Math.round(Math.random()*10-5));
Instead you should interpolate/animate to your desired rotation instead of just jumping right to it. There are a few ways to do this, but not sure how your animation is set up.
To keep insects from going right to the screen edges you could put in an offset and limit the x/y positions.
Such as going:
var offset:int = 100; // limits the max x to be 100 pixels from the right edge of the stage
if (tempEnemy.x > (stage.stageWidth - offset)){
tempEnemy.x = stage.stageWidth - offset;
}

startdrag start point limitations?

I have a slider that controls a movie clip by dragging it through the frames to animate and this works great when dragging from left to right, But i want the slider to start in the middle and drag through the movie clip from a center point being able to go 350 to the right and 350 to the left.
Is this possible?
Heres my code so far and as you can see it drags 350 to the right through dialSpin_mc.
Is there a way to make the slider start at a certain frame and go backwards and forwards?
dialSpin_mc.stop();
slider_mc.knob_mc.buttonMode = true;
slider_mc.knob_mc.addEventListener(MouseEvent.MOUSE_DOWN, onDragKnob);
stage.addEventListener(MouseEvent.MOUSE_UP, onReleaseKnob)
slider_mc.knob_mc.buttonMode = true;
function onDragKnob(myEvent:Event):void
{
slider_mc.knob_mc.startDrag(false, new Rectangle(0,0,350,0));
slider_mc.knob_mc.addEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onReleaseKnob(myEvent:Event):void
{
slider_mc.knob_mc.stopDrag();
slider_mc.knob_mc.removeEventListener(Event.ENTER_FRAME, onScrubMovie);
}
function onScrubMovie(myEvent:Event):void {
var playHead:int=Math.round((slider_mc.knob_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}
As discussed in comments this is how you could code the slider functionality without using the startDrag() and stopDrag() functions.
The idea is that when you press the mouse button down over the slider, an ENTER_FRAME listener is created. Every frame the sliders X position will be updated to match the mouseX position, and to make sure it can only travel 175 pixels either way we also check the sliders new position.
After making sure the sliders position is valid, you can use the same code to set the dialSpin_mc frame.
Once the mouse button is released, the enter frame listener is removed.
The sliderOrigin declared at the top of the code will need to be changed to whatever is appropriate for your project (whatever the sliders xposition is when you move it to the middle of the slide area rather than the very left).
var sliderOrigin:int = 150; // The x position the slider is in when in the center of the slide bar
slider_mc.x = sliderOrigin;
slider_mc.addEventListener(MouseEvent.MOUSE_DOWN, mDown);
slider_mc.addEventListener(MouseEvent.MOUSE_UP, mUp);
function mDown(e:MouseEvent):void
{
addEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function mUp(e:MouseEvent):void
{
removeEventListener(Event.ENTER_FRAME, UpdateDrag);
}
function UpdateDrag(e:Event):void
{
slider_mc.x = mouseX;
// Check if the slider is 'out of bounds' and change its position if it is
if(slider_mc.x < sliderOrigin - 175)
slider_mc.x = sliderOrigin - 175;
else if(slider_mc.x > sliderOrigin + 175)
slider_mc.x = sliderOrigin + 175
var playHead:int = Math.round((slider_mc.x/350*8)+1);
dialSpin_mc.gotoAndStop(playHead);
}
Depending on the start position of the slider the range of playHead will change (so if the slider starts at x pos 200 the range would be between 2 and 10, at x pos 400 the range is between 6 and 14 - simple fix by changing the offset from +1 to whatever is necassary).

How to make my character move relative to the mouse position with actionscript 3?

ok so i have a character called character_mc and i want it to move towards the mouse when you press the forward arrow and strafe relative to right angles of that.
i am quite new to actionscript so could you please include and example of your code in my original code
Here is my current code:
import flash.events.MouseEvent;
//Event Listners
stage.addChild(crosshair_mc);
crosshair_mc.mouseEnabled = false;
crosshair_mc.addEventListener(Event.ENTER_FRAME, fl_CustomMouseCursor);
function fl_CustomMouseCursor(event:Event)
{
crosshair_mc.x = stage.mouseX;
crosshair_mc.y = stage.mouseY;
}
Mouse.hide();
stage.addEventListener(MouseEvent.MOUSE_MOVE,facecursor);
stage.addEventListener(KeyboardEvent.KEY_DOWN, fl_KeyboardDownHandler);
//Functions
function facecursor(event):void
{
character_mc.rotation = (180 * Math.atan2(mouseY - character_mc.y,mouseX - character_mc.x))/Math.PI + 90;
}
function fl_KeyboardDownHandler(event:KeyboardEvent):void
{
trace("Key Code Pressed: " + event.keyCode);
if (event.keyCode == 38)
{
character_mc.y = character_mc.y - 5;
}
if (event.keyCode == 40)
{
character_mc.y = character_mc.y + 5;
}
if (event.keyCode == 39)
{
character_mc.x = character_mc.x + 5;
}
if (event.keyCode == 37)
{
character_mc.x = character_mc.x - 5;
}
}
I can tell you the basic concept of how you could do this, but you'll have to apply it to your own code. To involves converting your movement code to use a vector, then modifying the vector to get a direction facing the mouse (or at right angles to that direction) and a little bit of math.
Right now you have the character moving straight along the x and y axis only in each key press case. Left/Right only move along the X and Up/Down only move along the Y.
To move towards the mouse will require the character to move both along the X and Y when the Up/Down/Left/Right keys are pressed. Clearly you can see if you move both the character's x/y positions by the same amount, say 5, then it'll move exactly at 45 degrees (though it'll actually move a step of 7.07 pixels, hopefully you can see why). You can represent this as a vector: (5,5). You can use a Point object to represent this vector:
var movementVector:Point = new Point(5, 5);
trace(movementVector.x); // gives 5
trace(movementVector.y); // also gives 5
With that in mind, you can also use a vector to represent movement straight up and down on the y axis:
// set the x to 0 and y to 5
movementVector.x = 0; // 0 would mean not to move the character along the x
movementVector.y = 5; // using -5 would move the character up
And to move along the x axis only:
movementVector.x = 5; // using -5 would move the character right
movementVector.y = 0; // 0 would mean not to move the character along the y
To do the actual movement of the character would be the same as you are doing now, except you use the vector's values:
character_mc.x = character_mc.x + movementVector.x;
character_mc.y = character_mc.y + movementVector.y;
Now to figure out the proper vector to move on a diagonal from the character's position to the mouse position is pretty simple. The x value of the vector is the x distance from the character to the mouse, and the y value of the vector is the y distance from the character to the mouse.
Let's say the character is ay 125, 100 and the mouse at 225, 150. This means the distance between the character and mouse is 100, 50 x and y. Thus you'd end up with a vector:
movementVector.x = 100;
movementVector.y = 50;
If you were to apply this vector as it is to the character's position as it is, it would arrive at the mouse instantly (and then go beyond it) as the character is moving 100 pixels along the x and 50 pixels along the y right away. The step size would be 111.8 pixels long -too big. You would need to scale it down to the character's speed. You can do this by calling the normalise() method on the Point class to scale down the vector:
trace(movementVector.x); // gives 100
trace(movementVector.y); // gives 50
// assuming '5' is the max speed of the character
movementVector.normalise(5);
trace(movementVector.x); // gives 4.47213595499958
trace(movementVector.y); // gives 2.23606797749979
This would result in a 'step' size of 5 now. Applying this would make your character move 5 pixels towards a point 100 pixels to the right and 50 pixels down from where it started.
To transform a vector exactly 90 degrees, a quick and simple way is to swap the x and y values around.
If you are curious on what normalise() method mathematically does, is that it takes the x and y values of the vector (or point) and divides it by the length to get a unit vector (or a vector with a step size of 1), then times the input you give it to scale it to the desired length.
To move your character_mc towards the mouse point you only need the direction vector between the two:
var dir:Point = new Point(mouseX - character_mc.x, mouseY - character_mc.y);
dir.Normalize();
// The following should be called when the 'up' or 'forward' arrow is pressed
// to move the character closer to mouse point
character_mc.x += dir.x; // dir can be multiplied by a 'speed' variable
character_mc.y += dir.y;
Strafing left and right around the point is a little more tricky:
// Where radius is the distance between the character and the mouse
character_mc.x = mouseX + radius * Math.cos(rad);
character_mc.y = mouseY + radius * Math.sin(rad);
You should find this tutorial useful as it does everything you describe and more:
http://active.tutsplus.com/tutorials/actionscript/circular-motion-in-as3-make-one-moving-object-orbit-another/

Correct formula to "invert" rotation (in degrees) in AS3?

I have my player movieclip on the stage, and when the mouse is clicked a bullet is fired and projected at the correct angle to point itself at the mouse location. I also want a "mirroring" enemy, that fires at the complete opposite direction when the player does.
For example, when the player shoots upwards, the enemy should shoot down. Likewise, shooting to the right will cause the enemy to shoot to the left.
Is there a formula to convert the rotation in degrees to it's complete opposite?
Using Matrix is a very simple and exact solution. just multiple a or c with -1 ( to flip vertical and horizontal ).
Sample code:
var _tmpMatrix:Matrix = sprite.transform.matrix;
_tmpMatrix.a *= -1;
if ( _tmpMatrix.a < 0 ) {
_tmpMatrix.tx = sprite.width + sprite.x;
} else {
_tmpMatrix.tx = 0;
}
sprite.transform.matrix = _tmpMatrix;
Wouldn't adding or subtracting 180 degrees point in the opposite direction?
or
obj.scaleX = -1;
will do the same thing. =)