2
\$\begingroup\$

I'm currently creating 2D game from top perspective. I'm having problems with bullets. Yes, I currently simulate their movement so user can see them (about 2x ). Moving them with

// this is static
Direction = new Vector2(mouse.X, mouse.Y) - new Vector2(player.x, player.y);
Direction.Normalize();
Speed = 900f;

//this is called in Draw(GameTime gameTime) 
Position += Direction * 9f * Speed * (float)gameTime.ElapsedGameTime.TotalSeconds;

actually it's working perfectly, however, they're too fast so I can't check their collision each frame and I need to re-play their way each frame. How would I do it? And how would I do this available for both server (which doesn't use XNA as I want to port it to Linux later) and client (using XNA)?

Here's an image which shows the problem (1. bullet is before target 2. bullet is behind target, so it can no longer intersect the target. My goal is to calculate whether it intersected the target before)

I have almost forgot to mention! These objects are moving, these are player, that means that user can get out of the bullet's trace

\$\endgroup\$
6
  • 2
    \$\begingroup\$ It might be worth noting that if the target and bullet are always moving in a straight line and constant speed, the entire result of the shot can be calculated at the time of firing and no collision detection is required since the result can be 100% predictable (calculated). This may or may not fit your game play but it's worth remembering. \$\endgroup\$
    – Steve H
    Commented Jan 22, 2012 at 13:01
  • \$\begingroup\$ You mean I should calculate the hit right after firing? What if player manages to get away from the bullet's trace? \$\endgroup\$
    – Martin.
    Commented Jan 22, 2012 at 15:02
  • \$\begingroup\$ gamedev.stackexchange.com/questions/22313/… \$\endgroup\$
    – notlesh
    Commented Jan 22, 2012 at 16:34
  • \$\begingroup\$ gamedev.stackexchange.com/questions/313/… \$\endgroup\$
    – Tetrad
    Commented Jan 22, 2012 at 17:59
  • 1
    \$\begingroup\$ @Feanor - no I'm not. I'm meaning that if a target is traveling at a constant velocity & your bullet will be traveling at a constant velocity, You can calculate with a quadratic equation if and when the two will collide. If your calc predicts the collision, simply wait the time span til impact & register/respond to the hit without needing any collision detection. See my answer here: gamedev.stackexchange.com/questions/14469/… \$\endgroup\$
    – Steve H
    Commented Jan 23, 2012 at 2:44

3 Answers 3

3
\$\begingroup\$

The simplest way to solve this problem is to use fixed time steps in XNA and tell it you want more fps for your update method, this makes your update code run more often and with smaller time steps which in turn means that your bullet will travel a shorter distance each time you check for collisions. This is essentially what Nick mentioned above, but with less changes needed to your code.

In the constructor for your Game class put the following two lines of code:

base.IsFixedTimeStep = true;
base.TargetElapsedTime = new TimeSpan((long)(TimeSpan.TicksPerSecond / 600f));

600f Is the number of frames per second you want, most likely your already running with fixed time step (this is the default in XNA) at 60fps, by changing it to 600 your bullets will be checked 10 times more often.

Once you understood how this works in practice however I would recommend that you do this manually by dividing the ElapsedGameTime you receive in your update with the speed of your bullet and then update the bullet multiple times per update, this way you don't force your entire game to run at higher frames per second just to accommodate your bullets moving fast. Hope this helps.


PS. Swept objects is an interesting solution to this problem, while probably overkill for your scenario, it involves sweeping the object (the bullet) along its movement vector and then comparing this new shape to the other objects for collision. Sweeping a circle would give you a capsule for instance. You would normally do this with the bounding boxes of the sprites since its easier to calculate, but using algorithms like GJK you can do it with arbitrary shapes as well (in both 2D and 3D).

