I converted my game engine’s code from Java2D to Slick and LWJGL completely, and it seems to be working about 70% correctly but with a few things I’m trying to work out. Namely, I’m having a huge amount of flickering when rendering anything to the screen.
Everything I’m rendering is a Slick2D Image, though it’s being rendered to an LWJGL Display context. The reason for this is I converted my code first to LWJGL then realized there were things in Slick I wanted, so I converted all of the Image code and the like to Slick’s code, as well as Slick’s Animations, SpriteSheets, etc. while retaining the LWJGL Display, figuring since Slick is essentially based on LWJGL, they would still work together.
The point of the question is: is there a particular issue with rendering Slick Images to an LWJGL Display window? I have been trying to figure it out for myself but to no avail yet. I would greatly appreciate the help! If any code is necessary, I will be happy to post it, but it seems to me like others more experienced with the libraries would probably find this question easy to answer regardless of such. Thanks!
better not to mix LWJGL and Slick2D code unless you really know what’s going on under the hood of Slick2D. If you are using Slick2D, better to drop all the LWJGL code and use just the Slick2D API’s.
While it’s true Slick was never designed to be used alongside low-level GL calls, it’s entirely possible to do so granted you take care of a few things.
If you’re comfortable with OpenGL, I’d personally suggest rolling your own sprite renderer, as it may lead to better performance (i.e. using VBOs instead of immediate mode) and more reliability.
Show us your rendering code – there’s not much we can do without it.
I believe you’re manually calling Display.update(), right? Slick2D also calls that, most likely resulting in every other screen being black = flickering. Let Slick2D handle the buffer swapping or drop Slick2D altogether.
I was thinking along the same lines, only because I didn’t realize just how many tools Slick has that I was programming myself before and which are done more efficiently since it interfaces with OpenGL rather than Java’s graphics libraries.
To be honest, I’m not terribly comfortable with OpenGL just yet (been doing some reading and tutorials and such, which has been helping but only scratching the surface). I will post my rendering code below. :]
As theagentd described, it looks exactly as if every other frame is black, so there is a constant flicker on the screen.
You’re right, I am, and so I got rid of the Display.update() call in my game loop and it ended up crashing the game and giving me only a black screen, unfortunately. I was probably supposed to do something else as well, wasn’t I?
Here’s the relevant rendering code:
This is the core game loop.
public void gameLoop()
{
long startTime = System.currentTimeMillis();
long currTime = startTime;
// initialization code OpenGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Display.getWidth(), Display.getHeight(), 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
while (isRunning)
{
long elapsedTime =
System.currentTimeMillis() - currTime;
currTime += elapsedTime;
glClear(GL_COLOR_BUFFER_BIT);
// update
update(elapsedTime);
// draw the screen
draw();
while (!Display.isCloseRequested())
{
Display.update();
// sync the Display so it maintains 60 frames per second
Display.sync(60);
}
isRunning = false;
}
Display.destroy();
System.exit(0);
}
This method is the core draw method.
public void draw()
{
player = (Player)map.getPlayer();
renderer.draw(map, Display.getWidth(), Display.getHeight());
guiManager.draw();
if (inventoryOpen)
{
guiManager.renderInventory();
}
if (chestOpen)
{
guiManager.renderChest(currentChest);
}
}
This is the renderer’s draw method, which is called from the core draw method, just as an example.
public void draw(TileMap map, int screenWidth, int screenHeight)
{
Sprite player = map.getPlayer();
int mapWidth = tilesToPixels(map.getWidth());
int mapHeight = tilesToPixels(map.getHeight());
// get the scrolling position of the map
// based on player's position
int offsetX = screenWidth / 2 -
Math.round(player.getX()) - TILE_SIZE;
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, screenWidth - mapWidth);
// get the y offset to draw all sprites and tiles
int offsetY = screenHeight / 2 -
Math.round(player.getY()) - TILE_SIZE;
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, screenHeight - mapHeight);
/*int offsetY = screenHeight -
tilesToPixels(map.getHeight()); */
// draw parallax background image
int bx = offsetX *
(screenWidth - background.getWidth()) /
(screenWidth - mapWidth);
int by = screenHeight - background.getHeight();
background.draw(bx, by);
// draw the visible tiles
int firstTileX = pixelsToTiles(-offsetX);
int lastTileX = firstTileX +
pixelsToTiles(screenWidth) + 1;
int firstTileY = pixelsToTiles(-offsetY);
int lastTileY = firstTileY + pixelsToTiles(screenHeight) + 1;
for (int y = firstTileY; y < lastTileY; y++)
{
for (int x = firstTileX; x <= lastTileX; x++)
{
Image imageF = map.getTileF(x, y);
Image imageB = map.getTileB(x, y);
// draw background tiles
if (imageB != null)
{
imageB.draw(tilesToPixels(x) + offsetX, tilesToPixels(y) + offsetY);
}
// draw foreground tiles
if (imageF != null)
{
imageF.draw(tilesToPixels(x) + offsetX, tilesToPixels(y) + offsetY);
}
}
}
// draw player
player.draw(Math.round(player.getX() + offsetX), Math.round(player.getY()) + offsetY);
// draw sprites
Iterator i = map.getSprites();
while (i.hasNext())
{
Sprite sprite = (Sprite)i.next();
int x = Math.round(sprite.getX()) + offsetX;
int y = Math.round(sprite.getY()) + offsetY;
sprite.draw(x, y);
// wake up the creature when it's on screen
if (sprite instanceof Creature &&
x >= 0 && x < screenWidth)
{
((Creature)sprite).wakeUp();
}
}
}
Thanks for all the help, everyone! I’m really liking Slick and LWJGL at this point and I don’t mind dropping LWJGL if I have to, considering Slick is basically an extended version of it; the features the library offers is a breath of fresh air after studying how engines work and how to program all my own stuff for 2 years. lol
It’s flickering because you are alternating between the front buffer and the back buffer, since you only draw once.
Display.update() and Display.sync(60) are supposed to be called once after updating and rendering on the screen. Display.isCloseRequested() returns true only when the window X button is pressed. This means that your while loop runs infinitely until you close the screen.
Wow, I’m surprised I didn’t see that before. I think that came about because I added in the update, draw, and other stuff after I replaced my old loop with the new one when converting the code. Thanks so much, ra4king! Workin beautifully!