I'm writing a 2D platformer game on Java with LWJGL. I'm doing this just for the sake of learning and not the result itself, so when I decided to implement scrolling I did it two ways I could invent myself:

  • Three "sky" rectangle entities that located in a row and when my camera is moved to the right (fully on third), I move my first rectangle (from the far left) to the far right, etc. Pretty sure it can be made that way only with two entities, but I didn't have enough motivation to do it right now.
  • Not infinite, but you can just stack these Sky entities in a row for the whole level width. Very lame approach.

But I realised that to optimize it, I can move not the "canvas", but the "painting" on the "canvas" itself. So, is it possible to move it this way? I'm not entirely sure that's possible at all, but I think it should be. How I see it: I change not position.x or position.y, but the texture coordinates, they should repeat, aren't they?

My code, if that will be helpful anyway. Render function in Main class:

private void render() {
        GL11.glTranslatef(-Camera.x, -Camera.y, 0.0f);
        GL11.glScissor(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);

Draw function of the Sky entity, and yes, I know that immediate mode is bad, but I still haven't got my hands on arrays and other drawing methods.

public void draw() {
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, TextureWrapper.get(EntityTypes.SKY).getTextureID());
    GL11.glColor3f(1.0f, 1.0f, 1.0f);
        GL11.glTexCoord2f(0.0f, 1);
        GL11.glVertex2f(this.x, this.y + this.height);

        GL11.glTexCoord2f(1, 1);
        GL11.glVertex2f(this.x + this.width, this.y + this.height);

        GL11.glTexCoord2f(1, 0);
        GL11.glVertex2f(this.x + this.width, this.y);

        GL11.glTexCoord2f(0.0f, 0);
        GL11.glVertex2f(this.x, this.y);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, 0);
  • \$\begingroup\$ "Skybox" implies 3D, but you say you're working on a 2D game. Maybe this is a terminology thing. Have you seen this question? \$\endgroup\$ – Anko May 27 '13 at 11:13
  • \$\begingroup\$ You are right, it's just "background", thank you. I've seen that question, but that's not helpful, it describes how I've made my current infinite scrolling implementation. \$\endgroup\$ – the-lay May 27 '13 at 11:35

It's even easier to do if your sky is bigger than what's shown on screen and it's continuous/repetitive:

  • Always draw your quad with coordinates filling the whole screen.
  • Adjust texture coordinates based on the camera's actual position.
  • Set the texture clamping to repeat the texture.

As an alternative (especially if you're not using your whole texture), you can move the quad on screen as you did already with some minor modifications:

  • Draw the background twice in every dimension the camera might be moving (2 copies for horizontal movement; 4 for diagonal/horizontal+vertical movement).
  • Use a modulo operation to clamp the offset/repetition to screen space (e.g. when the left background quad leaves the left screen on the left, it replaces the former right quad; which itself is moved back to the right).
  • \$\begingroup\$ First alternative is pretty much how I have it done right now. Second alternative look like not optimal way to do it, maybe I just didn't get it right... \$\endgroup\$ – the-lay May 27 '13 at 11:38
  • \$\begingroup\$ And about the main answer: can you please elaborate on second and third point: "Adjust texture coordinates based on the camera's actual position." and "Set the texture clamping to repeat the texture." \$\endgroup\$ – the-lay May 27 '13 at 11:39
  • \$\begingroup\$ You can define OpenGL's behavior on what happens with texture coordinates being outside the 0..1 range. For example, using texture coordinates from 0 to 2 would repeat the texture (showing it twice) or just drawing it over half width, with the second half being stretched/unicolored (based on settings; read up on texture parameters GL_TEXTURE_WRAP_S and GL_TEXTURE_WRAP_T). E.g. to move the background a bit to the right, you'd use texture coordinates 0.25 and 1.25 rather than 0 and 1. \$\endgroup\$ – Mario May 27 '13 at 12:26
  • \$\begingroup\$ Sorry, still didn't get my hands on this, but don't think I've forgotten! :) \$\endgroup\$ – the-lay May 28 '13 at 10:29
  • 1
    \$\begingroup\$ There's no time limit attached. Take all the time you need, then reply (or don't). Plus, just noticed a small mistake above: Using my oordinates, the background would be offset to the left, not the right. \$\endgroup\$ – Mario May 28 '13 at 10:30

Not the answer you're looking for? Browse other questions tagged or ask your own question.