Translate

Saturday, March 15, 2014

Collision Tutorial

This tutorial is long overdue so I decided to finally make it. Today I'm going to teach you all how I made my collision system. The only thing it is missing is quad trees or BSP trees, which I will fiddle around with eventually.

I would like to say this is not the best collision system in the world, and I bet there are better ways to do rectangle collision, but this is how I did it.

The most common approach to rectangle collision is that if a collision occurs it will move the object back to where it initially was. In my opinion, this is a bad and sloppy method to go about because you get this:

Do you see the problem here? The problem is the block is pixels above the ground which looks, well bad. So what should we do?





First off we are going to calculate collisions differently. When we collide with the wall, floor, etc. rather than moving the player back to where they previously were, we are going to calculate how far to move them back. Note: I am going to be using C++ and SDL for the programming.

We need to be able to check if there's a collision before we fix it.

Code:
1    bool CheckCollision(SDL_Rect A, SDL_Rect B)
2    {
3        if(A.y+A.h<=B.y or A.y>=B.y+B.h or A.x+A.w<=B.x or A.x>=B.x+B.w)
4        {
5            return false;
6        }
7        return true;
8    }

So now we can check collisions. What we now want to do is actually fix the collisions.
Since we are using SDL_Rects we have 4 values given to us, the x, y, w(width), h(height). We need to get this point(the corner):
Lets just call the point "player.c"
To do this we add the x+w. Now you may be thinking, why do we need this? We use it to be able to identify how far to push the player back when hitting a wall to the right of it.
For this example lets just say that:
player.x=10                                    Wall.x=16
player.y=0                                      Wall.y=27
player.w=16                                   Wall.w=8
player.h=16                                    Wall.h=52

Note: This example will be used multiple times.
.
So we subtract player.c to wall.x from player.x, or (10+16)-16=10. We know we need to move the player 10 pixels to the left. 
Now lets generalize it to programming terms:

Code:
1    player.x-=player.c-wall.x;

And revise it to do all of that at once:

Code:
1    player.x-=(player.x+player.w)-wall.x;

Now if you implement this code you may notice that it only works correctly when colliding with a wall left of the player. This is because the code says to move the player to the left of the wall whenever colliding with a wall. To fix this we need to add support to the player when colliding to a wall left of it. To do this we reverse it. Rather than adding player.x and player.w and subtracting from wall.x we add wall.x. Also instead of subtracting the player.x, you add the player.x.

Example: (using the original example)
(16+8)-10=14, So we need to move the player 14 pixels to the right.


Code:
1    player.x+=(wall.x+wall.w)-player.x;

So now we can fix collision to the right or left of the player. There are only one thing we need to do before implementing the collision for the y axis. We need to be able to know which direction the player is going, since we can't get proper collision by running both of these at the same time. Note: There are different methods to determine which direction the player is, this method, in my opinion, is the easiest method to use.

The way we're going to find the direction is by storing where the player is before we move him.

Code:
1    oldx=player.x;
2    player.x+=5;

We then see if there is a collision and if there is we check if oldx is less than or greater than player.x. greater=moving right, less=moving left

Code:
1    if(oldx<player.x) {player.x-=(player.x+player.w)-wall.x;}
2    if(oldx>player.x) {player.x+=(wall.x+wall.w)-player.x;}

And there we go! Moving left or right will properly move the player back.
When you implement collision to the Y axis (up and down collision), all you need to do is replace the values.

For example:
Code:
1    if(oldx<player.x) {player.x-=(player.x+player.w)-wall.x;}

is:

Code:
1    if(oldy<player.y) {player.y-=(player.y+player.h)-wall.y;}

We are know almost done. The last thing I need to show you is how to implement this code correctly. To have correctly working collision you need to check collision to the x axis, and then the y axis. DO NOT check both at the same time, as this will cause buggy collision.

Code:
//Move X
1    if(oldx<player.x) {player.x-=(player.x+player.w)-wall.x;}
2    if(oldx>player.x) {player.x+=(wall.x+wall.w)-player.x;}

//Move Y
3    if(oldy<player.y) {player.y-=(player.y+player.h)-wall.y;}
4    if(oldy>player.y) {player.y+=(wall.y+wall.h)-player.y;}

And now you're all done!

Note: The source code does not have the exact same code, but it still should help you if you are having problems, also you need to have SDL2 downloaded and insert SDL2.dll into the compiled program file.

Friday, March 14, 2014

Platformer Scrapped

As you can tell by the title, I've decided to scrap the platformer game, and create a new one. There are multiple reasons why I've decided to do this (one reason is because the game got so cluttered). I will still make a platformer game but it will be drastically different. This means that it will take longer for an alpha version to come out, however the game will be better planned out then before. Anyways I just thought I would let you know.

Thursday, March 13, 2014

Sorry!

I am sorry for the lack of posts that has been going on for awhile. This happened when I started watching extracreditz youtube page (it's not their fault it's my fault). After watching their videos on how games are it made me question if my game was worth making, and I still don't have an answer. I plan to release a very early build (without graphics), and I plan on trying to gain more of an audience for my games. Anyways I hope this won't happen again, and I hopefully will keep posting.

Tuesday, March 4, 2014

Project 5

Here is the completed image I said I would show yesterday. It doesn't look the best because I was rushed to finish 2-3 days of work and cram it into one day of work. The only parts I don't like are the sky, the boat, the motorcycle and the train as I had to rush to finish it.

Here is the image:

Monday, March 3, 2014

Collision WORKING!

Sorry for not having posts for a couple of days, I just hadn't got much done (other than in Minecraft but you don't care about that stuff). I finally finished the collision code it, and now works properly. You may be asking so how does it work? The thing is this collision code is different than the common, sloppy way of just moving the player back to where they where when they hit a wall. In this collision code when a wall is hit it actually calculates how much the player needs to move so that he will be 1 pixel away from touching the wall. See the problem with other people's collision is that because they move the player where they where before there are pixels in between the player and wall. This is ugly and sloppy in my opinion. I am still having problems (currently with class initialization, but I identified the exact problem.) Tomorrow I'll try to upload my project I finished for Computer Graphics Design II.

Thursday, February 27, 2014

Posting

Sorry I haven't been posting on my blog recently, I just haven't gotten much work done lately. Currently though I'm working on the collision and a project for Graphic Design II. I also am experimenting with encryption and decryption. When the project is done I will post it on the blog.

Sunday, February 23, 2014

Yesterday I beat COD Ghosts extinction mode, ya! I however got lazy and did nothing productive that day, which was yesterday. And I haven't gotten much farther in my code.