【LWJGL2 WIKI】【基础篇】基础4:计时

原文:http://wiki.lwjgl.org/wiki/LWJGL_Basics_4_(Timing)

Timers 计时器

精确计时对于高性能游戏很重要。一般计时器的精度至少得是1毫秒。
Java的System.currentTimeMillis()方法可以根据运行的操作系统具备1至55毫秒之间某个精度,这将导致游戏跨平台不太容易。

System.nanoTime()

Java 1.5引入了此方法,可以提供毫秒级的精度。用System.nanoTime()取毫秒的话,必须将返回值除以1,000,000(纳秒→毫秒)

/**
 * Get the time in milliseconds
 *
 * @return The system time in milliseconds
 */
public long getTime() {
    return System.nanoTime() / 1000000;
}
Sys.getTime()

LWJGL里的Sys.getTime()方法是一个高度的解决方案。它将返回以“滴达”单位返回时间。这值可以转成任何的格式(纳秒、微秒、毫秒等等)以合理适应它的平台。Sys.getTimerResolution()方法将返回一秒内的滴达数。此两个方法使用时都可以转换为任何需要的单位(包括毫秒)。详见Javadoc里的LWJGL Sys类
为了从Sys.getTime()取得毫秒数,滴达数要乘以1000,然后再除以每秒的滴达数。

/**
 * Get the time in milliseconds
 *
 * @return The system time in milliseconds
 */
public long getTime() {
    return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}

以上任何一个计时器都是可以满足需求的。

Delta Time 时刻差

在许多游戏里,有一个叫时刻差的整数值经常被用来保存上一帧到本帧经过的毫秒数。此值可以用来在游戏中以帧独立的方式来移动实体们,也就是说,不需要刻意去关注fps是快了还是慢了,所有的东西都会以固定的速度移动的。
想计算这值,需要保存每帧的时刻值,然后用本帧的减去上一帧的。

public int getDelta() {
    long time = getTime();
    int delta = (int) (time - lastFrame);
    lastFrame = time;

    return delta;
}

Sleeping and Display.sync() 休眠和Display.sync()

休眠对游戏来说很重要,不然游戏循环将会能跑多快跑多快,占尽系统资源并且热爆CPU、GPU,耗电超快。休眠使程序可以适当休息,以免用尽系统全部资源。有许多种方式可用,比如Thread.sleep()或者Thread.yield()。然后LWJGL提供了更简便的Display.sync(int fps)方法。此方法允许游戏循环以特定的帧率运行(如60fps)并且可以在任何额外的时间里休眠。这方法必须在每帧里调用(可以放在游戏循环内)。另一个实现的方法是使用Vsync,这个之后的教程会再讲。

Calculating FPS 计算FPS

每秒帧数(Frame Per Second,即FPS)可以通过每帧累加一个整数值来计算,几秒过去,将此值显示给用户(然后在下帧就就归零并重新计算)。为了简便,我们用Display.setTitle(String title)方法将帧率显示在窗口标题中。

public void start() {
    //some startup code
    lastFPS = getTime(); //set lastFPS to current Time
}


/**
 * Calculate the FPS and set it in the title bar
 */
public void updateFPS() {
    if (getTime() - lastFPS > 1000) {
        Display.setTitle("FPS: " + fps);
        fps = 0; //reset the FPS counter
        lastFPS += 1000; //add one second
    }
    fps++;
}

Example 例子

以下是一个完整例子,它使用时刻差旋转或移动一个方形,用方向键可以移动方形。

import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.GL11;

public class TimerExample {

    /** position of quad */
    float x = 400, y = 300;
    /** angle of quad rotation */
    float rotation = 0;

    /** time at last frame */
    long lastFrame;

    /** frames per second */
    int fps;
    /** last fps time */
    long lastFPS;

    public void start() {
        try {
            Display.setDisplayMode(new DisplayMode(800, 600));
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            System.exit(0);
        }

        initGL(); // init OpenGL
        getDelta(); // call once before loop to initialise lastFrame
        lastFPS = getTime(); // call before loop to initialise fps timer

        while (!Display.isCloseRequested()) {
            int delta = getDelta();

            update(delta);
            renderGL();

            Display.update();
            Display.sync(60); // cap fps to 60fps
        }

        Display.destroy();
    }

    public void update(int delta) {
        // rotate quad
        rotation += 0.15f * delta;

        if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) x -= 0.35f * delta;
        if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) x += 0.35f * delta;

        if (Keyboard.isKeyDown(Keyboard.KEY_UP)) y -= 0.35f * delta;
        if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) y += 0.35f * delta;

        // keep quad on the screen
        if (x < 0) x = 0;
        if (x > 800) x = 800;
        if (y < 0) y = 0;
        if (y > 600) y = 600;

        updateFPS(); // update FPS Counter
    }

    /**
     * Calculate how many milliseconds have passed
     * since last frame.
     *
     * @return milliseconds passed since last frame
     */
    public int getDelta() {
        long time = getTime();
        int delta = (int) (time - lastFrame);
        lastFrame = time;

        return delta;
    }

    /**
     * Get the accurate system time
     *
     * @return The system time in milliseconds
     */
    public long getTime() {
        return (Sys.getTime() * 1000) / Sys.getTimerResolution();
    }

    /**
     * Calculate the FPS and set it in the title bar
     */
    public void updateFPS() {
        if (getTime() - lastFPS > 1000) {
            Display.setTitle("FPS: " + fps);
            fps = 0;
            lastFPS += 1000;
        }
        fps++;
    }

    public void initGL() {
        GL11.glMatrixMode(GL11.GL_PROJECTION);
        GL11.glLoadIdentity();
        GL11.glOrtho(0, 800, 0, 600, 1, -1);
        GL11.glMatrixMode(GL11.GL_MODELVIEW);
    }

    public void renderGL() {
        // Clear The Screen And The Depth Buffer
        GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);

        // R,G,B,A Set The Color To Blue One Time Only
        GL11.glColor3f(0.5f, 0.5f, 1.0f);

        // draw quad
        GL11.glPushMatrix();
            GL11.glTranslatef(x, y, 0);
            GL11.glRotatef(rotation, 0f, 0f, 1f);
            GL11.glTranslatef(-x, -y, 0);

            GL11.glBegin(GL11.GL_QUADS);
                GL11.glVertex2f(x - 50, y - 50);
                GL11.glVertex2f(x + 50, y - 50);
                GL11.glVertex2f(x + 50, y + 50);
                GL11.glVertex2f(x - 50, y + 50);
            GL11.glEnd();
        GL11.glPopMatrix();
    }

    public static void main(String[] argv) {
        TimerExample timerExample = new TimerExample();
        timerExample.start();
    }
}

Credit

Tutorial Credit - Ninja Cave

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值