LWJGL Forum

Programming => Lightweight Java Gaming Library => Topic started by: Izman on October 16, 2012, 03:06:00

Title: Lag when scrolling backgrounds/moving
Post by: Izman on October 16, 2012, 03:06:00
Hey all, this is my first post on the LWJGL forums.

So a few months ago I started a little 2D platforming project with a couple friends.  I've taken a course in Java and I have a small background with C++, but generally I'm a "beginner"

Here's my setup so far:

I'm using SlickUtil + LWJGL 2.8.4, drawing a 800x600 window with a 1920x1080 background and equivalently long floor and ceiling sprites with a couple platforms.  When the player moves past a certain point in the centre of the screen, movement is taken from the player and instead I move the 1920x1080 background (of course, there are specific cases when the player reaches the end of the map).

However, occasionally I'm noticing lag while moving the background.  When the player starts to trigger the background-moving logic, the screen starts to stutter (70% of the time).  Even when the screen isn't moving, occasionally the player starts to lag (~10% of the time). This is all while setting the Display.sync(60).

However, I figured out a solution: setting Display.sync() to really large values (~700) makes the game run completely smooth.  Now, obviously having a 700-fps requirement for a 2D game is nothing short of ridiculous, which brings me here.

Am I going about scrolling completely wrong?  Is this a problem with my movement algorithms? Display.sync()? Sprite data type?  Some direction would be nice before I start ripping my code apart :)
Title: Re: Lag when scrolling backgrounds/moving
Post by: kappa on October 16, 2012, 09:19:09
It could be a number of thing, ranging from simple screen tearing to garbage collection, try  Display.setVSyncEnabled(boolean) to enable vertical synchronization instead of Display.sync().
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on October 16, 2012, 17:51:34
Thanks for the reply :)

I tried disabling Display.sync() and put Display.setVSyncEnabled() in my initializer, but it made the game dramatically choppy (both Display.sync() and VSync() capped the frames at 60) :(

I was also looking up a lot on Garbage collection, and even used the JVM arguments to change the garbage collection method, but it changed nothing.  AFAIK, I shouldn't be creating much garbage aside from maybe loading the areas, and I explicitly call System.gc() after.

This is an insert of my Sprite class:

public Sprite(String filename, float x, float y)
{
try
{
texture = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("game/" + filename));
   
}
catch (IOException e)
{
e.printStackTrace();
}

this.x = x;
this.y = y;
flip = false;

                textureX = (float)texture.getImageWidth()/texture.getTextureWidth();
textureY = (float)texture.getImageHeight()/texture.getTextureHeight();
}
public void draw()
{
GL11.glPushMatrix();
texture.bind();

if(flip)
{
GL11.glTranslatef(x, y, 0);
GL11.glRotatef(180,0,1,0);
}
else
{
GL11.glTranslatef(x, y, 0);
}

GL11.glBegin(GL11.GL_QUADS);
{
GL11.glTexCoord2f(0,0);
GL11.glVertex2f(0,0);
GL11.glTexCoord2f(textureX,0);
GL11.glVertex2f(texture.getImageWidth(),0);
GL11.glTexCoord2f(textureX,textureY);
GL11.glVertex2f(texture.getImageWidth(),texture.getImageHeight());
GL11.glTexCoord2f(0,textureY);
GL11.glVertex2f(0,texture.getImageHeight());
}
GL11.glEnd();

GL11.glPopMatrix();
}


This is the correct method for drawing 2D sprites, right?
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on October 31, 2012, 04:49:30
Okay so with a bit of playing around:

Exporting the game as a runnable Jar and running it eliminated 90% of the lag.

There still exists a bit of lag, but it's muuucchh better.

As well,  I set up my project on a Mac OSX Lion machine and, with using Java 6 (Apple) and Vertical Sync, there is absolutely 0 lag.

Here are the 2 machines:

Mac Mini:  OSX Mountain Lion, Intel Core 2 Duo 2.2GHz, NVIDIA 9400M, 4GB 1033(?)MHz DDR3:  Vertical Sync on, Java 6 Update 37
PC Tower:  Windows 7 Home Premium 64 bit, AMD Phenom II x4 955, AMD HD 6850, 8GB 1333MHz DDR3:  Display.sync(60), Java 7 Update 7

* Note: I tried JRE 6 Update 35 & Vertical Sync on the PC machine

Any ideas why my less powerful Mac runs this flawlessly?

EDIT:  Summary of my tests:

Windows 7:

Java 6 or 7 is pretty much the same
Vertical Sync makes the game look laggy as hell
Display.sync() to my monitors refresh rate has small lags, but is way better than vertical sync. Increasing value to insanely large values fixes all lag.

Mac:

Java 6
Display.sync() to monitors refresh rate has screen tearing
Vertical Sync yields flawless gameplay

