diff --git a/api/build.gradle b/api/build.gradle index 0d3e20c7..2022cb11 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -12,4 +12,5 @@ repositories { dependencies { implementation "org.joml:joml:${jomlVersion}" implementation "org.slf4j:slf4j-api:${slf4jVersion}" + implementation "org.apache.commons:commons-math3:${apacheCommonsVersion}" } \ No newline at end of file diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationDelegate.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationDelegate.java new file mode 100644 index 00000000..0fc6736b --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationDelegate.java @@ -0,0 +1,147 @@ +package com.bartlomiejpluta.base.api.game.animation; + +import com.bartlomiejpluta.base.api.game.camera.Camera; +import com.bartlomiejpluta.base.api.game.screen.Screen; +import com.bartlomiejpluta.base.api.internal.object.Placeable; +import com.bartlomiejpluta.base.api.internal.render.ShaderManager; +import org.joml.Matrix4fc; +import org.joml.Vector2fc; +import org.joml.Vector2ic; + +public abstract class AnimationDelegate implements Animation { + private final Animation animation; + + public AnimationDelegate(Animation animation) { + this.animation = animation; + } + + @Override + public void setStepSize(float x, float y) { + animation.setStepSize(x, y); + } + + @Override + public Vector2ic getCoordinates() { + return animation.getCoordinates(); + } + + @Override + public void setCoordinates(Vector2ic coordinates) { + animation.setCoordinates(coordinates); + } + + @Override + public void setCoordinates(int x, int y) { + animation.setCoordinates(x, y); + } + + @Override + public void setAnimationSpeed(float speed) { + animation.setAnimationSpeed(speed); + } + + @Override + public Integer getRepeat() { + return animation.getRepeat(); + } + + @Override + public void setRepeat(Integer repeat) { + animation.setRepeat(repeat); + } + + @Override + public boolean finished() { + return animation.finished(); + } + + @Override + public void update(float dt) { + animation.update(dt); + } + + @Override + public Vector2fc getPosition() { + return animation.getPosition(); + } + + @Override + public void setPosition(float x, float y) { + animation.setPosition(x, y); + } + + @Override + public void setPosition(Vector2fc position) { + animation.setPosition(position); + } + + @Override + public void movePosition(float x, float y) { + animation.movePosition(x, y); + } + + @Override + public void movePosition(Vector2fc position) { + animation.movePosition(position); + } + + @Override + public float getRotation() { + return animation.getRotation(); + } + + @Override + public void setRotation(float rotation) { + animation.setRotation(rotation); + } + + @Override + public void moveRotation(float rotation) { + animation.moveRotation(rotation); + } + + @Override + public float getScaleX() { + return animation.getScaleX(); + } + + @Override + public void setScaleX(float scale) { + animation.setScaleX(scale); + } + + @Override + public float getScaleY() { + return animation.getScaleY(); + } + + @Override + public void setScaleY(float scale) { + animation.setScaleY(scale); + } + + @Override + public void setScale(float scale) { + animation.setScale(scale); + } + + @Override + public void setScale(float scaleX, float scaleY) { + animation.setScale(scaleX, scaleY); + } + + @Override + public float euclideanDistance(Placeable other) { + return animation.euclideanDistance(other); + } + + @Override + public Matrix4fc getModelMatrix() { + return animation.getModelMatrix(); + } + + @Override + public void render(Screen screen, Camera camera, ShaderManager shaderManager) { + animation.render(screen, camera, shaderManager); + } +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationRunner.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationRunner.java new file mode 100644 index 00000000..0a709831 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/AnimationRunner.java @@ -0,0 +1,9 @@ +package com.bartlomiejpluta.base.api.game.animation; + +import com.bartlomiejpluta.base.api.game.context.Context; +import com.bartlomiejpluta.base.api.game.map.layer.base.Layer; +import org.joml.Vector2fc; + +public interface AnimationRunner { + void run(Context context, Layer layer, Vector2fc origin); +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/DelayedAnimation.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/DelayedAnimation.java new file mode 100644 index 00000000..6b4df4ec --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/DelayedAnimation.java @@ -0,0 +1,31 @@ +package com.bartlomiejpluta.base.api.game.animation; + +import com.bartlomiejpluta.base.api.game.camera.Camera; +import com.bartlomiejpluta.base.api.game.screen.Screen; +import com.bartlomiejpluta.base.api.internal.render.ShaderManager; + +public class DelayedAnimation extends AnimationDelegate { + private final int delay; + private int accumulator = 0; + + public DelayedAnimation(Animation animation, int delay) { + super(animation); + this.delay = delay; + } + + @Override + public void update(float dt) { + if (accumulator >= delay) { + super.update(dt); + } else { + accumulator += dt * 1000; + } + } + + @Override + public void render(Screen screen, Camera camera, ShaderManager shaderManager) { + if (accumulator >= delay) { + super.render(screen, camera, shaderManager); + } + } +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/RandomAnimationsRunner.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/RandomAnimationsRunner.java new file mode 100644 index 00000000..c3234502 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/RandomAnimationsRunner.java @@ -0,0 +1,140 @@ +package com.bartlomiejpluta.base.api.game.animation; + +import com.bartlomiejpluta.base.api.game.context.Context; +import com.bartlomiejpluta.base.api.game.map.layer.base.Layer; +import org.apache.commons.math3.distribution.NormalDistribution; +import org.apache.commons.math3.distribution.RealDistribution; +import org.apache.commons.math3.distribution.UniformRealDistribution; +import org.joml.Vector2fc; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import static java.lang.Math.max; + +public class RandomAnimationsRunner implements AnimationRunner { + private final Random random = new Random(); + private final List animationUids = new ArrayList<>(); + private final int count; + + private float scale = 1.0f; + private RealDistribution scaleDistribution; + + private float rangeX = 0f; + private float rangeY = 0f; + private RealDistribution rangeDistribution; + + private float delay = 0f; + private RealDistribution delayDistribution; + + private float speed = 0.05f; + private RealDistribution speedDistribution; + + private float rotation = 0f; + private RealDistribution rotationDistribution; + + public RandomAnimationsRunner(int count) { + this.count = max(count, 0); + } + + public RandomAnimationsRunner with(String animationUid) { + animationUids.add(animationUid); + return this; + } + + public RandomAnimationsRunner scale(float scale) { + this.scale = scale; + return this; + } + + public RandomAnimationsRunner uScale(float min, float max) { + this.scaleDistribution = new UniformRealDistribution(min, max); + return this; + } + + public RandomAnimationsRunner nScale(float mean, float sd) { + this.scaleDistribution = new NormalDistribution(mean, sd); + return this; + } + + public RandomAnimationsRunner range(float rangeX, float rangeY) { + this.rangeX = rangeX; + this.rangeY = rangeY; + return this; + } + + public RandomAnimationsRunner uRange(float min, float max) { + this.rangeDistribution = new UniformRealDistribution(min, max); + return this; + } + + public RandomAnimationsRunner nRange(float mean, float sd) { + this.rangeDistribution = new NormalDistribution(mean, sd); + return this; + } + + public RandomAnimationsRunner speed(float speed) { + this.speed = speed; + return this; + } + + public RandomAnimationsRunner uSpeed(float min, float max) { + this.speedDistribution = new UniformRealDistribution(min, max); + return this; + } + + public RandomAnimationsRunner nSpeed(float mean, float sd) { + this.speedDistribution = new NormalDistribution(mean, sd); + return this; + } + + public RandomAnimationsRunner delay(float delay) { + this.delay = delay; + return this; + } + + public RandomAnimationsRunner uDelay(float min, float max) { + this.delayDistribution = new UniformRealDistribution(min, max); + return this; + } + + public RandomAnimationsRunner nDelay(float mean, float sd) { + this.delayDistribution = new NormalDistribution(mean, sd); + return this; + } + + public RandomAnimationsRunner rotation(float rotation) { + this.rotation = rotation; + return this; + } + + public RandomAnimationsRunner uRotation(float min, float max) { + this.rotationDistribution = new UniformRealDistribution(min, max); + return this; + } + + public RandomAnimationsRunner nRotation(float mean, float sd) { + this.rotationDistribution = new NormalDistribution(mean, sd); + return this; + } + + @Override + public void run(Context context, Layer layer, Vector2fc origin) { + for (int i = 0; i < count; ++i) { + var animation = context.createAnimation(animationUids.get(random.nextInt(animationUids.size()))); + + if (rangeDistribution != null) { + animation.setPosition(origin.x() + (float) rangeDistribution.sample(), origin.y() + (float) rangeDistribution.sample()); + } else { + animation.setPosition(origin.x() + rangeX, origin.y() + rangeY); + } + + animation.setScale(scaleDistribution != null ? (float) scaleDistribution.sample() : scale); + animation.setAnimationSpeed(speedDistribution != null ? (float) speedDistribution.sample() : speed); + animation.setRotation(rotationDistribution != null ? (float) rotationDistribution.sample() : rotation); + + layer.pushAnimation(new DelayedAnimation(animation, (int) (delayDistribution != null ? delayDistribution.sample() : delay))); + } + } +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/SimpleAnimationRunner.java b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/SimpleAnimationRunner.java new file mode 100644 index 00000000..625cfcb0 --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/game/animation/SimpleAnimationRunner.java @@ -0,0 +1,56 @@ +package com.bartlomiejpluta.base.api.game.animation; + +import com.bartlomiejpluta.base.api.game.context.Context; +import com.bartlomiejpluta.base.api.game.map.layer.base.Layer; +import org.joml.Vector2fc; + +public class SimpleAnimationRunner implements AnimationRunner { + private final String animationUid; + + private Integer repeat = 1; + private float scale = 1.0f; + private int delay = 0; + private float speed = 0.05f; + private float rotation = 0f; + + public SimpleAnimationRunner(String animationUid) { + this.animationUid = animationUid; + } + + public SimpleAnimationRunner repeat(int n) { + this.repeat = n; + return this; + } + + public SimpleAnimationRunner infinite() { + this.repeat = null; + return this; + } + + public SimpleAnimationRunner scale(float scale) { + this.scale = scale; + return this; + } + + public SimpleAnimationRunner delay(int delay) { + this.delay = delay; + return this; + } + + public SimpleAnimationRunner speed(float speed) { + this.speed = speed; + return this; + } + + public SimpleAnimationRunner rotation(float rotation) { + this.rotation = rotation; + return this; + } + + @Override + public void run(Context context, Layer layer, Vector2fc origin) { + var animation = new DelayedAnimation(context.createAnimation(animationUid), delay); + animation.setPosition(origin); + layer.pushAnimation(animation); + } +} diff --git a/gradle.properties b/gradle.properties index a8a6f238..be0cfe16 100644 --- a/gradle.properties +++ b/gradle.properties @@ -10,4 +10,5 @@ ikonliVersion=12.2.0 protobufPluginVersion=0.8.14 protobufVersion=3.14.0 richtextfxVersion=0.10.5 -janinoVersion=3.1.3 \ No newline at end of file +janinoVersion=3.1.3 +apacheCommonsVersion=3.6.1 \ No newline at end of file