I'm working on a 2D Platform game, and I was wondering what's the best (performance-wise) way to implement Surface (Collision) Detection.
So far I'm thinking of constructing a list of level objects constructed of a list of lines, and I draw tiles along the lines.
alt text http://img375.imageshack.us/img375/1704/lines.png
I'm thinking every object holds the ID of the surface that he walks on, in order to easily manipulate his y position while walking up/downhill.
Something like this:
//Player/MovableObject class
MoveLeft()
{
this.Position.Y = Helper.GetSurfaceById(this.SurfaceId).GetYWhenXIs(this.Position.X)
}
So the logic I use to detect "droping/walking on surface" is a simple point (player's lower legs)-touches-line (surface) check
(with some safety approximation
- let`s say 1-2 pixels over the line).
Is this approach OK?
I`ve been having difficulty trying to find reading material for this problem, so feel free to drop links/advice.
Having worked with polygon-based 2D platformers for a long time, let me give you some advice:
Make a tile-based platformer.
Now, to directly answer your question about collision-detection:
You need to make your world geometry "solid" (you can get away with making your player object a point, but making it solid is better). By "solid" I mean - you need to detect if the player object is intersecting your world geometry.
I've tried "does the player cross the edge of this world geometry" and in practice is doesn't work (even though it might seem to work on paper - floating point precision issues will not be your only problem).
There are lots of instructions online on how to do intersection tests between various shapes. If you're just starting out I recommend using Axis-Aligned Bounding Boxes (AABBs).
It is much, much, much, much, much easier to make a tile-based platformer than one with arbitrary geometry. So start with tiles, detect intersections with AABBs, and then once you get that working you can add other shapes (such as slopes).
Once you detect an intersection, you have to perform collision response. Again a tile-based platformer is easiest - just move the player just outside the tile that was collided with (do you move above it, or to the side? - it will depend on the collision - I will leave how to do this is an exercise).
(PS: you can get terrific results with just square tiles - look at Knytt Stories, for example.)
Check out how it is done in the XNA's Platformer Starter Kit Project. Basically, the tiles have enum for determining if the tile is passable, impassable etc, then on your level you GetBounds of the tiles and then check for intersections with the player and determine what to do.
I've had wonderful fun times dealing with 2D collision detection. What seems like a simple problem can easily become a nightmare if you do not plan it out in advance.
The best way to do this in a OO-sense would be to make a generic object, e.g. classMapObject. This has a position coordinate and slope. From this, you can extend it to include other shapes, etc.
From that, let's work with collisions with a Solid object. Assuming just a block, say 32x32, you can hit it from the left, right, top and bottom. Or, depending on how you code, hit it from the top and from the left at the same time. So how do you determine which way the character should go? For instance, if the character hits the block from the top, to stand on, coded incorrectly you might inadvertently push the character off to the side instead.
So, what should you do? What I did for my 2D game, I looked at the person's prior positioning before deciding how to react to the collision. If the character's Y position + Height is above the block and moving west, then I would check for the top collision first and then the left collision. However, if the Character's Y position + height is below the top of the block, I would check the left collision.
Now let's say you have a block that has incline. The block is 32 pixels wide, 32 pixels tall at x=32, 0 pixels tall at x=0. With this, you MUST assume that the character can only hit and collide with this block from the top to stand on. With this block, you can return a FALSE collision if it is a left/right/bottom collision, but if it is a collision from the top, you can state that if the character is at X=0, return collision point Y=0. If X=16, Y=16 etc.
Of course, this is all relative. You'll be checking against multiple blocks, so what you should do is store all of the possible changes into the character's direction into a temporary variable. So, if the character overlaps a block by 5 in the X direction, subtract 5 from that variable. Accumulate all of the possible changes in the X and Y direction, apply them to the character's current position, and reset them to 0 for the next frame.
Good luck. I could provide more samples later, but I'm on my Mac (my code is on a WinPC) This is the same type of collision detection used in classic Mega Man games IIRC. Here's a video of this in action too : http://www.youtube.com/watch?v=uKQM8vCNUTM
You can try to use one of physics engines, like Box2D or Chipmunk. They have own advanced collision detection systems and a lot of different bonuses. Of course they don't accelerate your game, but they are suitable for most of games on any modern devices
It is not that easy to create your own collision detection algorithm. One easy example of a difficulty is: what if your character is moving at a high enough velocity that between two frames it will travel from one side of a line to the other? Then your algorithm won't have had time to run in between, and a collision will never be detected.
I would agree with Tiendil: use a library!
I'd recommend Farseer Physics. It's a great and powerful physics engine that should be able to take care of anything you need!
I would do it this way:
Strictly no lines for collision. Only solid shapes (boxes and triangles, maybe spheres)
2D BSP, 2D partitioning to store all level shapes, OR "sweep and prune" algorithm. Each of those will be very powerfull. Sweep and prune, combined with insertion sort, can easily thousands of potentially colliding objects (if not hundreds of thousands), and 2D space partitioning will allow to quickly get all nearby potentially colliding shapes on demand.
The easiest way to make objects walk on surfaces is to make then fall down few pixels every frame, then get the list of surfaces object collides with, and move object into direction of surface normal. In 2d it is a perpendicular. Such approach will cause objects to slide down on non-horizontal surfaces, but you can fix this by altering the normal slightly.
Also, you'll have to run collision detection and "push objects away" routine several times per frame, not just once. This is to handle situations if objects are in a heap, or if they contact multiple surfaces.
I have used a limited collision detection approach that worked on very different basis so I'll throw it out here in case it helps:
A secondary image that's black and white. Impassible pixels are white. Construct a mask of the character that's simply any pixels currently set. To evaluate a prospective move read the pixels of that mask from the secondary image and see if a white one comes back.
To detect collisions with other objects use the same sort of approach but instead of booleans use enough depth to cover all possible objects. Draw each object to the secondary entirely in the "color" of it's object number. When you read through the mask and get a non-zero pixel the "color" is the object number you hit.
This resolves all possible collisions in O(n) time rather than the O(n^2) of calculating interactions.
Related
I am new to StackOverflow and my first question here is, how do I collide with objects in a game, removed them from scene and add 1 to the score .
To help you understand this question more here is an example: If the player collides with a coin, the coin will get removed from the scene and it will add 1 to the score
The only code I have is generating the diamonds and that't but I am not sure how to get round this question, I think I need to write the code in beginContact or something similar. I would be really glad if someone could help me with this issue. Thanks!
Object collision can be done in several ways depending on the complexity of the game.
The simplest method is to track the entire field in a 2d or 3d matrix and if the user moves into the same coordinates as an obtainable object remove the object and increment the score. This has obvious issues when it comes to large maps or complex systems that would run the hardware out of memory. So this works for something like a chess/checkers board but not a driving simulation.
The second method is to keep a linked list of objects visible on the field with it's central coordinates and it drawing directions. The objects might look like coords (1007.2053, 489.2111) shape (box). Where box is a function that generates all the border coordinates. Then detect collisions by checking if primary target overlaps any of the object in the list. You'll probably have to write a collision function for each shape. The simpler the shape the easier the collision function. For more complex object it's often easier just to simplify the shape to a box no mater what it looks like. This is why 3d games often have clipping errors and why you could shoot the edge of an object in a fps and still not be considered to hit it.
Your question is too broad for a better answer but Here is a very basic article that discusses the second method.
More Info. The game is apparently a 2d endless runner.
So you could set up a 2d matrix that acts as a queue. Say your board is 3 high so your character can walk, jump, or high jump.
highjump
jump
walk
This would be a simple matrix like board 10 X 3 (x, y)
With each frame the board removes the front column and adds a new column to the back. Think front of matix is left side, back is right side. When adding to back you randomly decide which box to put the coin in. In each frame the user must be in one of the 3 positions. if his position is the same as the object collect it and gain points. Or if the object is undesirable lose a life and start game over, etc.
more links
Information specific to endless runners here and another stack overflow question similar to yours here
I am creating a game where the character can jump in the direction opposite of the surface he lands on. For example if he is on the ground he can only jump up. If he is on a right edge he can only jump left...etc etc.. Currently I have set up my SKNodes into leftWall, rightWall, bottomSurface, topSurface and have a huge if/else... this works but will become way more complicated as I add different surfaces with different angles etc...
I thought a better way to implement this would be to find the normal vector direction at the point of contact between the character sprite and a general wallNode sprites.
Can anyone help me determine A) the point of contact between sprites assuming the character has a circle physics body and the walls are always straight edges. and B) the normal to the contact point
thank you!
I don't think the vector or angle of impact will do you much good as your player's jump would likely be in an ark. As such, hitting the same surface at different points of the player's jump ark would yield different results.
I suggest you use unique category bit masks for your surfaces. A more advanced version of that would be to use only one category and utilize the SKSpriteNode's dictionary property to hold the angle value.
Based on the contact data you can then set the correctly angled jump for your player.
My question maybe a bit too broad but i am going for the concept. How can i create surface as they did in "Cham Cham" app
https://itunes.apple.com/il/app/cham-cham/id760567889?mt=8.
I got most of the stuff done in the app but the surface change with user touch is quite different. You can change its altitude and it grows and shrinks. How this can be done using sprite kit what is the concept behind that can anyone there explain it a bit.
Thanks
Here comes the answer from Cham Cham developers :)
Let me split the explanation into different parts:
Note: As the project started quite a while ago, it is implemented using pure OpenGL. The SpiteKit implementation might differ, but you just need to map the idea over to it.
Defining the ground
The ground is represented by a set of points, which are interpolated over using Hermite Spline. Basically, the game uses a bunch of points defining the surface, and a set of points between each control one, like the below:
The red dots are control points, and eveyrthing in between is computed used the metioned Hermite interpolation. The green points in the middle have nothing to do with it, but make the whole thing look like boobs :)
You can choose an arbitrary amount of steps to make your boobs look as smooth as possible, but this is more to do with performance.
Controlling the shape
All you need to do is to allow the user to move the control points (or some of them, like in Cham Cham; you can define which range every point could move in etc). Recomputing the interpolated values will yield you an changed shape, which remains smooth at all times (given you have picked enough intermediate points).
Texturing the thing
Again, it is up to you how would you apply the texture. In Cham Cham, we use one big texture to hold the background image and recompute the texture coordinates at every shape change. You could try a more sophisticated algorithm, like squeezing the texture or whatever you found appropriate.
As for the surface texture (the one that covers the ground – grass, ice, sand etc) – you can just use the thing called Triangle Strips, with "bottom" vertices sitting at every interpolated point of the surface and "top" vertices raised over (by offsetting them against "bottom" ones in the direction of the normal to that point).
Rendering it
The easiest way is to utilize some tesselation library, like libtess. What it will do it covert you boundary line (composed of interpolated points) into a set of triangles. It will preserve texture coordinates, so that you can just feed these triangles to the renderer.
SpriteKit note
Unfortunately, I am not really familiar with SpriteKit engine, so cannot guarantee you will be able to copy the idea over one-to-one, but please feel free to comment on the challenging aspects of the implementation and I will try to help.
I've been working on a basic 3D XNA game. So far I've managed to load various character models onto a larger level/world model. I've put in some basic controls which allows the user/player to move one of the characters around the world - and even implemented some collision detection using BoundingSphere/BoundingBox with other character models.
However, the character models (at the moment) are stuck in a fixed place on the Y-axis, and so my world is really just a flat plane for them to glide across.
What I want to do now is implement a gravity like force, which will allow characters to rise and fall with the flow of the terrain. I've spent a couple of hours on google searching (in vain) for some way of checking for a detailed collision between the bounding sphere of my character and the actual mesh of the world. The articles I have found all seem to explain how to use the sphere and box methods, or to implement some external physics engine (all of which seem really quite elaborate for what I want to achieve).
So my question is twofold -
Firstly, Am I approaching this in the best way? With a single large-ish model for my world?
Secondly, Is there a relatively simple way to check for the type of collision I need, using the XNA library itself, or some other library that doesn't require me to introduce an entirely new layer of physics.
NB. The models that I want to check for collisions are: Microsoft.Xna.Framework.Graphics.Model
EDIT:
I should also mention that I am not creating a single level, but a game engine which will work with various levels loaded from a Database. For this reason, I don't want to have to separately/manually define the constraints of the level. I would ideally like to load my single mesh from the database and be able to detect collisions with it as is, or alternatively automatically work out the constraints/bounding areas from the mesh data.
3d collision detection is more complex than it may seem at a glance, so using one of the prescribed methods (I.e. the BoundingSphere Object can help). Check http://msdn.microsoft.com/en-us/library/bb203906(v=xnagamestudio.10).aspx
Specifically this code block gives an idea:
static void CheckForCollisions( ref WorldObject c1, ref WorldObject c2 )
{
for (int i = 0; i < c1.model.Meshes.Count; i++)
{
// Check whether the bounding boxes of the two cubes intersect.
BoundingSphere c1BoundingSphere = c1.model.Meshes[i].BoundingSphere;
c1BoundingSphere.Center += c1.position;
for (int j = 0; j < c2.model.Meshes.Count; j++)
{
BoundingSphere c2BoundingSphere = c2.model.Meshes[j].BoundingSphere;
c2BoundingSphere.Center += c2.position;
if (c1BoundingSphere.Intersects( c2BoundingSphere ))
{
c2.ReverseVelocity();
c1.Backup();
c1.ReverseVelocity();
return;
}
}
}
}
The first answer gave you a first-pass test for detailed collision detection. You could refine that first-pass and use an AABB test. The second pass would then require a ray-triangle intersection test. Be careful since some of these will fail when the ray hits a triangle edge or vertex - so make sure that the tester code/algorithm you chose considers these. There are further modifications using quad-trees or other space-partitioning schemes to increase the speed of collision detection.
Here is a detailed description of a sphere/triangle technique I once adapted for 2D collision detection:
http://www.peroxide.dk/papers/collision/collision.pdf
I cannot say for certain that it will help you, but it may be useful for collisions with a terrain mesh and gravity. Combining that with collisions with other "characters" may be challenging, depending on exactly what it is you want to do. However, it does specifically describe how to implement gravity, and overall it is one of the simpler approaches you might take to collision detection and character physics in 3D.
As for the question of whether colliding with the entire terrain mesh is the "correct" way to go... if it is a simple mesh and you aren't resource-constrained, then sure. However, collision detection is computationally expensive, and applying it to all the triangles in your mesh may quickly become impossible. Generally, you may want to store your triangles in some efficiently searchable structure, like an octree or a k-d tree, and then do a rough search for triangles near your character which can then be tested more precisely for collisions in much less time than it would take to test every triangle in the mesh.
You could fake it. In other words, I'm assuming, at every update call you could just set the height of your player to the height of the terrain wherever the player happens to be. I imagine not the most professional way to handle things, but might work.
How can I implement the A* algorithm on a gridless 2D plane with no nodes or cells? I need the object to maneuver around a relatively high number of static and moving obstacles in the way of the goal.
My current implementation is to create eight points around the object and treat them as the centers of imaginary adjacent squares that might be a potential position for the object. Then I calculate the heuristic function for each and select the best. The distances between the starting point and the movement point, and between the movement point and the goal I calculate the normal way with the Pythagorean theorem. The problem is that this way the object often ignores all obstacle and even more often gets stuck moving back and forth between two positions.
I realize how silly mu question might seem, but any help is appreciated.
Create an imaginary grid at whatever resolution is suitable for your problem: As coarse grained as possible for good performance but fine-grained enough to find (desirable) gaps between obstacles. Your grid might relate to a quadtree with your obstacle objects as well.
Execute A* over the grid. The grid may even be pre-populated with useful information like proximity to static obstacles. Once you have a path along the grid squares, post-process that path into a sequence of waypoints wherever there's an inflection in the path. Then travel along the lines between the waypoints.
By the way, you do not need the actual distance (c.f. your mention of Pythagorean theorem): A* works fine with an estimate of the distance. Manhattan distance is a popular choice: |dx| + |dy|. If your grid game allows diagonal movement (or the grid is "fake"), simply max(|dx|, |dy|) is probably sufficient.
Uh. The first thing that come to my mind is, that at each point you need to calculate the gradient or vector to find out the direction to go in the next step. Then you move by a small epsilon and redo.
This basically creates a grid for you, you could vary the cell size by choosing a small epsilon. By doing this instead of using a fixed grid you should be able to calculate even with small degrees in each step -- smaller then 45° from your 8-point example.
Theoretically you might be able to solve the formulas symbolically (eps against 0), which could lead to on optimal solution... just a thought.
How are the obstacles represented? Are they polygons? You can then use the polygon vertices as nodes. If the obstacles are not represented as polygons, you could generate some sort of convex hull around them, and use its vertices for navigation. EDIT: I just realized, you mentioned that you have to navigate around a relatively high number of obstacles. Using the obstacle vertices might be infeasible with to many obstacles.
I do not know about moving obstacles, I believe A* doesn't find an optimal path with moving obstacles.
You mention that your object moves back and fourth - A* should not do this. A* visits each movement point only once. This could be an artifact of generating movement points on the fly, or from the moving obstacles.
I remember encountering this problem in college, but we didn't use an A* search. I can't remember the exact details of the math but I can give you the basic idea. Maybe someone else can be more detailed.
We're going to create a potential field out of your playing area that an object can follow.
Take your playing field and tilt or warp it so that the start point is at the highest point, and the goal is at the lowest point.
Poke a potential well down into the goal, to reinforce that it's a destination.
For every obstacle, create a potential hill. For non-point obstacles, which yours are, the potential field can increase asymptotically at the edges of the obstacle.
Now imagine your object as a marble. If you placed it at the starting point, it should roll down the playing field, around obstacles, and fall into the goal.
The hard part, the math I don't remember, is the equations that represent each of these bumps and wells. If you figure that out, add them together to get your final field, then do some vector calculus to find the gradient (just like towi said) and that's the direction you want to go at any step. Hopefully this method is fast enough that you can recalculate it at every step, since your obstacles move.
Sounds like you're implementing The Wumpus game based on Norvig and Russel's discussion of A* in Artifical Intelligence: A Modern Approach, or something very similar.
If so, you'll probably need to incorporate obstacle detection as part of your heuristic function (hence you'll need to have sensors that alert your agent to the signs of obstacles, as seen here).
To solve the back and forth issue, you may need to store the traveled path so you can tell if you've already been to a location and have the heurisitic function examine the past N number of moves (say 4) and use that as a tie-breaker (i.e. if I can go north and east from here, and my last 4 moves have been east, west, east, west, go north this time)