public class Screen extends Canvas implements Runnable {
private static final int MAX_FPS = 60;
private static final int FPS_SAMPLE_SIZE = 6;
private boolean[] keysPressed = new boolean[256];
private ArrayList<Character> characters = new ArrayList<>();
private ArrayList<Character> ai = new ArrayList<>();
private Thread thread;
private BufferedImage bg;
//for testing putposes
private Player slime = new Player("Slime.png", 100, 100);
private Player bird = new Player("Bird.png", 250, 250);
private Player giant = new Player("Giant.png", 250, 500);
private Player swordsman = new Player("Swordsman.png", 500, 250);
//screen dimensions
private int height = ((Toolkit.getDefaultToolkit().getScreenSize().height-32)/5*4);
private int width = Toolkit.getDefaultToolkit().getScreenSize().width;
private long prevTick = -1;
private LinkedList<Long> frames = new LinkedList<>();
private int averageFPS;
private boolean running;
public Screen() {
setSize(width, height);
try {bg = ImageIO.read(new File("GUI Images/success.jpg"));}
catch (Exception e) {Utilities.showErrorMessage(this, e);}
characters.add(slime);
// ai.add(bird);
//ai.add(giant);
// ai.add(swordsman);
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {keysPressed[e.getKeyCode()] = true;}
public void keyReleased(KeyEvent e) {keysPressed[e.getKeyCode()] = false;}
public void keyTyped(KeyEvent e) {}
});
addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
});
addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {}
public void mouseMoved(MouseEvent e) {}
});
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {}
});
setVisible(true);
start();
}
public void paint(Graphics g){
BufferStrategy bs = getBufferStrategy();
if(getBufferStrategy() == null){
createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.drawImage(bg,0,0,width,height, null);
g.drawString(String.valueOf(averageFPS), 0, 0);
for (Character character : ai){
character.setY(character.getY() + (int)(Math.random() * 10 - 5));
character.setX(character.getX() + (int)(Math.random() * 10 - 5));
}
for (Character character : ai) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
for (Character character : characters) {g.drawImage(character.getImage(), character.getX(), character.getY(), null);}
g.dispose();
bs.show();
}
public void run() {
while (running) {
tick();
repaint();
}
}
public synchronized void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
try {thread.join();}
catch (InterruptedException e) {Utilities.showErrorMessage(this, e);}
}
public void tick() {
if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {slime.setY(slime.getY() - 1);}
if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {slime.setY(slime.getY() + 1);}
if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {slime.setX(slime.getX() - 1);}
if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {slime.setX(slime.getX() + 1);}
// System.out.println(slime.getX() + ", " + slime.getY());
long pastTime = System.currentTimeMillis() - prevTick;
prevTick = System.currentTimeMillis();
if (frames.size() == FPS_SAMPLE_SIZE) {
frames.remove();
}
frames.add(pastTime);
// Calculate average FPS
long sum = 0;
for (long frame : frames) {
sum += frame;
}
long averageFrame = sum / FPS_SAMPLE_SIZE;
averageFPS = (int)(1000 / averageFrame);
// Only if the time passed since the previous tick is less than one
// second divided by the number of maximum FPS allowed do we delay
// ourselves to give Time time to catch up to our rendering.
if (pastTime < 1000.0 / MAX_FPS) {
try {
Thread.sleep((1000 / MAX_FPS) - pastTime);
System.out.println(averageFPS);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
有我的代码,基本上这只是屏幕的测试代码,看我是否可以正确地将对象绘制到屏幕上,但是有不稳定的白色框架不断被绘制。它们似乎并不是由任何类型的输入引起的,它们只是在帧刷新期间看似随机发生。关于它可能是什么的任何想法?
答案 0 :(得分:1)
不要覆盖绘画并在其中使用BufferStrategy
。绘画通常需要做基础(AKA“被动”渲染)。 BufferStrategy
是一种“主动”渲染方法,您可以控制绘制过程并直接更新缓冲区,两者不能很好地协同工作
从当前paint
方法中获取逻辑,并将其置于游戏循环中。
这将要求您在构造函数中删除对start
的调用,因为该组件不会被添加到有效的本机对等方(屏幕上显示的组件)。
相反,创建一个Screen
的实例,将其添加到您的框架然后调用start,例如......
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferStrategy;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.imageio.ImageIO;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class TestScreen {
public static void main(String[] args) {
new TestScreen();
}
public TestScreen() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
Frame frame = new Frame("Testing");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Screen screen = new Screen();
frame.add(screen);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
screen.start();
}
});
}
public class TestPane extends JPanel {
public TestPane() {
}
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.dispose();
}
}
public class Screen extends Canvas implements Runnable {
private static final int MAX_FPS = 60;
private static final int FPS_SAMPLE_SIZE = 6;
private boolean[] keysPressed = new boolean[256];
private ArrayList<Character> characters = new ArrayList<>();
private ArrayList<Character> ai = new ArrayList<>();
private Thread thread;
private BufferedImage bg;
private long prevTick = -1;
private LinkedList<Long> frames = new LinkedList<>();
private int averageFPS;
private boolean running;
public Screen() {
try {
bg = ImageIO.read(new File("GUI Images/success.jpg"));
} catch (Exception e) {
e.printStackTrace();
}
addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
keysPressed[e.getKeyCode()] = true;
}
public void keyReleased(KeyEvent e) {
keysPressed[e.getKeyCode()] = false;
}
public void keyTyped(KeyEvent e) {
}
});
addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
});
addMouseMotionListener(new MouseMotionListener() {
public void mouseDragged(MouseEvent e) {
}
public void mouseMoved(MouseEvent e) {
}
});
addMouseWheelListener(new MouseWheelListener() {
public void mouseWheelMoved(MouseWheelEvent e) {
}
});
}
@Override
public Dimension getPreferredSize() {
int height = ((Toolkit.getDefaultToolkit().getScreenSize().height - 32) / 5 * 4);
int width = Toolkit.getDefaultToolkit().getScreenSize().width;
return new Dimension(width, height);
}
public void run() {
createBufferStrategy(3);
BufferStrategy bs = null;
while (running) {
bs = getBufferStrategy();
Graphics g = bs.getDrawGraphics();
g.drawImage(bg, 0, 0, getWidth(), getHeight(), null);
FontMetrics fm = g.getFontMetrics();
g.setColor(Color.RED);
g.drawString(String.valueOf(averageFPS), 0, fm.getAscent());
g.dispose();
bs.show();
tick();
}
}
public synchronized void start() {
running = true;
thread = new Thread(this);
thread.start();
}
public synchronized void stop() {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void tick() {
// if (keysPressed[KeyEvent.VK_W] && (slime.getY() > 0)) {
// slime.setY(slime.getY() - 1);
// }
// if (keysPressed[KeyEvent.VK_S] && (slime.getY() < height)) {
// slime.setY(slime.getY() + 1);
// }
// if (keysPressed[KeyEvent.VK_A] && (slime.getY() > 0)) {
// slime.setX(slime.getX() - 1);
// }
// if (keysPressed[KeyEvent.VK_D] && (slime.getY() < width)) {
// slime.setX(slime.getX() + 1);
// }
// // System.out.println(slime.getX() + ", " + slime.getY());
long pastTime = System.currentTimeMillis() - prevTick;
prevTick = System.currentTimeMillis();
if (frames.size() == FPS_SAMPLE_SIZE) {
frames.remove();
}
frames.add(pastTime);
// Calculate average FPS
long sum = 0;
for (long frame : frames) {
sum += frame;
}
long averageFrame = sum / FPS_SAMPLE_SIZE;
averageFPS = (int) (1000 / averageFrame);
// Only if the time passed since the previous tick is less than one
// second divided by the number of maximum FPS allowed do we delay
// ourselves to give Time time to catch up to our rendering.
if (pastTime < 1000.0 / MAX_FPS) {
try {
Thread.sleep((1000 / MAX_FPS) - pastTime);
System.out.println(averageFPS);
} catch (InterruptedException e) {
System.out.println(e);
}
}
}
}
}