Sign in to follow this  

Scrolling Map (non tile-based)

This topic is 4693 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am making a game that is comparable in style to Soldat or Leiro (basically Worms in realtime instead of turnbased), and so a level will have a main map, some parallax backgrounds, some worms, projectiles, particles, bonuses, etc. I want the player to be able to scroll around the whole map by moving the mouse to the edge of the screen, but i have some questions about scrolling. (i am using SDL, if that makes any difference) 1. For scrolling, the only idea i could come up with was to make a pair of global 'xoffset' and 'yoffset' variables, and just apply them to every single x/y coordinates. Is this the best way? 2. With a big map, how much of it do i have to be calculating and blitting? The way i assume it should be done is that the code for everything would always run, but only the sprites onscreen would be blitted? Also, does anyone know how to do destroyable landscape(like Worms)? I vaguely remember hearing once that you could do it with a 2d boolean array that had a 'destroyable value' (1 or 0 obviously) for every pixel of the map. Though im not sure how to impliment that. Thanks in advance for your help!

Share this post


Link to post
Share on other sites
Quote:
Original post by djalias1. For scrolling, the only idea i could come up with was to make a pair of global 'xoffset' and 'yoffset' variables, and just apply them to every single x/y coordinates. Is this the best way?


That's pretty much the basic concept. You could go with the opengl-esque method, which has what could be described as a 3d cursor (misdominer) which you place things with. OpenGL uses a similar concept, only it uses matricies to store the "compiled" effect for faster math, to reduce the high number for cos/sin math required.

Quote:
2. With a big map, how much of it do i have to be calculating and blitting? The way i assume it should be done is that the code for everything would always run, but only the sprites onscreen would be blitted?


Well, you could use a quadtree or related concept, or even a simplified version of that general idea: partition space into a certain grid layout, and only render the grid cells that could potentially be onscreen.

Quote:
Also, does anyone know how to do destroyable landscape(like Worms)? I vaguely remember hearing once that you could do it with a 2d boolean array that had a 'destroyable value' (1 or 0 obviously) for every pixel of the map. Though im not sure how to impliment that.

Thanks in advance for your help!


Well, here's how I did it for a basic tank game in BASIC oh so many years ago (psuedoish coding in C++ because it's been so long since I've touched basic, very sloppy design, but it should get the idea accross):

char pixelcolor[width][height];

//X direction goes from left to right
//Y direction goes from top to bottom

void explode( int x , int y , int radius )
{
//FIXME: Code can access beyond map, which in the best case will SEGFAULT.
//(hint: implement get/set pixel which return black/set nothing if out of bounds)
for ( int i_x = x - radius ; i_x < x + radius ; ++i_x )
{
for ( int i_y = y - radius ; i_y < y + radius ; ++i_y )
{
int dx = i_x - x;
int dy = i_y - y;
if (( dx * dx + dy * dy ) < (radius * radius)) //if within radius
{
char color = pixelcolor[i_x][i_y];
switch( color )
{
case PLAYER1_COLOR:
player1.armor--; //NOTE: damages based on how many pixels of the player get covered in the blast
break;
case PLAYER2_COLOR:
player2.armor--;
break;
default: //terrain
pixelcolor[i_x][i_y] = black;
}
}
}
}
}

void apply_tank_physics( ctank & tank )
{
//Note: we're making the tank rest only on the pixel directly bellow it's center
while ( pixelcolor[ tank.x ][ tank.y + 1 ] == black ) //FIXME: also not bounds checked, see previous FIXME
{
//Note: we dont even attempt to restore the terrain.
//This may eat up some terrain.
tank.erase();
++tank.y; //REMEMBER: +Y is down in our coordinates.
tank.render();
}
}


Remember, this was done in BASIC using 16 colors (I think, maybe 256) in which the only "global" variables were the tank positions, health, last shot angle/power, and the pixel data which was also the storage of the terrain. If it was brown it was ground, black signified nothingness, and... well yeah.

Share this post


