我对使用Java创建游戏有点新意。我之前创建了一些简单的游戏,就像一个收集游戏的包,但现在我想制作一个自上而下的僵尸射击游戏。我已经有一个可以移动的玩家,但现在我想实现射击。 问题在于我不确定如何制作一个从玩家向右/向上/向下/向左射到屏幕末端的新子弹,具体取决于玩家所面对的屏幕部分。 /强> 我已粘贴下面的所有代码(4个类):
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;
}
}
这是我的GamePanel课程。 这是我的主要课程:
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();
}
}
这是我的Player类:
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);
}
}
最后这是我的子弹课程,我真的不知道如何使用甚至正确使用它:
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;
}
}
}
任何帮助都会很棒!非常感谢你!
答案 0 :(得分:2)
修改强> 我刚看到你只有四个方向。在这种情况下,您不需要方向向量。只需设置方向一次。 好的代码示例。
首先是游戏循环。在gameloop中添加要更新的firedBullets。每个被射击的子弹都会在方向向量上移动。
private void gameUpdate() {
if (!paused && !gameOver) {
movePlayer();
foreach(Bullet bullet : player.getFiredBullets(){
bullet.moveInDirection();
}
}
}
你的子弹课程:
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.
}
}
所以玩家应该有一个方法火。 这会创建具有玩家位置的子弹。子弹的方向与玩家面对的方向相同。子弹被添加到列表中,因此每个游戏循环都会更新。
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.
}
}
所以当子弹射击时,方向会被设置一次。每个游戏更新子弹都按子弹的速度向这个方向移动。此逻辑可用于必须在游戏中移动的所有内容。例如,如果您想要一个在空中改变方向的子弹,您只需在半空中改变方向。