• Advertisement
Sign in to follow this  

Scaling game to different resolutions (LWJGL)

This topic is 2070 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have made a pong clone in java using the LWJGL game library. I am not sure how to make it so the game plays the same way in different resolutions. It is kind of hard to explain. I made the game based on a 1920x1080 resolution. When I change the resolution the paddle and ball and everything remains the same size in pixels. So in a lower resolution you are playing in an extremely small space and the paddles and the ball are huge. This is the code that I use to set up the display and stuff:

From main class:
[CODE]
package com.gmail.l5p4ngl312.pong;
import java.awt.Dimension;
import java.awt.Toolkit;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
public class main {
static boolean running = true;
int fps;
long lastFPS;
int currentDelta;
static long lastFrame;
public void start()
{
game game = new game();

Toolkit toolkit = Toolkit.getDefaultToolkit();
Dimension screensize = toolkit.getScreenSize();

System.out.println(screensize);
game.xRes = (int) screensize.getWidth();
game.yRes = (int) screensize.getHeight();

try {
setDisplayMode(game.xRes, game.yRes, false);
Display.create();
Display.setVSyncEnabled(true);
} catch (LWJGLException e) {
e.printStackTrace();
System.exit(0);
}
game.OnInit();
this.lastFPS = getTime();
while ((!Display.isCloseRequested()) && (running))
{
currentDelta = getDelta();
game.OnEvent(currentDelta);
game.OnUpdate(currentDelta);
updateFPS();
game.OnRender();
Display.update();
Display.sync(120);
}
Display.destroy();
}
public void setDisplayMode(int width, int height, boolean fullscreen)
{
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)) && (
(targetDisplayMode == null) || (current.getBitsPerPixel() > targetDisplayMode.getBitsPerPixel()))) {
targetDisplayMode = current;
freq = targetDisplayMode.getFrequency();
}
if ((current.getBitsPerPixel() != Display.getDesktopDisplayMode().getBitsPerPixel()) ||
(current.getFrequency() != Display.getDesktopDisplayMode().getFrequency())) continue;
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);
}
}
public static long getTime()
{
return Sys.getTime() * 1000L / Sys.getTimerResolution();
}
public void updateFPS()
{
if (getTime() - this.lastFPS > 1000L) {
this.fps = 0;
this.lastFPS += 1000L;
}
this.fps += 1;
}

public static int getDelta()
{
long time = getTime();
int delta = (int)(time - lastFrame);
lastFrame = time;
return delta;
}
public static void main(String[] argv)
{
main display = new main();
display.start();
}

}
[/CODE]


From game class:
[CODE]
package com.gmail.l5p4ngl312.pong;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.util.Stack;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.GL11;
public class game
{
static Stack<stateManager> stateStack = new Stack();
String TITLE = "Pong";
static int xRes = 0;
static int yRes = 0;
public static boolean lmbPressed;
public static boolean rmbPressed;
public void OnInit()
{

Display.setTitle(this.TITLE);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
GL11.glEnable(GL11.GL_BLEND);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA , GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glLoadIdentity();
GL11.glViewport(0, 0, xRes, yRes);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glOrtho(0.0D, xRes, 0.0D, yRes, 1.0D, -1.0D);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
textures.LoadTextures();
ChangeState(stateMenu.Instance());
}
public void OnEvent(int delta)
{
if (Mouse.isButtonDown(0))
{
lmbPressed = true;
}
else lmbPressed = false;
if (Mouse.isButtonDown(1))
{
rmbPressed = true;
}
else rmbPressed = false;
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).OnEvent(delta);
}
}
public void OnUpdate(int delta)
{
if ((!stateStack.empty()) && (!((stateManager)stateStack.peek()).Paused))
{
((stateManager)stateStack.peek()).OnUpdate(delta);
}
}
public static void OnRender()
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT);
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).OnRender();
}
}
public static void OnCleanup()
{
while (!stateStack.empty())
{
((stateManager)stateStack.peek()).OnCleanup();
stateStack.pop();
}
main.running = false;
}
public static void ChangeState(stateManager state) {
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).OnCleanup();
stateStack.pop();
}
stateStack.push(state);
((stateManager)stateStack.peek()).OnInit();
}
public static void PopState()
{
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).OnCleanup();
stateStack.pop();
}
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).Resume();
}
}
public static void PushState(stateManager state)
{
if (!stateStack.empty())
{
((stateManager)stateStack.peek()).Pause();
}
stateStack.push(state);
((stateManager)stateStack.peek()).OnInit();
}
}
[/CODE] Edited by Lane Spangler

Share this post


Link to post
Share on other sites
Advertisement
It's been a while since I played with OpenGL, so take this with a grain of salt, but glOrtho doesn't require you to use the actual resolution of the screen.

That is, your call
[CODE]
GL11.glOrtho(0.0D, xRes, 0.0D, yRes, 1.0D, -1.0D);
[/CODE]
could be replaced with, for instance
[CODE]
GL11.glOrtho(0.0D, 1920.0D, 0.0D, 1080.0D, 1.0D, -1.0D);
[/CODE]

which ought to solve your problem.

Share this post


Link to post
Share on other sites
I thought this as well. When I do that it does achieve the desired effect except the game no longer fits the game window. For example, in a 1024x576 window using

[color=#000000]GL11[/color][color=#666600].[/color][color=#000000]glOrtho[/color][color=#666600]([/color][color=#006666]0.0D[/color][color=#666600],[/color][color=#000000] [/color][color=#006666]1920.0D[/color][color=#666600],[/color][color=#000000] [/color][color=#006666]0.0D[/color][color=#666600],[/color][color=#000000] [/color][color=#006666]1080.0D[/color][color=#666600],[/color][color=#000000] [/color][color=#006666]1.0D[/color][color=#666600],[/color][color=#000000] [/color][color=#666600]-[/color][color=#006666]1.0D[/color][color=#666600]);[/color]
The game is fit to roughly the bottom left corner of the window. It seems to have scaled correctly at least.

Share this post


Link to post
Share on other sites
Ok, I fixed it. The issue was that I was using the current resolution to position game objects instead of the 1920x1080 resolution. So for example I would do
[CODE]
Paddle P1 = new Paddle(0, Display.getDisplayMode().getHeight()/2);
[/CODE]
\
When I should be doing
[CODE]
Paddle P1 = new Paddle(0, 540);
[/CODE]

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement