原文:http://wiki.lwjgl.org/wiki/LWJGL_Basics_5_%28Fullscreen%29
Why use Fullscreen? 为何用全屏?
有许多原因,包括以下:
- 改变屏幕分辨率会得到更快的游戏运行速度,使图片看起来效果更佳
- 使垂直同步可以自由分割图形(??不知道什么意思)
- 使用户更有沉浸感
Using Fullscreen 使用全屏
创建教程1里的Display窗口
Display.setDisplayMode(new DisplayMode(width,height));
Display.create();
要用全屏Display,设置好DisplayMode后,调用Display.setFullscreen(true).
Display.setDisplayMode(displayMode);
Display.setFullscreen(true);
Display.create();
What is a DisplayMode? DisplayMode是什么?
DisplayMode将许多参数压缩组成的一个类,包括以下参数:
- getWidth() - 窗口的象素宽度
- getHeight() - 窗口的象素高度
- getBitsPerPixel() - 每象素的位数,也就是色彩数
- getFrequency() - 画帧时的刷新率
初始化DisplayMode和桌面分辨率一样,原始的桌面分辨率可以任意时候调用DisplayMode取到。
Display.getDesktopDisplayMode().
Obtaining DisplayModes supported in fullscreen 获取全屏支持的DisplayMode
显卡支持的全屏分辨率可以调用Display.getAvailableDisplayModes()方法取到,此列表可以之后拿来遍历以获取对应的DisplayMode。
DisplayMode[] modes = Display.getAvailableDisplayModes();
for (int i=0;i<modes.length;i++) {
DisplayMode current = modes[i];
System.out.println(current.getWidth() + "x" + current.getHeight() + "x" +
current.getBitsPerPixel() + " " + current.getFrequency() + "Hz");
}
用Display.setDisplayMode()来设置DisplayMode。如果窗口己创建,它将直接立刻调整大小。如果还没创建,用Display.create()创建。
当前的DisplayMode可以用Display.getDisplayMode()取到,如果还没设置的话,它将和Display.getDesktopDisplayMode()一样。
Display.setFullscreen(boolean)方法用来切换全屏、窗口模式。
BitsPerPixel值更适用于32位色(Windows)和24位色(Linux和Mac),现在16位色、256色甚至更震惊的16色的老式电脑应该已经十分稀有了。因此,直接使用默认的桌面色彩值就是一个不错的主意。
Frequency值是帧描画率,同样的,使用默认的桌面刷新率可能对显示器支持最佳(虽然某些视频卡可能支持其他的)。CRT显示器可以轻松支持各种不同的频率和刷新率,但是TFT显示器现在越来越通用一些,所以最好用默认的频繁就好。
Convenience method to Switch Resolution 方便的切换分辨率的方法
根据上面讲的,用下面例子里的方法可以获取并切换到一个需要的分辨率。
/**
* Set the display mode to be used
*
* @param width The width of the display required
* @param height The height of the display required
* @param fullscreen True if we want fullscreen mode
*/
public void setDisplayMode(int width, int height, boolean fullscreen) {
// return if requested DisplayMode is already set
if ((Display.getDisplayMode().getWidth() == width) &&
(Display.getDisplayMode().getHeight() == height) &&
(Display.isFullscreen() == fullscreen)) {
return;
}
try {
DisplayMode targetDisplayMode = null;
if (fullscreen) {
DisplayMode[] modes = Display.getAvailableDisplayModes();
int freq = 0;
for (int i=0;i<modes.length;i++) {
DisplayMode current = modes[i];
if ((current.getWidth() == width) && (current.getHeight() == height)) {
if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
targetDisplayMode = current;
freq = targetDisplayMode.getFrequency();
}
}
// if we've found a match for bpp and frequence against the
// original display mode then it's probably best to go for this one
// since it's most likely compatible with the monitor
if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel()) &&
(current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
targetDisplayMode = current;
break;
}
}
}
} else {
targetDisplayMode = new DisplayMode(width,height);
}
if (targetDisplayMode == null) {
System.out.println("Failed to find value mode: "+width+"x"+height+" fs="+fullscreen);
return;
}
Display.setDisplayMode(targetDisplayMode);
Display.setFullscreen(fullscreen);
} catch (LWJGLException e) {
System.out.println("Unable to setup mode "+width+"x"+height+" fullscreen="+fullscreen + e);
}
}
Vsync 垂直同步
为了自由分割图形,需要开启垂直同步。用Display.setVSyncEnabled(boolean)来开启或禁用此功能。垂直同步仅在全屏时工作,因为窗口程度是没有直接权限访问或控制整个屏幕的,所有的缓冲区交换都是由操作系统处理的。但是在窗口模式下,垂直同步仍然可以用来限制帧率。
一个完整的例子如下。用F键切换全屏/窗口,用V键开启或禁用简直同步。
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 FullscreenExample {
/** 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;
/** is VSync Enabled */
boolean vsync;
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;
while (Keyboard.next()) {
if (Keyboard.getEventKeyState()) {
if (Keyboard.getEventKey() == Keyboard.KEY_F) {
setDisplayMode(800, 600, !Display.isFullscreen());
}
else if (Keyboard.getEventKey() == Keyboard.KEY_V) {
vsync = !vsync;
Display.setVSyncEnabled(vsync);
}
}
}
// 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
}
/**
* Set the display mode to be used
*
* @param width The width of the display required
* @param height The height of the display required
* @param fullscreen True if we want fullscreen mode
*/
public void setDisplayMode(int width, int height, boolean fullscreen) {
// return if requested DisplayMode is already set
if ((Display.getDisplayMode().getWidth() == width) &&
(Display.getDisplayMode().getHeight() == height) &&
(Display.isFullscreen() == fullscreen)) {
return;
}
try {
DisplayMode targetDisplayMode = null;
if (fullscreen) {
DisplayMode[] modes = Display.getAvailableDisplayModes();
int freq = 0;
for (int i=0;i<modes.length;i++) {
DisplayMode current = modes[i];
if ((current.getWidth() == width) && (current.getHeight() == height)) {
if ((targetDisplayMode == null) || (current.getFrequency() >= freq)) {
if ((targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel())) {
targetDisplayMode = current;
freq = targetDisplayMode.getFrequency();
}
}
// if we've found a match for bpp and frequence against the
// original display mode then it's probably best to go for this one
// since it's most likely compatible with the monitor
if ((current.getBitsPerPixel() == Display.getDesktopDisplayMode().getBitsPerPixel()) &&
(current.getFrequency() == Display.getDesktopDisplayMode().getFrequency())) {
targetDisplayMode = current;
break;
}
}
}
} else {
targetDisplayMode = new DisplayMode(width,height);
}
if (targetDisplayMode == null) {
System.out.println("Failed to find value mode: "+width+"x"+height+" fs="+fullscreen);
return;
}
Display.setDisplayMode(targetDisplayMode);
Display.setFullscreen(fullscreen);
} catch (LWJGLException e) {
System.out.println("Unable to setup mode "+width+"x"+height+" fullscreen="+fullscreen + e);
}
}
/**
* 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) {
FullscreenExample fullscreenExample = new FullscreenExample();
fullscreenExample.start();
}
}