Background in a 2d side scroller

Started by
9 comments, last by SuperVGA 11 years, 3 months ago

I'm working on a 2d side scrolling game, and so far I have been making everything based on tiles - each tile has foreground textures and a background texture. This obviously has limitations to what it can do, as each tile background is a tiny piece and you can't actually get a huge background image displayed this way, unless you just tile a bunch of tile-able smaller ones.

Obviously being able to place a background image of some sort gives a lot more freedom. But I'm having trouble deciding how to define a background image in the most extensible way. By background image I mean the standard background image that has 'depth' - i.e. it doesn't move with the level, but rather scrolls a small amount of the distance that the level moves by. Since my level design allows for various sizes in both height and width of the level, I have to account for that as well. While most background images can be expected to be tiled horizontally, tiling them vertically is obviously not going to work. Which makes me wonder how I could define an 'anchor' point, or starting position of the background image in relation to the level?

Anyone here have any experience programming this sort of thing? Any ideas you guys can share would be greatly appreciated.

Advertisement

I programmed a game that used both tiles drawn behind the player and large backgrounds that scrolled as you describe. If you don't have to use tiles for your background then don't. Use large images if you can, or several images that make up your entire background. What I would do is I would have one background image that didn't move, like a sky. That image would be the size of the game screen. The next background would be drawn in front of that(like mountains). That image I would make 2 screens wide and 1 screen high(you can make it wider). The image when divided into 2 would actually be the same image twice. This is just so I can loop the image when it goes too far left or too far to the right. If you make it wider than 2 screens you just need to make the first and last screen exactly the same so switching between the 2 is seemless. So many 2d games from the past utilized that little "trick". It makes it much easier on the artist. He or she doesn't have to create extremely large backgrounds.

I'm actually looking for information on the same subject right now. It's called parallaxing--searching for that term brings up a decent number of tutorials and sample code, which I'll finish reading tomorrow as it's nearly 3AM.

