My bullets spawn in the wrong place

146 views Asked by At

In my game, the player can rotate using the arrow keys. Based on the angle of the player's rotation, when a bullet is fired, it travels in the direction the player is facing.

That part works, however, the bullet is spawning in the wrong place. Below are two pictures that show the difference in the spawn. In the first picture, the bullet spawns on the red dot. However, when rotating the dot does not move accordingly which prevents the bullets from spawning correctly.

Note: the red dot is just for visuals (based on the spawn co-ordinates of the bullets)

the bullet spawns correctly when facing upwards

the bullet spawns incorrectly when facing every other direction

Here is the relevant code:

KeyListener in Main:

if (e.getKeyCode() == KeyEvent.VK_SPACE) {
                //Creates bullets when the spacebar is pressed, as long as the user is not exceeding 3 at a time
                if(player.amountOfBullets() >= 0 && player.amountOfBullets() < 10)
                {
                player.setNB(player.getGunX(), player.getGunY(), player.getAngle());
                }
}

Player:

public class Player {
private BufferedImage spriteSheet;

private double x;
private double y;
private int height;
private int width;

private int gunX;
private int gunY;


private BufferedImage[] sprites = new BufferedImage[13];
private BufferedImage currentImg;
private int frame;
private double angle = 0;

private ArrayList<Bullet> nb = new ArrayList<Bullet>(10); 

public Player(){
    try { 
        spriteSheet = ImageIO.read(getClass().getResource("/Sprites.png"));
    } catch (IOException e) { 
        System.err.println("Sprites3.png could not be found");
    }

    for (int i = 0; i < sprites.length; i++){
        sprites[i] = grabImage(1, i+1, 100);
    }
    currentImg = sprites[0];
    x = 10;
    y = 10;
    width = currentImg.getWidth();
    height = currentImg.getHeight();

    gunX = (int) x + width - 15;
    gunY = (int) y;
}

public BufferedImage grabImage(int col, int row, int length){
    BufferedImage img = spriteSheet.getSubimage(((col-1) * length), ((row-1) * length), length, length);
    return img;
}

public void paint(Graphics2D g2d){

    for(int i = 0; i < nb.size(); i++)
    {
        if(nb.get(i).getTime()*10 >= 15)
        {
            nb.set(0, null);
            nb.remove(nb.get(0));//removes bullets based on the time they are in game
        }
    }

    double rotationRequired = Math.toRadians (angle);
    double locationX = currentImg.getWidth() / 2;
    double locationY = currentImg.getHeight() / 2;
    AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);

    for (int i = 0; i < nb.size(); i++)
    {
        nb.get(i).move();//moves the bullets
        nb.get(i).paint(g2d);
    }

    // Drawing the rotated image at the required drawing locations
    g2d.drawImage(op.filter(currentImg, null), (int)x, (int)y, null);
    //g2d.fillOval(x, y, 10, 10);
    g2d.setColor(Color.RED);
    int x = (int) this.x;
    int y = (int) this.y;
    g2d.fillOval(gunX, gunY, 10, 10);
}

public void update(){
    currentImg = sprites[frame];
}

public void move(double xM, double yM){
    if (yM == 5) xM = -5;
    else xM = 5;
    x += xM * Math.sin(Math.toRadians(angle));
    y += yM * Math.cos(Math.toRadians(angle));

    gunY += yM * Math.cos(Math.toRadians(angle));
    gunX += xM * Math.sin(Math.toRadians(angle));

    if (frame < 12){
        frame++;
    }
    else frame = 0;
}

public void turn(double angle){    
    this.angle += angle;
}

public int getX() {
    return (int) x;
}

public int getY(){
    return (int) y;
}

public int getGunX() {
    return gunX;
}

public int getGunY(){
    return gunY;
}

public int getHeight(){
    return height;
}

public int getWidth(){
    return width;
}

public void setNB(int x, int y, double angle)//sets position and movement of bullet
{
    if (nb.size() > 10)
    {
        nb.set(0, null);
        nb.remove(nb.get(0));//removes the bullets from the game when tried to exceed 3
    }
    if (nb.size() < 10)//only 3 shots allowed at a time
    {
        nb.add(new Bullet(x, y, angle));//adds bullets to list when a new one is shot
    }
}

public ArrayList<Bullet> getNB()//sets position and movement of bullet
{
    return nb;
}

