Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (523)
Games in Android Showcase (127)
games submitted by our members
Games in WIP (592)
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  
  How to shoot from the tip of a rotating gun?  (Read 3633 times)
0 Members and 1 Guest are viewing this topic.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Posted 2013-06-27 01:00:38 »

So far in my game, I have been rotating by rendering w/ slick2d. I was working, and realized that I needed the coords of a point on an object when it is rotated. So that, say I rotate it 78 degrees: the object should rotate and I should be able to get the coords of (6, 1) on the image, while rotating.
Sorry if it is unclear what I am asking!


EDIT:
I realize that that is incredibly unclear, let me elaborate:
I have a gun that rotates, and I need to shoot from the tip of the gun. The gun's sprite is 8x8, and the tip is at (1, 6). When I rotate, I want to make the bullets instantiate at the tip, so how would I do that? I tried this post, but it did not work at the last post. Just looped around in circles around the x and y... Useless. So what would I do?


ANOTHER EDIT:
Okay, here is my problem in excruciating detail:
I have a player that I render. Then I have a gun that I render. See the two sprites:


I have the gun take the player's rotation, and fire from a point, 1, 6 on the gun. I want to rotate it. So I do this formula:
1  
2  
3  
float tipx = (float) ((getPlayer().getX() + 1) + 8 * Math.cos(Math.toRadians(getPlayer().getRot())));
float tipy = (float) ((getPlayer().getY() + 6) + 8 * Math.sin(Math.toRadians(getPlayer().getRot())));
shotline = new Line(tipx, tipy, mousex, mousey);

But instead of the line starting at 1,6 on the gun, and ending on the mouse, I get this:
NOTE: Mouse is not visible, but the mouse is in all pictures at the farthest point on the line away from the player.



Offline Nitram

Senior Newbie


Medals: 1



« Reply #1 - Posted 2013-06-27 08:12:29 »

Oh, I think you can solve this quite simply.

I'll guess you know your rotation angle that was applied to rotate the gun. What you need to do is to calculate the angle of the vector from (x,y) to (1,6) (using atan2). The angle of that vector to the vector of the bullet that will launch from the tip is your "base rotation". You just add your gun rotation to that and use sin() and cos() to calculate the new location of your original (1,6). This way you know the location where the bullet launches. Your gun rotation without the "base rotation" gives you the flying vector of the bullet.

Is that in anyway a help? ^^

Nitram

Playable work in progress online RPG: http://illarion.org
Jabber user: nitram0815@jabber.ccc.de
Offline Oskuro

JGO Knight


Medals: 40
Exp: 6 years


Coding in Style


« Reply #2 - Posted 2013-06-27 11:54:14 »

A simple solution would be to have the projectile movement vector angle match that of the rotating shooter, and then just "teleport" the bullet upon instantiation a distance equal to the barrel length.

That way you save on calculating the position of the barrel's tip.

But you do need to have a decent vector class to handle the projectile's motion in any case.

Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline davedes
« Reply #3 - Posted 2013-06-27 13:38:51 »

Relevant:
http://www.rodedev.com/tutorials/gamephysics/

Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #4 - Posted 2013-06-27 17:46:46 »

Oh, I think you can solve this quite simply.

I'll guess you know your rotation angle that was applied to rotate the gun. What you need to do is to calculate the angle of the vector from (x,y) to (1,6) (using atan2). The angle of that vector to the vector of the bullet that will launch from the tip is your "base rotation". You just add your gun rotation to that and use sin() and cos() to calculate the new location of your original (1,6). This way you know the location where the bullet launches. Your gun rotation without the "base rotation" gives you the flying vector of the bullet.

Is that in anyway a help? ^^

Nitram
Okay, I see what you are getting at, but I don't know how to translate that to code. Could you give a small example?

Offline jonjava
« Reply #5 - Posted 2013-06-28 10:33:22 »

It's just simple trigonometry.

Basic Trigonometry: http://www.youtube.com/watch?v=Jsiy4TxgIME
Basic Vectors: http://www.youtube.com/watch?v=xp6ibuI8UuQ

