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

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

This might be a useful reference for you, if you've not come across it. I'm tinkering with a 2D platformer at the moment, and it's been a good read. 

http://higherorderfun.com/blog/2012/05/20/the-guide-to-implementing-2d-platformers/

They provide some detailed (and experienced) tips on how to consider tilemap collision from a platformers perspective. 

 

Share this post


Link to post
Share on other sites

There was a similar post/problem some time ago you might think usefull to read. Physics in 2D-Games can/should be as simple as comparing 2 rectnagles to each other and go ahead from there

https://www.gamedev.net/forums/topic/691635-trouble-with-collision-detection-response-in-monogame/?tab=comments#comment-5354926

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


  • Forum Statistics

    • Total Topics
      628682
    • Total Posts
      2984196
  • Similar Content

    • By lawnjelly
      It comes that time again when I try and get my PC build working on Android via Android Studio. All was going swimmingly, it ran in the emulator fine, but on my first actual test device (Google Nexus 7 2012 tablet (32 bit ARM Cortex-A9, ARM v7A architecture)) I was getting a 'SIGBUS illegal alignment' crash.
      My little research has indicated that while x86 is fine with loading 16 / 32 / 64 bit values from any byte address in memory, the earlier ARM chips may need data to be aligned to the data size. This isn't a massive problem, and I see the reason for it (probably faster, like SIMD aligned loads, and simpler for the CPU). I probably have quite a few of these, particular in my own byte packed file formats. I can adjust the exporter / formats so that they are using the required alignment.
      Just to confirm, if anyone knows this, is it all 16 / 32 / 64 bit accesses that need to be data size aligned on early android devices? Or e.g. just 64 bit size access? 
      And is there any easy way to get the compiler to spit out some kind of useful information as to the alignment of each member of a struct / class, so I can quickly pin down the culprits?
      The ARM docs (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.faqs/ka15414.html) suggest another alternative is using a __packed qualifier. Anyone used this, is this practical?
    • By Josheir
      In the following code:

       
      Point p = a[1]; center of rotation for (int i = 0; I<4; i++) { int x = a[i].x - p.x; int y = a[i].y - p.y; a[i].x = y + p.x; a[i].y = - x + p.y; }  
      I am understanding that a 90 degree shift results in a change like:   
      xNew = -y
      yNew = x
       
      Could someone please explain how the two additions and subtractions of the p.x and p.y works?
       
      Thank you,
      Josheir
    • By alex1997
      Hey, I've a minor problem that prevents me from moving forward with development and looking to find a way that could solve it. Overall, I'm having a sf::VertexArray object and looking to reander a shader inside its area. The problem is that the shader takes the window as canvas and only becomes visible in the object range which is not what I'm looking for.. 
      Here's a stackoverflow links that shows the expected behaviour image. Any tips or help is really appreciated. I would have accepted that answer, but currently it does not work with #version 330 ...
    • By noodleBowl
      I just finished up my 1st iteration of my sprite renderer and I'm sort of questioning its performance.
      Currently, I am trying to render 10K worth of 64x64 textured sprites in a 800x600 window. These sprites all using the same texture, vertex shader, and pixel shader. There is basically no state changes. The sprite renderer itself is dynamic using the D3D11_MAP_WRITE_NO_OVERWRITE then D3D11_MAP_WRITE_DISCARD when the vertex buffer is full. The buffer is large enough to hold all 10K sprites and execute them in a single draw call. Cutting the buffer size down to only being able to fit 1000 sprites before a draw call is executed does not seem to matter / improve performance.  When I clock the time it takes to complete the render method for my sprite renderer (the only renderer that is running) I'm getting about 40ms. Aside from trying to adjust the size of the vertex buffer, I have tried using 1x1 texture and making the window smaller (640x480) as quick and dirty check to see if the GPU was the bottleneck, but I still get 40ms with both of those cases. 

      I'm kind of at a loss. What are some of the ways that I could figure out where my bottleneck is?
      I feel like only being able to render 10K sprites is really low, but I'm not sure. I'm not sure if I coded a poor renderer and there is a bottleneck somewhere or I'm being limited by my hardware

      Just some other info:
      Dev PC specs: GPU: Intel HD Graphics 4600 / Nvidia GTX 850M (Nvidia is set to be the preferred GPU in the Nvida control panel. Vsync is set to off) CPU: Intel Core i7-4710HQ @ 2.5GHz Renderer:
      //The renderer has a working depth buffer //Sprites have matrices that are precomputed. These pretransformed vertices are placed into the buffer Matrix4 model = sprite->getModelMatrix(); verts[0].position = model * verts[0].position; verts[1].position = model * verts[1].position; verts[2].position = model * verts[2].position; verts[3].position = model * verts[3].position; verts[4].position = model * verts[4].position; verts[5].position = model * verts[5].position; //Vertex buffer is flaged for dynamic use vertexBuffer = BufferModule::createVertexBuffer(D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE, sizeof(SpriteVertex) * MAX_VERTEX_COUNT_FOR_BUFFER); //The vertex buffer is mapped to when adding a sprite to the buffer //vertexBufferMapType could be D3D11_MAP_WRITE_NO_OVERWRITE or D3D11_MAP_WRITE_DISCARD depending on the data already in the vertex buffer D3D11_MAPPED_SUBRESOURCE resource = vertexBuffer->map(vertexBufferMapType); memcpy(((SpriteVertex*)resource.pData) + vertexCountInBuffer, verts, BYTES_PER_SPRITE); vertexBuffer->unmap(); //The constant buffer used for the MVP matrix is updated once per draw call D3D11_MAPPED_SUBRESOURCE resource = mvpConstBuffer->map(D3D11_MAP_WRITE_DISCARD); memcpy(resource.pData, projectionMatrix.getData(), sizeof(Matrix4)); mvpConstBuffer->unmap(); Vertex / Pixel Shader:
      cbuffer mvpBuffer : register(b0) { matrix mvp; } struct VertexInput { float4 position : POSITION; float2 texCoords : TEXCOORD0; float4 color : COLOR; }; struct PixelInput { float4 position : SV_POSITION; float2 texCoords : TEXCOORD0; float4 color : COLOR; }; PixelInput VSMain(VertexInput input) { input.position.w = 1.0f; PixelInput output; output.position = mul(mvp, input.position); output.texCoords = input.texCoords; output.color = input.color; return output; } Texture2D shaderTexture; SamplerState samplerType; float4 PSMain(PixelInput input) : SV_TARGET { float4 textureColor = shaderTexture.Sample(samplerType, input.texCoords); return textureColor; }  
      If anymore info is needed feel free to ask, I would really like to know how I can improve this assuming I'm not hardware limited
    • By John Mckrugins
      My short-term  goal right now is a job as a Junior Programmer in any game company, just to get my foot int the door and start earning some income.
      My long term goal is to Programme for bigger more established  game companies and help games that interest me.
      Im in semi-fortunate position where i don't have to work a full time job so i have the  learn how to programme.
      i did my research into whats a good beginner way to start,  Unity and C# came up a lot, so i threw my hat in.
      For the past 5 months i've been learning C# and Unity using the udemy tutorials at a slow but steady pace as i come from a 0 maths/ programming background.
      Right now  getting the hang of things , understanding most code and the  unity engine to a point where i feel comfortable at my current level around Beginner/ Intermediate.
      Although im still keen to continue with Unity, I cant help this nagging feeling that(lets say for arguments sake i do actually get a job) if i do peruse this path and end up with a job as a developer for a company that uses Unity or whatever else uses C# . There is going to be a point at however many X years down the line i am, im still using unity,  im going to be in a position where i want to work on bigger more mainstream games that use C++.
      I want to get a job ASAP, i know it will take at the very least another 7 months probably, learning more code, making a portfolio and all the rest, so i dont really want to change and start from scratch again.
      Im not bashing unity but it looks like its main use is mobile games, which would be perfectly fine as a starting point, but not as a long term career. 
      Hypothetically  If i continue to focus on learning C# / Unity to reach my goal, and at some-point i want to move into bigger prospects and learn C++, how screwed would i be if i wanted to transition over.
      Im by no means a  smart guy that picks up things fast, im just willing to put in the time/effort.
      Should i scrap learning C# and unity for C++ / Unreal  or just power on through and transition later down the line after i get some experience first.
      Time is a factor, but i want to make sure im not condemning myself to a path i wont like later down the line...
       
       
  • Popular Now