【发布时间】:2016-06-04 17:54:01
【问题描述】:
在我的“SpcaeShip”游戏中,我有一个循环游戏,可以更新和绘制我的所有对象。现在我想在游戏中添加一个小行星数组列表并绘制它们,但问题是如果我在循环游戏中绘制小行星数组,游戏运行速度非常慢。我的解决方案是在计时器线程上绘制小行星,游戏速度非常完美。我唯一的问题是我的小行星一直在闪烁。我需要使用 bufferStrategy 或类似的东西吗?
这是我在游戏循环中的绘制方法(在这个循环中我调用了游戏状态绘制方法):
private void tick()
{
//update all objects
}
private void render()
{
//how many buffers(hold the same data as our screen) the canvas would use
bs = display.getCanvas().getBufferStrategy();
if(bs == null)
{
display.getCanvas().createBufferStrategy(3);
return;
}
g = bs.getDrawGraphics();
g.clearRect(0, 0, width, height);
if(State.getState() != null)
{
State.getState().render(g);
}
bs.show();
g.dispose();
}
public void run()
{
init();
int fps = 60;
double timePerTick = 1000000000/ fps;
double delta = 0;
long now;
long lastTime =System.nanoTime();
long timer = 0;
//game loop
while(running)
{
now = System.nanoTime();
delta += (now - lastTime) / timePerTick;
timer += now - lastTime;
lastTime = now;
if(delta >= 1)
{
tick();
render();
}
}
stop();
}
这是我的游戏状态方法:
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import javax.swing.Timer;
public class GameState extends State
{
private SpaceShip spaceShip;
private BgHandler bgHandler;
private ArrayList<Meteor> meteors;
public GameState(Handler handler)
{
super(handler);
bgHandler = new BgHandler(handler.getWidth(), handler.getHeight());
spaceShip = new SpaceShip(handler, handler.getWidth() / 2 - Things.DEFAULT_OBJECT_WIDTH / 2,
handler.getHeight() - Things.DEFAULT_OBJECT_HEIGHT - 100);
meteors = new ArrayList<Meteor>();
for(int i = 0; i < 5; i++)
{
Meteor m = new Meteor(handler,(int) (Math.random() * (handler.getWidth() - Things.DEFAULT_OBJECT_WIDTH ))
, -Things.DEFAULT_OBJECT_WIDTH,
Things.DEFAULT_OBJECT_WIDTH,
Things.DEFAULT_OBJECT_HEIGHT);
meteors.add(m);
}
timer.start();
}
Timer timer = new Timer (50, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
tickMeteor();
renderMeteor();
}
});
public void tickMeteor()
{
for(int i = 0; i < meteors.size(); i++)
{
Meteor m = meteors.get(i);
if(m.getVisible())
{
m.tick();
}
else
{
meteors.remove(i);
}
}
}
public void renderMeteor()
{
for(Meteor m: meteors)
{
Meteor m1 = (Meteor) m;
if(m1.getVisible())
{
m1.render(handler.getGame().getGraphics());
}
}
}
@Override
public void tick()
{
spaceShip.tick();
for(int i = 0; i < meteors.size(); i++)
{
Meteor m = meteors.get(i);
if(m.getVisible())
{
m.tick();
}
else
{
meteors.remove(i);
}
}
}
}
@Override
public void render(Graphics g)
{
bgHandler.render(g);
spaceShip.render(g);
}
}
【问题讨论】:
-
检查
if(State.getState() != null)生成空白帧的频率 -
如果你使用的是 BufferStategy,那么你不需要使用 Swing Timer,你可以使用自己的 Thread,因为你不再需要担心与 EDT 同步绘画过程,因为它们是独立的进程
-
好的,一切都应该在同一个线程中更新和绘制,并且应该在同一个过程中一起完成
标签: java bufferedimage flicker 2d-games