Physics of shooting

If you look at the following image, the green line represents the direction the ship is actually moving.
The blue line is direction the ship is facing, and the direction I would like the shot to travel.
The red line, is the actual shot trajectory.

http://farm5.static.flickr.com/4064/4418904806_047ff82f68_o.jpg

Edit:missed the latest post.

So in that picture the bullet’s velocity is unrelated to the ship’s velocity. Just don’t add anything when you create the bullet…

No, if I don’t add the ship’s velocity, it is much worse.
It needs to be a combination of the ship’s vector and the shot vector, I am just not sure the combination.

http://farm3.static.flickr.com/2713/4418418121_0c3dc1c947_o.jpg

Looks like you got the physics of ship-movement wrong, with multiple bugs canceling out eachother. The bullet physics in this case are so simple that if it doesn’t work (and your last image shows that) then there must be a bug somewhere else. So take a few steps back, fix it, until the code makes sense (instead of: it appears to work), and then add the bullets.

I’d advise you to start without camera movement, as I’m pretty sure that’s bugged.

[s]OK, I found a solution.

I needed to add the ship’s movement vector with the shot’s vector and then set that as the length of the shot’s new vector while forcing the angle to be the desired firing angle.

Previously, I was starting with the shot moving the same as the ship and trying to apply a force to it in order to move it in the correct direction.[/s]

Just updating this post as this solution didn’t work. I needed to add the ship vector and the shot vector and make the resulting vector the shot’s new vector.

I haven’t read anything except the posts with the pictures, so I’m pretty sure someone must have said this already.

But.

The ship’s velocity does not matter. Let me emphasize it again. The ship’s velocity? Yeah. It doesn’t matter. You shouldn’t be using it.

All you need is the ship’s rotation.


bulletVelX = cos(shipRotation) * bulletSpeed;
bulletVelY = sin(shipRoation) * bulletSpeed;

Seriously, try that code out. It’s correct.

If you were using the ship’s velocity plus the rotation values, then the bullet would very weirdly continue to travel with the ship (if it maintained velocity) but still travel along whatever way you’re pointing. Imagine a laser beam; it would stay attached to the front of the ship, or so appear to. That’s not what you want. Say the ship is flying directly to the right, you turn it to the left (it will maintain its velocity to the right) then shoot a bullet. If the ship is going faster than bulletSpeed, then by adding the ship’s velocity and the rotation values you would end up with a bullet traveling backwards.

[EDIT] I actually read a few posts. Okay, so you do in fact need the ship’s velocity (so the ship can’t overtake a bullet). But as mentioned above this creates problems if you turn and shoot to fire opposite your velocity. [/EDIT]

Actually, it was still behaving a little off, I needed to use the result of the vector addition.
Just add the two vectors and the new vector is the shot vector.
I could have sworn I had tried that first, but I must not have.

@DemonPants, no issues with firing backwards relative to ship movement. While it is true that shot will be moving in the same direction as the ship if the ship is traveling faster than the shot speed, the ship cannot decelerate fast enough to get hit by its own shot. Any enemy holding pace with or overtaking the ship from behind will still get hit by the shot. Like throwing a tennis ball from the front seat of the car to the back, it still hits the back seat even though it is moving forward almost as fast as the car.

Indeed.

go inside an airplane, moving at 1000km/h, and shoot a bullet traveling 800km/h (?) from the tail to the nose of the plane. I can guarantee you, the bullet will not move towards you at 200km/h. You will not shoot yourself (if you are standing behind the gun, obviously). The velocity of the bullet relative to the object that fired it, at the instant of firing.

fire a handgun when standing still: the bullet travels at 800km/h forward, 0km/h sideways.
fire a handgun when driving your car at 60km/h: the bullet travels at 860km/h forward, 0km/h sideways.
fire a handgun when driving your car at 60km/h in reverse: the bullet travels at 740km/h forward, 0km/h sideways.
fire a handgun when walking/strafing to the left at 5km/h: the bullet travels at 800km/h forward, 5km/h sideways.

The INITIAL bullet velocity is ALWAYS: GUN_VELOCITY_3D + BULLET_VELOCITY_3D

