»doc flabby Posted May 18, 2009 Report Posted May 18, 2009 Having tried out a number of physics engines for Subspace2 none of them quite meet the performance demands I require. The biggest issue is that many of the engines support alot of features that I'm not interested in at the moment such as collisions with rotating objects. I want a much more simpler system (arcade style). Unfortunately this whole area I'm woefully lacking knowledge in in. Fortunately after ALOT of research I found a tutorial http://gafferongames.com/game-physics/ that started to make some sence to me. and from the knowledge i've learnt in the tutorial i have begun to build my own engine based on the work of many others. I still have plans to use other physics engines for other game modes. The subspace world only contains AABB (squares or rectangles) collision objects. Collision handling and physics are usually done separately. In my engine I move all the objects first using numerical integration and process the collisions afterwards by looking for intersecting objects (this is a pretty standard way of doing things). So there are 2 district phases. That are repeated around 60times/second while (GameLoop) Integrate CollisionCheckResponse end 1. Physics As objects in subspace have no mass there are only 2 equations governing the movement of objects.position = velocity * timevelocity = acceleration * time A simple Eular Integrator can be used to calculate your new position for a change in time. public void EularIntergrate(float deltaTime) { position += velocity * deltaTime; velocity += acceleration * deltaTime; } the problem with Eular Integration is its horrible inaccurate which can lead to nasty quirks appearing in the game. Therefore after reading this article http://gafferongames.com/game-physics/integration-basics/ I managed to implement a RK4 (Runge-Kutta Integration) integrator. Thus the Physics part of the engine is now complete, we have a decent integrator which is producing the accurate simulation we require. 1. Collisions The First step in a collision detection is to detect if an object has collided with another (wow big surpise)In the example i'm using I test every object against each other, which is very inefficient, though the use of spacial partitioning and/or broad phase the number of tests can be minimised. ( http://stackoverflow.com/questions/414553/broad-phase-collision-detection-quadtrees-bsp-etc) The test if two AABB bodies intersect is pretty simple: Min refers to the top left corner, Max refers to the bottom right corner. public bool Intersects(aabb other) { if (this.Max.X < other.Min.X || this.Max.Y < other.Min.Y || this.Min.X > other.Max.X || this.Min.Y > other.Max.Y) { return false; } return true; } Following testing for intersections we will have a list of objects that are colliding, we are now ready to create responses to the collisions.In order to create accurate responses we need to find the collision vector, which can be obtained from the Minimum Translation Distance or MTD Vector. This is more complex to calculate: public Vector2 minimumTranslation(aabb other) { Vector2 amin = this.Min; Vector2 amax = this.Max; Vector2 bmin = other.Min; Vector2 bmax = other.Max; Vector2 mtd = new Vector2(); float left = (bmin.X - amax.X); float right = (bmax.X - amin.X); float top = (bmin.Y - amax.Y); float bottom = (bmax.Y - amin.Y); // box dont intersect if (left > 0 || right < 0) throw new Exception("no intersection"); if (top > 0 || bottom < 0) throw new Exception("no intersection"); // box intersect. work out the mtd on both x and y axes. if (Math.Abs(left) < right) mtd.X = left; else mtd.X = right; if (Math.Abs(top) < bottom) mtd.Y = top; else mtd.Y = bottom; // 0 the axis with the largest mtd value. if (Math.Abs(mtd.X) < Math.Abs(mtd.Y)) mtd.Y = 0; else mtd.X = 0; return mtd; } Now we have the MTD we can use it to move our objects out of collision, and correct there velocities to ensure they should not collide next time mtd = this.minimumTranslation(ab); this.position += mtd ; if (interv.X != 0) { this.velocity.X = -this.velocity.X ; //* bounce factor\ } else if (interv.Y != 0) { this.velocity.Y = -this.velocity.Y;//* bounce factor } This is more a reminder to myself than a particularly useful tutorial, but maybe it will help someone somewhere Referenceshttp://gafferongames.com/game-physics/http://www.gamedev.net/community/forums/topic.asp?topic_id=531478http://www.gamedev.net/community/forums/topic.asp?topic_id=520224http://www.deannolan.co.uk/pt/blog/default.aspx?id=23&t=2D-Collision-Detection-and-Response Any quite a few other random pages, that I can't remember I've attached my C# source code to a test project I created. Keys AWSD Mouse clicks create another object. Its quick and messy but gives you enough to play with physics2.zip Quote
Samapico Posted May 18, 2009 Report Posted May 18, 2009 And if you collide horizontally at the same time as you collide vertically, are both speeds inverted?And if so, if you collide horizontally with 2 objects at the same time, is the speed inverted twice? Quote
Drake7707 Posted May 18, 2009 Report Posted May 18, 2009 Nice, but you have to watch out for rounding errors here, if you add up a lot of small delta's the sum of the rounding errors could get pretty nasty which lead to the inaccuracies you speak of Quote
»doc flabby Posted May 18, 2009 Author Report Posted May 18, 2009 (edited) And if you collide horizontally at the same time as you collide vertically, are both speeds inverted?And if so, if you collide horizontally with 2 objects at the same time, is the speed inverted twice? Hmm i hadn't thought of that looks like theres more I need to work on Edit: found something here that looks useful http://games.fourtwo.se/xna/2d_collision_response_xna/ Edited May 19, 2009 by doc flabby Quote
Samapico Posted May 18, 2009 Report Posted May 18, 2009 From what I seen in your code (a quick look), it looks like what we have in the Test Map of DCME, and the horizontal+vertical collisions are not handled correctly. In fact, you also have to be aware of a diagonal collision... If you just check if (pos.x+vel.x, pos.y) intersects something, then if (pos.x, pos.y+vel.y) intersects something, you could go through a tile diagonally, that is if (pos.x+vel.x, pos.y+vel.y) intersects something; then you have to figure out which way to make it actually bounce. Did you take a look at Discretion's code for its collision handling? Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.