Java-Gaming.org Hi !
Featured games (83)
games approved by the League of Dukes
Games in Showcase (541)
Games in Android Showcase (133)
games submitted by our members
Games in WIP (603)
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 rotate a (muzzle)point to follow a rotated (weapon)image in 2D? [SOLVED]  (Read 1749 times)
0 Members and 1 Guest are viewing this topic.
Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Posted 2012-07-11 11:04:53 »

Firstly, I had posted this in the Java2D section, but came to think it was more of a n00b-question than a Java2D issue.
I made this little video to better explain what I'm dealing with.

<a href="http://www.youtube.com/v/TXrJjKuAQHI?version=3&amp;hl=en_US&amp;start=" target="_blank">http://www.youtube.com/v/TXrJjKuAQHI?version=3&amp;hl=en_US&amp;start=</a>

I want the projectiles to spawn at the end of the gun-barrel while the arm is waving and flailing about. Each gun has a different muzzle-offset. How would I go about figuring out the new muzzle-offset for the projectiles after I rotate the arms? Can I somehow rotate a point using the same transform-matrix as I do for the arm (which is calculated every update() so far; I will eventually change that, so it doesn't run unnecessarily)?

I've been pulling hair out of my already balding head for days pondering over this. I mean, I've tried circle-math and stuff, but I'm just too confused about which points are important in this endeavour, and which steps to take. I finally got the arms to rotate properly, though.

Note: This is using nothing but Java2D. I know... For my next project I'll use LWJGL

Here's some code:

Method in Main-class for shooting projectiles (yeah yeah, it's a temporary placement):
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
public void shootProjectile() {
   // 35 and 40 are the currently fixed muzzle-offsets, from player-position (at his feet, in the middle)
   double muzzleX = player.getPosX()+35, muzzleY = player.getPosY()-40;
       
   double angleInRad = Math.atan2(mouseController.getMouseY()-(player.getPosY()-40), mouseController.getMouseX()-(player.getPosX()+35));
       
   double angle = (double) angleInRad*180/Math.PI;

   playerProjectiles.add(creator.spawnProjectile("9mm", muzzleX, muzzleY, angle));
}


Creator-class code for spawning projectiles into the world:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
public Projectile spawnProjectile(String projectileName, double originX, double originY, double angle){
      // clone the projectile from HashMap, using ID
      Projectile p = Game.projectileMap.get(projectileName).cloneProjectile();
     
      // clone Animation from HashMap, using ID in Projectile
      Animation a = Game.projectileAnimations.get(projectileName).cloneAnimation();
     
      // set Animation on new Projectile object
      p.setAnim(a);
     
      // set init position and angle
      p.setInitX(originX-(a.getImage().getWidth()/2));
      p.setInitY(originY-(a.getImage().getHeight()/2));
      p.setPosX(originX-(a.getImage().getWidth()/2));
      p.setPosY(originY-(a.getImage().getHeight()/2));
      p.setAngle(angle);
      p.setTimeLived(0);
     
      // create the collison rectangle
      p.createMainCollisionRectangle();
     
      // return Projectile
      return p;
   }


Code for rendering projectiles:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
for (int i = 0; i < playerProjectiles.size(); i++) {
   
   AffineTransform transform = new AffineTransform();
   Projectile p = playerProjectiles.get(i);
   Point center = p.getImageCenter();

   // translate and rotate the sprite
   transform.setToTranslation(p.getPosX(), p.getPosY());
   transform.rotate(p.getAngle() * Math.PI / 180.0, center.x, center.y);
               
   // draw it
   g.drawImage(playerProjectiles.get(i).getAnim().getImage(), transform, null);
}


Rotating the arm:
1  
2  
3  
4  
5  
6  
// Transform the arm, using the x,y offsets for the initial placement of the image.
armTransform.setToTranslation(player.getPosX()+player.getArmOffsetX(), player.getPosY()-player.getArmOffsetY());

// Factoring in the shoulder-offset of the arm-image (4 x, -10 y)
armTransform.rotate(Math.atan2(mouseController.getMouseY()-(player.getPosY()-player.getArmOffsetY()+10), mouseController.getMouseX()-(player.getPosX()+4+player.getArmOffsetX())), 4, 10);
           

- Jonas
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #1 - Posted 2012-07-11 13:14:10 »

You are rotating around the spawn point. You want to rotate around the same location as you rotate the arm.

Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #2 - Posted 2012-07-11 17:00:14 »

I wouldn't only rotate the sprite. (That could lead to Collision problems...)

I'd do it with trigonometry. Heard from sinus and cosinus?

Use them here Wink

You could set other starting positions for the bullet:

1  
2  
double bulletX = Math.cos(Math.toRadians(angleInRadians))*distanceFromArm + muzzleX // mussleX without the distance from the arm. I mean, the position directly on the shoulder of the Player should be mussleX
double bulletY = Math.sin(Math.toRadians(angleInRadians))*distanceFromArm + muzzleY // see the comment on top ;)


I hope this helps. If you get weird issues, try switching sin and cos for x and y. I'm not sure which one to use for x and y Cheesy

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Mads

JGO Ninja


Medals: 26
Projects: 3
Exp: 6 years


One for all!


« Reply #3 - Posted 2012-07-11 18:38:57 »

I wouldn't only rotate the sprite. (That could lead to Collision problems...)

I'd do it with trigonometry. Heard from sinus and cosinus?

Use them here Wink

You could set other starting positions for the bullet:

1  
2  
double bulletX = Math.cos(Math.toRadians(angleInRadians))*distanceFromArm + muzzleX // mussleX without the distance from the arm. I mean, the position directly on the shoulder of the Player should be mussleX
double bulletY = Math.sin(Math.toRadians(angleInRadians))*distanceFromArm + muzzleY // see the comment on top ;)


I hope this helps. If you get weird issues, try switching sin and cos for x and y. I'm not sure which one to use for x and y Cheesy

Cos is for X, Sin is for Y.  Smiley

Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #4 - Posted 2012-07-11 20:48:28 »

If the angle is in radians, you don't want to give it to Math.toRadians(double) XD

Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #5 - Posted 2012-07-11 22:00:42 »

You are rotating around the spawn point. You want to rotate around the same location as you rotate the arm.

Yeah, but that's only because I did half the work so far. I only did the code to rotate the projectile-images, and that's all happening by getting the angle from the spawnpoint to the mouse, and it is the spawnpoint I need to rotate around the shoulder.

So, I just woke up and I think I got it right in my dream Tongue
The spawnpoint is calculated from playerPosition, with an offset relative to that. So if I rotate the playerPosition point around the shoulder, and then add the offset x and y (multiplied by the sin and cos for the angle respectively), that should get me the right point, right?

I'm going to play around with it some more.

Thanks for all the suggestions, guys! I'll post back if I get it right

- Jonas
Offline ra4king

JGO Kernel


Medals: 356
Projects: 3
Exp: 5 years


I'm the King!


« Reply #6 - Posted 2012-07-11 22:44:53 »

You're absolutely correct Smiley

Offline Ultroman

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #7 - Posted 2012-07-11 23:01:39 »

YAY! That wasn't so hard! I just had to remember my trigonometry. Man, I'd wish I had known I wanted to be a programmer when I was attending school. Then I might have listened to my SOB teachers, heheh.

Is it bad to make this amount of new variables every time a projectile is fired? Should I make all these variables global, since they're used all the time, so I don't put the GC on overdrive?
The shoulder point should be a global final static, really.

This is working perfectly, for anyone who has the same question:
1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
   public void shootProjectile() {
     
      // Currently fixed shoulder-offsets, from player-position (player-position is at his feet, in the middle)
      double shoulderX = player.getPosX(), shoulderY = player.getPosY()-40;
     
       // Calculate the radians for the angle the bullets should be rotated
       double angleInRad = Math.atan2(mouseController.getMouseY()-shoulderY, mouseController.getMouseX()-shoulderX);
       
       // Calculate the starting-positions of the bullets.
       Point shoulder = new Point((int)Math.round(shoulderX), (int)Math.round(shoulderY));
       Point muzzleOffset = new Point((int)Math.round(shoulderX)+2, (int)Math.round(shoulderY)+42);
       
       // Find the distance from the shoulder to the muzzle; -8 for correction
       double distanceFromShoulderToMuzzle = shoulder.distance(muzzleOffset) - 8;
       
       // Calculate new start-positions for the bullets
      double bulletX = Math.cos(angleInRad)*distanceFromShoulderToMuzzle + shoulderX;
      double bulletY = Math.sin(angleInRad)*distanceFromShoulderToMuzzle + shoulderY;
     
      // Calculate the angle the bullets should be traveling at; is also used to rotate the projectile images
       double angle = (double) angleInRad*180/Math.PI;

      playerProjectiles.add(creator.spawnProjectile("9mm", bulletX, bulletY, angle));
   }

- Jonas
Offline matheus23

JGO Kernel


Medals: 114
Projects: 3


You think about my Avatar right now!


« Reply #8 - Posted 2012-07-12 13:09:42 »

If the angle is in radians, you don't want to give it to Math.toRadians(double) XD
Ups lol. Was late for me Smiley

See my:
    My development Blog:     | Or look at my RPG | Or simply my coding
http://matheusdev.tumblr.comRuins of Revenge  |      On Github
Offline 65K
« Reply #9 - Posted 2012-07-12 13:39:17 »

Is it bad to make this amount of new variables every time a projectile is fired? Should I make all these variables global, since they're used all the time, so I don't put the GC on overdrive?
The primitive doubles are no objects and do not ever meet any GC. They end up on the stack or in registers.
And storing point objects in class variables does not ease the life of the GC if you replace them as frequently as in your actual code. But "shooting garbage" is most likely only a fraction of the whole game loop garbage anyway.
A modern garbage collector takes care of that while still being half-asleep. Grin

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

JGO Knight


Medals: 25
Projects: 1


Snappin' at snizzes since '83


« Reply #10 - Posted 2012-07-13 02:32:48 »

Thanks! Cheesy

- Jonas
Offline DrZoidberg

Senior Devvie


Medals: 17



« Reply #11 - Posted 2012-07-14 04:12:45 »

Should I make all these variables global, since they're used all the time, so I don't put the GC on overdrive?

The Oracle JVM can create and destroy 100 million objects per second. You could write a game with thousands of objects and recreate all the objects every single frame with 1000 frames per second and the GC woudn't break a sweat. On Android however things look different. But since doubles are no objects anyway it doesn't matter here.
Offline _Al3x

Senior Devvie


Medals: 7


Indie Games FTW!


« Reply #12 - Posted 2012-07-14 13:40:46 »

(...) But since doubles are no objects anyway (...)

I'm pretty sure they are: Double extends Number wich extends Object

A good friend of mine once told me: "In Java, EVERYTHING is an object"
[size=2pt]And then he killed the dog.[/size]
Smiley

Offline Sickan

Senior Devvie


Medals: 9



« Reply #13 - Posted 2012-07-14 13:53:23 »

(...) But since doubles are no objects anyway (...)

I'm pretty sure they are: Double extends Number wich extends Object

A good friend of mine once told me: "In Java, EVERYTHING is an object"
[size=2pt]And then he killed the dog.[/size]
Smiley
Not the primitives. The primitives are pass-by-value keywords. You can use their object forms, yes, but it's more common to use the primitives. So, not everything is an object. And I feel sorry for the dog.
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.

Mr.CodeIt (24 views)
2014-12-23 03:34:11

rwatson462 (54 views)
2014-12-15 09:26:44

Mr.CodeIt (45 views)
2014-12-14 19:50:38

BurntPizza (85 views)
2014-12-09 22:41:13

BurntPizza (110 views)
2014-12-08 04:46:31

JscottyBieshaar (79 views)
2014-12-05 12:39:02

SHC (90 views)
2014-12-03 16:27:13

CopyableCougar4 (97 views)
2014-11-29 21:32:03

toopeicgaming1999 (156 views)
2014-11-26 15:22:04

toopeicgaming1999 (153 views)
2014-11-26 15:20:36
Resources for WIP games
by kpars
2014-12-18 10:26: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
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!