While you can still change things around, try picturing these layers, scrolling at different speeds, being drawn on the top of oneanother. If you could fit any size graphic in any of the layers, like a simplistic jigsaw puzzle, I'm sure you'll find it very flexible. This is the representation i suggest (I'm imagining it written in XML in a file, but it could be any data structure, really.)
<!-- level_00.gfx -->
<layer level="-2" parallax="1.05">
 <sprite file="somesprite.png" position="0, 128" />
 <sprite file="anothersprite.png" position="32, 0" />
</layer>
<layer level="0" parallax="1.0">
 <sprite file="graffiti.png" position="96, 64" />
 <sprite file="vine.png" position="8, 16" />
</layer>
<layer level="1" parallax="-1.3">
 <sprite file="somesprite.png" position="480, 64" />
 <sprite file="anothersprite.png" position="128, 16" />
</layer>
You could have more strict tile layouts and/or collision information defined elsewhere.
Layers -n..-1 could be painted before the basic level layout, and layers 1..n on the top of.
The layers would each be offset by scroll * layer.parallax when drawn.
It's only a suggestion, -it will still take a slightly more refined editor, but I think it could make you more productive later on.
I programmed a game that used both tiles drawn behind the player and large backgrounds that scrolled as you describe. If you don't have to use tiles for your background then don't. Use large images if you can, or several images that make up your entire background. What I would do is I would have one background image that didn't move, like a sky. That image would be the size of the game screen. The next background would be drawn in front of that(like mountains). That image I would make 2 screens wide and 1 screen high(you can make it wider). The image when divided into 2 would actually be the same image twice. This is just so I can loop the image when it goes too far left or too far to the right. If you make it wider than 2 screens you just need to make the first and last screen exactly the same so switching between the 2 is seemless. So many 2d games from the past utilized that little "trick". It makes it much easier on the artist. He or she doesn't have to create extremely large backgrounds.

That actually sounds like a pretty good idea. Having one background image that's static, and one that's moving. Actually might work with a background color and an image too, but that sounds like a good start on how to design this. There's still a bit of an issue of how to get set the moving image's initial position relative to the level, and whether to allow images to scroll at different speeds. I can't quite think of a great way to do that yet.

I'm actually looking for information on the same subject right now. It's called parallaxing--searching for that term brings up a decent number of tutorials and sample code, which I'll finish reading tomorrow as it's nearly 3AM.

Yes, indeed, parallax is the correct term. I don't quite need information on how to implement it though, more like just design ideas on how to make it work with the variations in sizes that I have with my levels. Though reading some of those tutorials is probably not a bad idea anyway.

This sample code may help. Keep in mind that this was my first attempt at coding parallax scrolling. It worked but I am sure there is better code out there that does the same thing. Just repeat code like this for every background you have. Lower the numbers screenmovecount is divided by for backgrounds that are closer.


float screenmovecountx_;
float screenmoveoucnty_;
float moveamountx;
float moveamounty;
	

	

	
	

	if(levelstate_ == 0)
	{
 //Screenlocation is the camera world location
//Screenmovecount is how many pixels away the camera is from the middle of the level's
//first screen

		screenmovecountx_ = 512.0f - screenlocationx_;
		screenmovecounty_ = 384.0f - screenlocationy_;


		if(playlevel_.GetBackGround("static").IsOccupied() == true)
		{
			
		}
		if(playlevel_.GetBackGround("dynamica").IsOccupied() == true)
		{
		  
		//Making the numbers greater makes the background move slower in x or y direction
		        moveamountx = screenmovecountx_ / 32;
	                moveamounty = screenmovecounty_ / 64;

			
       // Background is 2048 x 768, game screen is 1024x 768x
       // The background's inital drawing position when the level starts is 1024x 340x
       // These do while loops prevents the background from being drawn offscreen
			if(moveamountx > 0.0f)
			{
				do{
					moveamountx = moveamountx - 1024.0f;
				}while(moveamountx > 0.0f);


			}

			if(moveamountx < -1024.0f)
			{
				do{
					moveamountx = moveamountx + 1024.0f;
				}while(moveamountx < -1024.0f);

			}

			
   //If the camera is at 512x340(middle of first screen) background moveamountx
// and y would be 0 and the background would be drawn at 1024x 340x, fitting snug
// For every 32 pixels the camera moves to the right the background will be drawn 1 
// pixel to the left
			levelbackgrounds_.at(1).SetSpritePosition(1024.0f + moveamountx, 384.0f + moveamounty);
			
		}

This sample code may help. Keep in mind that this was my first attempt at coding parallax scrolling. It worked but I am sure there is better code out there that does the same thing. Just repeat code like this for every background you have. Lower the numbers screenmovecount is divided by for backgrounds that are closer.




float screenmovecountx_;
float screenmoveoucnty_;
float moveamountx;
float moveamounty;
	

	

	
	

	if(levelstate_ == 0)
	{
 //Screenlocation is the camera world location
//Screenmovecount is how many pixels away the camera is from the middle of the level's
//first screen

		screenmovecountx_ = 512.0f - screenlocationx_;
		screenmovecounty_ = 384.0f - screenlocationy_;


		if(playlevel_.GetBackGround("static").IsOccupied() == true)
		{
			
		}
		if(playlevel_.GetBackGround("dynamica").IsOccupied() == true)
		{
		  
		//Making the numbers greater makes the background move slower in x or y direction
		        moveamountx = screenmovecountx_ / 32;
	                moveamounty = screenmovecounty_ / 64;

			
       // Background is 2048 x 768, game screen is 1024x 768x
       // The background's inital drawing position when the level starts is 1024x 340x
       // These do while loops prevents the background from being drawn offscreen
			if(moveamountx > 0.0f)
			{
				do{
					moveamountx = moveamountx - 1024.0f;
				}while(moveamountx > 0.0f);


			}

			if(moveamountx < -1024.0f)
			{
				do{
					moveamountx = moveamountx + 1024.0f;
				}while(moveamountx < -1024.0f);

			}

			
   //If the camera is at 512x340(middle of first screen) background moveamountx
// and y would be 0 and the background would be drawn at 1024x 340x, fitting snug
// For every 32 pixels the camera moves to the right the background will be drawn 1 
// pixel to the left
			levelbackgrounds_.at(1).SetSpritePosition(1024.0f + moveamountx, 384.0f + moveamounty);
			
		}

Thanks, but it's more the design details that I'm more interested in. The basic principle of moving the background a fraction of what the player/camera moves isn't entirely too difficult.

I also have variable screen size, so your earlier suggestion of making the background be 2 screens wide by 1 screen high can't really be applied. Although I don't think that I'm going to have zooming in/out on the level affect the background (game-wise it's in the distance, so minor view changes locally shouldn't really affect how you zoom on it).

Also, nitpicking here :) but your blocks of "if (...) { do { ... } while (...) }" can just be replaced by a single "while (....) { ... }"

Haha you are right about the do while's. Oh well. Kinda funny.

What is stopping you from using a single large image as your background? That is exactly how I do it.

While you can still change things around, try picturing these layers, scrolling at different speeds, being drawn on the top of oneanother. If you could fit any size graphic in any of the layers, like a simplistic jigsaw puzzle, I'm sure you'll find it very flexible. This is the representation i suggest (I'm imagining it written in XML in a file, but it could be any data structure, really.)


<!-- level_00.gfx -->
<layer level="-2" parallax="1.05">
 <sprite file="somesprite.png" position="0, 128" />
 <sprite file="anothersprite.png" position="32, 0" />
</layer>
<layer level="0" parallax="1.0">
 <sprite file="graffiti.png" position="96, 64" />
 <sprite file="vine.png" position="8, 16" />
</layer>
<layer level="1" parallax="-1.3">
 <sprite file="somesprite.png" position="480, 64" />
 <sprite file="anothersprite.png" position="128, 16" />
</layer>
You could have more strict tile layouts and/or collision information defined elsewhere.
Layers -n..-1 could be painted before the basic level layout, and layers 1..n on the top of.
The layers would each be offset by scroll * layer.parallax when drawn.
It's only a suggestion, -it will still take a slightly more refined editor, but I think it could make you more productive later on.

Huh, I missed your post the first time. data structure type to use isn't really my concern, as you said, any data structure would do.

Your definition here though got me thinking - one, I've been wondering whether to allow for different parallax amounts for different sprites, or whether to have just 1 parallaxed layer of images behind the main level display. I'm not a fan of layers that show up in front of the main level, cause they usually just get in the way.

What's interesting in your definition - I suppose the position is the position of the object relative to the level's 0,0 - and that when the view is centered on 0,0, those background objects should appear at that given position. I think i can picture how to handle this in my head right now. I don't know if what i said made sense, but it's helped me at least.

What is stopping you from using a single large image as your background? That is exactly how I do it.

Nothing is stopping me from using a single large image. I'm not sure if you meant a static image though - If you have a visual (video or something) of how a single large background image looks in your game, feel free to share.

I just don't want a single large static image as the background, and I was wondering about how other people have handled backgrounds. So far, I'm more inclined to go with one layer of parallax images, and one static layer that's just a backdrop (like a sky gradient or something)

This topic is closed to new replies.

Advertisement