# Resource Drawing a line

Discussion in 'Spigot Plugin Development' started by finnbon, Aug 29, 2016.

1. ### finnbon

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
// 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

#1
Last edited: Dec 28, 2016
• Useful x 20
• Like x 8
• Winner x 2
• Friendly x 2
2. ### Choco Moderator

: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

• Like x 2
• Friendly x 1
3. ### avighnash

YEES!!! I HAVE BEEN WAITING FOR THIS MOMENT! I NEEDED THIS TUTORIAL SO BAD... TANK U GOD

• Like x 2
4. ### iTouchedTrump

Great tutorial! I love how this actually makes sense now because I'm taking higher level geo

• Like x 2
5. ### avighnash

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

6. ### Choco Moderator

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)

• Agree x 1
7. ### finnbon

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.

• Like x 1
8. ### avighnash

Thank you!

• Like x 1
• Friendly x 1
9. ### Choco Moderator

@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.normalize().multiply(0.4);
pig.setVelocity(velocity);

theta += Math.PI / 16;
}
};
}

// 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

• Winner x 2
10. ### Varni1

What have you done.
The pigs will now take over the world!

• Like x 1
11. ### Varni1

Excellent resource fin!

• Like x 1
12. ### lookcook

Already done that with my MiniMe

couple seconds into the video

we got babies in mc running around in circles.

Edit: Dat lag

• Funny x 1
13. ### Choco Moderator

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

• Agree x 3
• Like x 2
14. ### Shortninja

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

• Funny x 1

Thanks

17. ### Squanchy

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?

18. ### CJP10

use getEyeLocation

19. ### Squanchy

@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);