Solved Turn particle effect

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

Thread Status:
Not open for further replies.
  1. 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 He-light, Apr 2, 2020
    Last edited: Apr 2, 2020
  2. 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. 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 He-light, Apr 2, 2020
    Last edited: Apr 2, 2020
  4. 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) {
                return plrLoc.add(0,0,-d); //North
            } else if (22.5 <= rotation && rotation < 67.5) {
                return plrLoc.add(d,0,-d); //North east
            } else if (67.5 <= rotation && rotation < 112.5) {
                return plrLoc.add(d,0,0); //East
            } else if (112.5 <= rotation && rotation < 157.5) {
                return plrLoc.add(d,0,d); //South east
            } else if (157.5 <= rotation && rotation < 202.5) {
                return plrLoc.add(0,0,d); //South
            } else if (202.5 <= rotation && rotation < 247.5) {
                return plrLoc.add(-d,0,d); //South west
            } else if (247.5 <= rotation && rotation < 292.5) {
                return plrLoc.add(-d,0,0); //West
            } else if (292.5 <= rotation && rotation < 337.5) {
                return plrLoc.add(-d,0,-d); //North west
            } else if (337.5 <= rotation && rotation < 360.0) {
                return plrLoc.add(0,0,-d); //North
            } else {
                return null;
            }
        }
     
    Try this code for getting the circle center or starting position :)
     
    • Friendly 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:
    [​IMG]

    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 Winner x 1
  6. Thanks for the answere, i will try my best ^^
     
  7. 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. 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 Agree x 1
    • Winner Winner x 1
  10. 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();
                    double rad = Math.toRadians(eyeLoc.getYaw());
                   
                   
                    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);
                   
                    v1.rotateAroundY(rad);
                    v2.rotateAroundY(rad);
                    v3.rotateAroundY(rad);
                    v4.rotateAroundY(rad);
                   
                    Location centerOfCircle = v1.subtract(v2).toLocation(eyeLoc.getWorld());
                    centerOfCircle.add(eyeLoc);
                   
                    Location particleLoc = centerOfCircle.add(v1).add(v2).add(v3).add(v4);
                   
                    ParticleBuilder pb = new ParticleBuilder(Particle.FLAME);
                    pb.location(particleLoc);
                    pb.count(0);
                    pb.spawn();
                   
                    if (t > Math.PI) {
                        this.cancel();
                       
                    }

                }
            }.runTaskTimer(getP(), 0, 1);
     
  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. 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 He-light, Apr 3, 2020
    Last edited: Apr 3, 2020
  13. 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();
                }
            }.runTaskTimer(getP(), 0, 1);
     
  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 Winner x 1
  15. 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();
                }
            }.runTaskTimer(getP(), 0, 1);
     
  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 Winner x 1
  17. 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.rotateAroundZ(Math.toRadians(i*2*Math.PI/8));
                        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();
                }
            }.runTaskTimer(getP(), 0, 1);
     
  18. drives_a_ford

    Moderator

    Looks like it could work. But you tell me.
     
  19. 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.
     
Thread Status:
Not open for further replies.