Jump to content
  • Advertisement
DonPedro

C++ C++ tile map collision detection

Recommended Posts

Hi! I'm trying to implement collision for my 2d platformer game.I understand basic meanings of how to detect it. I don't know how to implement it correctly though.

That's how I render my map : 

void MapScreen::Draw(SDL_Renderer*renderer)
{
  	for (int y = 0; y <= map.size(); ++y)
	{
		for (int x = 0; x < map[y].size(); ++x)
		{
			if(map[y][x] != 0)
			{
				SDL_Rect DestRect = {x * 64, y * 64, 64, 64 };
				SDL_Rect sourceRect = {map[y][x] * 64, 0, 64, 64 };
              
				tileSet[0]->Draw(renderer, sourceRect, DestRect);
       		}
      	}
	}
}

And that's how I would like to detect a collision. GetBlockID returns where on a map the block is set.

Getter::getFM() returns instance for fileManager class ->getH() returns window height value.

Int x, int y, int hitboxX, int hitboxX - these are player coordinates and width and height of the sprite.

Vector2* GameplayScreen::getBlockID(int x, int y)
{
	return new Vector2(x < 0 ? 0 : x / 64, y > Getter::getFM()->getH() ? 0 : (y + 64) / 64);
}

bool GameplayScreen::checkCollision(Vector2* v2)
{

}

bool GameplayScreen::checkCollisionRB(int x, int y, int hitBoxX, int hitBoxY)
{
	return checkCollision(getBlockID(x + hitBoxX, y + hitBoxY));
}
bool GameplayScreen::checkCollisionLB(int x, int y, int hitBoxY)
{
	return checkCollision(getBlockID(x, y + hitBoxY));
}
bool GameplayScreen::checkCollisionRT(int x, int y, int hitBoxX)
{
	return checkCollision(getBlockID(x + hitBoxX, y));
}
bool GameplayScreen::checkCollisionLT(int x, int y)
{
	return checkCollision(getBlockID(x, y));
}
bool GameplayScreen::checkCollisionRC(int x, int y,int hitBoxX, int hitBoxY)
{
	return checkCollision(getBlockID(x + hitBoxX, y + hitBoxY));
}
bool GameplayScreen::checkCollisionLC(int x, int y,int hitBoxY)
{
	return checkCollision(getBlockID(x, y + hitBoxY));
}

 

In player class movement method, I want to say : "if not collision you can move, if there is, you can't". Like :

if(!Getter::getMap()->checkCollisionLC){

movement things

}

Edited by DonPedro

Share this post


Link to post
Share on other sites
Advertisement

I would start by checking the basic function of the collision code, which is getBlockID.

If you feed it an x & y, does it give you the right block id?

 

Given that you render in multiples of 64 and blockID seems to work in multiples of 32, this would be worth checking, ihmo.

 

18 minutes ago, DonPedro said:

In player class movement method, I want to say : "if not collision you can move, if there is, you can't". Like :

So what happens if you do?

 

Share this post


Link to post
Share on other sites

Em, there should be /64. My mistake. Code in a IDE is good. I'll fix it in a post. 

In player I want it to works like this : 

	bool rightBot = Getter::getMap()->checkCollisionRB(posX - Getter::getMap()->getPosX() + moveSpeed, posY - Getter::getMap()->getPosY(), getHitBoxX(), getHitBoxY());
	bool rightCenter = Getter::getMap()->checkCollisionRC(posX - Getter::getMap()->getPosX() + moveSpeed, posY - Getter::getMap()->getPosY(), getHitBoxX(), getHitBoxY()/2);
	bool rightTop = Getter::getMap()->checkCollisionRT(posX - Getter::getMap()->getPosX() + moveSpeed, posY - Getter::getMap()->getPosY(), getHitBoxX());

	if (velX > 0)
	{
		if(!rightCenter && !rightTop && !rightBot)
		{
			if (posX >= (Getter::getFM()->getW() / 2) - getHitBoxX() && Getter::getMap()->getMoveMap())
			{
				Getter::getMap()->MoveMap(-velX, 0);
			}
			else posX += velX;

			moveAnim = true;
		}
	}


Right now, it doesn't do nothing bout the move right, because bool checkCollision() is empty. 

Edited by DonPedro

Share this post


Link to post
Share on other sites
1 hour ago, DonPedro said:

Right now, it doesn't do nothing bout the move right, because bool checkCollision() is empty. 

So that would be something you'll want to fix ;)

To be clear on this, I won't be giving ready-to-paste solutions, and I don't expect anyone else to do that either. We have a simple rule, everybody solves his/her own problems.

 

So it seems to me you're somewhat stuck with this collision thing I guess?

A useful strategy in many cases is to simplify the problem, then solve the simpler problem, then use that knowledge to solve the bigger problem. (Your'e stuck doing it in 1 step as it looks too difficult, so take 3 smaller simpler steps instead.)

 

In this case solve only one of the 3 tests. You may also want to consider first only the case that your player is a single pixel (width and height are both 1). Then the question becomes "when does the pixel collide?", ie what test must be done?

If you can solve that, consider how the solution changes if the height is still 1, but width is, say 10. If you can solve that generalize to any width, then change height (reverting width to 1 if you don't see the solution), etc

Solve the elementary test (when do I have a collision with a pixel at (x,y)), and then solve several close related problems with changing width and height, and soon enough you will see a pattern what to do.

Once you have that, extend back to 3 tests instead of 1.

Share this post


Link to post
Share on other sites

That's right. I'm not even looking for ready-to-paste. I'm looking for some, you know, advices, maybe examples, for that what can help me, to understand what I should change in my thinking. I don't exactly understand what do you mean about these 3 smallser simpler steps.

Share this post


Link to post
Share on other sites

For anything you can't solve, your problem is too big. Too many different things play a role all at the same time, interacting and what not.

The general strategy is

  1. simplify the problem,
  2. solve the simpler problem, and
  3. find out how the solution changes when you "unsimplify" it (ie use the knowledge you gained to solve the original problem)

That's 3 steps :P

If you get stuck at step 2, "for anything you can't solve, your problem is too big ....."

That is, you can often simplify several times before you hit rock-bottom. In your case, it's rock-bottom is "Is pixel (x,y) a collision?", some sort of expression that decides whether the (x,y) position represents a collision or not.

It's not entirely rock-bottom though, you can simplify further to eg "Is pixel (251, 749) a collision?" (Instead of variables first try to decide given specific values for your variables.)

 

 

 

 

Edited by Alberth
clarify "it"

Share this post


Link to post
Share on other sites

I think I know what you are about. I should create a new project with minimalistic player physics. In this case, create basic map class and try to collide. 

Edited by DonPedro

Share this post


Link to post
Share on other sites

Not entirely.

You can only program things that you know how to solve. If you don't know the solution, you can't code it. A new project won't make it simpler, as the rock-bottom case is still the rock-bottom case that needs to be solved.

 

At such a time, stop coding, turn off the computer, grab a pencil and paper (or take a walk, or do the dishes, or whatever works for you to get that grey stuff in your head working), and try to solve the problem on paper (or in your head).

 

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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!