Java-Gaming.org Hi !
 Featured games (90) games approved by the League of Dukes Games in Showcase (780) Games in Android Showcase (233) games submitted by our members Games in WIP (856) games currently in development
 News: Read the Java Gaming Resources, or peek at the official Java tutorials
Pages: [1]
 ignore  |  Print
 How to shoot from the tip of a rotating gun?  (Read 17062 times) 0 Members and 1 Guest are viewing this topic.
wessles
 « 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.

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
Oskuro

JGO Ninja

Medals: 77
Exp: 10 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.

davedes
 « Reply #3 - Posted 2013-06-27 13:38:51 »

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

It's just simple trigonometry.

Oskuro

JGO Ninja

Medals: 77
Exp: 10 years

Coding in Style

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

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

Eli Delventhal

JGO Kernel

Medals: 42
Projects: 11
Exp: 10 years

Game Engineer

 « Reply #6 - 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
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #7 - 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.
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #8 - 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);`
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #9 - 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 readabilityfloat 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.
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #10 - 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.
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #11 - 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.
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #12 - 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.
BurntPizza

« JGO Bitwise Duke »

Medals: 486
Exp: 7 years

 « Reply #13 - 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.
Chili

Senior Newbie

Projects: 1

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

Funny looking. High-res lighting on 8x8 sprites.
Pages: [1]
 ignore  |  Print

 hadezbladez (695 views) 2018-11-16 13:46:03 hadezbladez (342 views) 2018-11-16 13:41:33 hadezbladez (677 views) 2018-11-16 13:35:35 hadezbladez (167 views) 2018-11-16 13:32:03 EgonOlsen (2359 views) 2018-06-10 19:43:48 EgonOlsen (2468 views) 2018-06-10 19:43:44 EgonOlsen (1461 views) 2018-06-10 19:43:20 DesertCoockie (2126 views) 2018-05-13 18:23:11 nelsongames (1896 views) 2018-04-24 18:15:36 nelsongames (2566 views) 2018-04-24 18:14:32
 SkyAphid 19x orange451 13x VaTTeRGeR 10x gouessej 10x philfrei 7x Zemlaynin 7x dime26 6x ral0r2 5x CJC 5x KaiHH 4x cygnus 3x Pilvinen 3x torbuntu 2x WinterGuardian 2x Shatterhand 2x SHC 1x
 Deployment and Packagingby mudlee2018-08-22 18:09:50Java Gaming Resourcesby gouessej2018-08-22 08:19:41Deployment and Packagingby gouessej2018-08-22 08:04:08Deployment and Packagingby gouessej2018-08-22 08:03:45Deployment and Packagingby philfrei2018-08-20 02:33:38Deployment and Packagingby philfrei2018-08-20 02:29:55Deployment and Packagingby philfrei2018-08-19 23:56:20Deployment and Packagingby philfrei2018-08-19 23:54:46
 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