我创建了一个简单的程序,绘制一个以恒定速率下降到屏幕的矩形。我首先运行Main.java:
package highst;
public class Main {
public static void main(String args[]){
new GameFrame();
}
}
创建GameFrame.java的新实例:
package highst;
import javax.swing.JFrame;
public class GameFrame extends JFrame {
public GameFrame() {
super("Falling rectangle");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setSize(800, 600);
GameLogic game = new GameLogic();
this.getContentPane().add(game);
this.setVisible(true);
game.run();
}
}
反过来又创建了GameLogic.java的新实例:
package highst;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JPanel;
public class GameLogic extends JPanel implements Runnable, KeyListener {
Marvin marvin;
private enum GameState{
Running, Dead
}
GameState state = GameState.Running;
public GameLogic(){
marvin = new Marvin(50, 50);
Thread thread = new Thread(this);
thread.start();
addKeyListener(this);
setFocusable(true);
this.setBackground(Color.black);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
g.setColor(Color.white);
g.fillRect(marvin.getX(), marvin.getY(), 50, 50);
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_SPACE){
marvin.jump();
}
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void run() {
if(state == GameState.Running){
while(true){
marvin.update();
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
最终利用了我的可玩角色Marvin.java,现在是一个白色矩形:
package highst;
public class Marvin {
private int x, y;
public Marvin(int x, int y){
this.x = y;
this.y = y;
}
public void update(){
y -= -1;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void jump() {
x += 1;
}
}
它运行正常但矩形在页面下落时没有平滑地绘制。它似乎一次跳几个像素。我认为将线程休眠17毫秒会导致一切顺利呈现。我究竟做错了什么?
答案 0 :(得分:1)
要获得流畅的动画,您需要以恒定速率对屏幕进行更新。
在这里,你正在做一个图形重绘,这可能需要花费任何时间,然后等待17ms无论如何。这导致每个帧花费不同的时间量。第一帧可能在2ms完成,下一帧可能需要5ms,然后是3ms等等......你的帧将显示19ms然后22ms然后20ms ......
您需要的是一个专用线程,其唯一的工作是等待适当的时间,然后通知主线程重绘。然后你的画面(假设画面不超过17毫秒)每隔17毫秒出现一次,完全是在提示上。
答案 1 :(得分:0)
试试这些:
1>减少线程的休眠时间以查看效果并获得最佳的跌落速度。
2 - ;利用双缓冲(一种在屏幕上首先绘制内存然后在显示屏上绘制的概念):
Double Buffering - Google Search Results
3>简单的建议:避免使用sleep()。而是使用计时器。它是一个非常有趣和强大的线程替代品。此外,它不会在游戏开发的后期阶段产生问题。检查这些链接:
4>查看这些有关Java动画的有趣教程:
答案 2 :(得分:0)
有几件事情错了......
run
的实例上调用GameLogic
并创建Thread
,再次调用run
,设置为循环。这实际上是愚蠢的运气。这样做是调用marvin.update
两次......和随机间隔,意味着对象以不一致的速率移动基本上,您应该删除行game.run()
并在new GameFrame();
来电的上下文中包裹EventQueue.invokeLater
...
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
GameFrame frame = new GameFrame();
}
});
}
就我个人而言,我建议您不要直接从JFrame
扩展,不要在课程中添加任何功能,只需在main
中创建一个添加GameLogic
的实例面板到。这使得游戏在部署方面变得更加灵活,因为您没有将自己锁定在单个容器中。
我还建议您不要使用KeyListener
,而应使用Key Bindings API,因为它解决了与KeyListener
相关的焦点问题