0

I am making a game but I can only get one bullet to fire, how can I get multiple bullets to fire when the space bar is pressed?

There is a main class. This contains the the size of the frame for the space game.

This is the shooter class. Here I draw the bullet and spaceship and set the left and right controls for the movement of the spaceship.

    boolean right, left; 
    int bulletX;
    int rectX = 320;
    int rectY = 435;
    int bulletY;
    Rectangle bullet;
    boolean space, fire;
    boolean shot;

    public ShooterGame() {
        addKeyListener(this);
        this.setFocusTraversalKeysEnabled(false);
        this.setFocusable(true);
    }

    public void paintComponent(Graphics graphics) {
        graphics.setColor(Color.BLUE);
        graphics.drawRect(0, 0, 700, 500);
        graphics.fillRect(0, 0, 700, 500);

        graphics.setColor(Color.YELLOW);
        graphics.drawRect(rectX, rectY, 50, 30);
        graphics.fillRect(rectX, rectY, 50, 30);

        if (shot) {
            graphics.setColor(Color.RED);
            graphics.fillRect(bullet.x, bullet.y, bullet.width, bullet.height);
        }
        repaint();
    }

    


    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
                moveToRight();
        }

        if (e.getKeyCode() == KeyEvent.VK_LEFT) {
                moveToLeft();
        }
        if (e.getKeyCode() == KeyEvent.VK_SPACE) {
            if (bullet == null) {
                fire = true;
                if (fire) {
                    bulletX = rectX;
                    bulletY = rectY;
                    bullet = new Rectangle(bulletX + 25, bulletY, 3, 5);
                    shot = true;
                }
            }
        }
    }

   


    public void shootBullet() {
        if (shot) {
            bullet.y--;
            System.out.println("shot fired");
        }
   
Ronan
  • 9
  • 2
  • 2
    keyPressed does just that: when you PRESS the key, not WHILE you press the key. You can start a loop at keyPressed, and stop that loop at keyReleased. – Stultuske Aug 25 '22 at 12:02
  • Watch out -- entering a loop at KeyPressed doesn't solve the problem, and in fact would create some interesting behavior in this program since it would block the thread. – Byron Lagrone Aug 25 '22 at 12:54
  • 2
    1) never invoke repaint() from a painting method. 2) you need to invoke super.paintComponent(..) as the first statement in the paintComponent() method to make sure the background is cleared. 3) check out https://stackoverflow.com/questions/54028090/get-width-and-height-of-jpanel-outside-of-the-class/54028681#54028681 for an example of animating multiple objects. How you add/remove object from the ArrayLiist is up to the requirements of your game. – camickr Aug 25 '22 at 17:47
  • Just as a side note, you should use `javax.swing.Timer` instead of using a `Thread`. Swing is supposed to be single-thread and your code isn't thread-safe right now, so you could have memory consistency errors. (There are times when you want to use a background thread but it's more complicated to get right.) See this answer for some examples of how to refactor to use a timer: https://stackoverflow.com/a/29837148/2891664 You should also call `repaint` in your game loop instead of inside `paintComponent`. – Radiodef Aug 25 '22 at 17:49
  • Add a tag for what Java GUI framework you are using. (Swing, JavaFX, SWT, Vaadin, etc.) – Basil Bourque May 02 '23 at 23:01

1 Answers1

2

Based on the code, your KeyPressed/KeyReleased logic is correct for firing multiple bullets -- you are setting a boolean fireBullet to true on keyPressed events and then to false on keyReleased.

However, it appears you can only have exactly one Rectangle bullet at any given time because you have only declared one. The bullet instance will always be overwritten during the keyPressed event (the relevant line bullet = new Rectangle(0, 0, 0, 0);).

In order to have more than one bullet on-screen at a time, you need to keep track of the bullets via a List, array, or other structure allowing multiple instances of Rectangles representing bullet.

The refactor would look something like this:

  • Change the Rectangle bullet to List<Rectangle> bullets (or an array, or a Set, etc)
  • shootBullet should check to see if fireBullet is true. If it is, you should add a new bullet to the list
  • shootBullet should also move every bullet in the list (currently it moves the single instance of bullet)

One other thing to note -- depending on how frequently the frame updates, you may also want to keep track of how many bullets can be fired per second (the suggested changes would allow one bullet to be created per frame update, which may be too many). You would then need to track the time (or number of frame updates) since the last bullet was fired prior to spawning another. That would also need to happen in shootBullet.

Byron Lagrone
  • 911
  • 1
  • 7
  • 15