00001
00002
00003
00004
00005
00006
00007
00009
00010 #include "utils.h"
00011 #include <cassert>
00012 #include <cstdarg>
00013 #include "video.h"
00014 #include <math.h>
00015 #include "gui.h"
00016
00017 using namespace std;
00018 using namespace hoa_video::private_video;
00019
00020 namespace hoa_video
00021 {
00022
00023
00024 const int32 VIDEO_TIME_BETWEEN_SHAKE_UPDATES = 50;
00025
00026
00027
00028
00029
00030
00031
00032 bool GameVideo::ShakeScreen(float force, float falloff_time, ShakeFalloff falloff_method)
00033 {
00034
00035 if(force < 0.0f)
00036 {
00037 if(VIDEO_DEBUG)
00038 cerr << "VIDEO ERROR: passed negative force to ShakeScreen()!" << endl;
00039 return false;
00040 }
00041
00042 if(falloff_time < 0.0f)
00043 {
00044 if(VIDEO_DEBUG)
00045 cerr << "VIDEO ERROR: passed negative falloff time to ShakeScreen()!" << endl;
00046 return false;
00047 }
00048
00049 if(falloff_method <= VIDEO_FALLOFF_INVALID || falloff_method >= VIDEO_FALLOFF_TOTAL)
00050 {
00051 if(VIDEO_DEBUG)
00052 cerr << "VIDEO ERROR: passed invalid shake method to ShakeScreen()!" << endl;
00053 return false;
00054 }
00055
00056 if(falloff_time == 0.0f && falloff_method != VIDEO_FALLOFF_NONE)
00057 {
00058 if(VIDEO_DEBUG)
00059 cerr << "VIDEO ERROR: ShakeScreen() called with 0.0f (infinite), but falloff method was not VIDEO_FALLOFF_NONE!" << endl;
00060 return false;
00061 }
00062
00063
00064
00065 int32 milliseconds = int32(falloff_time * 1000);
00066 ShakeForce s;
00067 s.current_time = 0;
00068 s.end_time = milliseconds;
00069 s.initial_force = force;
00070
00071
00072
00073 switch(falloff_method)
00074 {
00075 case VIDEO_FALLOFF_NONE:
00076 s.interpolator.SetMethod(VIDEO_INTERPOLATE_SRCA);
00077 s.interpolator.Start(force, 0.0f, milliseconds);
00078 break;
00079
00080 case VIDEO_FALLOFF_EASE:
00081 s.interpolator.SetMethod(VIDEO_INTERPOLATE_EASE);
00082 s.interpolator.Start(0.0f, force, milliseconds);
00083 break;
00084
00085 case VIDEO_FALLOFF_LINEAR:
00086 s.interpolator.SetMethod(VIDEO_INTERPOLATE_LINEAR);
00087 s.interpolator.Start(force, 0.0f, milliseconds);
00088 break;
00089
00090 case VIDEO_FALLOFF_GRADUAL:
00091 s.interpolator.SetMethod(VIDEO_INTERPOLATE_SLOW);
00092 s.interpolator.Start(force, 0.0f, milliseconds);
00093 break;
00094
00095 case VIDEO_FALLOFF_SUDDEN:
00096 s.interpolator.SetMethod(VIDEO_INTERPOLATE_FAST);
00097 s.interpolator.Start(force, 0.0f, milliseconds);
00098 break;
00099
00100 default:
00101 {
00102 if(VIDEO_DEBUG)
00103 cerr << "VIDEO ERROR: falloff method passed to ShakeScreen() was not supported!" << endl;
00104 return false;
00105 }
00106 };
00107
00108
00109 _shake_forces.push_front(s);
00110
00111 return true;
00112 }
00113
00114
00115
00116
00117
00118
00119 bool GameVideo::StopShaking()
00120 {
00121 _shake_forces.clear();
00122 _x_shake = _y_shake = 0.0f;
00123 return true;
00124 }
00125
00126
00127
00128
00129
00130
00131 bool GameVideo::IsShaking()
00132 {
00133 return !_shake_forces.empty();
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 float GameVideo::_RoundForce(float force)
00147 {
00148 int32 fraction_pct = int32(force * 100) - (int32(force) * 100);
00149
00150 int32 r = rand()%100;
00151 if(fraction_pct > r)
00152 force = ceilf(force);
00153 else
00154 force = floorf(force);
00155
00156 return force;
00157 }
00158
00159
00160
00161
00162
00163
00164
00165 void GameVideo::_UpdateShake(int32 frame_time)
00166 {
00167 if(_shake_forces.empty())
00168 {
00169 _x_shake = _y_shake = 0;
00170 return;
00171 }
00172
00173
00174
00175
00176 float net_force = 0.0f;
00177
00178 list<ShakeForce>::iterator iShake = _shake_forces.begin();
00179 list<ShakeForce>::iterator iEnd = _shake_forces.end();
00180
00181 while(iShake != iEnd)
00182 {
00183 ShakeForce &s = *iShake;
00184 s.current_time += frame_time;
00185
00186 if(s.end_time != 0 && s.current_time >= s.end_time)
00187 {
00188 iShake = _shake_forces.erase(iShake);
00189 }
00190 else
00191 {
00192 s.interpolator.Update(frame_time);
00193 net_force += s.interpolator.GetValue();
00194 ++iShake;
00195 }
00196 }
00197
00198
00199
00200 static int32 time_til_next_update = 0;
00201 time_til_next_update -= frame_time;
00202
00203 if(time_til_next_update > 0)
00204 return;
00205
00206 time_til_next_update = VIDEO_TIME_BETWEEN_SHAKE_UPDATES;
00207
00208
00209
00210
00211
00212
00213 _x_shake = _RoundForce(RandomFloat(-net_force, net_force));
00214 _y_shake = _RoundForce(RandomFloat(-net_force, net_force));
00215 }
00216
00217
00218 }