我希望屏幕上有一个图像,只需移动即可。我能够让它显示在屏幕上,但我无法让它移动。这是一些代码:
播放器:
public class Player {
double positionX;
double positionY;
int destinationX;//Used when moving from place to place
int destinationY;
Tool currentTool;
int direction; //Position the image is facing
int dx;
int dy;
private String girl = "girl.png";
ImageIcon ii = new ImageIcon(this.getClass().getResource(girl));
private Image image = ii.getImage();
private boolean visible = true;
Image playerImage;
public Player(){
positionX=30;
positionY=20;
dx = 2;
dy = 2;
destinationX=(int)positionX;
destinationY=(int)positionY;
//this.playerImage=playerImage;
}
public void doAction() {
//currentTool.getNum();
}
public boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public Image getImage() {
return image;
}
public void move(){
//MOVE LEFT AND RIGHT
if(destinationX<positionX){
positionX-=dx;
}
if(destinationX>positionX){
positionX+=dx;
}
//MOVE UP AND DOWN
if(destinationY<positionY){
positionY-=dy;
}
if(destinationY>positionY){
positionY+=dy;
}
}
public void setDestination(int x, int y){
positionX=x;
positionY=y;
System.out.println(x + "," + y);
}
public void draw(Graphics g,ImageObserver io){
g.drawImage(image, (int)positionX,(int) positionY,io);
}
Board(实现游戏元素/组件):
public class Board extends JPanel implements Runnable {
private static final int NO_DELAYS_PER_YIELD = 16;
/* Number of frames with a delay of 0 ms before the
animation thread yields to other running threads. */
private static int MAX_FRAME_SKIPS = 5;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
private Thread animator;
int x, y;
final int frameCount = 8;
BufferedImage flowers;
private int[][] fPos = {{232, 15},{400, 200},{335, 335}}; // flower coordinates
private static int bWIDTH = 500; // width of window
private static int bHEIGHT = 400;// height of window
private Font font;
private FontMetrics metrics;
private House house = new House();
private Flower flower = new Flower();
private Player girlP = new Player();
private int px = 200;
private int py = 400;
private long period;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private volatile boolean isPaused = false;
private Graphics dbg;
private Image dbImage = null;
public Board(long period) {
this.period = period;
setBackground(Color.white);
setPreferredSize(new Dimension(bWIDTH, bHEIGHT));
setFocusable(true);
requestFocus(); //JPanel now receives key events
readyForTermination();
// create game components
// listen for mouse presses
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
testPress(e.getX(), e.getY());
}
});
// set up message font
font = new Font("SansSerif", Font.BOLD, 24);
metrics = this.getFontMetrics(font);
x = 15;
y = 150;
} // end of 'Board()'
public void addNotify() {
super.addNotify();
startGame();
}
public void startGame() {
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
}
public void pauseGame() {
isPaused = true;
}
public void resumeGame() {
isPaused = false;
}
public void stopGame() {
running = false;
}
private void readyForTermination() {
addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent e) {
// listen for escape, q, or ctrl-c
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE) ||
(keyCode == KeyEvent.VK_Q) ||
(keyCode == KeyEvent.VK_END) ||
((keyCode == KeyEvent.VK_C) && e.isControlDown()) ){
running = false;
}
}
});
}
private void testPress(int x, int y) {
if (!isPaused && !gameOver) {
// do something..
px = x;
py = y;
System.out.println(px + ", " + py);
}
}
private void gameRender() {
if (dbImage == null) { // creating the buffer
//dbImage = createImage(bWIDTH, bHEIGHT);
if (dbImage == null) {
//System.out.println("dbImage is null");
return;
}
else
dbg = dbImage.getGraphics();
}
// clearing the background
dbg.setColor(Color.gray);
//dbg.fillRect(0, 0, bWIDTH, bHEIGHT);
dbg.setColor(Color.blue);
dbg.setFont(font);
//drawing game elements....
if (gameOver) {
gameOverMessage(dbg);
} // end of gameRender()
}
private void gameUpdate() {
if (!isPaused && !gameOver) {
//girlP.move();
}
}
private void gameOverMessage(Graphics g)
// center the game-over message
{ // code to calculate x and y...
String msg = "Game Over";
g.drawString(msg, x, y);
} // end of gameOverMessage( )
public void paint(Graphics g) {
super.paint(g);
if (dbImage != null) {
g.drawImage(dbImage, 0, 0, null);
}
// if (house.isVisible()) {
// g.drawImage(house.getImage(), 10, 10, this);
// }
if (flower.isVisible()) {
for (int i = 0; i < 3; i++) {
g.drawImage(flower.getImage(), fPos[i][0], fPos[i][1],this);
}
}
girlP.draw(g, this);
//girlP.setDestination(0, 0);
//girlP.move();
// int red = 103;
// int green = 10;
// int blue = 100;
// Color square = new Color(red, green, blue);
// g.fillRect(x, y, sqW, sqH);
//Toolkit.getDefaultToolkit().sync();
}
private void paintScreen() {
// actively render the buffer to the screen
Graphics g;
try {
g = this.getGraphics(); // get the panel's graphic context
if ((g != null) && (dbImage != null))
g.drawImage(dbImage, 0, 0, null);
Toolkit.getDefaultToolkit().sync(); // sync the display on some systems
g.dispose();
}catch (Exception e) {
System.out.println("Graphics context error: " + e);
}
}
public void run() {
// repeatedly update, render, and sleep
long beforeTime, afterTime, timeDiff, sleep;
long overSleepTime = 0L;
int noDelays = 0;
long excess = 0L;
beforeTime = System.nanoTime();
running = true;
while (running) {
gameUpdate();
gameRender();
paintScreen(); // this will draw buffer to screen instead of repaint()
//updateChange();
girlP.move();
afterTime = System.nanoTime();
timeDiff = afterTime - beforeTime;
sleep = (period - timeDiff) - overSleepTime; // time left in this loop
if (sleep > 0) { // some time left in this cycle
try {
Thread.sleep(sleep/1000000L); // nano -> ms
}catch (InterruptedException e) {
System.out.println("Interrupted");
}
overSleepTime = (System.nanoTime() - afterTime) - sleep;
}
else { // sleep <= 0; frame took longer than the delay
excess -= sleep; // store excess time value
overSleepTime = 0L;
if (++noDelays >= NO_DELAYS_PER_YIELD) {
Thread.yield( ); // give another thread a chance to run
noDelays = 0;
}
}
beforeTime = System.nanoTime();
/* If frame animation is taking too long, update the game state
without rendering it, to get the updates/sec nearer to
the required FPS. */
int skips = 0;
while((excess > period) && (skips < MAX_FRAME_SKIPS)) {
excess -= period;
gameUpdate(); // update state but don't render
skips++;
}
}
System.exit(0);
} // end of run();
}
答案 0 :(得分:2)
有很多事情让我很突出。
使用getGraphics
是一个非常糟糕的主意。 Swing使用由RepaintManager
控制的被动渲染引擎。这基本上意味着虽然您可以请求重新绘制,但您无法控制何时可能发生更新。
paint
方法之一中重新应用。
你的动作代码错了。您将值直接分配给position
而不是destination
变量。如果不需要移动,我修改了移动代码什么都不做,我实际上是出于调试目的而这样做,但干草。
你的核心渲染引擎......很奇怪......
你不太可能需要更多大约25 fps或等效物,所以使用纳秒可能有点过分,毫秒精度可能就足够了。当我改变延迟引擎时,我得到了更好的结果。
我还改变了核心渲染过程。引擎现在使用页面翻转过程。它使用两个BufferedImages
,一个是绘制到屏幕的activeBuffer
,另一个是scratchBuffer
,用于更新游戏状态。然后根据需要翻转。这意味着屏幕上绘制的内容受到引擎渲染的内容的影响。
可能还有十几个其他的东西,但你可以自己比较差异;)
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.tools.Tool;
public class AnimationEngine {
public static void main(String[] args) {
new AnimationEngine();
}
public AnimationEngine() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new Board(40));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static class Board extends JPanel implements Runnable {
protected static final Object UPDATE = new Object();
private static final int NO_DELAYS_PER_YIELD = 16;
/* Number of frames with a delay of 0 ms before the
animation thread yields to other running threads. */
private static int MAX_FRAME_SKIPS = 5;
// no. of frames that can be skipped in any one animation loop
// i.e the games state is updated but not rendered
private Thread animator;
int x, y;
final int frameCount = 8;
BufferedImage flowers;
private int[][] fPos = {{232, 15}, {400, 200}, {335, 335}}; // flower coordinates
private static int bWIDTH = 500; // width of window
private static int bHEIGHT = 400;// height of window
private Font font;
private FontMetrics metrics;
// private House house = new House();
// private Flower flower = new Flower();
private Player girlP = new Player();
private int px = 200;
private int py = 400;
private long period;
private volatile boolean running = false;
private volatile boolean gameOver = false;
private volatile boolean isPaused = false;
// private Graphics dbg;
private BufferedImage activeBuffer = null;
private BufferedImage scratchBuffer = null;
public Board(long period) {
this.period = period;
setBackground(Color.white);
setPreferredSize(new Dimension(bWIDTH, bHEIGHT));
setFocusable(true);
requestFocus(); //JPanel now receives key events
readyForTermination();
// create game components
// listen for mouse presses
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
System.out.println("Clicked");
girlP.setDestination(e.getX(), e.getY());
}
});
// set up message font
font = new Font("SansSerif", Font.BOLD, 24);
metrics = this.getFontMetrics(font);
x = 15;
y = 150;
} // end of 'Board()'
public void addNotify() {
super.addNotify();
startGame();
}
public void startGame() {
if (animator == null || !running) {
animator = new Thread(this);
animator.start();
}
}
public void pauseGame() {
isPaused = true;
}
public void resumeGame() {
isPaused = false;
}
public void stopGame() {
running = false;
}
private void readyForTermination() {
addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
// listen for escape, q, or ctrl-c
int keyCode = e.getKeyCode();
if ((keyCode == KeyEvent.VK_ESCAPE)
|| (keyCode == KeyEvent.VK_Q)
|| (keyCode == KeyEvent.VK_END)
|| ((keyCode == KeyEvent.VK_C) && e.isControlDown())) {
running = false;
}
}
});
}
@Override
public void invalidate() {
synchronized (UPDATE) {
activeBuffer = null;
scratchBuffer = null;
}
super.invalidate();
}
private void gameRender() {
synchronized (UPDATE) {
if (getWidth() > 0 && getHeight() > 0) {
if (scratchBuffer == null) {
scratchBuffer = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_RGB);
}
Graphics2D dbg = scratchBuffer.createGraphics();
// clearing the background
dbg.setColor(Color.GRAY);
dbg.fillRect(0, 0, scratchBuffer.getWidth(), scratchBuffer.getHeight());
dbg.setColor(Color.blue);
dbg.setFont(font);
//drawing game elements....
girlP.draw(dbg, this);
if (gameOver) {
gameOverMessage(dbg);
} // end of gameRender()
dbg.dispose();
}
BufferedImage tmp = activeBuffer;
activeBuffer = scratchBuffer;
scratchBuffer = tmp;
}
}
private void gameUpdate() {
if (!isPaused && !gameOver) {
girlP.move();
}
}
private void gameOverMessage(Graphics g) // center the game-over message
{ // code to calculate x and y...
String msg = "Game Over";
g.drawString(msg, x, y);
} // end of gameOverMessage( )
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (activeBuffer != null) {
g.drawImage(activeBuffer, 0, 0, null);
}
}
public void run() {
long beforeTime, afterTime, timeDiff, sleep;
beforeTime = System.currentTimeMillis();
running = true;
while (running) {
gameUpdate();
gameRender();
repaint();
afterTime = System.currentTimeMillis();
timeDiff = afterTime - beforeTime;
sleep = (period - timeDiff); // - overSleepTime; // time left in this loop
if (sleep > 0) { // some time left in this cycle
try {
Thread.sleep(sleep); // nano -> ms
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
} else { // sleep <= 0; frame took longer than the delay
System.out.println("Over...");
}
beforeTime = System.currentTimeMillis();
}
System.exit(0);
} // end of run();
}
public static class Player {
double positionX;
double positionY;
int destinationX;//Used when moving from place to place
int destinationY;
Tool currentTool;
int direction; //Position the image is facing
int dx;
int dy;
private String girl = "/Player01.png";
ImageIcon ii = new ImageIcon(this.getClass().getResource(girl));
private Image image = ii.getImage();
private boolean visible = true;
Image playerImage;
public Player() {
positionX = 30;
positionY = 20;
dx = 4;
dy = 4;
destinationX = (int) positionX;
destinationY = (int) positionY;
//this.playerImage=playerImage;
}
public void doAction() {
//currentTool.getNum();
}
public boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public Image getImage() {
return image;
}
public void move() {
if (destinationX != positionX || destinationY != positionY) {
//MOVE LEFT AND RIGHT
if (destinationX < positionX) {
positionX -= dx;
}
if (destinationX > positionX) {
positionX += dx;
}
//MOVE UP AND DOWN
if (destinationY < positionY) {
positionY -= dy;
}
if (destinationY > positionY) {
positionY += dy;
}
}
}
public void setDestination(int x, int y) {
destinationX = x;
destinationY = y;
}
public void draw(Graphics g, ImageObserver io) {
g.drawImage(image, (int) positionX, (int) positionY, io);
}
}
}