# Solved Turn particle effect

Discussion in 'Spigot Plugin Development' started by He-light, Apr 2, 2020.

Not open for further replies.
1. ### He-light

Hi!
I added to my plugin some particle effects, to make thinks cooler. In this specific case, i want to create a circle of flame particles infront of the player and then shoot a fireball through it.

So far, everything works, except, that if the player turns in an other direction, the circle of flame particles spawns beside the player and not infront of him.

My question is now: What can i do to make shure, that the portal always spawns infront of him, regardles his looking-direction?

I know that i can get the direction of the players view, with Player.getDirection().normalize().
But how does the calculation has to look like?

This is an example of the Circle
https://christopherchudzicki.github...uNjk1NTgyNDk1NzgxMzE3LCJmcm9tVVJMIjp0cnVlfQ==

Note that it is offset by 1 on the Y-axis, to make it appear infront of the player and offset by 1 on the Z-axis, because the players center of his body is at a hight of 1

#1
Last edited: Apr 2, 2020
2. ### MiMiMiEnot

l`m so sorry if l doesn`t understood you correctrly, but, maybe spawn every particle at every time calculater player location

like, Player move - you get new location for circle and every particle spawn at new location

If you need moving all previusly particles so you need spawn they again

3. ### He-light

The problem is, that i don't know, how to spawn the particles in any other direction. If you watch the circle from the link, you will see, that with these x y z coordinates, all particles will always spawn on the same location.

The problem appears not when the player moves, but when he turns

The circle should always spawn infront of the player

Video for clarification
https://gfycat.com/inferiorunfortunategentoopenguin

#3
Last edited: Apr 2, 2020
4. ### SignorPollito

You have to get the player looking direction and then add the distance of particles from him.

Code (Text):

public static Location getCardinalDirection(Player player) {
double rotation = (player.getLocation().getYaw() - 90) % 360;
Location plrLoc = player.getLocation();
double d = 1; //Blocks distance of the circle from the player

if (rotation < 0) {
rotation += 360.0;
}
if (0 <= rotation && rotation < 22.5) {
} else if (22.5 <= rotation && rotation < 67.5) {
return plrLoc.add(d,0,-d); //North east
} else if (67.5 <= rotation && rotation < 112.5) {
} else if (112.5 <= rotation && rotation < 157.5) {
return plrLoc.add(d,0,d); //South east
} else if (157.5 <= rotation && rotation < 202.5) {
} else if (202.5 <= rotation && rotation < 247.5) {
return plrLoc.add(-d,0,d); //South west
} else if (247.5 <= rotation && rotation < 292.5) {
} else if (292.5 <= rotation && rotation < 337.5) {
return plrLoc.add(-d,0,-d); //North west
} else if (337.5 <= rotation && rotation < 360.0) {
} else {
return null;
}
}

Try this code for getting the circle center or starting position

• Friendly x 1
5. ### drives_a_ford Moderator

Let's look at this problem from geometry point of view.

You're looking at the direction (nx, 0, nz) (let's leave y out of this so the circle always appears perpendicular to the ground).
Going out in that direction from from the player's eye location a certain distance, you'll arrive at the center of the proposed circle, (x0, y0, z0).
Since you don't know how to draw a circle there exactly, you start off with a sphere, (x-x0)^2+(y-y0)^2+(z-z0)^2.
But you also know that the circle would need to be on a plane which is perpendicular to your (planar) viewing direction. Thus you get a plane, (x - x0) nx + (z - z0) nz = 0 or nx * x + nz * z = nx * x0 + nz * z0 (in standard form).

Now, your circle will have to be both on the plane and on the sphere. So its points will need to satisfy both equations.
Something along the lines of:

Getting the locations of such points is not trivial.

Another approach would be to specify locations of a circle just as you have done and then simply rotate them about the y axis in order to position them in the correct direction.
What you want to do is get a set of the circle's local coordinates (coordinates with respect to the player),
You can then rotate it using the Rotation Matrix (Ry in your case most likely).
Then you can add the center position of the circle (x0, y0, z0) to the local coordinates and show the particles.

• Winner x 1
6. ### He-light

Thanks for the answere, i will try my best ^^

7. ### He-light

Ok, so far I know now, I can use the Rotation Matrix with VECTOR.rotateAroundY(radiant). But im struggling to figure out, what I should actually turn, because at the moment, I have the players location and a vector of his facing direction. But I cant rotate a location and to rotate the facing direction wouldnt make sense^^

8. ### Schottky

You can use the player's yaw. You'll have to convert it to radians firts

9. ### drives_a_ford Moderator

I forgot such convenience methods were there.

In any case, what you do is
• Generate vectors for particle locations on the circle of your choosing around (0,0,0)
• These vectors will all be of the same length which is the radius
• In order to rotate correctly, the circle will have to "be directed" towards the z axis
• In our case this means you'll be generating it on the x-y plane
• Rotate each vector using Vector#rotateAroundY
• Now get the location of the center of the circle
• For each rotated vector
• Add vector to center location
• Spawn particle

• Agree x 1
• Winner x 1
10. ### He-light

Ok, this is what i came up with, but it doesn't seem to work. (I know that it is my fault^^)
Code (Java):

