Sign in to follow this  
wicked357

Collision for a tilemap

Recommended Posts

Right now I know it is pretty basic only a 5x5 tile map in a 2D array with images stored into a vector, but I wanted to keep it small till I figure out how to determine collision between certain areas of the tilemap. For instance in my little example here I would like to collide with the dirt area and not be able to move into it, but maintain movement everywhere else. I am having a hard time coming up with a way to test for collision, anyone able to assist me on this little problem so I can move on to actual doing something with this? Any ideas/suggestions are appreciated and thanks in advance.
#include <SFML/Graphics.hpp>
#include <vector>

int main(int argv, char** argc)
{
	//Create the game window
	sf::RenderWindow Game(sf::VideoMode(800, 600, 32), "Simple 5x5 tilemap");

	//Create the event handler
	sf::Event Event;

	//Declare the size of the tile map
	const int tileMapWidth = 5;
	const int tileMapHeight = 5;

	//Fill up the tile map with data (for sprites)
	int map[tileMapWidth][tileMapHeight] =
	{
		1, 1, 1, 1, 1,
		1, 0, 0, 0, 1,
		1, 0, 0, 0, 1,
		1, 0, 0, 0, 1,
		1, 1, 1, 1, 1
	};

	//Choose the size of the tiles
	int tileWidth = 64;
	int tileHeight = 64;

	//Load and store all the sprite images into a vector (0 = Grass, 1 = Dirt)
	std::vector<sf::Sprite> tileTextures;
	sf::Image image;
	sf::Image image2;
	sf::Sprite sprite;

	if(!image.LoadFromFile("grass.jpg"))
		return 1;
	sprite.SetImage(image);
	tileTextures.push_back(sprite);

	if(!image2.LoadFromFile("dirt.jpg"))
		return 1;
	sprite.SetImage(image2);
	tileTextures.push_back(sprite);

	//Load the player sprite image and sets it staring location and movement speed
	sf::Sprite player;
	sf::Image playerImage;
	if(!playerImage.LoadFromFile("player.png"))
		return 1;
	player.SetImage(playerImage);
	int x = 128;
	int y = 128;
	int movement = 1;

	//Main game loop
	while(Game.IsOpened())
	{
		//Handle the events in the game
		while(Game.GetEvent(Event))
		{
			//If the game is X'd out then close the game
			if(Event.Type == sf::Event::Closed)
				Game.Close();
		}

		//Exit the game if Escape is pressed
		if(Game.GetInput().IsKeyDown(sf::Key::Escape))
			Game.Close();

		//Move the player around
		if(Game.GetInput().IsKeyDown(sf::Key::W))
			y -= movement;
		if(Game.GetInput().IsKeyDown(sf::Key::S))
			y += movement;
		if(Game.GetInput().IsKeyDown(sf::Key::A))
			x -= movement;
		if(Game.GetInput().IsKeyDown(sf::Key::D))
			x += movement;

		player.SetPosition(sf::Vector2f(x, y));

		//Clear the game screen and set it to cornflower blue
		Game.Clear(sf::Color(100, 149, 236));

		//Draw the tile map and scale down the sprites to 1/4 the original size
		for(int x = 0; x < tileMapWidth; x++)
		{
			for(int y = 0; y < tileMapHeight; y++)
			{
				int textureIndex = map[y][x];
				sf::Sprite texture = tileTextures[textureIndex];
				texture.SetPosition(sf::Vector2f(x * tileWidth, y * tileHeight));
				texture.SetScale(sf::Vector2f(0.25f, 0.25f));
				Game.Draw(texture);
			}
		}

		//Draw the player sprite
		Game.Draw(player);

		//Display the graphics to the game window
		Game.Display();
	}

	return EXIT_SUCCESS;
}


[Edited by - wicked357 on May 4, 2010 1:50:16 PM]

Share this post


Link to post
Share on other sites
Okay since no one has come up with any ideas here, ill give one and see if it can be workable with this way to do a tile map.


bool checkCollision(sf::Sprite sprite1, sf::Sprite sprite2)
{
//Check rect collision of each sprite
}



I am not really sure how well this would work because it cannot be just a simple one object test, if you tested it on all the type of tiles in this case say textureIndex is 1 for the dirt, you would always have collision unless there are a lot of && in the arguments.

Here is an example how I was looking at using this...

checkCollision(player, tileTextures[1])
{
//Test all rects of collision

//If no collision found return false
}



Any kind of ideas are very welcome here and appreciated by any. I am not sure if I am even working in the right direction since this is my first tilemap program and I will be trying to check for collision.

Share this post


Link to post
Share on other sites
You can store a seperate 2d array which contains collision data. Extremely quick example coming up.


Your tilemap:


// each int refers to a tile sprite.
// 0 = grass
// 1 = dirt
// 2 = water....

int map[tileMapWidth][tileMapHeight] =
{
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
};




The collision map:



// 0 = tile is passable
// 1 = tile is impassable

int collisionmap[tileMapWidth][tileMapHeight] =
{
1, 1, 1, 1, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 0, 0, 0, 1,
1, 1, 1, 1, 1
};




Check the collision map for collisions



// player wants to move to tile 3,1

if(collisionmap[3][1] == 1){
// cannot move here
}else{
// can move here
}


Share this post


Link to post
Share on other sites
You could have your tile map refer to a list of TileType data - your current idea uses it for sprites, but what if it also contained information about collision?

Eg:


struct TileType
{
int TileTypeId;
bool Collidable;
... sprite info ...
... anything else ...
};


You could create an array or vector of these types, and then do a quick lookup do get the info you need.

eg: int TileType = tilemap[x][y];
if (tileTypes[TileType].Collidable == 1)
{
... etc
}


A downside of this is that you'll have to give all tiles of the same type the exact same properties. So to make secret walls you'd have you have a different TypeId and use the same graphics.

Alternatively, as stated before you could keep a separate map for collision types. This gives you the benefit of having special collision maps that exist outside of the graphics, but may be harder to manage.

Share this post


Link to post
Share on other sites
Okay at either, firstly it would seem you could do the same thing with just map instead of having a collisionMap unless you wanted to have invisible walls than you would want to create a separate map for collision. Secondly, other seems a bit redundant when it comes to having a large map but would work fine on a simple little map as my example shows, but I plan on getting much larger. For collision I am thinking instead of stoping the movement from happening it would take x and store it in previous x and make x = previous x or same for y that way the movement can still happen but moving in that area would make you stay at the previous location, but could still move away, is that right?

Share this post


Link to post
Share on other sites

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