1 /*
2 * This file is part of EasyRPG Player.
3 *
4 * EasyRPG Player is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * EasyRPG Player is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #ifndef EP_SHAKE_H
19 #define EP_SHAKE_H
20
21 #define _USE_MATH_DEFINES
22 #include <cmath>
23 #include "utils.h"
24
25 /** Contains helper functions for flash effect */
26 namespace Shake {
27 static constexpr int kShakeContinuousTimeStart = 65535;
28
29 /**
30 * Computes new shake position from inputs
31 *
32 * @param strength strength of shake effect
33 * @param speed speed of shake effect
34 * @param time_left amount of time left for shake effect
35 * @param position current shake position
36 */
NextPosition(int strength,int speed,int time_left,int position)37 inline int NextPosition(int strength, int speed, int time_left, int position) {
38 int amplitude = 1 + 2 * strength;
39 int newpos = amplitude * sin((time_left * 4 * (speed + 2)) % 256 * M_PI / 128);
40 int cutoff = (speed * amplitude / 8) + 1;
41
42 return Utils::Clamp<int>(newpos, position - cutoff, position + cutoff);
43 }
44
45 /**
46 * Perform one time step of shake animation
47 *
48 * @param position shake position
49 * @param time_left amount of time left for shake effect
50 * @param strength strength of shake effect
51 * @param speed speed of shake effect
52 * @param continous whether this is a continuous shake
53 */
Update(int32_t & position,int32_t & time_left,int32_t strength,int32_t speed,bool continuous)54 inline void Update(int32_t& position, int32_t& time_left, int32_t strength, int32_t speed, bool continuous)
55 {
56 if (time_left > 0) {
57 --time_left;
58
59 // This fixes a bug in RPG_RT where continuous shake would actually stop after
60 // 18m12s of gameplay.
61 if (time_left <= 0 && continuous) {
62 time_left = kShakeContinuousTimeStart;
63 }
64
65 if (time_left > 0) {
66 position = NextPosition(strength, speed, time_left, position);
67 } else {
68 position = 0;
69 time_left = 0;
70 }
71 }
72 }
73
74 } //namespace Shake
75
76 #endif
77