Implement a camera shake

Started by
2 comments, last by Koshmaar 18 years, 3 months ago
Hello, Can someone suggest what is a good way to implement a camera shake? Thanks!
Nachi Lau (In Christ, I never die)www.sky-dio.com/Nachi
Advertisement
Modulate the normal movement of the camera with high-frequency, low amplitude sines/cosines, perhaps?
My way of doing this was to take several random points in a certain radius, and then construct a spline based on them. Using TCB you can choose proper coefficients for desired smoothness/"sharpness".

Then use it as an offset for, say, 3 seconds long amount of time.
Here's a small sample from my engine's API. I have incorporated shaking into Renderer class.

Header:

  //! Only sets some values, actual shaking will appear on the next frame and will last for _time miliseconds.  void ShakeScreen(int _factorX, int _factorY, ulint _time);       void SetShakeBoundaries(int _boundaryX, int _boundaryY)   {    boundaryX = _boundaryX;    boundaryY = _boundaryY;    }  //! Immediately sets shake screen state to given _state  void SetShakeScreenState(bool _state) { shakeScreenEnabled = _state; }       //! Returns actual shake screen state   bool GetShakeScreenState() const { return shakeScreenEnabled; }        void UpdateShakeState(); // -------------------------------------------------             private:             bool shakeScreenEnabled;     float shakeFactorX, shakeFactorY;     TimeMarker shakeStart;     ulint shakeTime;     int boundaryX, boundaryY;


Implementation:

// ------------------------------------------------- start Rendervoid SC :: Renderer :: Render() {  if (shakeScreenEnabled && shakeTime)   {    UpdateShakeState();   }     SDL_GL_SwapBuffers(); }// ------------------------------------------------- end Render// ------------------------------------------------- start ShakeScreen void SC :: Renderer :: ShakeScreen(int _factorX, int _factorY, ulint _time) {  // multiple users can call ShakeScreen, screen should be shaked for the longest time  if (shakeTime == 0)   {    shakeTime = _time;    glPushMatrix();    shakeStart.Mark();   }  else   {    shakeTime = Max(shakeTime, _time);   }     shakeFactorX += _factorX;  shakeFactorY += _factorY;   }     // ------------------------------------------------- end ShakeScreen// ------------------------------------------------- start UpdateShakeStatevoid SC :: Renderer :: UpdateShakeState() {  if (shakeStart.HasElapsed(shakeTime))   {    shakeTime = 0;    shakeStart.Reset();    glPopMatrix();    shakeFactorX = 0;    shakeFactorY = 0;    return;   }    else   {    int sign = 1;    if (getRandGen.Integer(100) > 50)	 sign = -1;	     glPopMatrix();    glPushMatrix();    float timeLeft =  ( (float) shakeTime - (float) shakeStart.HowManyElapsed() + 1) / 1000.0f;	     float shakeX = sign * timeLeft * (getRandGen.FloatingPoint( shakeFactorX * 8 ) / 8) ;    float shakeY = sign * timeLeft * (getRandGen.FloatingPoint( shakeFactorY * 8 ) / 8) ;        shakeX -= 10 * getTimer.GetDeltaTime();    shakeY -= 10 * getTimer.GetDeltaTime();        shakeX = ClampTo(shakeX, (float) -boundaryX, (float) boundaryX);    shakeY = ClampTo(shakeY, (float) -boundaryY, (float) boundaryY);    glTranslatef( shakeX, shakeY, 0 );   } } // ------------------------------------------------- end UpdateShakeState


Sample usage:

 if ( getInput.GetMouseButtonNowPressed(mb_Left) )  getRenderer.ShakeScreen(2, 2, 15000); // will shake a little for 15 seconds


You can see how this this shake looks in real world game - it's been used in "Herbata Kto Ty Tak Kroliczk" (link in sig).

HTH :-)

This topic is closed to new replies.

Advertisement