38

I'd like to shake the camera around a bit during an explosion, and I've tried a few different functions for rocking it around, and nothing seems to really give that 'wow, what a bang!' type feeling that I'm looking for. I've tried some arbitrary relatively high frequency sine wave patterns with a bit of linear attenuation, as well as a square wave-type pattern. I've tried moving just one axis, two, and all three (although the dolly effect was barely noticeable in that case).

Does anyone know of a good camera shaking pattern?

AttackingHobo
  • 7,091
  • 4
  • 36
  • 48
falstro
  • 1,328
  • 1
  • 9
  • 14

6 Answers6

36

I've got decent camera shake by applying Perlin noise to the camera's orientation. It gives you a decent big jolt with higher frequency shaking built in, and can look really good.

http://mrl.nyu.edu/~perlin/doc/oscar.html has more details and sample code for generating noise.

  • 3
    Oh, noise, why didn't I think of that... Afterall a bang i pretty much short burst of noise, isn't it... Excellent idea! – falstro Jul 29 '10 at 13:45
  • good idea, is there anything you cant use perlin noise to solve? :P – Cubed2D Jul 30 '10 at 08:21
  • 1
    Noise is definitely the way to go, if you even picture the effect your after, its short changes of random motion in different directions. But it can't be a spasm, so you need brief sections of uniformity. Sounds like a perfect use for Perlin noise. – hiddensunset4 Apr 22 '11 at 00:18
18

If you are referring to that juddering screen shake from an explosion, I have tried to implement this in my prototype game (it's 2d but should translate to 3d quite well, I expect). Take a look at the youtube video and see if that's what you're looking for - the screen shake kicks off about 1:35

Anyway, the way I achieved it was to create a viewport for the sceen and store the centre point (centre).

When an explosion kicks off, I create a random radius of ~30px. I then offset the viewport from centre by this many pixels in a random direction.

For each subsequent update (between draws to screen), I reduce radius by 10-20% and offset the viewport by this many pixels from centre again. However, instead of picking a random angle for this offset, I instead take the previous viewport angle from centre and added 180+/-60 degrees to it.

So basically, each update (or 10-20ms or so), I offset the viewport by a diminishing number of pixels from the centre of the screen.

Here's some pseudocode:

viewportCentre = (400,300) //Lets say screen size is 800 x 600
radius = 30.0
randomAngle = rand()%360
offset = ( sin(randomAngle) * radius , cos(randomAngle) * radius) //create offset 2d vector
viewport.setCentre(viewportCentre + offset) // set centre of viewport
draw()  

while(true)  //update about every 10-20ms
{ 
    radius *=0.9 //diminish radius each frame
    randomAngle +=(180 +\- rand()%60) //pick new angle 
    offset = (sin(randomAngle) * radius , cos(randomAngle) * radius) //create offset 2d vector
    viewport.setCentre(viewportCentre + offset) //set centre of viewport
    draw() //redraw
}

I usually stop the screen shake when radius gets lower than 2.0, at which point I reset the viewport back to centre.

miklatov
  • 191
  • 1
  • 4
4

To make a camera shake "feel" correct is less about the direction of motion and more about acceleration curves.

Camera shakes are diving into the realm of animation and so all the rules of action/reaction apply. If you are moving in a linear fashion from point to point it will feel smooth and uniform and not like an impact.

If you shake your head back and forth you'll notice that it moves fastest at the midpoint between changing direction and slows down on each side as you first have to decelerate and then start up in the new direction.

Here is a listing of various easing functions to apply to your motion. You might want to only EaseOut the first motion to make it feel a little more abrupt, and then EaseInOut the rest to simulate the head/camera movement.

wkerslake
  • 5,757
  • 21
  • 31
  • 1
    I think easing would still make it too smooth. The perlin noise seem like a good idea, or otherwise a plain random with the random range diminishing to zero over time to make it fade out (I would rather experiment with different ease functions on the diminishing radius than on the actual movement, easing the movement itself will make the camera feel like it's on a spring, doesn't feel right with camera shake in my experience). – Kaj Aug 14 '10 at 06:48
3

wkerslake is right, camera shakes appear to be more complex than you might think.

When emulating a shaking camera you'd have to think about what type of camera (operator) you want to mimic. The weight of the camera affects inertia, eg. heavier cameras smooth out small 'random' movements. A camera operator on a rail or in a car adds additional noise.

Using Perlin or Simplex noise is definitely an option, then it's all about finding the right balance between different noise ratios. But I found using interpolation between values is less computationally intensive and can be just as effective.

A while ago, I've found a Maya script that seems to get a lot of things right. You could take a look at that.

Also, you might want to take a look at Gran Turismo (5), their team did an impressive job at doing various types of realtime camera shaking when you watch a replay in the game.

2

If you've got dynamic object physics [probably not the right word, but sort of what I mean], where any objects not fixed would be 'blown away' by the explosion, you could have the camera affected as an object like that.
Only difference would be just change the rotation/pitch/yaw/roll of the camera, and not the position.
Other than that, maybe generate a random number sequence and convert those to rotation somehow? Think that heightmap, grayscale stuff may be an example; they're not totally different, but are random.

PrettyPrincessKitty FS
  • 10,315
  • 8
  • 43
  • 68
  • +1 interesting idea, I think I'll try the noise movement, and when I've got that running, I'll try to add a more smoth dolly effect, sort of as if the camera was attached to a spring and pressed backwards by the shock. – falstro Jul 30 '10 at 07:55
1

I recently added a camera shake effect to Open Saucer after stumbling across (serendpitous autocomplete) a method that sets a camera's projection offset. This attribute is animated bidirectionally using dossinant sine waves of around 10 Hz, with a cubed falloff. Contrary to rotating/panning the camera, this leaves the perspective intact, which makes it more like a 2D shift, and with it - I think - easier on the eyes. One might argue it is also "more realistic", since perspective remains unchanged when panning a camera in real life as well.

Open Saucer camera shake

The exact implementation would be engine-specific. In the Dry engine I use it's a matter of calling SetProjectionOffset(Vector2) on the Camera, either directly or through an attribute animation. This then affects the camera's 4x4 projection matrix, by scaling the first two elements of its third column.

魔大农
  • 91
  • 6