为什么我的射弹(图像对象)不动? Java 摇摆
Why my projectile(Image object) is not moving? Java Swing
我正在尝试制作一个演示 spaceship shooter。每次我按下 space 条时,我都会在 paintComponent(Graphics g)
方法中绘制一个新的射弹(Image
)并调用 moveProjectile()
方法。问题是 moveProjectile()
方法似乎已关闭。
MyJPanel.java
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyJPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private Timer timer;
private Image backgroundImage;
private Image player;
private int playerX, playerY;
private int projectileX,projectileY;
private Image projectileImage;
private ArrayList<Image> projectiles = new ArrayList<Image>();
boolean flag = false;
public MyJPanel(Image backgroundImage, Image player,Image projectileImage)
{
this.backgroundImage = backgroundImage;
this.player = player;
this.projectileImage = projectileImage;
this.setLayout(null);
timer = new Timer(50, this);
timer.start();
this.addKeyListener(new KeyAdapter() // Listens for a keyboard event
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
}
});
// Mouse listener
this.addMouseMotionListener(new MouseMotionListener()
{
@Override
public void mouseMoved(MouseEvent e)
{
playerX = e.getX();
playerY = e.getY();
}
@Override
public void mouseDragged(MouseEvent e)
{
}
});
hideMouseCursor();
this.setFocusable(true);
this.setVisible(true);
} // End of JPanle constructor
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
graphics.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),null); // Draw the background
graphics.drawImage(player,playerX,playerY,null); // Draw the player
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
}
public void moveProjectile()
{
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
}
public void hideMouseCursor() // Hides the mouse cursor
{
//Transparent 16 x 16 pixel cursor image.
BufferedImage cursorbackgroundImgage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
cursorbackgroundImgage, new Point(0, 0), "Blank Cursor");
// Set the blank cursor to the JPanel.
this.setCursor(blankCursor);
}
@Override
public void actionPerformed(ActionEvent actionEvent) // Without the method and the repaint() the mouse listener will not work
{
repaint();
}
public class ProjectileThread extends Thread
{
@Override
public void run()
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("A Game by me");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // Making the frame take a full screen
ImageIcon backgroundImageIcon = new ImageIcon("space_background_2.jpg");
Image backgroundImgage = backgroundImageIcon.getImage();
ImageIcon playerImageIcon = new ImageIcon("spaceship_1.png");
Image playerImage = playerImageIcon.getImage();
ImageIcon projectileIcon = new ImageIcon("spaceship_projectile_1.png");
Image projectileImage = projectileIcon.getImage();
frame.add(new MyJPanel(backgroundImgage,playerImage,projectileImage));
frame.setVisible(true);
}
} // End of MyJPanel
有些变量和方法我不使用,请不要介意。代码中需要注意的地方:
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
如果按 space -> flag = true 表示
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
绘制弹丸并将其向右移动。问题是它从来没有向右移动过。相反,它跟随由鼠标移动的 space飞船。
如有任何建议,我们将不胜感激。
public class ProjectileThread extends Thread
{
public ProjectileThread(int playerX,int playerY)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
@Override
public void run()
{
while (projectileX < getWidth())
{
projectileX += 2;
}
}
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
ProjectileThread projectileThread = new ProjectileThread(playerX,playerY);
projectileThread.start();
}
repaint();
}
您的 moveProjectile 方法通过在其 X 坐标上加 2 水平移动射弹
this.projectileX += 2;
但是,您的绘制方法会用您的玩家 X 坐标覆盖此值:
projectileX = playerX + player.getWidth(null);
所以每次你绘制弹丸时,它都在相对于玩家的相同位置。您需要先使用玩家坐标绘制弹丸,然后在不重置其 X 坐标的情况下移动它。
你有一个线程应该在射弹发射时启动。因此,在 space 键的处理程序中,启动线程并将玩家坐标传递给它。这是你的起点。然后在线程的运行方法中,移动弹丸,循环等待一下。
while (projectileX < getWidth())
{
projectileX += 2;
}
所有这一切都是设置 projectile = getWidth() + 1(或可能+2)。
同样,您的 moveProjectile 方法具有以下内容:
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
做同样的事情。请注意,循环主体中的 repaint() 基本上什么都不做,因为您阻塞了事件线程,直到 moveProjectile() 方法 returns
我正在尝试制作一个演示 spaceship shooter。每次我按下 space 条时,我都会在 paintComponent(Graphics g)
方法中绘制一个新的射弹(Image
)并调用 moveProjectile()
方法。问题是 moveProjectile()
方法似乎已关闭。
MyJPanel.java
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
public class MyJPanel extends JPanel implements ActionListener
{
private static final long serialVersionUID = 1L;
private Timer timer;
private Image backgroundImage;
private Image player;
private int playerX, playerY;
private int projectileX,projectileY;
private Image projectileImage;
private ArrayList<Image> projectiles = new ArrayList<Image>();
boolean flag = false;
public MyJPanel(Image backgroundImage, Image player,Image projectileImage)
{
this.backgroundImage = backgroundImage;
this.player = player;
this.projectileImage = projectileImage;
this.setLayout(null);
timer = new Timer(50, this);
timer.start();
this.addKeyListener(new KeyAdapter() // Listens for a keyboard event
{
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
}
});
// Mouse listener
this.addMouseMotionListener(new MouseMotionListener()
{
@Override
public void mouseMoved(MouseEvent e)
{
playerX = e.getX();
playerY = e.getY();
}
@Override
public void mouseDragged(MouseEvent e)
{
}
});
hideMouseCursor();
this.setFocusable(true);
this.setVisible(true);
} // End of JPanle constructor
public void paintComponent(Graphics graphics)
{
super.paintComponent(graphics);
graphics.drawImage(backgroundImage,0,0,this.getWidth(),this.getHeight(),null); // Draw the background
graphics.drawImage(player,playerX,playerY,null); // Draw the player
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
}
public void moveProjectile()
{
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
}
public void hideMouseCursor() // Hides the mouse cursor
{
//Transparent 16 x 16 pixel cursor image.
BufferedImage cursorbackgroundImgage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
// Create a new blank cursor.
Cursor blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
cursorbackgroundImgage, new Point(0, 0), "Blank Cursor");
// Set the blank cursor to the JPanel.
this.setCursor(blankCursor);
}
@Override
public void actionPerformed(ActionEvent actionEvent) // Without the method and the repaint() the mouse listener will not work
{
repaint();
}
public class ProjectileThread extends Thread
{
@Override
public void run()
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
}
public static void main(String[] args)
{
JFrame frame = new JFrame("A Game by me");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setExtendedState(JFrame.MAXIMIZED_BOTH); // Making the frame take a full screen
ImageIcon backgroundImageIcon = new ImageIcon("space_background_2.jpg");
Image backgroundImgage = backgroundImageIcon.getImage();
ImageIcon playerImageIcon = new ImageIcon("spaceship_1.png");
Image playerImage = playerImageIcon.getImage();
ImageIcon projectileIcon = new ImageIcon("spaceship_projectile_1.png");
Image projectileImage = projectileIcon.getImage();
frame.add(new MyJPanel(backgroundImgage,playerImage,projectileImage));
frame.setVisible(true);
}
} // End of MyJPanel
有些变量和方法我不使用,请不要介意。代码中需要注意的地方:
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
flag = true;
moveProjectile();
}
repaint();
如果按 space -> flag = true 表示
if (flag)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2 - 27;
graphics.drawImage(projectileImage,projectileX,projectileY,null);
}
绘制弹丸并将其向右移动。问题是它从来没有向右移动过。相反,它跟随由鼠标移动的 space飞船。
如有任何建议,我们将不胜感激。
public class ProjectileThread extends Thread
{
public ProjectileThread(int playerX,int playerY)
{
projectileX = playerX + player.getWidth(null);
projectileY = playerY + player.getHeight(null) / 2;
}
@Override
public void run()
{
while (projectileX < getWidth())
{
projectileX += 2;
}
}
}
public void keyPressed(KeyEvent e)
{
if (e.getKeyCode() == KeyEvent.VK_SPACE) // If pressing space - shoot
{
ProjectileThread projectileThread = new ProjectileThread(playerX,playerY);
projectileThread.start();
}
repaint();
}
您的 moveProjectile 方法通过在其 X 坐标上加 2 水平移动射弹
this.projectileX += 2;
但是,您的绘制方法会用您的玩家 X 坐标覆盖此值:
projectileX = playerX + player.getWidth(null);
所以每次你绘制弹丸时,它都在相对于玩家的相同位置。您需要先使用玩家坐标绘制弹丸,然后在不重置其 X 坐标的情况下移动它。
你有一个线程应该在射弹发射时启动。因此,在 space 键的处理程序中,启动线程并将玩家坐标传递给它。这是你的起点。然后在线程的运行方法中,移动弹丸,循环等待一下。
while (projectileX < getWidth())
{
projectileX += 2;
}
所有这一切都是设置 projectile = getWidth() + 1(或可能+2)。 同样,您的 moveProjectile 方法具有以下内容:
while (projectileX < this.getWidth())
{
this.projectileX += 2;
repaint();
}
做同样的事情。请注意,循环主体中的 repaint() 基本上什么都不做,因为您阻塞了事件线程,直到 moveProjectile() 方法 returns