new BukkitRunnable() {
double t = 0;
public void run() {
t = t + Math.PI / 16;
Location eyeLoc = getPlayer().getEyeLocation();

Vector v1 = new Vector(0, 1, 1);
Vector v2 = new Vector(1, 0, 1);
Vector v3 = new Vector(0, -1, 1);
Vector v4 = new Vector(-1, 0, 1);

Location centerOfCircle = v1.subtract(v2).toLocation(eyeLoc.getWorld());

ParticleBuilder pb = new ParticleBuilder(Particle.FLAME);
pb.location(particleLoc);
pb.count(0);
pb.spawn();

if (t > Math.PI) {
this.cancel();

}

}

11. ### drives_a_ford Moderator

I've got no idea what you're trying to do here.
You've created a variable t (presumably for the angle) and are incrementing it, but you're never actually using it other than to cancel the BukkitRunnable.

In any case, you're definitely not following the instructions I laid out above.

12. ### He-light

Sorry, i really try my best and it took me a long time to "understand" your instructions.
The variable t was a leftover from my previous attempts. I am in generall, really new to the topic of particle effects and just learnd 2 days ago, how to even spawn particles. And i was never particularly good at math and this was even the first time i had to do more than basic math within my plugin.
I will try it again.

If you want to know, where i got the idea of my code (and my only reference point)

#12
Last edited: Apr 3, 2020
13. ### He-light

is this better by any chance?
Code (Java):

new BukkitRunnable() {
double r = 1;
public void run() {
Location eyeLoc = getPlayer().getEyeLocation();
double rad = Math.toRadians(eyeLoc.getYaw()); // rotation value

Vector v;
Location centerOfCircle = eyeLoc.add(getPlayer().getLocation().getDirection().normalize()); // get center of circle relative to the player
ParticleBuilder pb = new ParticleBuilder(Particle.FLAME);
for (int i = 0; i < 8; i++) {//for 8 particles
v = new Vector(r, r,0); // generate vectors with same length on the x-y plane
v.rotateAroundY(rad);    //rotating every vector

Location particalLoc = centerOfCircle.add(v); // get final location of particle

pb.count(0);                //
pb.location(particalLoc);    // spawn particle
pb.spawn();                    //

}

this.cancel();
}

14. ### drives_a_ford Moderator

Make sure to clone your locations. Location#add mutates the existing location. So you're adding to it on every iteration.

Another issue is the fact that (if you fixed the above issue) you're creating all your 8 particles in the same location.
But this could (kind of) work to your advantage.
If you initially created a vector (r, 0, 0) and then rotated it by i * 2*pi/8 radians about the z axis, you'd get each vector in a different position on the circle.
And after that you can rotate about the y axis (like you're doing).
And finally add it to the center location (again - you need to clone the location, otherwise you're mutating the existing one).

• Winner x 1
15. ### He-light

Ok, i see i get closer.
My code does now produce a horizontal circle of particles, but the circle is not always perfect. Some times there are gaps between the particles or the circle is just displayed as a half circle. But the generell direction is right.

Code (Java):

new BukkitRunnable() {
double r = 1;
public void run() {
Location eyeLoc = getPlayer().getEyeLocation();
double rad = Math.toRadians(eyeLoc.getYaw()); // rotation value

Location particalLoc;
Location centerOfCircle = eyeLoc.clone().add(getPlayer().getLocation().getDirection().normalize()); // get center of circle relative to the player
ParticleBuilder pb = new ParticleBuilder(Particle.FLAME);
Vector v = new Vector(r,0,0); // generat vector with same length on the x-y plane
for (int i = 0; i < 8; i++) {//for 8 particles

v.rotateAroundZ(Math.toRadians(i*2*Math.PI/8)); // rotating the vector to form a circle at the end
v.rotateAroundY(rad);    //rotating every vector

particalLoc = centerOfCircle.clone().add(v); // get final location of particle

pb.count(0);                //
pb.location(particalLoc);    // spawn particle
pb.spawn();                    //

}

this.cancel();
}

16. ### drives_a_ford Moderator

You want to create a new vector within the loop. Because right now, you're rotating the same one every which way.
In fact, I'd be surprised to see this result in something resembling a circle.

• Winner x 1
17. ### He-light

like i did before?
Code (Java):

public void doVisualEffect() {
new BukkitRunnable() {
double r = 1;
public void run() {
Location eyeLoc = getPlayer().getEyeLocation();
double rad = Math.toRadians(eyeLoc.getYaw()); // rotation value

Location particalLoc;
Location centerOfCircle = eyeLoc.clone().add(getPlayer().getLocation().getDirection().normalize()); // get center of circle relative to the player
ParticleBuilder pb = new ParticleBuilder(Particle.FLAME);

for (int i = 0; i < 8; i++) {//for 8 particles
Vector v = new Vector(r,0,0); // generat vector with same length on the x-y plane
v.rotateAroundY(rad);    //rotating every vector

particalLoc = centerOfCircle.clone().add(v); // get final location of particle

pb.count(0);                //
pb.location(particalLoc);    // spawn particle
pb.spawn();                    //

}

this.cancel();
}

18. ### drives_a_ford Moderator

Looks like it could work. But you tell me.

19. ### He-light

It seems that all particles are just spawning in the same spot

20. ### drives_a_ford Moderator

You're going to have to do some debugging then.
I.e you could print out the different vectors. You could even print them out between steps to make sure they're changing.