Java-Gaming.org    
Featured games (81)
games approved by the League of Dukes
Games in Showcase (487)
Games in Android Showcase (110)
games submitted by our members
Games in WIP (552)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  Angle of slope for mouse movement.  (Read 4242 times)
0 Members and 1 Guest are viewing this topic.
Offline SkyAphid
« Posted 2012-05-07 01:14:49 »

So, I'm wanting smooth mouse movement, so I'm going to have the player move in directions (0-360).

I click the screen, and I have the slope. Which, is (y2-y1) / (x2-x1)

Now, I need to use trig to get the angle. I'm just stuck right there. Any help? I'm a freshie, so I'm just finishing geometry. So, I know about the whole SohCahToa thing, I'm just not very skilled in its use seeing as we messed with it for like a week out of the whole year.

Thanks.

EDIT/P.S:
I'm also going to need means of moving the players X/Y towards the direction we get from this, so advice on that too is appreciated.

“Life is pretty simple: You do some stuff. Most fails. Some works. You do more of what works. If it works big, others quickly copy it. Then you do something else. The trick is the doing something else.” ~Leonardo da Vinci
Offline theagentd
« Reply #1 - Posted 2012-05-07 02:06:18 »

1  
Math.atan2(mouseY - playerY, mouseX - playerX); //Both are in world coordinates

Myomyomyo.
Offline DavidW

Junior Member


Medals: 3
Exp: 7 years



« Reply #2 - Posted 2012-05-07 15:08:03 »

What theagentd said is correct, but ultimately you don't really want that angle since it will have to be transformed back into Cartesian coordinates to move your player.  Here is how you would achieve what you want.  Have three variables, dx, dy, and speed. The variables dx and dy represent the change in the players X and Y coordinate per game loop.  In case you are curious, they are named this way with the d because of calculus.  Not really important actually, you could name them "changeInX, changeInY" if you prefer.  Each game loop, you calculate what dx and dy are:
1  
2  
dx = mouseX - playerX
dy = mouseY - playerY

So now you have the proper direction, but not the proper speed.  If you add dx and dy to your players location now they will instantly teleport to the mouse location, which isn't what you want.  To fix this, we scale the values of dx and dy.  Think of dx and dy as the sides of a right triangle, and the hypotenuse is the direction you are going to travel.  We want this hypotenuse to be the same length no matter which direction the player is heading.   We can use the Pythagorean Theorem to figure out that what we want is
1  
dx^2 + dy^2 = speed^2

So what we will do is normalize the d variables: scale the triangle they currently make to have hypotenuse of length one.  We do this by calculating the distance using the Pythagorean theorem and then dividing both variables by that distance.  Finally, we multiply dx and dy by speed, which will give us the result we want!  Here it all is:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
double hypotenuse = Math.sqrt(dx*dx + dy*dy);
dx /= hypotenuse;
dy /= hypotenuse;
dx *= speed;
dy *= speed;

// now we have the correct dx and dy, so add those to the players position!

playerX += dx;
playerY += dy;


You can of course do a slight optimization here by dividing speed by hypotenuse and multiplying dx and dy by that.  If you are heart set on using trigonometry, then the code would look like this:
1  
2  
3  
4  
5  
6  
double theta = Math.atan2(mouseY - playerY, mouseX - playerX);
dx = speed*Math.cos(theta);
dy = speed*Math.sin(theta);

playerX += dx;
playerY += dy;


This will work just fine as well and basically does the same thing, however, it involves these trig functions which are slow.  In a small game it probably won't matter though.  If I were you, I would avoid using math that you haven't learned about yet since you will not be able to fix any bugs that show up.  Hope this helps!  Grin

Hello!
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline DruLeeParsec

Junior Member


Medals: 2
Projects: 1



« Reply #3 - Posted 2012-05-07 15:18:13 »

I just wrote very similar code for a game I'm working on.  In this code example I have a gun turret in a stationary object which I want to point at my tank.  My tank is the playerEntity.  The getX and getY are returning the X and Y of THIS object (My gun turret).

