简体   繁体   中英

Java Game: Shooting Bullets

I am (kind of) new to creating games with Java. I created some simple games before like a bag collecting game but now I want to make a top-down zombie shooting game. I already have a player that can move, but now I want to implement shooting. The problem is that I am not sure how to make a new bullet that shoots from the player to the right / up / down /left to the end of the screen depending on what part of the screen the player is facing. I have pasted all my of code below (4 classes):

package me.mateo226.main;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JPanel;

import me.mateo226.entities.Player;
import me.mateo226.guns.Bullet;

public class GamePanel extends JPanel implements Runnable {
    private static final long serialVersionUID = 1L;
    private static final int PWIDTH = 720;
    private static final int PHEIGHT = 480;
    private static Thread game;
    private static volatile boolean running = false;
    public static volatile boolean gameOver = false;
    public static volatile boolean paused = false;
    public static Graphics g;
    public static Image gImage;
    public static long lastLoopTime = System.currentTimeMillis();
    public static long delta;
    public static volatile boolean upPressed = false;
    public static volatile boolean downPressed = false;
    public static volatile boolean leftPressed = false;
    public static volatile boolean rightPressed = false;
    public BufferedImage backgroundImage;
    public Player player;
    Bullet bullet;

    public GamePanel() {

        setPreferredSize(new Dimension(PWIDTH, PHEIGHT));
        setBackground(Color.white);

        setFocusable(true);
        requestFocus();
        waitForTermination();

    }

    public void addNotify() {
        super.addNotify();
        startGame();
    }

    public void waitForTermination() {
        addKeyListener(new KeyListener() {
            @Override
            public void keyPressed(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_ESCAPE) {
                    GamePanel.stopGame();
                }
                if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) {
                    upPressed = true;
                }
                if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) {
                    downPressed = true;
                }
                if (keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT) {
                    leftPressed = true;
                }
                if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) {
                    rightPressed = true;
                }

