Java-Gaming.org Hi !
 Featured games (84) games approved by the League of Dukes Games in Showcase (565) Games in Android Showcase (151) games submitted by our members Games in WIP (606) 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 4382 times) 0 Members and 1 Guest are viewing this topic.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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 Knight

Medals: 44
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.

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

wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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?

jonjava

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

It's just simple trigonometry.

Oskuro

JGO Knight

Medals: 44
Exp: 6 years

Coding in Style

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

wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

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

It's just simple trigonometry.

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.

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
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

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

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

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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.

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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);`
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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:

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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.

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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.

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

 « 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...

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

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

BurntPizza

« JGO Bitwise Duke »

Medals: 356
Exp: 6 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.
wessles

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

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

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

Chili

Senior Newbie

Projects: 1

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

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

JGO Wizard

Medals: 103
Projects: 3
Exp: 3 years

Enthusiast of amusement. Lover of code.

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

What? Also, necro

Pages: [1]
 ignore  |  Print

You cannot reply to this message, because it is very, very old.

 ags1 (10 views) 2015-03-31 10:55:12 theagentd (13 views) 2015-03-27 23:08:20 wxwsk8er (54 views) 2015-03-20 15:39:46 Fairy Tailz (47 views) 2015-03-15 21:52:20 Olo (29 views) 2015-03-13 17:51:59 Olo (32 views) 2015-03-13 17:50:51 Olo (39 views) 2015-03-13 17:50:16 Olo (44 views) 2015-03-13 17:47:07 ClaasJG (58 views) 2015-03-10 11:36:42 ClaasJG (42 views) 2015-03-10 11:33:01
 LiquidNitrogen 21x BurntPizza 21x basil_ 20x KevinWorkman 18x EgonOlsen 17x theagentd 17x Roquen 16x 65K 11x wessles 11x Riven 10x Varkas 10x princec 9x phu004 8x SHC 8x Ashedragon 8x Ecumene 7x
 How to: JGO Wikiby Mac702015-02-17 20:56:162D Dynamic Lighting2015-01-01 20:25:42How do I start Java Game Development?by gouessej2014-12-27 19:41:21Resources for WIP gamesby kpars2014-12-18 10:26:14Understanding relations between setOrigin, setScale and setPosition in libGdx2014-10-09 22:35:00Definite guide to supporting multiple device resolutions on Android (2014)2014-10-02 22:36:02List of Learning Resources2014-08-16 10:40:00List of Learning Resources2014-08-05 19:33:27
 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