Both are on exported jars, rendering 8 sprites in Immediate mode, 4 of which are the map (800x600, 2000x600, 2000x150, 2000x150), A player (40x80), and 3 platforms (150x50, 150x50, 150x50).
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 01, 2012, 12:38:37
hi izman,
Do you print on the system.out while running the executable ?
There may be sync issue if multiple threads print out to the jvm. however if, e.g. with windows, you run with the JavaW.exe , then the jvm does not log the system.out console, so it should explain why it's much faster.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 02, 2012, 04:37:52
Quote from: broumbroum on November 01, 2012, 12:38:37
hi izman,
Do you print on the system.out while running the executable ?
There may be sync issue if multiple threads print out to the jvm. however if, e.g. with windows, you run with the JavaW.exe , then the jvm does not log the system.out console, so it should explain why it's much faster.


Hi broum,

Aside from Slick-Util creating some output at the beginning of the program, I don't output anything.

If it makes a difference, I'm compiling in Eclipse on a version I downloaded a couple months ago.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 08, 2012, 06:14:20
Yet another update...

All Windows machines run perfect in Full Screen Mode + Vertical sync (same performance as MacOSX Windowed/Full Screen Mode Vertical Sync).

However, in windowed mode, the Windows machines run like crap (vertical sync) and less crap (Display.sync(125)) and perfect (Display.sync(999)).

Here's a summary of my tests:

Machine 1: Windows 7 Home Premium, Intel i7 3.4GHz, AMD HD Radeon 6870, 8GB RAM
Machine 2: Windows 7 Home Premium, AMD Phenom II x4 3.2GHz, AMD HD Radeon 6850, 8GB RAM
Machine 3: Mac OSX Lion, Intel Duo Core 2.2GHz, NVIDIA 9400M, 4GB RAM
Laptop 1: Windows 7 Home Premium, Intel Processor, AMD Card (Friend's Laptop, mid-low range)

Windowed Mode & Vertical Sync:  M1 and M2 lag, M3 and L1 look playable/perfect
Windowed Mode & 125 FPS Cap: M1, M2, L1 look playable (some lag), M3 Screen tearing

Fullscreen Mode & Vertical Sync: M1, M2, M3, L1 perfect
Fullscreen Mode & 125 FPS Cap: M1, M3 Screen Tearing, M2 & L1 untested

Something to note is that high-end cards perform horribly with Vertical Sync windowed mode.  Most notably, they are from the 6800 series.
Mid-low range cards seem to handle it fine.

Could this be because Immediate Mode is not supported in newer versions of OpenGL?
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 08, 2012, 07:37:00
This may be related to buffer unsync'ed updates. Theres an option in the catalyst driver windows panel : right click on the tray icon in windows task bar and select your video card, opengl , triple buffering. Set it on, if necessary.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 08, 2012, 08:42:50
Quote from: broumbroum on November 08, 2012, 07:37:00
This may be related to buffer unsync'ed updates. Theres an option in the catalyst driver windows panel : right click on the tray icon in windows task bar and select your video card, opengl , triple buffering. Set it on, if necessary.


Thanks for the suggestion :)

Sadly, Triple Buffering has no effect on the issue.

Something to note is that the lag feel "jerky", like all the updating is happening in bursts (imagine a delta going from 16/17 to 40 every second), but delta is staying uniform...
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 08, 2012, 17:28:41
Ok, I experience the same issue in my test project while I use a secondary thread to load stuff. It has no sync with the rendering gl thread, which causes this pause-then-burst effect on screen. Whenever the loading task finishes everything is fluent.
We should have a look at your rendering loop.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 08, 2012, 17:37:34
Quote from: broumbroum on November 08, 2012, 17:28:41
Ok, I experience the same issue in my test project while I use a secondary thread to load stuff. It has no sync with the rendering gl thread, which causes this pause-then-burst effect on screen. Whenever the loading task finishes everything is fluent.
We should have a look at your rendering loop.

Sure thing,

        private void gameLoop()
{
while(gameState != 0 && !Display.isCloseRequested())
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();

delta = getTime() - lastLoopTime;
lastLoopTime = getTime();
lastFpsTime += delta;
fps++;

if(lastFpsTime >= 1000)
{
Display.setTitle(WINDOW_TITLE + " (FPS: " + fps + ")");
lastFpsTime = 0;
fps = 0;
}

applyControls(); //Take input from keyboard
SoundStore.get().poll(0); //Sound storage

if(gameState == 3) //gameState is equal to 3 when the game is out of the main menu
{
capDelta(); //if Delta is over 18 (aka, sub 60FPS), set to 17
moveEntities(); //Move the entities
logic(); //Displace entities based on collision and logic
}

render(); //Draw entities

Display.update();
Display.sync(125);
}
Display.destroy();
AL.destroy();
System.exit(0);
}
private void render()
{
if(gameState == 1)
{
menu.draw();
}
else if(gameState == 3)
{
map.draw();
player[0].draw();
player[1].draw();
}
}


The actual draw methods are inefficient (take a look at my Sprite class above to see), but for ~6 textures it shouldn't make a huge deal.
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 08, 2012, 17:41:58
What the applyControis() looks like? Does it poll last events ?
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 08, 2012, 22:35:14
Quote from: broumbroum on November 08, 2012, 17:41:58
What the applyControis() looks like? Does it poll last events ?