public void removeNB(int i)//removes bullet from game when it hits an asteroid
{
    nb.set(i, null);
    nb.remove(nb.get(i));
}

public int getBulletX(int i)//gets bullet X coord
{
    return nb.get(i).getX();
}

public int getBulletY(int i)//gets bullet Y coord
{
    return nb.get(i).getY();
}

public int getBulletWidth(int i)//gets bullet width
{
    return nb.get(i).getWidth();
}

public int getBulletHeight(int i)//gets bullet height
{
    return nb.get(i).getHeight();
}

public int getBulletAngle(int i)//gets bullet angle
{
    return nb.get(i).getAngle();
}

public double getAngle() {
    return angle;
}

public int amountOfBullets() //checks amount of bullets in game
{
    return nb.size();
}
}

Bullet:

public class Bullet
{  
//width = 6px, height = 8px
private BufferedImage bullet = null;
private BufferedImage img2 = null;
private double x, y;
private double angle;
//Creates an instance of timer since each bullet is supposed to only last 1.5 seconds
private Stopwatch timer = new Stopwatch();

public Bullet(int x, int y, double angle)
{   
    //Get the image of the normal bullet
    try { 
        bullet = ImageIO.read(getClass().getResource("/Bullet.png"));
    } catch (IOException e) { 
        System.err.println("Bullet.png could not be found");
    }
    //Sets the position and direction of the bullet relative to the spacecraft when it is created
    timer.start();
    this.x=x;
    this.y=y;
    this.angle=angle+90;
}

public void paint(Graphics2D g2d)
{
    //Since the bullet sprite is not always oriented in the direction of the shot, orient it properly
    angle-=90;

    double rotationRequired = Math.toRadians(angle);
    double locationX = bullet.getWidth() / 2;
    double locationY = bullet.getHeight() / 2;
    AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);

    // Drawing the rotated image at the required drawing locations
    int x = (int) this.x;
    int y = (int) this.y;
    //g.drawImage(img2, x - 150, y - 150, null);
    g2d.drawImage(op.filter(bullet, null), x, y, null);
    //Change the angle back to the original for the bullet to travel in the correct direction
    angle+=90;

}

public void move()
{
    //Move the projectile in the direction it is facing
    x+=-5* Math.cos(Math.toRadians(angle));
    y+=-5* Math.sin(Math.toRadians(angle));
}


//Returns how long the bullet has been in existence
public long getTime()
{
    return timer.getElapsedTime();
}

public int getX()//returns the x position of the bullet for collision detection
{
    return (int)x;
}

public int getY()//returns the y position of the bullet for collision detection
{
    return (int)y;
}

public int getWidth()//returns the width of the sprite for collision detection
{
    return bullet.getWidth();
}

public int getHeight()//returns the height of the sprite for collision detection
{
    return bullet.getHeight();
}

public int getAngle()//returns the angle of the bullet
{
    return (int)angle;
}
}
1

There are 1 answers

1
gpasch On BEST ANSWER

Ok heres your new paint move and turn methods - you need to transform the point of the gun also:

public void paint(Graphics g2d){
    // Drawing the rotated image at the required drawing locations
    if(op!=null) g2d.drawImage(op.filter(currentImg, null), (int)x, (int)y, null);
    else g2d.drawImage(currentImg, (int)x, (int)y, null);
    g2d.setColor(Color.blue);
    g2d.fillOval(gunX, gunY, 10, 10);
}


public void move(double xM, double yM){
    x += xM * Math.cos(Math.toRadians(angle));
    y += yM * Math.sin(Math.toRadians(angle));

    gunY += yM * Math.sin(Math.toRadians(angle));
    gunX += xM * Math.cos(Math.toRadians(angle));

    repaint();
}


public void turn(double angle){    
    this.angle += angle;
    double rotationRequired = Math.toRadians (this.angle);
    double locationX = currentImg.getWidth() / 2;
    double locationY = currentImg.getHeight() / 2;
    AffineTransform tx = AffineTransform.getRotateInstance(rotationRequired, locationX, locationY);
    op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR);
    int gx= currentImg.getWidth() - 15;
    int gy=0;
    Point pt1=new Point(gx, gy), pt2=new Point();
    tx.transform(pt1, pt2);
    gunX=(int)x+pt2.x; gunY=(int)y+pt2.y;
    repaint();
}

You need:

a global variable

AffineTransformOp op;

in Player.