\$\endgroup\$
4
  • \$\begingroup\$ Doing 600fps fixed update for the physics system is probably way more processor-intensive than doing sweep tests. \$\endgroup\$
    – Tetrad
    Commented Jan 23, 2012 at 8:11
  • \$\begingroup\$ Thought this is not the best way to do it and I'll need to move my UpdateInput() in Draw(), I'll use this one. \$\endgroup\$
    – Martin.
    Commented Jan 23, 2012 at 12:20
  • \$\begingroup\$ Of course its less efficient than just doing the physics in increased fps, but unless your game is cpu bound your not going to lose much doing it this way. This is the "simplest" approach and I tried to make it clear that it is, unless you wind up slowing your game down it won't hurt doing this to get a better understanding of how things work. \$\endgroup\$ Commented Jan 23, 2012 at 16:13
  • \$\begingroup\$ @Nick Wiggill suggestion on CCD is far better. You should consider that. \$\endgroup\$
    – NemoStein
    Commented Jan 24, 2012 at 11:29
8
\$\begingroup\$

There are two methods of collision detection.


Discrete stepping

Use basic calculus to step an object A through space by some (typically fixed) distance per step. At each step, check object A for colocation with other objects B in the same space.

Pros: Cheap to process.

Cons: Can miss objects through penetration, which occurs because your physics timestep (need not necessarily be your gameloop timestep!) is not small enough to catch those cases where a bullet would have hit another object. Either (a) reduce your timestep to a smaller value and iterate your physics more frequently, or (b) reduce and cap maximum velocities, or (c) opt for CCD, below.


Continuous Collision Detection (CCD) AKA raycasting

This uses linear algebra to determine whether a line (or lines) representing body A's trajectory, is intersected by another line representing the boundary of some other solid body B. .

Pros: 100% accurate.

Cons: Costly to process, as you have to check the line against everything within your scene, or at least your area of interest (AoI) near to the player.


A number of physics engines allow a choice between these, for given types of bodies. For instance, while it may be prudent to use CCD for very fast moving, small objects like bullets, it may be perfectly acceptable to use stepping for other objects, since the timestep is small enough, and they are large and slow-moving enough, that there is no way they could overshoot/penetrate.

\$\endgroup\$
3
  • \$\begingroup\$ How does CCD account for timing? I'm guessing you only project the ray as far as the bullet could have possibly traveled in the timestep; but what if two bullets pass within millimeters of each other; the rays would intersect, but may not be indicative of an actual collision. \$\endgroup\$ Commented Jan 24, 2012 at 17:39
  • \$\begingroup\$ Good call. I considered modifying the answer to include that when I wrote it, but thought better to keep it concise and clear. Yes, it can be done either way, depending on the speed and size of the CCD entity, nature of the projectile, and nature/density of the environment. Per-step raycasts are the guaranteed-correct method and are the ones that give CCD its rep for slow processing. One single raycast tends to be used either where rest of environment is static, or the projectile isn't a projectile in the truest sense (eg. super-fast energy beam that won't bounce). YMMV. \$\endgroup\$
    – Engineer
    Commented Jan 24, 2012 at 18:44
  • \$\begingroup\$ Also worth noting that for polygons, CCD raycasting can be accurately achieved by casting a ray for each vertex (slow), or finding out what the profile of the object is for it's present direction-of-motion (faster), so that you only need to cast 2 rays, one for each "Side" left and right (think of the mirrors on a 24-wheeler headed directly toward you... I'm sure that's what Toecutter in Mad Max did). For circles, you need to find a line cutting the circle perp to its direction of motion, to get the "side" points. Vector projection comes in handy in both instances. \$\endgroup\$
    – Engineer
    Commented Jan 24, 2012 at 18:46
4
\$\begingroup\$

If the bullet is moving very fast then I believe that you would use raycasting (at least that is what I think it is usually called) in order to determine collision. In this example you would have the old position, you would calculate the new position. Then you would represent this movement by a line/ray between these two positions. If this line intersects with any geometry in your scene, then the bullet has hit something.

While I am not familiar with XNA, I would be surprised if it doesn't have built-in support for performing raycasting checks.

Some links that may be useful:

http://www.synapsegaming.com/forums/p/825/3684.aspx

http://www.youtube.com/watch?v=o9E1AhpcXWg

\$\endgroup\$
2
  • 2
    \$\begingroup\$ it's called Continuous Collision Detection \$\endgroup\$
    – NemoStein
    Commented Jan 24, 2012 at 11:31
  • \$\begingroup\$ Will raycasting work in case I want to immediately after shot hit the user? \$\endgroup\$
    – Martin.
    Commented Jan 27, 2012 at 12:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .