我目前正在尝试学习编程游戏。 我得到了一个我自己编写的扩展精灵类的玩家类。 现在我想知道,我如何在正在运行的游戏中改变我的玩家对象的图像。想象一下宇宙飞船,当按下右箭头键时,它应该是一个不同的图像,向右倾斜。 现在我想这样做: 按下按钮时(例如空格)setImage(新图像) 但是现在,当我调用这种方法时,我的图像就会消失,而新图像也不会出现?
有什么想法吗? 我的主类代码:
public class Game extends JPanel implements Runnable{
private static final long serialVersionUID = 1L;
public boolean isRunning;
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
private Player player;
public Game() {
addKeyListener(new TAdapter());
setFocusable(true);
requestFocus();
start();
}
public void start() {
isRunning = true;
new Thread(this).start();
}
public void stop() {
isRunning = false;
}
public void run() {
init();
while(isRunning) {
update();
repaint();
try {
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void init() {
player = new Player("/ship_blue", WIDTH - 32/2, 400);
}
public void update() {
player.update();
}
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D)g;
drawPlayer(g2d);
}
public void drawPlayer(Graphics2D g2d) {
if(player.isVisible)g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), null);
}
public static void main(String[] args) {
Game gameComponent = new Game();
Dimension size = new Dimension(WIDTH*SCALE, HEIGHT*SCALE);
JFrame frame = new JFrame("Invaders");
frame.setVisible(true);
frame.setSize(size);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setResizable(false);
frame.add(gameComponent);
}
public class TAdapter extends KeyAdapter{
public void keyPressed(KeyEvent e) {
player.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
player.keyReleased(e);
}
}
}
那是主要类,现在是我试图在onPress()方法中更改图像的播放器类:
public class Player extends Sprite{
private double glideSpeed = .125;
private int fixY;
private int xDirection = 0;
private int yDirection = 1;
public Player(String source, int x, int y) {
this.x = x;
this.y = y;
ImageIcon ii = new ImageIcon(this.getClass().getResource(source));
setImage(ii.getImage());
setTileSize(ii.getIconWidth());
setSpeed(0.2);
fixY = y;
}
public void update() {
x += xDirection * 1.4;
glide(10);
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT) {
xDirection = 1;
}
if(key == KeyEvent.VK_LEFT) {
xDirection = -1;
}
if(key == KeyEvent.VK_SPACE) {
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
setImage(ii2.getImage()); //<-----Here I am trying to change the image
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if(key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_LEFT) {
xDirection = 0;
}
}
public void glide(int span) {
y += yDirection * glideSpeed;
if(y - fixY > span || fixY - y > span) {
yDirection = -yDirection;
}
}
}
并且完成这里的所有内容是我的精灵课程:
public class Sprite {
protected double x;
protected double y;
protected int tileSize;
protected double speed;
protected Image img;
protected boolean isVisible;
public Sprite() {
isVisible = true;
}
public double getSpeed() {
return speed;
}
public double getX() {
return x;
}
public double getY() {
return y;
}
public int getTileSize() {
return tileSize;
}
public Image getImage() {
return img;
}
public boolean getVisible() {
return isVisible;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public void setX(double x) {
this.x = x;
}
public void setY(double y) {
this.y = y;
}
public void setTileSize(int tileSize) {
this.tileSize = tileSize;
}
public void setImage(Image img) {
this.img = img;
}
public void die() {
isVisible = false;
}
}
答案 0 :(得分:4)
if(key == KeyEvent.VK_SPACE) {
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
存在基本问题。应在事件发生之前加载和缓存所有图像。事件发生时,使用缓存的图像,GUI应立即呈现。
作为mentioned by @camickr,使用ImageIcon
也会巧妙地从URL
滑落到String
(假设代表
File
路径)。坚持使用从URL
获得的getResource(..)
。
ImageObserver
。如果使用ImageObserver
绘制图像,将通知观察者对异步加载的图像的更新。所有组件(例如JPanel
)都实现ImageObserver
,所以..
g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), null);
应该是:
g2d.drawImage(player.getImage(),(int) player.getX(), (int) player.getY(), this);
class Game extends JPanel implements Runnable ..
Thread.sleep(5);
不要阻止EDT(事件调度线程) - 当发生这种情况时,GUI将“冻结”。 也不要尝试从EDT以外的任何其他方式更新GUI。
不是在Thread.sleep(n)
中调用Runnable
,而是为重复任务实现Swing Timer
,或为长时间运行的任务实现SwingWorker
。有关详细信息,请参阅Concurrency in Swing。
paintComponent(Graphics)
!public void paint(Graphics g) {
应该是:
@Override
public void paintComponent(Graphics g) {
答案 1 :(得分:2)
加载初始图像时,使用以下内容时没有问题:
ImageIcon ii = new ImageIcon(this.getClass().getResource(source));
更改使用的图像时:
ImageIcon ii2 = new ImageIcon("/player_blue_negativ");
我猜你找不到图像,可能是因为你不需要“/”。但为什么不使用你知道的相同方法呢?