Well yeah if your bullet is moving much faster than your vehicle then this will be the case. And if I were in an airplane traveling -801 km/s and I fired the bullet towards our velocity so at 800 km/s, it would not come back to hit the place because I will still be going -801 km /s and so will pull away from it, but the bullet will appear to pretty much drop out of the air. No matter what its net velocity will be less than that of the plane so it won’t catch up (unless you hit the brakes quickly).

That being said, I was referring more to a fictional environment, like this game: http://www.ambrosiasw.com/games/evn/ . In that game, it is in fact very possible for your ships to fly faster than your bullets, plus you’re in a frictionless environment, so all that combining means the situation I mentioned should be able to happen. But, there’s something tricky they did with their algorithm that appears to avoid it.

it will always be the case, regardless of velocity.

If you hit the breaks quickly, it also won’t be catching up, as both the speed of your bullet and you will be zero, but that would be nitpicking, right? :slight_smile:

Nobody in this thread was, and you certainly didn’t mention it. In ‘fictional physics’ anything can happen, you could just as well posted a solution using the square root of something. :wink:

Anyway, the math of shooting bullets is extremely simple:


bullet.position.x = gun.position.x
bullet.position.y = gun.position.y
bullet.velocity.x = gun.velocity.x + cos(gun.rotation) * bullet.initalSpeed
bullet.velocity.y = gun.velocity.y + sin(gun.rotation) * bullet.initalSpeed

this will always be correct, until you approach the speed of light. :persecutioncomplex:

Yup Riven is right. With this your bullet will go as you want him to go if you don’t change the speed of your ship (gun) while the bullet is on the screen.

If you want the bullet the move on the same visible trajectory no matter if the ship change speed or not, you need to reread my post. If you don’t understand what I mean just ask.

Good luck.

Hmm… A 2D shooter based on relativistic physics? Set the speed of light to something like 50 pixels per second, centre the screen on the ship’s frame-of-reference, and massage the laws of physics a bit so the end result isn’t too unplayable. Sounds like a winner to me! ::slight_smile:
Simon

If I have a plane and a guy inside with a gun, and the plane is going 1000 km/s, and the guy shoots his gun, then the plane magically loses all velocity instantly. Because the bullet is no longer a part of the plane (but the guy has his seatbelt on), the bullet would fly back from whence it came. The whiplash would probably be a lot worse, but the bullet wouldn’t go to zero speed.

As for the fictional environment - I saw that he was talking about Asteroids and a ship. So I assumed that things like instantly stopping ships could happen, therefore allowing for some weirdness of the bullets flying “backwards” through the ship if you add the velocity.

But yes I know what you’re saying and I realize I was assuming a lot of constraints about the fictional environment that are not necessarily true.

If the plane is moving forward and the gun is shot pointing forward:

  1. plane speed = 1000
  2. bullet speed = 1000 + 1000 = 2000
    (plane hits the breaks)
  3. plane speed = 0
  4. bullet speed = 2000 (same, because plane does not affect bullet after the shot was fired)

If the plane is moving backward (original example) and the gun is shot pointing forward:

  1. plane speed = -1000
  2. bullet speed = -1000 + 1000 = 0
    (plane hits the breaks)
  3. plane speed = 0
  4. bullet speed = 0 (same, because plane does not affect bullet after the shot was fired)

Well yes, I forgot to mention the speed of the bullet in my example. The plane must be traveling faster than the bullet for this particular problem to result (again, wouldn’t happen in the real world, but could definitely happen in a videogame where you need to be able to see projectiles traveling onscreen).

To bring it back towards a game and the specific potential undesirable situations I’m thinking of:

  1. ship is facing right (positive)
  2. ship speed = -10 px/ts (px = pixels, ts = timesteps)
  3. bullet speed = -10 + 10 = 0 px/ts

You end up with a bullet going nowhere, which you probably don’t want. The ship continues to drift away from the bullet, but the bullet will have the same position on the screen (given that it has no velocity at all).

  1. ship is facing right (positive)
  2. ship speed = -30 px/ts
  3. bullet speed = -30 + 10 = -20 px/ts
  4. ship stops

