Skip to content

Commit 47afa48

Browse files
committed
AnimateVars - Major Refactor, everything works!
Update game_interpreter.cpp
1 parent 5bf5bce commit 47afa48

File tree

1 file changed

+107
-180
lines changed

1 file changed

+107
-180
lines changed

src/game_interpreter.cpp

Lines changed: 107 additions & 180 deletions
Original file line numberDiff line numberDiff line change
@@ -5200,129 +5200,65 @@ int Game_Interpreter::ManiacBitmask(int value, int mask) const {
52005200

52015201
return value;
52025202
}
5203-
std::vector<double> parseBezier(const std::string& bezierParams) {
5204-
std::vector<double> params;
5205-
std::string temp;
5206-
size_t startPos = bezierParams.find("(") + 1;
5207-
size_t endPos = bezierParams.find(")");
5208-
std::string valuesString = bezierParams.substr(startPos, endPos - startPos);
52095203

5210-
size_t commaPos = valuesString.find(",");
5211-
while (commaPos != std::string::npos) {
5212-
temp = valuesString.substr(0, commaPos);
5213-
params.push_back(std::stod(temp));
5214-
valuesString = valuesString.substr(commaPos + 1);
5215-
commaPos = valuesString.find(",");
5216-
}
5217-
// Push the last value into the vector
5218-
params.push_back(std::stod(valuesString));
5219-
5220-
return params;
5221-
}
5222-
5223-
//FIXME: cubicBezier is completely Broken
5224-
// references to how it should work:
5204+
// references for cubic bezier:
52255205
// https://matthewlein.com/tools/ceaser
52265206
// https://cubic-bezier.com/
5207+
double cubicBezier(float t, const double& p0,const double& p1, const double& p2, const double& p3) {
52275208

5228-
double cubicBezier(double t, double p0, double p1, double p2, double p3) {
5229-
double u = 1 - t;
5230-
double tt = t * t;
5231-
double uu = u * u;
5232-
double uuu = uu * u;
5233-
double ttt = tt * t;
5209+
float u = 1 - t;
5210+
float tt = t * t;
5211+
float uu = u * u;
5212+
float uuu = uu * u;
5213+
float ttt = tt * t;
52345214

5235-
double p = uuu * p0; // (1-t)^3
5236-
double q = 3 * uu * t * p1; // 3t(1-t)^2
5237-
double r = 3 * u * tt * p2; // 3(1-t)t^2
5238-
double s = ttt * p3; // t^3
5215+
//Point2d p = {0,0};
5216+
//p.x = uuu * 0 + 3 * uu * t * p0 + 3 * u * tt * p2 + ttt * 1;
5217+
return uuu * 0 + 3 * uu * t * p1 + 3 * u * tt * p3 + ttt * 1;
52395218

5240-
return p + q + r + s;
5219+
//return p.y;
52415220
}
52425221

5243-
double getEasedT(const std::string& easingType, double t, double b, double c, double d) {
5244-
if (easingType == "linear") {
5245-
return c * t / d + b;
5246-
}
5247-
else if (easingType == "quadIn") {
5248-
t /= d;
5249-
return c * t * t + b;
5250-
}
5251-
else if (easingType == "quadOut") {
5252-
t /= d;
5253-
return -c * t * (t - 2) + b;
5254-
}
5255-
else if (easingType == "quadInOut") {
5256-
t /= d / 2;
5257-
if (t < 1) {
5258-
return c / 2 * t * t + b;
5259-
}
5260-
else {
5261-
t -= 1;
5262-
return -c / 2 * (t * (t - 2) - 1) + b;
5263-
}
5264-
}
5265-
else if (easingType == "cubicIn") {
5266-
t /= d;
5267-
return c * t * t * t + b;
5268-
}
5269-
else if (easingType == "cubicOut") {
5270-
t = (t / d) - 1;
5271-
return c * (t * t * t + 1) + b;
5272-
}
5273-
else if (easingType == "cubicInOut") {
5274-
t /= d / 2;
5275-
if (t < 1) {
5276-
return c / 2 * t * t * t + b;
5277-
}
5278-
else {
5279-
t -= 2;
5280-
return c / 2 * (t * t * t + 2) + b;
5281-
}
5282-
}
5283-
else if (easingType == "sinIn") {
5284-
return -c * cos(t / d * (M_PI / 2)) + c + b;
5285-
}
5286-
else if (easingType == "sinOut") {
5287-
return c * sin(t / d * (M_PI / 2)) + b;
5288-
}
5289-
else if (easingType == "sinInOut") {
5290-
return -c / 2 * (cos(M_PI * t / d) - 1) + b;
5291-
}
5292-
else if (easingType == "expoIn") {
5293-
return c * pow(2, 10 * (t / d - 1)) + b;
5294-
}
5295-
else if (easingType == "expoOut") {
5296-
return c * (-pow(2, -10 * t / d) + 1) + b;
5297-
}
5298-
else if (easingType == "expoInOut") {
5299-
t /= d / 2;
5300-
if (t < 1) {
5301-
return c / 2 * pow(2, 10 * (t - 1)) + b;
5302-
}
5303-
else {
5304-
t -= 1;
5305-
return c / 2 * (-pow(2, -10 * t) + 2) + b;
5306-
}
5307-
}
5308-
else if (easingType == "circIn") {
5309-
t /= d;
5310-
return -c * (sqrt(1 - t * t) - 1) + b;
5311-
}
5312-
else if (easingType == "circOut") {
5313-
t = (t / d) - 1;
5314-
return c * sqrt(1 - t * t) + b;
5315-
}
5316-
else if (easingType == "circInOut") {
5317-
t /= d / 2;
5318-
if (t < 1) {
5319-
return -c / 2 * (sqrt(1 - t * t) - 1) + b;
5320-
}
5321-
else {
5322-
t -= 2;
5323-
return c / 2 * (sqrt(1 - t * t) + 1) + b;
5324-
}
5325-
}
5222+
double getEasedTime(const std::string& easingType, double t, double b, double c, double d) {
5223+
if (easingType == "linear") return cubicBezier(t, 0.250, 0.250, 0.750, 0.750);
5224+
5225+
else if (easingType == "ease") return cubicBezier(t, 0.250, 0.100, 0.250, 1.000);
5226+
else if (easingType == "easeIn") return cubicBezier(t, 0.420, 0.000, 1.000, 1.000);
5227+
else if (easingType == "easeOut") return cubicBezier(t, 0.000, 0.000, 0.580, 1.000);
5228+
else if (easingType == "easeInOut") return cubicBezier(t, 0.420, 0.000, 0.580, 1.000);
5229+
5230+
else if (easingType == "quadIn") return cubicBezier(t, 0.550, 0.085, 0.680, 0.530);
5231+
else if (easingType == "quadOut") return cubicBezier(t, 0.250, 0.460, 0.450, 0.940);
5232+
else if (easingType == "quadInOut") return cubicBezier(t, 0.455, 0.030, 0.515, 0.955);
5233+
5234+
else if (easingType == "cubicIn") return cubicBezier(t, 0.550, 0.055, 0.675, 0.190);
5235+
else if (easingType == "cubicOut") return cubicBezier(t, 0.215, 0.610, 0.355, 1.000);
5236+
else if (easingType == "cubicInOut") return cubicBezier(t, 0.645, 0.045, 0.355, 1.000);
5237+
5238+
else if (easingType == "quartIn") return cubicBezier(t, 0.895, 0.030, 0.685, 0.220);
5239+
else if (easingType == "quartOut") return cubicBezier(t, 0.165, 0.840, 0.440, 1.000);
5240+
else if (easingType == "quartInOut") return cubicBezier(t, 0.770, 0.000, 0.175, 1.000);
5241+
5242+
else if (easingType == "quintIn") return cubicBezier(t, 0.755, 0.050, 0.855, 0.060);
5243+
else if (easingType == "quintOut") return cubicBezier(t, 0.230, 1.000, 0.320, 1.000);
5244+
else if (easingType == "quintInOut") return cubicBezier(t, 0.860, 0.000, 0.070, 1.000);
5245+
5246+
else if (easingType == "sineIn") return cubicBezier(t, 0.470, 0.000, 0.745, 0.715);
5247+
else if (easingType == "sineOut") return cubicBezier(t, 0.390, 0.575, 0.565, 1.000);
5248+
else if (easingType == "sineInOut") return cubicBezier(t, 0.445, 0.050, 0.550, 0.950);
5249+
5250+
else if (easingType == "ExpoIn") return cubicBezier(t, 0.950, 0.050, 0.795, 0.035);
5251+
else if (easingType == "expoOut") return cubicBezier(t, 0.190, 1.000, 0.220, 1.000);
5252+
else if (easingType == "expoInOut") return cubicBezier(t, 1.000, 0.000, 0.000, 1.000);
5253+
5254+
else if (easingType == "circIn") return cubicBezier(t, 0.600, 0.040, 0.980, 0.335);
5255+
else if (easingType == "circOut") return cubicBezier(t, 0.075, 0.820, 0.165, 1.000);
5256+
else if (easingType == "circInOut") return cubicBezier(t, 0.785, 0.135, 0.150, 0.860);
5257+
5258+
else if (easingType == "backIn") return cubicBezier(t, 0.600, -0.280, 0.735, 0.045);
5259+
else if (easingType == "backOut") return cubicBezier(t, 0.175, 0.885, 0.320, 1.275);
5260+
else if (easingType == "backInOut") return cubicBezier(t, 0.680, -0.550, 0.265, 1.550);
5261+
53265262
else if (easingType == "elasticIn") {
53275263
if (t == 0) {
53285264
return b;
@@ -5372,8 +5308,9 @@ double getEasedT(const std::string& easingType, double t, double b, double c, do
53725308
double postFix = a * pow(2, -10 * (t -= 1)); // this is a fix, again, with post-increment operators
53735309
return postFix * sin((t * d - s) * (2 * M_PI) / p) * 0.5 + c + b;
53745310
}
5311+
53755312
else if (easingType == "bounceIn") {
5376-
return c - getEasedT("bounceOut", d - t, 0, c, d) + b;
5313+
return c - getEasedTime("bounceOut", d - t, 0, c, d) + b;
53775314
}
53785315
else if (easingType == "bounceOut") {
53795316
if ((t /= d) < (1 / 2.75)) {
@@ -5394,65 +5331,30 @@ double getEasedT(const std::string& easingType, double t, double b, double c, do
53945331
}
53955332
else if (easingType == "bounceInOut") {
53965333
if (t < d / 2) {
5397-
return getEasedT("bounceIn", t * 2, 0, c, d) * 0.5 + b;
5334+
return getEasedTime("bounceIn", t * 2, 0, c, d) * 0.5 + b;
53985335
}
53995336
else {
5400-
return getEasedT("bounceOut", t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
5401-
}
5402-
}
5403-
if (easingType.substr(0, 6) == "bezier") {
5404-
std::vector < double > bezierParams = parseBezier(easingType.substr(7));
5405-
if (bezierParams.size() == 4) {
5406-
return cubicBezier(t / d, bezierParams[0], bezierParams[1], bezierParams[2], bezierParams[3]);
5337+
return getEasedTime("bounceOut", t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
54075338
}
54085339
}
54095340

5410-
return c * t / d + b; // Default to linear easing if the easing type is not recognized
5411-
}
5412-
5413-
std::vector<double> interpolate(double start, double end, double duration, const std::string& easingTypeAtStart, const std::string& easingTypeAtEnd) {
5414-
std::vector<double> interpolatedValues;
5415-
interpolatedValues.push_back(start);
5341+
if (easingType.substr(0, 6) == "bezier") {
5342+
std::vector<double> bezierParams;
54165343

5417-
// Calculate the number of steps based on the duration
5418-
int numSteps = static_cast<int>(duration); // Convert duration to an integer
5419-
double stepSize = 1.0 / numSteps;
5344+
size_t startPos = easingType.find("(") + 1;
5345+
size_t endPos = easingType.find(")");
5346+
std::string valuesString = easingType.substr(startPos, endPos - startPos);
54205347

5421-
// Calculate the halfway point
5422-
double halfway = start + (end - start) * 0.5;
5348+
std::istringstream iss(valuesString);
5349+
double value;
54235350

5424-
if (easingTypeAtEnd == "null") {
5425-
// Use easingTypeAtStart for the entire animation
5426-
for (int step = 1; step <= numSteps; ++step) {
5427-
double t = step * stepSize;
5428-
double easedT = getEasedT(easingTypeAtStart, t, 0, 1, 1); // Call getEasedT with appropriate parameters
5429-
double interpolatedValue = start + easedT * (end - start);
5430-
interpolatedValues.push_back(interpolatedValue);
5431-
}
5432-
}
5433-
else {
5434-
// Generate the first half of the interpolation
5435-
for (int step = 1; step <= numSteps / 2; ++step) {
5436-
double t = step * stepSize;
5437-
double normalizedT = t / 0.5; // Normalize the time for the first half
5438-
double easedT = getEasedT(easingTypeAtStart, normalizedT, 0, 1, 1); // Call getEasedT with appropriate parameters
5439-
double interpolatedValue = start + easedT * (halfway - start);
5440-
interpolatedValues.push_back(interpolatedValue);
5441-
}
5351+
while (iss >> value) bezierParams.push_back(value), iss.ignore();
54425352

5443-
// Generate the second half of the interpolation
5444-
for (int step = numSteps / 2 + 1; step <= numSteps; ++step) {
5445-
double t = step * stepSize;
5446-
double normalizedT = (t - 0.5) / 0.5; // Normalize the time for the second half
5447-
double easedT = getEasedT(easingTypeAtEnd, normalizedT, 0, 1, 1); // Call getEasedT with appropriate parameters
5448-
double interpolatedValue = halfway + easedT * (end - halfway);
5449-
interpolatedValues.push_back(interpolatedValue);
5450-
}
5353+
if (bezierParams.size() == 4)
5354+
return cubicBezier(t, bezierParams[0], bezierParams[1], bezierParams[2], bezierParams[3]);
54515355
}
54525356

5453-
interpolatedValues.push_back(end);
5454-
5455-
return interpolatedValues;
5357+
return c * t / d + b; // Default to linear easing if the easing type is not recognized
54565358
}
54575359

54585360
bool Game_Interpreter::CommandAnimateVariable(lcf::rpg::EventCommand const& com) {
@@ -5463,42 +5365,67 @@ bool Game_Interpreter::CommandAnimateVariable(lcf::rpg::EventCommand const& com)
54635365
int32_t end = ValueOrVariable(com.parameters[4], com.parameters[5]);
54645366
int32_t duration = ValueOrVariable(com.parameters[6], com.parameters[7]);
54655367

5368+
// Extract easing information
5369+
std::string easingTypeAtStart = ToString(com.string);
5370+
std::string easingTypeAtEnd = "null";
5371+
5372+
std::size_t pos = easingTypeAtStart.find('/');
5373+
5374+
if (pos != std::string::npos) {
5375+
easingTypeAtEnd = easingTypeAtStart.substr(pos + 1);
5376+
easingTypeAtStart = easingTypeAtStart.substr(0, pos);
5377+
}
5378+
54665379
// Prepare animation-related commands
54675380
lcf::rpg::EventCommand waitCom;
54685381
waitCom.code = int(Cmd::Wait);
54695382

54705383
lcf::rpg::EventCommand animatedCom;
54715384
animatedCom.code = int(Cmd::ControlVars);
54725385
std::vector<int32_t> animatedVarParams = { 0, static_cast<int32_t>(target), 0, 0, 0, static_cast<int32_t>(end) };
5473-
animatedCom.parameters = lcf::DBArray<int32_t>(animatedVarParams.begin(), animatedVarParams.end());
54745386

54755387
std::vector<lcf::rpg::EventCommand> cmdList;
54765388

5477-
// Extract easing information
5478-
std::string easeStart = ToString(com.string);
5479-
std::string easeEnd = "null";
5389+
int numSteps = static_cast<int>(duration);
5390+
double stepSize = 1.0 / numSteps;
54805391

5481-
std::size_t pos = easeStart.find('/');
5392+
for (int step = 1; step <= numSteps; ++step) {
5393+
double normalizedTime;
5394+
double currentTime = step * stepSize;
5395+
double halfway;
54825396

5483-
if (pos != std::string::npos) {
5484-
easeEnd = easeStart.substr(pos + 1);
5485-
easeStart = easeStart.substr(0, pos);
5486-
}
5397+
std::string easingType;
5398+
5399+
if (easingTypeAtEnd == "null") { // use a single interpolation.
5400+
normalizedTime = currentTime;
5401+
easingType = easingTypeAtStart;
5402+
halfway = (step <= numSteps / 2) ? end : start;
5403+
}
5404+
else {
5405+
if (step <= numSteps / 2) { // use 2 interpolations: start and end.
5406+
normalizedTime = currentTime / 0.5;
5407+
easingType = easingTypeAtStart;
5408+
}
5409+
else {
5410+
normalizedTime = (currentTime - 0.5) / 0.5;
5411+
easingType = easingTypeAtEnd;
5412+
}
5413+
halfway = start + 0.5 * (end - start);
5414+
}
5415+
5416+
double easedTime = getEasedTime(easingType, normalizedTime, 0, 1, 1);
54875417

5488-
// Insert animation commands
5489-
std::vector<double> interpolatedValues = interpolate(start, end, duration, easeStart, easeEnd);
5418+
double startValue = (step <= numSteps / 2) ? start : halfway;
5419+
double endValue = (step <= numSteps / 2) ? halfway : end;
5420+
double interpolatedValue = startValue + easedTime * (endValue - startValue);
54905421

5491-
// Insert animatedCom and waitCom commands for each interpolated value
5492-
for (int value : interpolatedValues) {
5493-
animatedVarParams.back() = value;
5422+
animatedVarParams.back() = interpolatedValue;
54945423
animatedCom.parameters = lcf::DBArray<int32_t>(animatedVarParams.begin(), animatedVarParams.end());
5495-
animatedCom.indent = com.indent + 1;
54965424

54975425
cmdList.push_back(animatedCom);
54985426
cmdList.push_back(waitCom);
54995427
}
55005428

5501-
// Update current_command index and return true to indicate success
55025429
Push(cmdList, 0, false);
55035430
return true;
55045431
}

0 commit comments

Comments
 (0)