Offline Oskuro

JGO Knight


Medals: 40
Exp: 6 years


Coding in Style


« Reply #6 - Posted 2013-06-28 11:00:58 »

From this thread:

Quote
and if you want to rotate them by hand around an arbitrary axis :

angle : rotation angle in Radians
axisX : x pos for rotation center
axisY : y pos for rotation center

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
class VectorXXX
{
   double x;
   double y;
   public void rotate(double angle,double axisX,double axisY)
   {
      double tY=y-axisX,tX=x-axisY;
      double cosa=Math.cos(angle);
      double sina=Math.sin(angle);
      x=tX*cosa + tY*sina + axisX;
      y=-tX*sina + tY*cosa + axisY;
   }
}


NB: adapted from 3DzzD not tested but should work

Really, there's a lot of information about this stuff. Use the forum's search function.

Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #7 - Posted 2013-06-28 19:40:31 »

It's just simple trigonometry.

Basic Trigonometry: http://www.youtube.com/watch?v=Jsiy4TxgIME
Basic Vectors: http://www.youtube.com/watch?v=xp6ibuI8UuQ

Yeah, it's a little stupid, but I am completely new to trigonometry. I wish my school was better at math, but they can't do everything. Thanks for the tutorials, they really help.

Offline Eli Delventhal

JGO Kernel


Medals: 42
Projects: 11
Exp: 10 years


Game Engineer


« Reply #8 - Posted 2013-06-28 20:25:45 »

Here is a very simple way of seeing it:

First, have an angle in radians.
Then, use Math.cos( angle ) to get the X amount, and Math.sin( angle ) to get the Y amount.

Cos always is X, and Sin always is Y.

See my work:
OTC Software
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #9 - Posted 2013-06-28 20:36:27 »

I get that, but look at the updated post. It does not work!

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

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #10 - Posted 2013-06-28 21:50:11 »

Code dump inbound: (sorry if this is long enough to qualify pastebin, wasn't sure)

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  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import javax.swing.JFrame;


public class RotationDemo extends JFrame implements Runnable {

   BufferedImage buffer;
   Player player;
   
   public RotationDemo() {
      super("Test");
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setSize(600,400);
      buffer = new BufferedImage(60,40,BufferedImage.TYPE_INT_RGB);
      player = new Player();
      Thread t = new Thread(this);
      setVisible(true);
      t.start();
   }

   @Override
   public void run() {
      while(true) {
         Graphics g = getGraphics();
         Graphics bufferGraphics = buffer.createGraphics();
         if(g==null)
            continue;
         player.update();
         render(bufferGraphics);
         g.drawImage(buffer,0,0,getWidth(),getHeight(),null);
         try {
            Thread.sleep(20);
         } catch (InterruptedException e) {}
      }
     
   }
   
   public void render(Graphics g) {
      g.setColor(Color.BLACK);
      g.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());
      player.render(g);
   }
   public static void main(String[] args) {
      new RotationDemo();
   }
}

class Player /*implements Updatable, Renderable or whatever*/ {
   int x=30,y=20;
   float rot=0;//in degrees
   
   
   private int radius = 4;
   private int gunOffsetX = 6, gunOffsetY = 1;       //gun "grip" location relative to player
   private int gunTipOffsetX = 0, gunTipOffsetY = 5; // "muzzle" location relative to "grip" (your mousex, mousey)
   
   public void update() {
      //sample behavior: spin in a circle
      rot++;
   }
   