It just grabs input from the keyboard (pretty much straight out of the example on the LWJGL Wiki)

        private void applyControls()
{
if(gameState == 1)
{
applyMenuControls();
}
else if(gameState == 3)
{
applyGameControls();
}
}
        while (Keyboard.next())
{
if(Keyboard.getEventKeyState()) //KEY PRESSED
{
//PLAYER 1
if (Keyboard.getEventKey() == control[0][0])
{
player[0].setMove(1);
}
if (Keyboard.getEventKey() == control[1][0])
{
player[0].setMove(2);
}
if (Keyboard.getEventKey() == control[2][0])
{
player[0].setMove(3);
}
if (Keyboard.getEventKey() == control[3][0])
{
player[0].setMove(4);
}
//PLAYER 2
if (Keyboard.getEventKey() == control[0][1])
{
player[1].setMove(1);
}
if (Keyboard.getEventKey() == control[1][1])
{
player[1].setMove(2);
}
if (Keyboard.getEventKey() == control[2][1])
{
player[1].setMove(3);
}
if (Keyboard.getEventKey() == control[3][1])
{
player[1].setMove(4);
}
                                ....


the .setMove(int) method flags a boolean in Player, which then moves the entities in the gameloop.
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 09, 2012, 07:48:22
Hi
By watching at your code, it turns out that the window status is updated every frame by Display.setTitle() which might update and wait for the Window ToolKit sync. Try to not access any of the awt member functions within the gameloop thread.
As you mentioned, applyControls() does flag boolean's'which is the _correct manner.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 09, 2012, 15:48:54
Quote from: broumbroum on November 09, 2012, 07:48:22
Hi
By watching at your code, it turns out that the window status is updated every frame by Display.setTitle() which might update and wait for the Window ToolKit sync. Try to not access any of the awt member functions within the gameloop thread.
As you mentioned, applyControls() does flag boolean's'which is the _correct manner.

Okay, thanks a ton :)

The only awt class I'm importing (and using) is

import java.awt.Rectangle;

and I make calls every gameloop to .intersects(Rectangle) I guess it's worth a try to disable it.

Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 10, 2012, 09:48:04
Sorry, just re-read your answer and I think I understand it now.

I'm going to be busy for a little bit, so I'll report back with the results in a bit.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 13, 2012, 04:06:18
Okay, so initially I thought it was a refresh rate issue, because the monitor on the Mac could handle 75Hz and, when using 75Hz and setting the game to 60Hz (via DisplayMode), it would recreate the issue I'm facing on my Windows machines.  However, after properly implementing refresh rate selections, I can't seem to recreate the issue.

I also removed the setTitle() from the game loop, it didn't really do much.

Quote from: broumbroum on November 09, 2012, 07:48:22
Try to not access any of the awt member functions within the gameloop thread.

What exactly is meant by this?  The awt classes I'm using are:

awt Font (for slick-util)
awt Rectangle (for collision detection via .intersects())

Do these really have a great effect on the performance?  I can probably find work arounds for these, but there's no point if I can't notice a difference.
Title: Re: Lag when scrolling backgrounds/moving
Post by: broumbroum on November 13, 2012, 07:57:12
Good to know you sorted it out!
Further more about the awt member function I'm pointing out, they involve the event dispatcher thred EDT. Each awt function that modifies the UI or looknfeel must but don't everytime need to synchronize with it. E.g. On Windows its the AWT-Windows thread that can make the UI update. Look for EDT across the forum, I should have found more about.
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 13, 2012, 10:15:47
Quote from: broumbroum on November 13, 2012, 07:57:12
Good to know you sorted it out!

Sorry, I probably wasn't clear.  Windows still performs like ass with windowed vertical sync :( I was mostly talking about my Mac in the post above.

Quote from: broumbroum on November 13, 2012, 07:57:12
Further more about the awt member function I'm pointing out, they involve the event dispatcher thred EDT. Each awt function that modifies the UI or looknfeel must but don't everytime need to synchronize with it. E.g. On Windows its the AWT-Windows thread that can make the UI update. Look for EDT across the forum, I should have found more about.

Okay, thanks for the information :)

--

Recap:

I feel like this is an issue with refresh rates.  When the Windows machine runs the game in fullscreen + vsync, it's a solid 57 FPS (which seems strange), but it doesn't lag at all.  In windowed mode however, lag exists at the lower framerates (60ish) but diminishes exponentially as Display.sync() is increased.  60 FPS by Vertical Sync "lags" noticeably more than 60 FPS by Sync().

I'll start removing AWT classes in general, but until then, any ideas?
Title: Re: Lag when scrolling backgrounds/moving
Post by: Izman on November 18, 2012, 01:59:40
Funny enough, I installed a Windows XP bootcamp on the Mac with the NVIDIA 9400M, and it ran perfectly with vertical sync...

Looks like the issue might lie with Windows 7/HD 6850...