Notice that the atan and atan2 return a positive or negative number depending on which quadrant you're in so you have to adjust for that.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
   public void doUpdate(int delta){
      Entity playerEntity = gameLevel.getPlayer();
      float px = playerEntity.getX();
      float py = playerEntity.getY();
     
      float diffX = px - getX();
      float diffY = getY() - py;
      float angle = 0;
     
      // Protect against a divide by zero error
     if(diffY != 0){
         angle = (float) Math.toDegrees(Math.atan(diffX/diffY));
      }

      if(diffX >0 && diffY >0){
         // do nothing
     }
      if(diffX <0 && diffY <0){
         angle = 180 + angle;
      }
      if(diffX >0 && diffY <0){
         // Note, angle is negative so I'm actually subtracting from 180
        angle = 180 + angle;
      }
      if(diffX <0 && diffY >0){
         // Note, angle is negative so I'm actually subtracting from 360
        angle = 360 + angle;
      }

      turretGun.setRotation((float) angle );
   }


At turretGun.setRotation((float) angle ); my angle is the proper angle in degrees.  So now my turret's gun is pointing at my tank.
Offline ra4king

JGO Kernel


Medals: 345
Projects: 2
Exp: 5 years


I'm the King!


« Reply #4 - Posted 2012-05-07 18:22:55 »

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
   public void doUpdate(int delta){
      Entity playerEntity = gameLevel.getPlayer();
      float px = playerEntity.getX();
      float py = playerEntity.getY();
     
      float diffX = px - getX();
      float diffY = getY() - py;
      float angle = 0;
     
-      // Protect against a divide by zero error
-      if(diffY != 0){
+         angle = (float) Math.atan2(diffY,diffX);
-      }

-      if(diffX >0 && diffY >0){
-         // do nothing
-      }
-      if(diffX <0 && diffY <0){
-         angle = 180 + angle;
-      }
-      if(diffX >0 && diffY <0){
-         // Note, angle is negative so I'm actually subtracting from 180
-         angle = 180 + angle;
-      }
-      if(diffX <0 && diffY >0){
-         // Note, angle is negative so I'm actually subtracting from 360
-         angle = 360 + angle;
-      }

      turretGun.setRotation((float) angle );
   }

FTFY: atan2 takes care of all that.

EDIT: @Riven, looks like your +/- feature is a bit buggy :/

Offline Roquen
« Reply #5 - Posted 2012-05-07 19:32:34 »

Do the sqrt.  Do the divide once and multiply by the recip.  Forget about atan2 in this instance as you don't care about the angle.  Degrees are for little kids and scripting...radians are your friend.
Online pitbuller
« Reply #6 - Posted 2012-05-07 20:56:43 »

1  
vec2 direction = normalize(pos - pos2);


Vectors, just learn those.
Offline theagentd
« Reply #7 - Posted 2012-05-08 02:20:30 »

What if he wants a cannon aimed at the mouse? atan2 has its uses. xd

Myomyomyo.
Offline DruLeeParsec

Junior Member


Medals: 2
Projects: 1



« Reply #8 - Posted 2012-05-08 02:44:04 »

Quote
FTFY: atan2 takes care of all that.

Math.toDegrees(Math.atan2(diffX,diffY)) gives positive degrees if the target is to the right of the source and negative degrees if you're to the left.

But it turns out that the Slick2D rotate command understands that so now the code is:

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
   public void doUpdate(int delta){
      Entity playerEntity = gameLevel.getPlayer();
      float px = playerEntity.getX();
      float py = playerEntity.getY();
     
      float diffX = px - getX();
      float diffY = getY() - py;

      turretGun.setRotation((float) Math.toDegrees(Math.atan2(diffX,diffY)));
   }
Offline ra4king

JGO Kernel


Medals: 345
Projects: 2
Exp: 5 years


I'm the King!


« Reply #9 - Posted 2012-05-08 02:57:18 »

You shouldn't be using degrees at all here. Everything works with radians.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Online Riven
« League of Dukes »

JGO Overlord


Medals: 782
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #10 - Posted 2012-05-08 03:00:28 »

1  
2  
      float diffX = px - getX();
      float diffY = getY() - py;

Didn't the alarm bells ring when you wrote that? Clueless

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline ra4king

JGO Kernel


Medals: 345
Projects: 2
Exp: 5 years


I'm the King!


« Reply #11 - Posted 2012-05-08 03:03:41 »

Looks fine to me if Y increases downwards.

Online UprightPath
« Reply #12 - Posted 2012-05-08 03:06:49 »