   public void render(Graphics g) {
      g.setColor(Color.GREEN);
      g.fillOval(x-radius, y-radius, radius*2, radius*2);
      g.setColor(Color.RED);
     double rad = Math.toRadians(rot);
     double gunPosMag = Math.hypot(gunOffsetX, gunOffsetY);
     double gunPosX = x+gunPosMag*Math.cos(rad + Math.atan2(gunOffsetX, gunOffsetY));
     double gunPosY = y+gunPosMag*Math.sin(rad + Math.atan2(gunOffsetX, gunOffsetY));
     
     double gunLength = Math.hypot(gunTipOffsetX, gunTipOffsetY);

   //now note here the gunPosX instead of x, this keeps the frame of referance correct (if we use from muzzle to grip, use
   // x if you want muzzle to player)

     double gunTipPosX = gunPosX+gunLength*Math.cos(rad + Math.atan2(gunTipOffsetX, gunTipOffsetY));
     double gunTipPosY = gunPosY+gunLength*Math.sin(rad + Math.atan2(gunTipOffsetX, gunTipOffsetY));

      g.drawLine((int)Math.round(gunPosX), (int)Math.round(gunPosY), (int)Math.round(gunTipPosX), (int)Math.round(gunTipPosY));
   }
}



Quick demo of the maths highlighted there for you. Give it a quick run. Its a bit messy with keeping track of separate x and y values instead of nice Vector2's, but alas. You need to make sure you keep track of the local frame of reference when calculating coordinates for parts of the sprite.

Look up 2D vector rotation, etc.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #11 - Posted 2013-06-29 03:30:13 »

Okay A little trouble not with the code itself, but the terminology. I cannot get what 'muzzle,' or 'grip.' Can you explain more about what those mean? I am having trouble implementing this into my code.

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #12 - Posted 2013-06-29 03:33:28 »

