Scrolling Screen

Sage
Posts: 1,066
Joined: 2004.07
Post: #1
Is there a way to scroll the screen around keeping the player in the center of the screen while using gluOrtho2D? My character has two functions, GetX() and GetY() that return the (x,y) of the center of the quad. Or is there a better view that will be the same looking as gluOrtho2D to do scrolling around?
Quote this message in a reply
Member
Posts: 72
Joined: 2006.10
Post: #2
gluOrtho2D() is a simplification of glOrtho().

If you use glOrtho(), you can define the reference value for each of the 4 edegs of your scene.

Let me clarify,
gluOrtho2D simply assumes that the bottom left corner is 0.0 , 0.0 , and lets you set the value of the top right corner. On the other hand, glOrtho lets you set all 4 values.

You could use that to scroll your scene.

HTH

Edit: erm... Also, a good old glTranslatef() at the start of the drawing function could help too Rasp You got me sidetracked with the gluOrtho2D() here.

- Sohta
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #3
Actually gluOrtho2D allows me to set the top left and bottom right. I have my top left set at (0,0) and my bottom right set to (GAME_WIDTH,GAME_HEIGHT).
Quote this message in a reply
Member
Posts: 72
Joined: 2006.10
Post: #4
Geez you're right Blush , okay! I'm going to bed now, I need it ZZZ

- Sohta
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #5
Now you're entering messy territory.

You need to carefully define what you're trying to do before asking for help with it. So far all we know is that you're making a top-down Zelda-esque game. So, consider what you want:

* scrolling game field fills portion of viewport, with some other stuff (stats etc) that don't scroll?
* scroll vertically? horizontally? diagonally? rotating? scaling? warping? when player leaves edge of screen? continuously?
* one layer? parallax? 3D? 2D? tiles? prerendered art? video? vector outlines? combination of all that?
* player and enemies etc are sprites (textured quads)? 3D models? both?
* kitchen sink?

If you just say "I want to make Zelda, on my Mac" then we have to start making some assumptions like:
* The game will play in a resizable window.
* The game will play fullscreen, on the various aspect ratio displays that Apple sells (5:4, 4:3, 3:2, 16:10) and at various resolutions.
* The game will be 2D tile based, scroll only horizontally or vertically, when the player leaves the edge of the screen.
* There's only one 2D layer of tiles, with some sprites on top of it. Stats above the playfield don't scroll.

Now, those assumptions could be completely wrong for your game, but based on those assumptions, what I'd do is:
* maintain a texture atlas (aka "blockset") of tile graphics.
* maintain a map datastructure hierarchy (overworld->rooms->tiles, plus event/object data)
* render a room as a grid of tiles, onto on offscreen render-to-texture context.
* render the playfield as two big quads from the offscreen texture, then the sprites on top of it.
* render the stats etc on top of the playfield.

Now in your game logic, when the player has moved off the edge of the screen, the scrolling math is really simple:
* screen will scroll the entire width of the playfield, let's say to the right.
* player starts at leftmost tile. will end up at rightmost tile. so he needs to move 1 tile to the left as the screen scrolls over.
* for N frames, scroll the playfield right width/N pixels (see below) and move the player position to the right by width/N - tilewidth/N pixels.

How do you scroll the playfield using an offscreen context texture? I wrote about it a little bit here but to recap, the idea is very simple:
* offscreen texture is "wraparound" playfield. As playfield scrolls right, the only part that's actually changing is the leftmost strip which has just scrolled onto the screen. So just update that strip in the texture from your texture atlas of tile graphics.
* then, draw the entire playfield as two quads, with the offscreen texture; from the left edge of the viewport to the right edge of the offscreen texture, and then from the left edge of the offscreen texture to the right edge of the viewport.

Here is an example I wrote that does everything I just described, using Metroid as the map. You can hit 'v' to see the blockset and the offscreen texture, to get an idea of how it works. Hit 'q' to see the quad outlines that are used to draw the playfield. See the about box for the other keys.

"Why do it like this? Isn't this a lot harder than drawing every tile as a separate quad?"

Yes, it is a bit of extra work. Particularly setting up the offscreen context. But you have to do it this way if you want to resize the viewport without any filtering artifacts between the tiles. Remember, everything in OpenGL is floating point. If you draw two textured quads for tiles next to each other, with two separate textures (or separate portions of a texture atlas), it will only look correct when you have an exact 1:1 texel to pixel match. I.e. you textures are drawn for 640x480 and your viewport is exactly 640x480. As soon as you resize the viewport to 800x600, texture filtering is going to make obvious discontinuities between the tiles.