Yeah, it depends on where your origin is!

Remember, that most GUI software places the origin (0,0) at the top left corner. Slick does this. If you're using LIBGDX then it's the bottom left corner.

Online Riven
« League of Dukes »

JGO Overlord


Medals: 782
Projects: 4
Exp: 16 years


Hand over your head.


« Reply #13 - Posted 2012-05-08 03:08:08 »

Yeah, it depends on where your origin is!

Looks fine to me if Y increases downwards.

Never correct for the projection matrix in your vecmath Cranky

Your cannon will be affected by the same projection matrix, so you'd have to 'flip' your angle again if you'd want to aim your cannon in model space. If you do it in screen space, you're going to create a mess in your code.



Keep all your logic/math in model space!

Hi, appreciate more people! Σ ♥ = ¾
Learn how to award medals... and work your way up the social rankings
Offline DruLeeParsec

Junior Member


Medals: 2
Projects: 1



« Reply #14 - Posted 2012-05-08 03:23:16 »

You shouldn't be using degrees at all here. Everything works with radians.

I understand that.  But the rotate method in SLick2D which I'm using requires degrees.

1  
2  
3  
4  
5  
rotate

public void rotate(float angle)

    Add the angle provided to the current rotation. The angle will be normalized to be 0 <= angle < 360. The image will be rotated around its center.


That's why I'm not using radians.

Also, while it says we're actually adding an angle to the existing angle it appears to work by simply feeding it the angle we calculated.  Although when I was coding the rotation of my tank turret I did have to get the current angle and subtract it from the calculated angle.  I'm reviewing my code now to see why it worked one way in one part of my code and another in a different part of my code.

I'm not asking for help, I'm just pointing out that it's interesting.  Wink

Offline Roquen
« Reply #15 - Posted 2012-05-08 03:53:24 »

What if he wants a cannon aimed at the mouse? atan2 has its uses. xd
Sure atan2 is handy.  But you don't need it in this example either.
Offline theagentd
« Reply #16 - Posted 2012-05-08 04:03:42 »

What if he wants a cannon aimed at the mouse? atan2 has its uses. xd
Sure atan2 is handy.  But you don't need it in this example either.
I claim wall hack and aimbot. Why not?

Myomyomyo.
Offline Roquen
« Reply #17 - Posted 2012-05-11 14:33:23 »

Opps I missed this...quick write up: HERE
Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #18 - Posted 2012-05-11 18:40:34 »

Yes, I agree with Riven. Logic / positioning should always be completely and totally separate from rendering. In other words, code the logic in whatever way makes sense to you. Meters, perhaps, where +Y is actually up? Then just do a conversion on these values when you draw. And do that conversion in one common place (a Camera class, perchance?).

Doing this also makes it very easy to zoom in and out, rotate the view, shake the screen, blah blah blah.

See my work:
OTC Software
Pages: [1]
  ignore  |  Print  
 
 
You cannot reply to this message, because it is very, very old.

 

Add your game by posting it in the WIP section,
or publish it in Showcase.

The first screenshot will be displayed as a thumbnail.

CopyableCougar4 (23 views)
2014-08-22 19:31:30

atombrot (34 views)
2014-08-19 09:29:53

Tekkerue (30 views)
2014-08-16 06:45:27

Tekkerue (28 views)
2014-08-16 06:22:17

Tekkerue (18 views)
2014-08-16 06:20:21

Tekkerue (27 views)
2014-08-16 06:12:11

Rayexar (65 views)
2014-08-11 02:49:23

BurntPizza (41 views)
2014-08-09 21:09:32

BurntPizza (31 views)
2014-08-08 02:01:56

Norakomi (41 views)
2014-08-06 19:49:38
List of Learning Resources
by Longor1996
2014-08-16 10:40:00

List of Learning Resources
by SilverTiger
2014-08-05 19:33:27

Resources for WIP games
by CogWheelz
2014-08-01 16:20:17

Resources for WIP games
by CogWheelz
2014-08-01 16:19:50

List of Learning Resources
by SilverTiger
2014-07-31 16:29:50

List of Learning Resources
by SilverTiger
2014-07-31 16:26:06

List of Learning Resources
by SilverTiger
2014-07-31 11:54:12

HotSpot Options
by dleskov
2014-07-08 01:59:08
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!