Hi.
I am making a really simple program to refresh my knowledge in java (which is obviously needed). When I click the screen, I want a bullet to appear in the center and move towards the point I clicked. Right now, when I click on the left half the bullet will go either straight up or directly left, and if I click the right half then it just stays in the center of the screen.
I have two classes (plus a third main class):
ShooterPanel class

package shooter;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.*;

public class ShooterPanel extends JPanel implements Runnable, MouseListener {

    boolean gameOver;
    int aimFPS = 60;

    int mouseX;
    int mouseY;
    boolean hasShot;
    Thread t = new Thread(this);

    Bullet[] bullets = new Bullet[100];

    public ShooterPanel(){

        addMouseListener(this);
        t.start();

    }

    public void fireShots(){

        if(hasShot){

            for(int i = 0; i < bullets.length; i++){

                if(bullets[i] == null){

                    bullets[i] = new Bullet(200, 200, mouseX, mouseY);
                    double angle = Math.atan2(bullets[i].targetY - bullets[i].posY, bullets[i].targetX - bullets[i].posX);
                    if(angle < 0){
                        angle += 360;
                    }
                    bullets[i].setAim(angle);
                    System.out.println("Created a new bullet object");
                    break;

                }

            }
            hasShot = false;

        }

    }

    public void moveBullets(){

        for(Bullet bullet : bullets){

            if(bullet != null){

                bullet.move();
                System.out.println("New bullet position is [" + bullet.posX + ", " + bullet.posY + "]");

            }

        }

    }

    @Override
    public void paintComponent(Graphics gc){

        super.paintComponent(gc);

        for(Bullet bullet : bullets){

            if(bullet != null){
                gc.setColor(Color.BLACK);
                gc.fillOval(bullet.posX, bullet.posY, 7, 7);
                System.out.println("Drew a bullet");
            }

        }
        gc.setColor(Color.BLACK);
        gc.fillOval(50, 50, 20, 20);
        gc.drawString("Hiya", 80, 80);

    }

    @Override
    public void run(){

        while(!gameOver){

            fireShots();

            moveBullets();

            repaint();

            try{
                Thread.sleep(1000 / aimFPS);
            }catch(InterruptedException ie){
                t.interrupt();
                System.out.println("Couldn't pause thread");
            }

        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        mouseX = e.getX();
        mouseY = e.getY();
        hasShot = true;
        System.out.println("Heard mouse realease at [" + mouseX + ", " + mouseY + "]");
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

}

Bullet class

package shooter;

public class Bullet {

    int posX;
    int posY;
    int targetX;
    int targetY;
    double aim;

    public Bullet(int posX, int posY, int targetX, int targetY){

        this.posX = posX;
        this.posY = posY;
        this.targetX = targetX;
        this.targetY = targetY;

    }

    public double getAim(){

        return aim;

    }

    public void setAim(double angle){

        this.aim = angle % (2 * Math.PI);

    }

    public void move(){

        double stepX = Math.cos(getAim());
        double stepY = Math.sin(getAim());
        posX += stepX;
        posY += stepY;

    }

}

Dani AI

Generated

Two separate issues are making the bullets behave oddly.

First, as already hinted, you mixed degrees and radians. Math.atan2(...) returns radians in the range [-π, π]. Adding 360 (degrees) to a radian value corrupts the angle. Fix that by using radians consistently (e.g. add 2*Math.PI instead of 360 if you want a positive wrap) — or better yet, avoid manual angle wrapping entirely and just use the raw radian value when feeding cos/sin.

Second, and more important for the “stuck” bullets: your positions are integers. In Java a compound assignment like posX += stepX where posX is an int will implicitly cast the sum back to int, discarding fractional motion. Since cos/sin produce values between -1 and 1, most steps round to zero and the bullet won’t move. Change the stored position to double and only cast when drawing.

Two practical fixes you can apply now:

  • Compute movement directly from the click vector (no trig unit confusion):

    // vector approach (use doubles)
    double dx = targetX - startX;
    double dy = targetY - startY;
    double dist = Math.hypot(dx, dy);
    double vx = (dx / dist) * speed;   // speed is >0, e.g. 3.0
    double vy = (dy / dist) * speed;
    posX += vx;
    posY += vy;
  • Keep internal coordinates as doubles and cast for rendering:

    double px = 200.0, py = 200.0;
    g.fillOval((int)Math.round(px), (int)Math.round(py), 7, 7);

Extra tips: if you do keep angle math, normalize safely with something like (a % (2*Math.PI) + 2*Math.PI) % (2*Math.PI) so negatives wrap correctly. Use a Swing Timer instead of managing your own Thread for UI updates. For quick debugging print Math.toDegrees(angle) (or the dx/dy and normalized vector) to verify directions. These changes will make bullets move smoothly in the true direction of the click.

Recommended Answers

All 2 Replies

28eab7aac59212799405257a808b9fcb
this is a picture of what happens. The bullets are either going straight up or directly left, not even diagonal.

The code does angle calcs using 360 in one place and 2pi in another, so maybe you are mixing or confusing degrees and radians?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.