You end up with the bullet flying out through the back of the ship, also something you probably don’t want. Imagine if you fire 5 bullets when going that speed, then press the down arrow to hit the breaks, and watch all the bullets come out the back. If the bullets already appeared to leave the gun (the player has had the opportunity to see the bullets leave at the correct velocity) then this makes sense because the bullet velocity will continue as-is. However, if the user hasn’t had a chance to see the bullets moving along their path and then stops (and say it’s a very fast but not instant reduction in velocity) then you’ll see all 5 bullets going out the wrong end at seemingly different speeds.

A much more common and potentially more important example:

  1. ship is facing right (positive)
  2. ship speed = 30 px/ts
  3. first bullet speed = 10 + 30 = 40 px/ts
  4. ship is reducing speed as it fires

This will have the bullets appearing to travel at completely different speeds. Logically this makes sense because the ship’s velocity was reducing as each bullet fired, but the user will see weirdness with 5 different bullets all fired at about the same time going completely different speeds. And in the reverse situation where the ship is accelerating as it shoots, the user will see the later bullets overtaking the first ones fired. That’s especially weird for a player and could even cause gameplay problems (say you fire your freeze missile first and then your concussion missile which only works on frozen targets, and your concussion missile arrives first).

Am I making sense now? Obviously this is pretty moot because Wildern’s situation is not one of the ones I’m posting, but it’s a very real problem to worry about in any game with projectiles. I can think of far more games that do not add in the shooter’s velocity when firing, because it is much more important to have constant bullet speed (as perceived by the user) then to have completely real physics. And with good reason, too, because as I mentioned before a bullet in the real world moves more or less instantly whereas one in a game must be visible, and therefore move very slowly. And if it’s moving very slowly, then it’s likely that a moving ship or player can make a large perceptible difference in the speed of the bullet, which would never happen in real life with a real bullet because I can only run 10 m/hr whereas a bullet flies 800 km/h.

Really the question is: which will look best in your game? Which aids the mechanics better?
So… that is why I said in the beginning not to use the ship’s velocity at all. Do I make sense yet?

PS - Have a look at these videos (only used these examples because they’re ones I know of):
In Super Metroid, even when running quickly the laser stays ahead of Samus. i.e. they decided to add Samus’s velocity on.


In Megaman X, the bullets appear to go nowhere when you’re going quickly, because you’re overtaking them. i.e. they don’t add Megaman’s velocity.

Time for a derail.

I’ve had a think about this before and it requires a bit of book-keeping, but should work ok. You need to keep track of the frame of reference of anything that has to make decisions: e.g. enemy ships that choose where to shoot (as opposed to random/fixed shooters), homing missiles, and the player’s ship.

For each frame of reference, you need a brief history of every object in the world. Each entry in the history belongs to a timestep, and needs to identify when the information about that entry would reach the centre of the frame of reference (player/enemy/bullet/whatever). This is to make sure, for example, that a bullet shot at you at the speed of light won’t be seen until it hits you.

I think the final thing needed was a mapping from the timesteps of the non-player frames of reference to the player’s timesteps. This is to handle timing issues when frames of reference are accelerated relative to one-another. This could affect things like firing rates. Maybe this could be ignored? Gameplay > realism.

You can do some other neat stuff like blue shifting and red shifting colours based on their velocity to/from the player.

The implementation is trivial, and is left as an exercise for the reader.

That’s the spirit! I knew someone here must have. ;D

Yes, that does highlight the problem that “realistic” and “fun to play” don’t necessarily go hand-in-hand.

Quite. The only tricky bit would be thinking up a name. Assuming a game in which you shoot chunks of rock, the best I could come up with was Relativisteroids. :stuck_out_tongue: There’s room for improvement.

Simon

Actually, I found a Java implementation of relativistic asteroids:
http://www.referencegames.com/index.html

It drops heaps of frames when you accelerate (at least for me), and I have a sneaking suspicion that the information reaches the ship instantly (so photons move faster than the speed of light). Asteroids still go invisible at the speed of light, but only because their length goes to zero… or is that the same thing as delayed information? …and now my brain is starting to hurt.

Yours is a vast improvement over the only one that pops into my head: Hemorrhoids.