0

I have been working on a top down game for about a day or two and I am trying to figure out how to get a point after I translate and rotate and object back to its original position. I have an image (a weapon) and I rotate it based off of the mouse location and player however, I want to get a certain point of the rotated image after I have rotated it so I can use this point to set the start draw location for bullets, animations, etc. Does anyone know how I can solve this? thanks!!

private Point hand, location, handle, barrelExit;
private BufferedImage image;

private double theta;

public WeaponSpriteBase(BufferedImage image, Point location, Point handle, Point barrelExit) {

    super(image, location);

    this.image = image;
    this.location = location;
    this.handle = handle;
    this.barrelExit = barrelExit;

    //Sets the hand location getter
    hand = PlayerSprite.playerHand();

}

public void draw(Graphics2D g2, int currentMouseX, int currentMouseY) {

    theta = PlayerSprite.DegreeFinder(currentMouseX, currentMouseY);

    //Refreshes the hands location getter
    hand = PlayerSprite.playerHand();

    setLocation(hand.x - handle.x, hand.y - handle.y);

    g2.translate(hand.x, hand.y);
    g2.rotate(-Math.toRadians(theta));

    setLocation(-handle.x, - handle.y);

    if(theta > 90 && theta < 270) {
        flipVert(g2);
    }

    else {
        super.draw(g2);
    }

    g2.rotate(Math.toRadians(theta));
    g2.translate(-hand.x, -hand.y);

    g2.setColor(Color.RED);
    g2.drawRect(hand.x - 1, hand.y - 1, 2, 2);
    g2.setColor(Color.black);


    //Want to get a certain point on the image and draw it here (with barrelExit.x , barrelExit.y) without rotating it

    
}

}

  • 1
    I fall back to “point on a circle” theory. You know the radius (length of the weapon) it’s rotation point and it’s angle, from there you can calculate the “point on a circle” a projectile should appear, and the angle it should travel – MadProgrammer Feb 19 '22 at 22:52
  • Two approaches are examined [here](https://stackoverflow.com/q/44363464/230513): one uses use the geometry directly, as @MadProgrammer suggests; the other uses the inverse transform. – trashgod Feb 19 '22 at 23:10

1 Answers1

1

If you know...

  • The position of the weapon
  • It's angle of direction
  • The length (from it's centre point to it's end point)

Then you can simply apply a "point on circle" approach to the problem, for example...

enter image description here

The blue line is the weapon, the red line is the projection of the projectile path. Oddly enough, it's calculating both the start and end point the projectile should follow

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Point2D;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;

public class Main {

    public static void main(String[] args) {
        new Main();
    }

    public Main() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    enum WeaponInput {
        LEFT, RIGHT, NONE
    }

    public class TestPane extends JPanel {

        private static final double MIN_WEAPON_ANGLE = -85;
        private static final double MAX_WEAPON_ANGLE = 85;

        private double angleOfWeapon = 0;
        private double weaponAngleDelta = 1;

        private WeaponInput weaponInput = WeaponInput.NONE;

        private Timer timer;

        public TestPane() {
            setBackground(Color.BLACK);

            InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
            ActionMap am = getActionMap();

            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "Pressed.weaponMoveLeft");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "Pressed.weaponMoveRight");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "Pressed.weaponReleasedLeft");
            im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "Pressed.weaponReleasedRight");

            WeaponMovementAction.WeaponObserver weaponObserver = new WeaponMovementAction.WeaponObserver() {
                @Override
                public void weaponDidMove(WeaponInput weaponInput) {
                    TestPane.this.weaponInput = weaponInput;
                }
            };

            am.put("Pressed.weaponMoveLeft", new WeaponMovementAction(WeaponInput.LEFT, weaponObserver));
            am.put("Pressed.weaponMoveRight", new WeaponMovementAction(WeaponInput.RIGHT, weaponObserver));
            am.put("Pressed.weaponReleasedLeft", new WeaponMovementAction(WeaponInput.NONE, weaponObserver));
            am.put("Pressed.weaponReleasedRight", new WeaponMovementAction(WeaponInput.NONE, weaponObserver));

            timer = new Timer(5, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    switch (weaponInput) {
                        case LEFT:
                            angleOfWeapon -= weaponAngleDelta;
                            break;
                        case RIGHT:
                            angleOfWeapon += weaponAngleDelta;
                            break;
                    }
                    if (angleOfWeapon < MIN_WEAPON_ANGLE) {
                        angleOfWeapon = MIN_WEAPON_ANGLE;
                    } else if (angleOfWeapon > MAX_WEAPON_ANGLE) {
                        angleOfWeapon = MAX_WEAPON_ANGLE;
                    }

                    repaint();
                }
            });
            timer.start();
        }

        protected Point2D getPointOnCircle(double degress, double radius) {
            double rads = Math.toRadians(degress - 90); // 0 becomes the top

            // Calculate the outter point of the line
            double xPosy = Math.cos(rads) * radius;
            double yPosy = Math.sin(rads) * radius;

            return new Point2D.Double(xPosy, yPosy);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(400, 400);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();

            int centerX = getWidth() / 2;
            int centerY = getHeight() / 2;

            g2d.setColor(Color.WHITE);
            g2d.drawRect(centerX - 20, centerY - 20, 40, 40);

            g2d.setColor(Color.RED);
            g2d.translate(centerX, centerY - 20);

            // Projection of projectile
            g2d.setColor(Color.BLUE);
            Point2D endOfWeaponPoint = getPointOnCircle(angleOfWeapon, 20);
            g2d.draw(new Line2D.Double(new Point2D.Double(0, 0), endOfWeaponPoint));

            // Weapon direction
            int radius = Math.max(getWidth(), getHeight());
            g2d.setColor(Color.RED);
            Point2D poc = getPointOnCircle(angleOfWeapon, radius);
            g2d.draw(new Line2D.Double(endOfWeaponPoint, poc));

            g2d.dispose();
        }

    }

    public class WeaponMovementAction extends AbstractAction {

        public interface WeaponObserver {

            public void weaponDidMove(WeaponInput weaponInput);
        }

        private WeaponInput weaponInput;
        private WeaponObserver observer;

        public WeaponMovementAction(WeaponInput weaponInput, WeaponObserver observer) {
            this.weaponInput = weaponInput;
            this.observer = observer;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            getObserver().weaponDidMove(getWeaponInput());
        }

        public WeaponInput getWeaponInput() {
            return weaponInput;
        }

        public WeaponObserver getObserver() {
            return observer;
        }

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366