-
-
Save hugmanrique/1bd273e3b20b419f625c437db61b7ff9 to your computer and use it in GitHub Desktop.
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); | |
} | |
} |
The start
method calls spawnStand
in a loop, which calls the Bukkit method World#spawn(Location, Class<? extends Entity>)
. That tells Bukkit you want to spawn an entity of the given type (in this case an ArmorStand) at the given location. Next, the start method creates a repeating task that will move the stands around a circle. You could save the return value of the task (a BukkitRunnable
) in a field so you can later cancel it to stop the animation (you would also need to despawn the stands by calling Entity#remove()
).
To start the whole thing, your plugin needs to create an instance of SwordAnimation
with the appropriate parameters.
If you have two locations, is it possible to calculate the locations between the given locations?
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 double
s yourself.
I know this is old, but I'm new to using armor stands in this manner. in the chance you see this, how exactly would you execute the code to get everything started?
Also how can i remove the armor stand after a period of time?