Link to post
Share on other sites
Quote:
Also, does anyone know how to do destroyable landscape(like Worms)? I vaguely remember hearing once that you could do it with a 2d boolean array that had a 'destroyable value' (1 or 0 obviously) for every pixel of the map. Though im not sure how to impliment that.


I would say that it could be a good way. You could hold an bitmap of the land area, where you would define one color as 'air' or 'destroyed' (transparent colour would be best). Then you would modify this bitmap on each explosion.
Drawing would be relatively easy, because you would allways just draw the land bitmap on the screen, (you would substract the camera_origin_x and camera_origin_y coordinates from it).

Share this post


Link to post
Share on other sites
Quote:
1. For scrolling, the only idea i could come up with was to make a pair of global 'xoffset' and 'yoffset' variables, and just apply them to every single x/y coordinates. Is this the best way?


That's the basic idea. HOWEVER i would not make them global. I'd create some basic blitting function that wrap those variables. Have

BlitGraphic( world_x, world_y, SDL_Surface* graphic ) {
SDL_BlitSurface( graphic, world_x - x_offset, world_y - y_offset )
}


or something like that. That way, no one has to know or understand how to use all that screen positioning hoopla.

Quote:
2. With a big map, how much of it do i have to be calculating and blitting? The way i assume it should be done is that the code for everything would always run, but only the sprites onscreen would be blitted?


For a worms clone, i think it might actually be a good idea to load the entire map image into memory. You would only blit the screen portion of course. That's a very easy thing to do in SDL, fortunately. Alternatively, you could load the image and break it up into tiles, then only blit the appropriate tiles. Another idea would be to break up the world into major sections if your world is truly huge and memory is an issue.

Quote:
Also, does anyone know how to do destroyable landscape(like Worms)? I vaguely remember hearing once that you could do it with a 2d boolean array that had a 'destroyable value' (1 or 0 obviously) for every pixel of the map. Though im not sure how to impliment that.


For 2D i would think you are better off using the actual pixel data rather than some other structure. That's easy in SDL too :-)

Share this post


Link to post
Share on other sites
I have just recently wrote a simple project that utilizes worms style damageable geometry - using openGL.
Its not a complete game, but I think you may find it usefull gimme some moments I'll upload the everything for it and link it here.

Share this post


Link to post
Share on other sites
Ok heres the the zip, it contains src code, plus an exe you can tryout.


<DamageableSceneTest.zip



Controls are arrow pad rotate ship/ use booster. Z/ numpad0 = shoot.
Simply fly around and blast the scenery.
I thought I would mention this, my technique doesnt require storing bitmap data, and thus can have quite large maps, currently this is 8*8 screen in size.

Share this post


Link to post
Share on other sites
wow thanks everyone for the input.


great idea with the wrapper for blitting, lol i never would have thought of that, i figured i would just put the offset into every blit. but should i offset all the code that controls movement of objects, or should i have it so in the code, there is no 'scrolling' and the offset is nothing more than a graphics thing?

And thanks for the code X-out, but im noob and cant really understand it too well.

The main map will be very graphic with lots of color and stuff, so i cant use cirtain colors to represent data. so should i have a map bitmap, and a 'data' bitmap (using a few specific colors); or should i use a map bitmap, and store the data in an array?


Share this post


Link to post
Share on other sites
When you move objects, it should be as simple as object.Move(x,y) . When you blit it should be as simple as image.Blit(x,y) , where x and y are always world coordinates, not screen coords and not offset coords. Let the blitting objects/functions worry about exactly how to do their job. For my project i recently reconfigured the whole blitting arrangement. I have a Texture class with a Blit(x,y) function. However, the Texture class also needs the screen offset data but this is the job of another object. So Texture has a static set of data members and a static function called SetScreenOffset(x,y) which it uses to factor in the blitting routines.

So each frame, my process is like:

1) camera object refocuses/recenters

2) camera object notifies Texture::SetScreenOffset()

3) objects draw themselves with texture.Blit(x,y)

Share this post


Link to post
Share on other sites

This topic is 4693 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this