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