Resource [Tutorial] Create an Expanding Shape Particle Effect

Discussion in 'Spigot Plugin Development' started by Nannerss, Jun 9, 2019.

  1. Hello people of Spigot!

    Today I will be teaching you how to create an expanding circle effect. This concept can be used with any shape, but to keep things simple, we will be using circles.
    Here is an example of what I mean:
    [​IMG]
    As you can see, we are not actually moving the particles (as there is no ideal way to control their movement), we are simply spawning in multiple circles with different radii to create the illusion of an expanding circle!

    Now, let's get started!

    First, to do this, we'll need to make some sort of method for spawning in a circle of particles. The easiest and best method in my opinion is this one.
    Code (Java):

    public static void playCircleEffect(Player player, Location loc, double radius) {
        for (double angle = 0; angle < 2 * Math.PI; angle += Math.PI / 36) {
            final double x = radius * Math.cos(angle);
            final double z = radius * Math.sin(angle);
     
            loc.add(x, 0, z);
            // Spawn the particle at Location loc.
            loc.subtract(x, 0, z);
        }
    }
     
    If you do not understand how this works, I highly suggest you check out @finnbon's tutorial on creating circles using sine and cosine here.

    Now, assuming you know how to create a circle, let's get into actually creating the effect!

    First, we are going to create a class that extends BukkitRunnable. We are doing this because it's the easiest way to perform tasks like this, and we are able to easily control the time between circles so that you can customize the speed of the effect!
    Code (Java):
    public class ExpandingCircleEffect extends BukkitRunnable {
     
    }
    Now, we are going to create private fields for the player to send the particle to, the location to start at, the radius we'll start at, the radius that we'll end at, and the amount that the radius will increase by each time we run through the run() method.

    Once we do this, we can create a constructor that will set it's parameters equal to the corresponding fields we just made. This is so that each time we want to spawn in the effect, we can simply just create a new instance of the ExpandingCircleEffect class.
    Code (Java):
        private Player player;
        private Location loc;
        private double startRadius;
        private double endRadius;
        private double radiusIncrease;
     
        public ExpandingCircleEffect(Player player, Location loc, double startRadius, double endRadius, double radiusIncrease) {
            this.player = player;
            this.loc = loc;
            this.startRadius = startRadius;
            this.endRadius = endRadius;
            this.radiusIncrease = radiusIncrease;
        }
    So now that we've got everything setup, we need to actually spawn in the circles. To do this, we'll override the run() method from the BukkitRunnable class. Everything in this method is run whenever we initialize the ExpandingCircleEffect class.
    Code (Java):
        @Override
        public void run() {
     
        }
    Now all we have to do is just call the playCircleEffect() method mentioned at the beginning of the tutorial, plug the fields into the parameters, and increase the radius by the value specified in the constructor.
    Code (Java):
        @Override
        public void run() {
            playCircleEffect(player, loc, startRadius); // Spawns in a circle at the specified location with the current radius.
            startRadius += radiusIncrease; // Increases the radius each time the task in run.
        }
    Awesome! Now we're done, right? Nope, we still have one more thing to do! Notice how there is nothing set in place to cancel the Runnable. This means that once we spawn in the effect, the task will repeat itself forever (or until the server is stopped).

    Lucky for us though, we can create a check that is only 3 easy lines of code. Remember the endRadius field we created earlier? Well, that is what we'll use to cancel the task. All we need to do is check if the startRadius variable is greater than or equal to the endRadius field. And since the startRadius field is increasing each time the task is run, that means that it will eventually be greater than or equal to our endRadius field.
    Code (Java):
        @Override
        public void run() {
            Circle.playCircleEffect(player, loc, particle, offsetX, offsetY, offsetZ, speed, amount, data, startRadius, angleIncrease, global);
            startRadius += radiusIncrease;
     
            // If the current radius is greater than or equal to the endRadius field, cancel the task.
            if (startRadius >= endRadius) {
                this.cancel();
            }
        }
    Now all you have to do is incorporate it into your plugin! To do this, you simply just initialize the ExpandingCircleEffect class. Make sure you include the runTaskTimer() method at the end of the line, otherwise it won't work!
    Code (Java):
    new ExpandingCircleEffect(player, location, radius).runTaskTimer(plugin, delay, timeInterval);

    Aaaand that's it! Pretty simple, but I thought I'd share how I go about doing it. If you have any issues, be sure to let me know below and I can help you out! If you have any suggestions to improve this tutorial, also be sure to leave it below so I can take a look!

    I hope this was helpful to you. If it was, please do consider leaving a positive rating below! It'll encourage me to do more of these.
     
    #1 Nannerss, Jun 9, 2019
    Last edited: Jun 13, 2019
    • Like Like x 9
    • Winner Winner x 2
    • Useful Useful x 1
  2. Although not too complex, that's pretty neat! Thanks for sharing /o/
     
    • Friendly Friendly x 1
  3. Very beautiful resource, and very interesting, thank you for taking the time to create this!
     
    • Friendly Friendly x 1
  4. This nicely captures the way to make "progressable" animations, good job! :)
     
  5. Not true
    You can move particles where you want , if you want to make a small expanding shape like your gif you do not need to spawn thousand of particles.
     
  6. How do you control their movement? Speed var?
     
  7. As far as I know, the only way to actually "control" their movement is through the speed variable. This, however, cannot be controlled, and the particle's movement is determined by the type of particle it is.
     
  8. Nope you can control the movement by setting amount to 0
    The offset x y and z are now vector
    And speed is still speed
     
    #9 cocoraid, Jun 12, 2019
    Last edited: Jun 12, 2019
  9. Not entirely true either. This works only for some particles. Furthermore, you can't really control them well in my opinion, and I prefer the method that's used in this resource by far. It has it's uses, when making things like an explosion or a pointer, but with well defined shapes, it's no use.
     
    • Friendly Friendly x 1