Java中的基本游戏循环

时间:2014-06-07 16:53:34

标签: java

我正在尝试在this site

上实施最后一个游戏循环

以下是该网站的代码:

const int TICKS_PER_SECOND = 25;
const int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
const int MAX_FRAMESKIP = 5;

DWORD next_game_tick = GetTickCount();
int loops;
float interpolation;

bool game_is_running = true;
while( game_is_running ) {

    loops = 0;
    while( GetTickCount() > next_game_tick && loops < MAX_FRAMESKIP) {
        update_game();

        next_game_tick += SKIP_TICKS;
        loops++;
    }

    interpolation = float( GetTickCount() + SKIP_TICKS - next_game_tick )
                    / float( SKIP_TICKS );
    display_game( interpolation );
}

  // GetTickCount() returns the current number of milliseconds
// that have elapsed since the system was started

我使用System.currentTimeMillis()代替GetTickCount()希望它可以做到这一点。

但是我的代码让我的结果变得非常奇怪: 有谁知道如何在java中实现这个游戏循环?

这是我的非工作示例:(我不断为插值获取大数字)

private final int TICKS_PER_SECOND = 25;
private final int SKIP_TICKS = 1000 / TICKS_PER_SECOND;
private final int MAX_FRAMESKIP = 5;

private double nextGameTick =  System.currentTimeMillis() ;

private int loops;
private float interpolation;

private boolean isGameRunning = true;

public GameLoop(){

while( isGameRunning ) {

    loops = 0;
    while(  System.currentTimeMillis() > nextGameTick && loops < MAX_FRAMESKIP) {
        //  update_game();

        nextGameTick += SKIP_TICKS;
        loops++;
    }

    interpolation = (float)(  System.currentTimeMillis() + SKIP_TICKS - nextGameTick )/ (float)( SKIP_TICKS );
    //display_game( interpolation );
    view.display(interpolation);
}

}

我使用网站上的公式在该位置画一个球,但球只是来回徘徊

view_position = position +(speed * interpolation)

我添加了其余的代码,因此不那么混乱: (虽然我甚至在我点击这段代码之前就遇到了问题,因为当我运行调试器并且它应该是一小部分时插值数量很大) 这是我绘制球的视图类:

public class View extends JPanel
{
    private static final long serialVersionUID = -2744215808270823059L;

    Ball myBall = new Ball();



    public void paintComponent(Graphics g){
        super.paintComponent(g);
        paintBall(g);
        g.drawString(String.valueOf(interpolation), 20, 20);
        g.drawString(String.valueOf(myBall.getLocation()), 20, 50);
    }

    private void paintBall(Graphics g){
        g.drawOval(myBall.getLocation().x, myBall.getLocation().y, myBall.getDiameter(), myBall.getDiameter() );

    }
    private float interpolation;
    public void display(float interpolation){
        Point location = new Point();
        this.interpolation = interpolation;

        location.x =  myBall.getLocation().x + (int)(myBall.getSpeedX() * interpolation);
        location.y =  myBall.getLocation().y + (int)(myBall.getSpeedY() * interpolation);
        myBall.setLocation(location);

        repaint();
    }



}

我的球类:

public class Ball {
    private Point location = new Point();
    private int diameter;


    private double speed;
    private double speedX;
    private double speedY;

    private double angle; 

    Ball(){
        this(new Point(0, 10));
    }

    Ball(Point location){
        this(10, 3, 60, location);
    }

    Ball(int diameter, double speed, double angleDeg, Point location ){
        this.speed = speed;
        setAngleDeg(angleDeg);
        setDiameter(diameter);
        setLocation(location);
    }
    //Getters and Setters


    public double getAngleRad() {
        return angle;
    }
    public void setAngleRad(double angle) {
        this.angle = angle;
        speedX = Math.cos(angle)*speed;
        speedY = Math.sin(angle)*speed;
    }

    public double getAngleDeg() {
        return angle*180/Math.PI;
    }
    public void setAngleDeg(double angle) {
        this.angle = angle * Math.PI/180;
        speedX = Math.cos(angle)*speed;
        speedY = Math.sin(angle)*speed;
    }

    public double getSpeedX() { 
        return speedX;
    }
    public void setSpeedX(double speedX) {
        this.speedX = speedX;
    }

    public double getSpeedY() {
        return speedY;
    }
    public void setSpeedY(double speedY) {
        this.speedY = speedY;
    }

    public Point getLocation() {
        return location;
    }
    public void setLocation(Point location) {
        this.location = location;
    }
    public int getDiameter() {
        return diameter;
    }
    public void setDiameter(int diameter) {
        this.diameter = diameter;
    }
    public double getSpeed() {
        return speed;
    }

    public void setSpeed(double speed) {
        this.speed = speed;
        speedX = Math.cos(angle)*speed;
        speedY = Math.sin(angle)*speed;
    }


}

1 个答案:

答案 0 :(得分:0)

在游戏循环中使用繁忙等待是不好的做法,我建议使用不同的策略,例如等待显示刷新以渲染​​下一帧。大多数游戏框架都包含他们自己的游戏循环逻辑,我强烈建议您查看其中一个。

问题看起来就像是将时差输入view_position而不是将其添加到获取实际时间的时间。所以球的位置是基于帧时间之间的抖动而不是时间本身。

在你想到用自己的车轮重新发明车轮之前,请尝试一下游戏框架;在游戏逻辑上工作更有趣,而不是调试低级别的东西。当你更有经验,并且如果你需要它来表现时,请回到这里。