Skip to content

Instantly share code, notes, and snippets.

@hugmanrique
Last active October 22, 2022 02:30
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hugmanrique/1bd273e3b20b419f625c437db61b7ff9 to your computer and use it in GitHub Desktop.
Save hugmanrique/1bd273e3b20b419f625c437db61b7ff9 to your computer and use it in GitHub Desktop.
Small ArmorStand animation created with the Bukkit API
public class SwordAnimation {
// Config variables
private static final float SEPARATOR = 2;
private static final float RAD_PER_SEC = 1.5F;
private static final float RAD_PER_TICK = RAD_PER_SEC / 20F;
private Location center;
private double radius;
private List<ArmorStand> swords;
public SwordAnimation(Location center, double radius) {
this.center = center;
this.radius = radius;
swords = Lists.newArrayList();
}
public void start(JavaPlugin plugin) {
for (double angle = 0; angle < Math.PI * 2; angle += SEPARATOR) {
spawnStand(angle);
}
new BukkitRunnable(){
int tick = 0;
public void run() {
++tick;
for (int i = 0; i < swords.size(); i++) {
ArmorStand stand = swords.get(i);
Location loc = getLocationInCircle(RAD_PER_TICK * tick + SEPARATOR * i);
// Entity falling bug
stand.setVelocity(new Vector(1, 0, 0));
stand.teleport(loc);
}
}
}.runTaskTimer(plugin, 0L, 1L);
}
private void spawnStand(double angle) {
Location loc = getLocationInCircle(angle);
ArmorStand stand = loc.getWorld().spawn(loc, ArmorStand.class);
// TODO Customize by hiding, adding items, rotation...
swords.add(stand);
}
private Location getLocationInCircle(double angle) {
double x = center.getX() + radius * Math.cos(angle);
double z = center.getZ() + radius * Math.sin(angle);
return new Location(center.getWorld(), x, center.getY(), z);
}
}
@CoetexDE
Copy link

CoetexDE commented Feb 3, 2022

If you have two locations, is it possible to calculate the locations between the given locations?

@hugmanrique
Copy link
Author

hugmanrique commented Feb 6, 2022

Considering the context of this gist, I don't know whether "between" means (1) the location whose distance to two other locations is equal, or, (2) given two angles in a circle, the location in the circle whose argument is the mean of both angles.

For (1), we can compute the arithmetic mean of both locations (say a, b) as

final var midpoint = a.add(b).multiply(0.5);

Note that this method doesn't account for overflow; this is unlikely to happen in a Minecraft world and is left as an exercise.

For (2), given the center c and the two locations a, b, find the midpoint as above, obtain the segment from the center to the midpoint, and scale it by the radius of the circle:

final var center = c.toVector();
final var diff = midpoint.toVector().subtract(center);
final var vect = center.add(diff.normalize().multiply(radius));
final var location = vect.toLocation(c.getWorld());

This method throws if the two points are antipodal (the normalize call divides by zero).

I wrote this on the fly and it isn't optimized, but it should work fine. If performance is a huge concern, avoid Location and Vector objects and handle the math on doubles yourself.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment