Quick question about 2D scrolling

Started by
6 comments, last by BionicBytes 15 years, 3 months ago
Hello, I am creating a 2D scrolling multiplayer game using OpenGL, somewhat similar to Worms, or even Super Mario Bros. I am relatively new to OpenGL, and had very little experience with it over the years. My question is, for a game like this, do I draw the whole map/level at all times, and adjust the "viewable screen position" as it scrolls along? Could anyone please give me some pseudo-code, or a simple explanation for what the best method to use here is? Thanks,
Advertisement
There are lots of approaches and the best method is boils down to the scope of what you are trying to achieve. For a small scale application - you might consider creating a really large background texture and only display a small piece of this at any one time. As the player moves the view(viewport) is moved along with the player - and thus the appearance of scrolling. Its advantages are that is is quick to implement - only requires a change of the texture coordinates. The disadvantage is the large amount of texture memory required to hold the source image.
Also, the source image *may* have to a power of two (unless you know that your target platforms can support non-power of two textures).

Another popular approach is to imagine the 2D surface area that you wish to scroll over as a grid. Each cell in the grid corresponds to a nxm pixel chunk of a texture from one or more texture maps. When ever the player moves you read the list of grid cells that the viewport currently contains and draw the corresponding set of texture cells. The advantage is scalability and re-use. A small set of textures can make a really large 2D scrollable area. The disadvantage is more complex coding required. (But its not really too hard!)

Quote:Original post by BionicBytes
There are lots of approaches and the best method is boils down to the scope of what you are trying to achieve. For a small scale application - you might consider creating a really large background texture and only display a small piece of this at any one time. As the player moves the view(viewport) is moved along with the player - and thus the appearance of scrolling. Its advantages are that is is quick to implement - only requires a change of the texture coordinates. The disadvantage is the large amount of texture memory required to hold the source image.
Also, the source image *may* have to a power of two (unless you know that your target platforms can support non-power of two textures).


This is what I'm looking for, but I can't seem to find much information about it.

I tried this as in example, called every frame:
float f = 0; //global//every frame:	glViewport(f, 0.0f, 640.0f, 480.0f);	f += 0.5f;


However, it just seems to move the contents of the screen to one side, rather than scroll through my 2D world.

A psudo-code example, or a list of functions I may find helpful would be great.

Thanks,
I dont think you want to move the viewport. That should stay constant and match the default framebuffer.

If you go for the super large texture idea, then lets say your texture is 4096x4096 (of course you must query opengl runtime to determine the max size texture and exit gracefully if the value returned does not meet your min spec).

You need to setup a 2D orthographic screen first of all - this is the viewport on which you will view the world.
Next you need to map a portion of the large texture into the visible view area. As a regular texture is always mapped between 0....1 in U and 0...1 in V, you must maintain a data structure that holds the current viewable texture coords.
You will then draw a full screen 2D quad and texture map it to the current viewable texture coordinates.

So pseudo code might be:

Setup Phase
Check for GL support for massive texture - terminate if no support found
Load massive texture - generate a GL texture object
Establish a 2D viewing camera.
Establish a data struct that holds texture coords of viewable texture

Loop:
Get Player Input()
Compute Full Screen Vertex and Texture Coords
Update data struct
bind texture
Issue GL commands for full screen quad and texture coords

        // Establish a 2D view	Gl.glMatrixMode(Gl.GL_PROJECTION);	Gl.glLoadIdentity();	Gl.glOrtho(0, _iOSWindowViewport[2], 0, _iOSWindowViewport[3], -1.0f, 1.0f);		Gl.glMatrixMode(Gl.GL_MODELVIEW);	Gl.glLoadIdentity();        // Bind Your texture here	Gl.glEnable (Gl.GL_TEXTURE_2D);	Gl.glBindTexture (Gl.GL_TEXTURE_2D, iTextureID);        // Draw a full screen quad        Gl.glBegin (Gl.GL_QUADS);	Gl.glTexCoord2f (0,0);	Gl.glVertex2f (0,0);				Gl.glTexCoord2f (0,1);	Gl.glVertex2f (0,_iOSWindowViewport[3]);				Gl.glTexCoord2f (1,1);	Gl.glVertex2f (_iOSWindowViewport[2],_iOSWindowViewport[3]);				Gl.glTexCoord2f (1,0);	Gl.glVertex2f (_iOSWindowViewport[2],0);	Gl.glEnd();


You should replace the texture coordinates with the fractional values in your data struct.


Look at my game engine. There's the engine itself, an editor and some examples. You can look at the source code to understand the main idea.
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
okay - I've had a look at this editor. All very good stuff.
When you are designing the level using the editor - when the current brush paints a cell on the level - what's happening here. Where is this 'bit' of information stored. Essentially, i'm trying to figure out how you have stored the visual representation the data for the level. I guess this would determine the best strategy for the scrolling aspect.

Each level contains several layers (tile layer, collision layer...)

Look at *.bnk files, it's actually xml and binary files in zip files (use WinZip or 7zip). In Levels/Level5.xml (it's a small level) look at the xml tag <tiles> in <layer>. It contains several <row> tags. Each one represents a row in the layer. Each number represent the tile ID.
- Iliak -
[ ArcEngine: An open source .Net gaming framework ]
[ Dungeon Eye: An open source remake of Eye of the Beholder II ]
Okay - then this is all you need to do the scrolling.

This type of tile based arrangement is similar to a retro vertical scrolling game i did several years ago. In that game i kept a fixed viewport and 2D ortho-screen and simply draw each tile on the screen.
You need a way to track where in the tile array your current scrolling offset should start from and a way to track your partial scrolled tile offset.
So, for example _fTileFractionOffset might range from 0....31 to represent a fraction of a tile, whilst _iTileOffsetX,_iTileOffsetY might represent the upper left tile of scrolling region.

Each frame:
_fTileFractionOffset ++;
if (_fTileFractionOffset > 31)
{
_fTileFractionOffset = 0 ;
_iTileOffsetX ++;
}

DrawTiles (_iTileOffsetX, _iTileOffsetY)
}

The key thing to remember is that OpenGL will automatically CULL pixels that go outside of the viewport region. That means that the fractional tile will always display correctly - even though the draw code draws a full Quad for the tile.

So, if your upper left corner of the viewport is say (0,0), then you must offset the drawing code by upto -31,-31 (for a 32x32 tile size). That is the x,y coordinates do not necessarily start at 0,0. They will start at - (_fTileFractionOffset) in X or in Y (depending if you want horizontal or vertical scrolling).



This topic is closed to new replies.

Advertisement