Hi i wrote really basic collision detection .Called (Pixel Perfect Collision Detection)but when i go backwards in game collision detection stops working.
Why this happens and how to fix.
Collision detection stops working after pressing "s" (backward key" on keyboard
0.1 for example has no EXACT binary representation, so there's no guarantee that a round trip of successively adding and subtracting 0.1 will ever get you back exactly to where you started.
You'll get back to approximately where you started.
/**
* Compares if two floating point numbers are equal.
* comparison precision is governed by epsilon value,
* lower the epsilon more accurate the result
*
* @param param1 first value used for comparison
* @param param2 second value used for comparison
* @tparam FType floating point type ie. float, double or long double
*
* @return true if given floating point values are equal
*/
template<typename FType>
bool compare_float(FType param1, FType param2, FType epsilon) noexcept
{
// Calculate the difference.
const FType diff = std::abs(param1 - param2);
param1 = std::abs(param1);
param2 = std::abs(param2);
// Find the largest
const FType largest = (param1 > param2) ? param1 : param2;
const FType temp = largest * epsilon;
if (diff <= temp)
returntrue;
returnfalse;
}
Here is a sample usage with DBL_EPSILON from <cfloat>:
You can obtain machine epsilon from <cfloat> standard header, or if you wish you can compute one yourself (ie. to avoid header) with the following formula:
/**
* Determinates epsilon specific to machine.
* gives an upper bound on the relative error due to rounding in floating point arithmetic.
* https://en.wikipedia.org/wiki/Machine_epsilon
*
* @tparam FType floating point type ie. float, double or long double
*
* @return machine specific epsilon
*/
template<typename FType>
FType machine_epsilon() noexcept
{
FType one = static_cast<FType>(1);
FType half = static_cast<FType>(.5);
FType epsilon = one;
while ((one + half * epsilon) > one)
epsilon = half * epsilon;
return epsilon;
}
This will work for for comparisons where arguments (compared floats) do not have to great precision
To make it work 100% we need yet another formula which will help us increase epsilon value (resulting is less accurate comparison):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
/**
* Shift decimal places of a value for specified amount of places.
*
* @param param value to be shifted
* @tparam FType Floating point type
* @param decimals amount of decimal places to shift
* negative value shifts to the right
*
* @return shifted value
*/
template<typename FType>
FType shift_decimals(FType param, short decimals)
{
return param * static_cast<FType>(std::pow(10, decimals));
}
Final example usage with shifted epsilon by ex: 10 decimal places now looks like this:
still i cant understand it. How i can do this without epsilon or etc.
theres any easy way to prevent this problem.
Code is not readable . Theres more easy way to do it.
still i cant understand it. How i can do this without epsilon or etc.
It's impossible to compare floating point types without epsilon, and without precision shift and expect to have correct result.
theres any easy way to prevent this problem.
no the is not an easy way, at least not as easy as you are expecting.
Code is not readable .
serriouslly? the code I posted is only about 20 lines, if you find that hard to read go ahead and implement your own more readable version.
I think your problem is that you don't understand what the code does despite detailed description, not that it's not readable. what portion of the code is not "readable"?
Theres more easy way to do it.
Let me know when you discover more easy way, I'm willing to import that into my library and replace the code with your solution.
For your solution you're comparing multiple floats, so you can re-implement compare_float above to take variable number of template arguments so that single function call is used.
But I'm surely not going to tell you how to do that.
I going to use stackoverflow beacuse your code adaptation in my project results 35 errors . And its want initalizer before noexpect but i cant understand it so i going to ask stackoverflow... If no one finds the answer i going to use world most inefficent way to make collisions this:
bool test;
if(tra_x == 0.4f)
if(test = true)
tra_x = false;
if(tra_z == 2.0f)
tra_x -=0.1f;
like thing.
probalary most cumbersome code i wrote ever.
Inefficent and problary my app its just now 15 kb after doing these cumbersome process it will be 500 mb collision code .
This teqnigue called Boolen Collisions most inefficent way to do it. None of modern games used it maybe in Dos days used by bad programmers.
Dos programmers were better than you can imagine. You can't even do collision detection; they had to work in < 1 MB of memory and single or low double digit MHZ cpus with no floating point processor at all for most of that time. Yet they made rich games and powerful software. Doom. Heretic. Wolf3d. Elite+. Xwing and tie fighter. Just a small # of 3-d collision detection enabled amazing games that ran on dos (granted, those were post FPU dos but they ran on machines with single digit MB ram and < 60 MHZ cpus). Dos kinda sucked. The people that worked on it were extremely good.
if you want to compare simply, swap to integers. 64 bit ints have enough resolution to handle using them as if floats via shifting, for example 123.4567 can just be made 1234567 and multiply everything by 10000 when doing your pixels math.
So i coded these myself you can't expect world most perfect collision detection.
I asked everyone but no one gave me a algorithm that works.
Soo i go and i tried to make this.
But its not works correctly so i smashed another keyboard.
If someone has a basic collision detection (3d) algorithm please give me.
see, I told you float are special beasts to deal with ;)
You can download some open source game engine projects such as Unreal engine 4 and take a look how their collision detection works.
but know that the code wont be readable. in fact the most game engine code is a complete madness in terms of complexity when you start using it.
I recommend you to halt your work on a project. take a look at some opensource code bases, start slow, gather information etc.. . Implemening game engine isn't a job for beginners.
a basic 3-d algorithm...
just take the 3-d linear distance between points on your objects. I think we went over this before... nearest points of object A and B to each other: (A.x-B.x)*(A.x-B.x) +(A.y-B.y)*(A.y-B.y) + (A.z-B.z)*(A.z-B.z) < collisionvalue //whatever looks good on your scale in your code here. you can use the center of the objects and a radius, whatever, here. This is good enough until you start writing an engine for others to use or for a commercial product.
you can still use the adjusted integer idea I gave you above here if you need high resolution: I removed the sqrt for speed and simplicity so you don't have anything that HAS to be a floating point in that.
I can try to help but if the above is not trivial to you, then you are not ready for this project.
i staying with world most buggy collision detection ever made. I just find alternative:An int will increase when the player moves. A little cumbersome to detect after a certain place in the code, but it works
its basic algorithm of it.
for example if player at 0.3 int will be 3 if player was on 2.0f other int value will be 20 and my collision detection system will be erude from tra_z value
Yes, if something is tile based, then I would suggest comparing integers (as if each integer is a different "tile").
If something is not-integer/tile based, then you must have some beginning boundary, and ending boundary. Never compare equality to the boundry itself, just ensure that the point you're testing is within the boundry, e.g. collision if left_side_of_boundary < point.x && point.x < right_side_of_boundary.