Here is an example of a game (16 megs, but some nice ideas) that draws the playfield as a bunch of quads. You can see the seams as everything scrolls around.

With the offscreen context in TileScroller, you can resize or do anything else you want to the playfield (rotate for example with the r key) and it looks fine, because it's just one big texture.

OK, enough off-topic babbling.
Quote this message in a reply
Member
Posts: 70
Joined: 2004.06
Post: #6
The way I would do it would be to draw the static objects (ie. player, score text) at the center (or corner, etc) of the screen. Then translate on the x and y axis the amount that the player has scrolled, and draw the world. This would mean that while the sprites would still be drawn at the same coordinates, to the player it would appear that they had moved.

This may have already been said (I haven't read the other posts thoroughly), and it may just be a silly idea full stop. Anyway, you can take it or leave it.
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #7
Does anybody know how to implement a simple scrolling (similar to SNES legend of zelda)? Also how can I overlay some icons for health and such?
Quote this message in a reply
Sage
Posts: 1,066
Joined: 2004.07
Post: #8
Ok sorry about not specifying. The scrolling will be larger than the game screen. The whole "tile" will be roughly three times as wide and three times as tall as the window. There will be a layer of the icons and such, a layer for the interactive sprites (buildings, objects, characters), and a layer for the basic ground.
Quote this message in a reply
Member
Posts: 233
Joined: 2003.05
Post: #9
Here is one relatively simple method.
Keep a big 2D array of all your tiles... keep track of what portion of the tile array you see, a viewport (and an offset in pixels for smooth scrolling.) Hmm...

Here is some crude example code:
Code:
int map[200][200]; //using an integer to identify each tile type or texture or whatever

loadmap("mapfile.map", map); //fills the 2D array with tile ID's or whatever

int x,y; //coordinates of upper left hand side of "viewport" (the part of the map that is visible)

//should check bounds here

screenY = 0 - smoothScrollingYOffset;
for (y = playerPosition.y - halfOfScreenHeightInTiles; y<ViewportHeightInTiles; y++)
{
    screenX = 0 - smoothScrollingXOffset;
    for (x = playerPosition.x - halfOfScreenWidthInTiles; x<ViewportWidthInTiles; x++)
    {
        drawCorrectTile(map[x][y], screenX, screenY); //draw using tileID, screen coordinates
        screenX += tileWidth;
    }
}

drawCorrectTile is just going to use a glTranslate2f(screenX, screenY) call to get to the right place before drawing the tile.

To overlay icons... just draw them afterwards in an absolute position. i.e.
glLoadIdentity();
glTranslate2f(50.0f, 50.0f);
drawHearts();
Smile

"Pay no attention to that man behind the curtain." - Wizard of Oz
Quote this message in a reply
Moderator
Posts: 102
Joined: 2003.07
Post: #10
what I do for BM is I set an array of camera variables like this Camera[2] then at the same time you press the key to make your character move you move the camera by that much too like this
Code:
void moveRight(void)
{
player.pos[0] += 2.0;
Camera[0] += 2.0;
}
.
.
.
//then in your drawing method (e.g. drawframe)

glTranslatef( camera[0], camera[1], 0.0);


keep in mind that this is a very crude example and in BM it takes measures to stop scrolling when the view hits the edge of the map and make sure not to start again until the player is in the middle of the screen... hope that helps Smile

-CarbonX
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #11
using the transform matrix to move your camera is probably optimal and easiest to keep track of in your head while coding. This way you just use global coordinates for all your sprites.

if you're not rotating, you can also do really easy culling...
Keep all your map tiles in a grid. Figure out the extremes of your frustum then just drop/add rows/columns as you scroll. Keep the visible rows and columns in 2 NSRanges. Since you are doing just 2D I doubt you're going to run into fill rate problems. You can probably just draw every tile in a vertex array and still get 100s+fps. (1024x768 display = 32x24 32x32 tiles = 768 quads = feh, ain't nothin.)

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Sage
Posts: 1,232
Joined: 2002.10
Post: #12
Don't overestimate the fillrate of a Rage128 or GF2MX. 768 quads = nothing, but a few hundred million pixels / second is hard for those cards when you turn on blending and texturing.
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #13
arekkusu Wrote:Don't overestimate the fillrate of a Rage128 or GF2MX. 768 quads = nothing, but a few hundred million pixels / second is hard for those cards when you turn on blending and texturing.
I've had no problems filling the entire screen with 32bpp textured quads on my Rage128 at 60fps.

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  OpenGL full screen mode leaves garbage on screen when exiting app Malarkey 5 5,102 Nov 19, 2008 12:51 PM
Last Post: Malarkey