diff --git a/build/pack.bat b/build/pack.bat index 73ad2ee..5af2a8e 100644 --- a/build/pack.bat +++ b/build/pack.bat @@ -6,4 +6,5 @@ dotnet pack ../src/OpenRpg.Localization -c Release -o ../../_dist /p:version=%ve dotnet pack ../src/OpenRpg.Data -c Release -o ../../_dist /p:version=%version% dotnet pack ../src/OpenRpg.Quests -c Release -o ../../_dist /p:version=%version% dotnet pack ../src/OpenRpg.Genres.Fantasy -c Release -o ../../_dist /p:version=%version% -dotnet pack ../src/OpenRpg.Cards -c Release -o ../../_dist /p:version=%version% \ No newline at end of file +dotnet pack ../src/OpenRpg.Cards -c Release -o ../../_dist /p:version=%version% +dotnet pack ../src/OpenRpg.CurveFunctions -c Release -o ../../_dist /p:version=%version% \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/LogisticCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/LogisticCurveFunction.cs new file mode 100644 index 0000000..8967adf --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/LogisticCurveFunction.cs @@ -0,0 +1,27 @@ +using System; +using OpenRpg.CurveFunctions.Extensions; + +namespace OpenRpg.CurveFunctions.Curves +{ + public class LogisticCurveFunction : ICurveFunction + { + public float Slope { get; } + public float VerticalSize { get; } + public float YShift { get; } + public float XShift { get; } + + public LogisticCurveFunction(float slope, float xShift, float yShift, float verticalSize) + { + Slope = slope; + XShift = xShift; + YShift = yShift; + VerticalSize = verticalSize; + } + + public float Plot(float value) + { + var outputValue = (float)(Slope / (1 + Math.Exp(-10.0 * VerticalSize * (value - 0.5 - XShift))) + YShift); + return this.SanitizeValue(outputValue); + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/LogitCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/LogitCurveFunction.cs new file mode 100644 index 0000000..6a230f9 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/LogitCurveFunction.cs @@ -0,0 +1,25 @@ +using System; +using OpenRpg.CurveFunctions.Extensions; + +namespace OpenRpg.CurveFunctions.Curves +{ + public class LogitCurveFunction : ICurveFunction + { + public float Slope { get; } + public float YShift { get; } + public float XShift { get; } + + public LogitCurveFunction(float slope, float xShift, float yShift) + { + Slope = slope; + XShift = xShift; + YShift = yShift; + } + + public float Plot(float value) + { + var outputValue = (float)(Slope * Math.Log((value - XShift) / (1.0 - (value - XShift))) / 5.0 + 0.5 + YShift); + return this.SanitizeValue(outputValue); + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/NormalCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/NormalCurveFunction.cs new file mode 100644 index 0000000..34979a9 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/NormalCurveFunction.cs @@ -0,0 +1,27 @@ +using System; +using OpenRpg.CurveFunctions.Extensions; + +namespace OpenRpg.CurveFunctions.Curves +{ + public class NormalCurveFunction : ICurveFunction + { + public float Slope { get; } + public float YShift { get; } + public float XShift { get; } + public float Exponent { get; } + + public NormalCurveFunction(float slope, float xShift, float yShift, float exponent) + { + Slope = slope; + XShift = xShift; + YShift = yShift; + Exponent = exponent; + } + + public float Plot(float value) + { + var outputValue = (float)(Slope * Math.Exp(-30.0 * Exponent * (value - XShift - 0.5) * (value - XShift - 0.5)) + YShift); + return this.SanitizeValue(outputValue); + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/PassThroughlCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/PassThroughlCurveFunction.cs new file mode 100644 index 0000000..7f7b392 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/PassThroughlCurveFunction.cs @@ -0,0 +1,8 @@ +namespace OpenRpg.CurveFunctions.Curves +{ + public class PassThroughlCurveFunction : ICurveFunction + { + public float Plot(float value) + { return value; } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/PolynomialCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/PolynomialCurveFunction.cs new file mode 100644 index 0000000..f72280f --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/PolynomialCurveFunction.cs @@ -0,0 +1,27 @@ +using System; +using OpenRpg.CurveFunctions.Extensions; + +namespace OpenRpg.CurveFunctions.Curves +{ + public class PolynomialCurveFunction : ICurveFunction + { + public float Slope { get; } + public float Exponent { get; } + public float YShift { get; } + public float XShift { get; } + + public PolynomialCurveFunction(float slope, float xShift, float yShift, float exponent) + { + Slope = slope; + XShift = xShift; + YShift = yShift; + Exponent = exponent; + } + + public float Plot(float value) + { + var outputValue = Slope * (float)Math.Pow((value - XShift), Exponent) + YShift; + return this.SanitizeValue(outputValue); + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/SineCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/SineCurveFunction.cs new file mode 100644 index 0000000..8a89c94 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/SineCurveFunction.cs @@ -0,0 +1,25 @@ +using System; +using OpenRpg.CurveFunctions.Extensions; + +namespace OpenRpg.CurveFunctions.Curves +{ + public class SineCurveFunction : ICurveFunction + { + public float Slope { get; } + public float YShift { get; } + public float XShift { get; } + + public SineCurveFunction(float slope, float xShift, float yShift) + { + Slope = slope; + XShift = xShift; + YShift = yShift; + } + + public float Plot(float value) + { + var outputValue = (float)(0.5 * Slope * Math.Sin(2.0 * Math.PI * (value - XShift)) + 0.5 + YShift); + return this.SanitizeValue(outputValue); + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Curves/StepCurveFunction.cs b/src/OpenRpg.CurveFunctions/Curves/StepCurveFunction.cs new file mode 100644 index 0000000..d66a373 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Curves/StepCurveFunction.cs @@ -0,0 +1,19 @@ +namespace OpenRpg.CurveFunctions.Curves +{ + public class StepCurveFunction : ICurveFunction + { + public float StepValue { get; } + public float MinValue { get; } + public float MaxValue { get; } + + public StepCurveFunction(float stepValue, float minValue = 0.0f, float maxValue = 1.0f) + { + StepValue = stepValue; + MinValue = minValue; + MaxValue = maxValue; + } + + public float Plot(float value) + { return value < StepValue ? MinValue : MaxValue; } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/Extensions/IEvaluatorExtensions.cs b/src/OpenRpg.CurveFunctions/Extensions/IEvaluatorExtensions.cs new file mode 100644 index 0000000..19822bb --- /dev/null +++ b/src/OpenRpg.CurveFunctions/Extensions/IEvaluatorExtensions.cs @@ -0,0 +1,14 @@ +namespace OpenRpg.CurveFunctions.Extensions +{ + public static class ICurveFunctionExtensions + { + public static float SanitizeValue(this ICurveFunction curve, float value) + { + if(float.IsInfinity(value)) { return 0.0f; } + if(float.IsNaN(value)) { return 0.0f; } + if(value < 0 ) { return 0.0f; } + if(value > 1.0f ) { return 1.0f; } + return value; + } + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/ICurveFunction.cs b/src/OpenRpg.CurveFunctions/ICurveFunction.cs new file mode 100644 index 0000000..a04960c --- /dev/null +++ b/src/OpenRpg.CurveFunctions/ICurveFunction.cs @@ -0,0 +1,7 @@ +namespace OpenRpg.CurveFunctions +{ + public interface ICurveFunction + { + float Plot(float value); + } +} \ No newline at end of file diff --git a/src/OpenRpg.CurveFunctions/OpenRpg.CurveFunctions.csproj b/src/OpenRpg.CurveFunctions/OpenRpg.CurveFunctions.csproj new file mode 100644 index 0000000..2cdc0f0 --- /dev/null +++ b/src/OpenRpg.CurveFunctions/OpenRpg.CurveFunctions.csproj @@ -0,0 +1,14 @@ + + + + 0.0.0 + netstandard2.0;net46 + OpenRpg.CurveFunctions + Grofit (LP) + https://github.com/openrpg/OpenRpg/blob/master/LICENSE + https://github.com/openrpg/OpenRpg + Adds premade curve functions for scaling values or other use cases + rpg game-development xna monogame unity godot + + + diff --git a/src/OpenRpg.CurveFunctions/PresetCurves.cs b/src/OpenRpg.CurveFunctions/PresetCurves.cs new file mode 100644 index 0000000..7a5261f --- /dev/null +++ b/src/OpenRpg.CurveFunctions/PresetCurves.cs @@ -0,0 +1,28 @@ +using OpenRpg.CurveFunctions.Curves; + +namespace OpenRpg.CurveFunctions +{ + public class PresetCurves + { + public static ICurveFunction Constant = new PolynomialCurveFunction(0f, 0, 0.5f, 0); + public static ICurveFunction Linear = new PolynomialCurveFunction(1.0f, 0, 0, 1.0f); + public static ICurveFunction InverseLinear = new PolynomialCurveFunction(-1.0f, 1.0f, 0, 1.0f); + public static ICurveFunction StandardCooldown = new PolynomialCurveFunction(1.0f, 0f, 0, 6.0f); + public static ICurveFunction StandardRuntime = new PolynomialCurveFunction(-1.0f, 0f, 1.0f, 6.0f); + public static ICurveFunction QuadraticLowerLeft = new PolynomialCurveFunction(1.0f, 1.0f, 0.0f, 4.0f); + public static ICurveFunction QuadraticLowerRight = new PolynomialCurveFunction(1.0f, 0.0f, 0.0f, 4.0f); + public static ICurveFunction QuadraticUpperLeft = new PolynomialCurveFunction(-1.0f, 1.0f, 1.0f, 4.0f); + public static ICurveFunction QuadraticUpperRight = new PolynomialCurveFunction(-1.0f, 0f, 1.0f, 4.0f); + public static ICurveFunction Logistic = new LogisticCurveFunction(1.0f, 0f, 0.0f, 1.0f); + public static ICurveFunction InverseLogistic = new LogisticCurveFunction(-1.0f, 0f, 1.0f, 1.0f); + public static ICurveFunction Logit = new LogitCurveFunction(1.0f, 0, 0); + public static ICurveFunction InverseLogit = new LogitCurveFunction(-1.0f, 0, 0); + public static ICurveFunction BellCurve = new NormalCurveFunction(1.0f, 0, 0, 1.0f); + public static ICurveFunction InverseBellCurve = new NormalCurveFunction(-1.0f, 0, 1.0f, 1.0f); + public static ICurveFunction SineWave = new SineCurveFunction(1.0f, 0, 0); + public static ICurveFunction InverseSineWave = new SineCurveFunction(-1.0f, 0, 0); + public static ICurveFunction GreaterThanHalf = new StepCurveFunction(0.5f); + public static ICurveFunction LessThanHalf = new StepCurveFunction(0.5f, 1.0f, 0.0f); + public static ICurveFunction PassThrough = new PassThroughlCurveFunction(); + } +} \ No newline at end of file diff --git a/src/OpenRpg.sln b/src/OpenRpg.sln index 3b58309..e0522d1 100644 --- a/src/OpenRpg.sln +++ b/src/OpenRpg.sln @@ -24,6 +24,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Cards", "Cards", "{C5E5EB5E EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRpg.Cards", "OpenRpg.Cards\OpenRpg.Cards.csproj", "{2A8FA13E-2E89-457B-9457-46C345768495}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Scaling", "Scaling", "{1566BC2E-78DC-4998-BEC8-65CEC3EC9A88}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenRpg.CurveFunctions", "OpenRpg.CurveFunctions\OpenRpg.CurveFunctions.csproj", "{91C35205-4EB6-4204-964E-D94427D362AA}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -58,6 +62,10 @@ Global {2A8FA13E-2E89-457B-9457-46C345768495}.Debug|Any CPU.Build.0 = Debug|Any CPU {2A8FA13E-2E89-457B-9457-46C345768495}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A8FA13E-2E89-457B-9457-46C345768495}.Release|Any CPU.Build.0 = Release|Any CPU + {91C35205-4EB6-4204-964E-D94427D362AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {91C35205-4EB6-4204-964E-D94427D362AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {91C35205-4EB6-4204-964E-D94427D362AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {91C35205-4EB6-4204-964E-D94427D362AA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {86FD715B-0B33-40EB-B8AC-25EE62398A66} = {6BE3D2A4-F53A-4879-868E-A7522A445FE9} @@ -67,5 +75,6 @@ Global {8D5C52B0-B68B-4539-9D2F-DA22C825B923} = {56A39779-8FA4-499E-8EF9-4757765CC230} {754A79DD-AC13-4EC1-9DDA-AF5D5F6DABCE} = {98CD79A9-0E41-49CE-8246-3A32C1A2E004} {2A8FA13E-2E89-457B-9457-46C345768495} = {C5E5EB5E-7F08-4CF4-B4DF-F20434DE2930} + {91C35205-4EB6-4204-964E-D94427D362AA} = {1566BC2E-78DC-4998-BEC8-65CEC3EC9A88} EndGlobalSection EndGlobal