Hello people of spigot! Today, as a start of my new & last high school year, I decided to write a tutorial on how to display a line of particles using a Vector. If you don't know what a vector is, you should read the text down below, but I also recommend googling some stuff about vectors. Vectors A vector can be used for different things, but in our case, you should imagine it as an arrow with a direction and a size. A vector has 3 values, x, y and z. These are the numbers which represent the direction. We're gonna use a 3D graph as an example. Let's say we have a vector with x = 3, y = 2 and z = 5. Let's put a dot at that coördinate; 3, 2, 5. Now, we draw a line from the origin (0, 0, 0) to our coördinate (3, 2, 5). This line is our vector. It's a arrow pointing from one point to another. If we'd multiple our vector by 2, we'd get x = 3 * 2 = 6 y = 2 * 2 = 4 z = 5 * 2 = 10 This gives us different values, but the same direction. The direction of the vector stayed the same, the size changed. Vectors are also used for moving objects, such as cars or falling objects. The faster the object is moving, the greater the size of the vector. In Bukkit, we can apply vectors to entities, to move them. By reading the above, you should have an idea on how this works now. In Bukkit, you can add vectors to locations. This simpl moves the location in the vector's direction. If we'd have a vector with x = 5, y = 3, z = 6, and we'd add that to a location at x = 42, y = 92, z = 102, we'd get: x = 42 + 5 = 47 y = 92 + 3 = 95 z = 102 + 6 = 108 The location would now be at x = 47, y = 95, z = 108. For drawing a line, we're going to make use of this. How we draw the line Now, like every particle shape/animation, we can't make a full shape. We have to pick parts on our shape, and place particles on a certain interval. This also goes for the line, we will be placing particles on a line with a certain space between them. In this tutorial we'll leave a gap of 0.5 blocks between each particle. The way of drawing the line is rather simple if you think about it. First, we get a location for the start position of the line. Then, we need a vector for the direction. After this, we make a for-loop with a double which will run until it has reached the desired lenght of the line. Then each iteration, add the desired size of the gap between each particle to the for-loop's double. Then each iteration, we multiply the vector by the for-loop's double. Then we add the vector to our start location to move it in the vector's direction, with the current size (the size is the for-loop's double). Then we display a particle at that location, and subtract the vector from that location to move it back to the start again. Then we call Vector#normalize() on the vector. This set's the length to 1, so we can use it next iteration as well. If we wouldn't do this, something like this would happen: Lenght of the vector starts at 1. First iteration: - Multiply vector by 0.1. - The lenght is now 0.1 Second iteration: - Multiply vector by 0.2. - The lenght is now 0.1 * 0.2 = 0.02. Third iteration: - Multiply vector by 0.3 - The length is now 0.02 * 0.3 = 0.006. etc However, on the second iteration the lenght should be 0.2 and on the third it should be 0.3 Coding Now let's move on to coding. Like it says above, we need a start location, a vector for direction, and a for-loop. Code (Java): Location start = /* whatever */; Vector dir = /* whatever */; for (double i = 0; i < 10 /* 10 is the length of the line */; i += 0.5 /* 0.5 is the gap between each particle */) { } Now, we can start moving our location and displaying and stuff. Again, like it says above, we multiple, add, display, subtract, normalize. Code (Java): Location start = /* whatever */; Vector dir = /* whatever */; for (double i = 0; i < 10 /* 10 is the length of the line */; i += 0.5 /* 0.5 is the gap between each particle */) { dir.multiple(i); // multiply start.add(dir); // add // display particle at 'start' (display) start.subtract(dir); // subtract dir.normalize(); // normalize } This is all you have to do! As you can see it's easier than you might think. As a little addition, I'll also explain how to draw a line from a given direction to another. Between 2 points This is as simple as getting the vector between both locations. Simply get the end location, subtract the start location from it and turn it into a vector: Code (Java): end.subtract(start).toVector(); NOTE: This will modify the end location. If you don't want this, you can clone end by putting #clone() in between end and #subtract(start). Thanks for reading! I hope this was useful and if it was don't hesitate to leave a rating! - Finn

:OOO You lil' bugger! I was just going to make a resource similar to this! Haha. Well done though ^-^ EDIT: I have learned to leave the mathematical resources to you

I have a quick question, if I want to make an entity go in the same direction forever, how would I do that with vectors? Its just a random question that popped up in my mind so I can understand vectors better

You could create a vector and using a runnable, constantly set the entity's velocity to the vector you had created ^-^ If you really wanted to have fun, you could use sin/cos to set different x and z values of the Vector to make the entity move in circles (EDIT: Actually... I want to do that now. Lol)

As Choco said, simply get a vector for the direction and multiple it by your desired speed. Then apply it to the entity (Entity#serVelocity(Vector) within a (Bukkit)Runnable.

@avighnash @finnbon I have taught the Pigs how to properly move in circles... You will thank me later Code (Java): private Pig pig; private BukkitRunnable pigRunnable; private final double radius = 3; @EventHandler public void onToggleSneak(PlayerToggleSneakEvent event){ final Player player = event.getPlayer(); final Location loc = player.getLocation(); // Sneak is on if (event.isSneaking()){ pig = (Pig) player.getWorld().spawnEntity(loc.subtract(0, 0, radius), EntityType.PIG); this.pigRunnable = new BukkitRunnable(){ private double theta = 0.0; private final Vector velocity = new Vector(0, 0, 0); @Override public void run() { this.velocity.setX(Math.cos(theta) * radius); this.velocity.setZ(Math.sin(theta) * radius); this.velocity.normalize().multiply(0.4); pig.setVelocity(velocity); theta += Math.PI / 16; } }; this.pigRunnable.runTaskTimer(this, 0L, 2L); } // Sneak is off else{ this.pig.remove(); this.pig = null; this.pigRunnable.cancel(); this.pigRunnable = null; } } Probably not the best way to do this, but oh well

Already done that with my MiniMe couple seconds into the video we got babies in mc running around in circles. Edit: Dat lag

Haha HE'S SO CUTE Kind of creepy though. I think it's just the face that constantly bobs side to side that just gives me the chills ;P

this was a bug i had while making a pokemon arena plugin a loonnngg time ago: https://i.gyazo.com/9103902e1608cb075a67ee2bbedeb5d6.gif yes those are full circles and it was basically a blackhole

I followed the tutorial and when I put player.getLocation() for the start and player.getDirection() for the direction I spawned particles only at my feet and not in a line?

@CJP10 Tried it, still only spawned 1 particle at my feet. Here's my code if you need it. Code (Text): Location start = event.getPlayer().getLocation() Vector dir = event.getPlayer().getEyeLocation().toVector(); for(double i = 0; i < 30; i += 0.5) { dir.multiply(i); start.add(dir); start.getWorld().spawnParticle(Particle.REDSTONE, start, 10); start.subtract(dir); dir.normalize(); }

Honestly, I never really understood Vectors.. but then I found this tutorial, and now it all makes sense. Thanks @finnbon <3