"Grip" is the handle of the gun, basically where Player is holding it (the point rotating around the player's location, in your case (1,6)).
The "muzzle" in my example is the end of the gun's barrel, but looking at your post, you are using mousex and mousey, so you can likely ignore that.

Mainly the gunPosX and gunPosY are what you were looking for and I hope I showed how to calculate them. (Although if I spent more than 5 mins I could put together a better way)

EDIT: Relevant: Wikipedia: Rotation(mathematics)
Using this, here is much more straightforward method (shoulda just looked this up earlier.. oops):
1  
2  
double gunPosX = x+gunOffsetX*Math.cos(rad) - gunOffsetY*Math.sin(rad);
double gunPosY = y+gunOffsetX*Math.sin(rad) + gunOffsetY*Math.cos(rad);
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #13 - Posted 2013-06-29 04:01:51 »

Okay the problem either lies in the angles I am feeding the code, or what offset means. I am assuming it means the point on the gun's sprite I want to find (1, 6)? Also, here is my result:
So the point where 1, 6 is supposed to be is really just stuck on the circumphfrance of a circle with a center point on the top left corner of the gun sprite, and a radius defined by the offset. It's weird.

EDIT:
1  
2  
3  
4  
5  
6  
7  
   float offx = 1, offy = 6;
   float x = getPlayer().getX(), y = getPlayer().getY();
   
   double rad = Math.toRadians(getPlayer().getRot() + 90);
   double tipx = x+offx*Math.cos(rad) - offy*Math.sin(rad);
   double tipy = y+offx*Math.sin(rad) + offy*Math.cos(rad);
   shotline = new Line((float) tipx, (float) tipy, getPlayer().getWorld().getCamera().getX() + getPlayer().getInput().getAbsoluteMouseX() / getPlayer().getWorld().getCamera().getScaling(), getPlayer().getWorld().getCamera().getY() + getPlayer().getInput().getAbsoluteMouseY() / getPlayer().getWorld().getCamera().getScaling());


And here is a visual rep of what the supposed 1, 6 is stuck to being on:

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #14 - Posted 2013-06-29 04:12:46 »

Well, based on your original code:
1  
2  
3  
float tipx = (float) ((getPlayer().getX() + 1) + 8 * Math.cos(Math.toRadians(getPlayer().getRot())));
float tipy = (float) ((getPlayer().getY() + 6) + 8 * Math.sin(Math.toRadians(getPlayer().getRot())));
shotline = new Line(tipx, tipy, mousex, mousey);

(not sure what that 8 is though...)

I think it would be this:
1  
2  
3  
4  
5  
float rad = (float)Math.toRadians(getPlayer().getRot()); // for convenience and readability

float tipx = (float) (getPlayer().getX() + 1 * Math.cos(rad) - 6 * Math.sin(rad));
float tipy = (float) (getPlayer().getY() + 1 * Math.sin(rad) + 6 * Math.cos(rad));
shotline = new Line(tipx, tipy, mousex, mousey);


I'm not familiar with Slick, so I'm assuming no crazy coordinate systems or anything, but aside from something like that, this should work.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #15 - Posted 2013-06-29 04:16:11 »

Well, it did not... And 8 is the width and height of the sprite. I was skeptic when I started using it too.
Also, look at the updated post.

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #16 - Posted 2013-06-29 04:23:37 »

Based on that pic, it looks like the rotation is working correctly, but your player x and y are already offset from where it is being rendered. (I hope that makes sense) It looks like the circle is centered out in front of his head, when it's supposed to be centered on the top of his head.

Try making offx and offy smaller, especially the offy, that should (should) bring it back toward the player sprite.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #17 - Posted 2013-06-29 04:25:42 »

Lowering them just brings the radius of the circle down!

EDIT:
By 'them' I mean the offsets.

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #18 - Posted 2013-06-29 04:29:40 »

Does the circle stay out in front of his head, even when you face a different direction? Or does it stay to to the above left of him, no matter where he faces? I'm pretty sure I know what it is if it is the latter.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #19 - Posted 2013-06-29 04:40:09 »

No matter where I face, that invisible circle will stay in the same place relative to the player...

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #20 - Posted 2013-06-29 04:45:20 »

Good news then: I know what's wrong, or at least how to fix it: subtract the player sprite's [radius] from it's coords when rendering.

Watch what happens when you change my demo code above:
1  
g.fillOval(x-radius, y-radius, radius*2, radius*2);

to this:
1  
g.fillOval(x, y, radius*2, radius*2); // now it's not centered on (x,y)! oh no!


It will now exhibit your same problem.
This is due to the fact that drawOval(x,y,w,h) draws the oval's top left corner at the given (x,y), instead of it's center.
I suspect this is what is happening to you, as I know that Slick is supposed to act like J2D.

So were ever you render the sprite, subtract width/2 from x and height/2 from y, or add them to the tipx,tipy if that interferes with your collision detection, etc.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #21 - Posted 2013-06-29 04:54:07 »

Have to change the offset to the offset off of the center, but it works! Thanks!

Offline BurntPizza

« JGO Bitwise Duke »


Medals: 271
Exp: 5 years



« Reply #22 - Posted 2013-06-29 04:56:55 »

No prob, was bored tonight, figured I help out the first person I saw here. I suspect that maybe the offsets could be divided by an equal factor, possibly related to the '8' earlier. Try some nums between 2 and 8 and see. Or just calculate how far off you are and find the exact constant.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #23 - Posted 2013-06-29 05:04:49 »

No need for that! Like I said, it works! Thanks!

Offline Chili

Senior Newbie


Projects: 1



« Reply #24 - Posted 2013-07-23 19:45:42 »

Funny looking. High-res lighting on 8x8 sprites.
Offline wessles

JGO Wizard


Medals: 74
Projects: 4
Exp: 4 years


Radirius Software


« Reply #25 - Posted 2013-07-24 03:01:58 »

What? Also, necro  Smiley

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.

SHC (24 views)
2014-11-25 12:00:59

SHC (23 views)
2014-11-25 11:53:45

Norakomi (21 views)
2014-11-25 11:26:43

Gibbo3771 (22 views)
2014-11-24 19:59:16

trollwarrior1 (36 views)
2014-11-22 12:13:56

xFryIx (74 views)
2014-11-13 12:34:49

digdugdiggy (52 views)
2014-11-12 21:11:50

digdugdiggy (46 views)
2014-11-12 21:10:15

digdugdiggy (41 views)
2014-11-12 21:09:33

kovacsa (68 views)
2014-11-07 19:57:14
Understanding relations between setOrigin, setScale and setPosition in libGdx
by mbabuskov
2014-10-09 22:35:00

Definite guide to supporting multiple device resolutions on Android (2014)
by mbabuskov
2014-10-02 22:36:02

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
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!