                if (keyCode == KeyEvent.VK_ESCAPE) {
                    System.exit(0);
                }

            }

            @Override
            public void keyReleased(KeyEvent e) {
                int keyCode = e.getKeyCode();
                if (keyCode == KeyEvent.VK_W || keyCode == KeyEvent.VK_UP) {
                    upPressed = false;
                }
                if (keyCode == KeyEvent.VK_S || keyCode == KeyEvent.VK_DOWN) {
                    downPressed = false;
                }
                if (keyCode == KeyEvent.VK_A || keyCode == KeyEvent.VK_LEFT) {
                    leftPressed = false;
                }
                if (keyCode == KeyEvent.VK_D || keyCode == KeyEvent.VK_RIGHT) {
                    rightPressed = false;
                }

            }

            @Override
            public void keyTyped(KeyEvent e) {

            }

        });

    }

    @Override
    public void run() {
        running = true;
        while (running) {
            delta = System.currentTimeMillis() - lastLoopTime;
            lastLoopTime = System.currentTimeMillis();

            gameUpdate();
            gameRender();
            checkMovement();
            paintpauseScreen();

            try {
                Thread.sleep(5);
            } catch (Exception e) {
                System.out.println("The thread couldn't sleep! Error info: "
                        + e);
            }

        }
        System.exit(0);

    }

    private void checkMovement() {
        if (!paused && !gameOver) {

        }
    }

    private void paintpauseScreen() {
        Graphics g;
        try {
            g = this.getGraphics();
            if ((g != null) && (gImage != null))
                g.drawImage(gImage, 0, 0, null);
            g.dispose();
        } catch (Exception e) {
            System.out.println("Graphics context error: " + e);
        }
    }

    private void gameRender() {
        if (gImage == null) {
            gImage = createImage(PWIDTH, PHEIGHT);
            if (gImage == null) {
                System.out
                        .println("image null after creating it??? Please check the code for any errors!");
            } else {
                g = gImage.getGraphics();
            }
        }
        if (!paused) {
            g.setColor(Color.white);
            g.fillRect(0, 0, PWIDTH, PHEIGHT);
            g.setColor(Color.blue);
        }
        try {
            backgroundImage = ImageIO.read(new File("res\\background.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        g.drawImage(backgroundImage, 0, 0, Color.white, null);

        if (player != null) {
            player.drawPlayer(g);
        }
        if (bullet != null) {
            bullet.drawBullet(g);
        }

    }

    private void gameUpdate() {
        if (!paused && !gameOver) {
            movePlayer();
            if (bullet != null){
                bullet.shootBullet(g, "right");
            }
        }
    }

    public void startGame() {
        if (game == null) {
            game = new Thread(this);
            if (game == null) {
                System.out.println("Couldn't create the thread!");
            } else {
                System.out.println("Thread created!");
                game.start();
            }
        }
        if (g == null) {
            g = this.getGraphics();
            if (g == null) {
                System.out.println("The graphics were not created!");
            } else {
                System.out.println("The graphics are successfully created!");
            }
        }

        player = new Player(32, 32, "res\\player.png");
        bullet = new Bullet("res\\grassTile.png", "right", player.x + 32,
                player.y);
        running = true;

    }

    public void movePlayer() {
        if (upPressed) {
            player.y -= player.moveSpeed * delta;
        }
        if (downPressed) {
            player.y += player.moveSpeed * delta;
        }
        if (leftPressed) {
            player.x -= player.moveSpeed * delta;
        }
        if (rightPressed) {
            player.x += player.moveSpeed * delta;
        }

    }

    public static void stopGame() {
        running = false;
    }

}

This was my GamePanel class. This is my Main class:

package me.mateo226.main;

import java.awt.Container;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class Main extends JFrame implements WindowListener {
    private static final long serialVersionUID = 1L;
    private static GamePanel panel;
    public static boolean DEBUGGING = false;

    public Main(){
        super("The Gun Reactor");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        addWindowListener(this);
        Container c = getContentPane();
        panel = new GamePanel();
        c.add(panel, "Center");
        setResizable(false);
        pack();
        setLocationRelativeTo(null);
        if(JOptionPane.showConfirmDialog(null, "Enable debugging?") == 1){
            DEBUGGING = true;
        } else {
            DEBUGGING = false;
        }
        setVisible(true);

    }

    @Override
    public void windowActivated(WindowEvent arg0) {


    }

    @Override
    public void windowClosed(WindowEvent arg0) {

    }

    @Override
    public void windowClosing(WindowEvent arg0) {

    }

    @Override
    public void windowDeactivated(WindowEvent arg0) {

    }

    @Override
    public void windowDeiconified(WindowEvent arg0) {

    }

    @Override
    public void windowIconified(WindowEvent arg0) {

    }

    @Override
    public void windowOpened(WindowEvent arg0) {

    }

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


}

This is my Player class:

package me.mateo226.entities;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class Player {

    public int x, y;
    public float moveSpeed = 0.1f;
    private BufferedImage playerTexture;;

    public Player(int x, int y, String texturePath){
        this.x = x;
        this.y = y;
        try {
        playerTexture = ImageIO.read(new File(texturePath));
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public void drawPlayer(Graphics g){

        g.setColor(Color.white);
        g.drawImage(playerTexture, x, y, null);

    }



}

And finally this is my bullet class which I don't really know how to use or even make it properly:

package me.mateo226.guns;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import me.mateo226.main.GamePanel;

public class Bullet {

    private int x, y;
    private BufferedImage bulletTexture;
    private float bulletSpeed = 0.1f;

    public Bullet(String bulletTexturePath, String dir, int x, int y) {
        this.x = x;
        this.y = y;
        try {
            bulletTexture = ImageIO.read(new File(bulletTexturePath));
        } catch (IOException e) {
            e.printStackTrace();
        }


    }

    public void drawBullet(Graphics g) {
        g.setColor(Color.white);
        g.drawImage(bulletTexture, x, y, null);
    }

    public void shootBullet(Graphics g, String dir) {
        switch (dir) {
        case "left":
            while (x > -32) {
                x -= bulletSpeed * GamePanel.delta;
                drawBullet(g);
            }
            break;
        case "right":
            while (x < 700) {
                x += bulletSpeed * GamePanel.delta;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
            break;
        case "up":
            while (y > -32) {
                y -= bulletSpeed * GamePanel.delta;
                drawBullet(g);
            }
            break;
        case "down":
            while (y < 480) {
                y += bulletSpeed * GamePanel.delta;
                drawBullet(g);
            }
            break;
        }
    }

}

Any help would be great! Thank you very much!

EDIT I just read that you only have four directions. In that case you do not need a direction vector. Just set the direction once. Ok so the code example.

First the gameloop. Add the firedBullets for update in the gameloop. Every fired bullet gets moved on its direction vector.

private void gameUpdate() {
    if (!paused && !gameOver) {
        movePlayer();
        foreach(Bullet bullet : player.getFiredBullets(){
             bullet.moveInDirection();
        }
    }
}

And your Bullet class:

public class Bullet {
    private Direction direction;
    private float speed = 1.2f;
    private int x;
    private int y;

    public Bullet(int x, int y){
         this.x =x;
         this.y=y;        
    }

    public void launchBullet(Direction direction){
        this.direction=direction;
    }

    public void moveInDirection() {
        //move the bullet with speed in the set direction. Same as you already have but without the while loop.
    }
}

So the player should have a method fire. This creates the bullet with position of the player. The bullet gets the same direction as where the player is facing. And the bullet get added to the list so it will be updated every gameloop.

public class Player {
   private List<Bullet> firedBullets = new ArrayList<Bullet>();

   public void fire(){
       Bullet bullet = new Bullet(playerX, playerY);
       firedbullets.add(bullet);
       bullet.launch(direction); //this should be calculated by which direction the player is facing.
   }
}

So the direction gets set once when the bullet is fired. Every game update the bullet is moved in this direction by the speed of the bullet. This logic can be used for everything that has to be moved in the game. For example if you want a bullet that changes direction in mid-air you would just change its direction in mid-air.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM