2
\$\begingroup\$

What I have at the moment is a series of data structures I'm using, and I would like to render the world onto the screen (just the visible parts).

I've actually already done this several times (lots of rewrites), but it's a bit buggy (rounding seems to make the screen jump ever so slightly every x tiles the player walks past).

Basically I've been confusing myself heavily on what I feel should be a pretty simple problem... so here I am asking for some help!

OK! So I have a 50x50 array holding the tiles of the world. I have the player position as 2 floats, x ([0, 49]) and y ([0, 49]) in that array. I have the application size exactly in pixels (x and y). I have an arbitrary TILE_SIZE static int (based on screen pixels).

What I think is heavily confusing me is using a 2d orthogonal projection in opengl which maps (0,0) to the top left of the screen and (SCREEN_SIZE_X, SCREEN_SIZE_Y) to the bottom right of the screen.

    gl.glMatrixMode(GL.GL_PROJECTION);
    gl.glLoadIdentity();

    glu.gluOrtho2D(0, getActualWidth(), getActualHeight(), 0);

    gl.glMatrixMode(GL.GL_MODELVIEW);
    gl.glLoadIdentity();

The map tiles are set so that the (0,0) in the array is the bottom left.

And the player has to be in the middle on the screen (SCREEN_SIZE_X/2, SCREEN_SIZE_Y/2).

What I've been doing so far is trying to render 1-2 tiles more all around what would be displayed on the screen so that I don't have to worry about figuring out rendering half a tile from the top left, depending where the player is.

It seems like such an easy problem but after spending about 40+hours on it rewriting it many times I think I'm at a point where I just can't think clearly anymore...

Any help would be appreciated. It would be great if someone can provide some very basic pseudo code on keeping the player in the middle when your projection is mapped to screen coordinates and only rendering basically the tiles that you would be any be see.

Thanks!

\$\endgroup\$
2
  • \$\begingroup\$ What is the actual problem here? Finding out what tile needs to be rendered and what tile doesn't? Or that the screen coordinates don't fit what you predicted? \$\endgroup\$
    – Nitram
    Apr 5, 2012 at 7:21
  • \$\begingroup\$ Each problem doesn't seem to be hard, but when I tried to put it all together, it gets confusing. I feel as if there should be a clean loop that can get everything rendering correctly. At the moment I've got a mountain of a mess in my code, the logic seems like it's taking the long way around and it doesn't work 100% (as the player walks past every 1 or 2 tiles, the whole screen jumps very slightly). \$\endgroup\$
    – Mick
    Apr 5, 2012 at 9:18

1 Answer 1

1
\$\begingroup\$

If I understand you correctly then I think the easiest way to solve this is to render the map always at the same coordinates.

So the render coordinates for the tiles would be something like: (x * TileWidth ; y * TileHeight). The location of the character is calculated just the same way. Now for the moving part you should translate of the OpenGL coordinates using glTranslatef. Using this function is you shift the origin location out of your screen. The values for the translate function would be something like: (playerPos.x * TileWidth - SCREEN_WIDTH/2; (playerPos.y * TileHeight - SCREEN_HEIGHT/2). You might have to alter the calculate by inverting the height by adding SCREEN_HEIGHT - (...). But I hope you get the general idea.

Now as for the problem that the screen coordinate are inverted compared to what you expected. You can fix this problem simply by using glScale. Using -1 as second parameter will invert the Y coordinate of all subsequent OpenGL calls. That should help you turning the coordinates as you need it.

And finally in detect if the tiles are on the screen and need to be rendered or not you can get use your render coordinates of your player character (playerPos.x * TileWidth; playerPos.y - TileHeight) and check if the location of the tile is within SCREEN_WIDTH/2 + TileWidth and SCREEN_HEIGHT/2 + TileHeight around your player location. If not you don't need to render the tile.

\$\endgroup\$
6
  • \$\begingroup\$ Thanks Nitram, I think I've understood all of it, but just to confirm (since I'm bound to get lost again the moment I try this): so when you say always render the map at the same coordinates, do you mean (for example), always have the bottom left of the map rendered to (0,0) on the screen, and iterate across the array like that? then for each step of the iteration do what you said in the last paragraph by checking if you actually have to render that square (is it within SCREEN_SIZE/2 of the player location), then lastly translating to the player location? \$\endgroup\$
    – Mick
    Apr 5, 2012 at 11:24
  • 1
    \$\begingroup\$ The first step, before all rendering operations is to translate the current OpenGL location offset so the position of the player is in the center of the screen. You keep this offset active during all render operations of the current render loop. After this you render the map. And say tile (0,0) you render at the openGL coordinates 0, 0. Tile (1,0) at TileWidth, 0. The location where the tile is actually rendered on the screen is effected by the initial translate call. \$\endgroup\$
    – Nitram
    Apr 5, 2012 at 12:28
  • \$\begingroup\$ Thanks Nitram! Not sure why this is so confusing for me... so after the initial translate (playerXTILE_WIDTH-SCREEN_WIDTH/2, playerYTILE_WIDTH-SCREEN_HEIGHT/2), this would put the opengl (0,0) coordinate to the bottom left of the screen with the player in the middle, correct? I guess this is the part that confuses me. If that is the case, if you render the bottom left of the map (0,0), at that location, wouldn't the bottom left of the screen always be the bottom left of the map? I really appreciate your replies, but as you can see, I'm pretty lost at the moment... \$\endgroup\$
    – Mick
    Apr 5, 2012 at 12:50
  • 1
    \$\begingroup\$ The initial translate is used to ensure that the location of the player is in the center of the screen. As a result the OpenGL location (0,0) is likely to be not at the bottom left of the screen. For example in case you character is at the OpenGL coordinate (in pixels) 100x100 but your display screen is only able to display 50 pixels in height and width. Then due the translate operation the corners of the screen will be at (75,75),(125,75),(75,125),(125,125). Due this offset you are still able to render the map origin at (0,0) and still get a consistent offset. \$\endgroup\$
    – Nitram
    Apr 5, 2012 at 13:02
  • \$\begingroup\$ Thanks Nitram! I actually did something very similar to get mine to work initially (though I didn't get why it was working). I'll give it a whirl tomorrow and hopefully everything works out this time! \$\endgroup\$
    – Mick
    Apr 5, 2012 at 13:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .