Tutorial Creating a helix / 3d spiral out of particles

Discussion in 'Resources' started by Skionz, Sep 28, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Skionz

    This is my first tutorial so here goes. Basically I am going to teach you how to create a helix out of particles. A helix is just a 3d spiral like this:
    [​IMG]
    First we are going to create a method that creates a helix at the players location
    Code:java
    1. public void createHelix(Player player) {
    2. }

    Then we get the players location and get the coordinates for where the particle should be created
    Code:java
    1. public void createHelix(Player player) {
    2. Location loc = player.getLocation();
    3. int radius = 2;
    4. for(double y = 0; y <= 50; y+=0.05) {
    5. double x = radius * Math.cos(y);
    6. double z = radius * Math.sin(y);
    7. }
    8. }

    Next we will create the particle packet and send it to everyone
    Code:java
    1. public void createHelix(Player player) {
    2. Location loc = player.getLocation();
    3. int radius = 2;
    4. for(double y = 0; y <= 50; y+=0.05) {
    5. double x = radius * Math.cos(y);
    6. double z = radius * Math.sin(y);
    7. PacketPlayOutWorldParticles packet = new PacketPlayOutWorldParticles("fireworksSpark", (float) (loc.getX() + x), (float) (loc.getY() + y), (float) (loc.getZ() + z), 0, 0, 0, 0, 1);
    8. for(Player online : Bukkit.getOnlinePlayers()) {
    9. ((CraftPlayer)online).getHandle().playerConnection.sendPacket(packet);
    10. }
    11. }
    12. }

    This will send the particles to every online player. The end result would look something like this
    [​IMG]
    This can be used for some badass teleportation effects especially if you randomize the particle effects :D
     
  2. Offline

    ChipDev

    *First. :D
    Such awesome...
     
    Skionz likes this.
  3. Offline

    Skionz

    ChipDev Using this method instead of "fireworksSpark" creates a pretty badass effect :p
    Code:java
    1. public String randParticle() {
    2. Random r = new Random();
    3. int rNumb = r.nextInt(5) + 1;
    4. if(rNumb == 1)
    5. return "fireworksSpark";
    6. else if(rNumb == 2)
    7. return "happyVillager";
    8. else if(rNumb == 3)
    9. return "witchMagic";
    10. else if(rNumb == 4)
    11. return "flame";
    12. else if(rNumb == 5) {
    13. return "blockcrack_152_0";
    14. }
    15. return null;
    16. }
     
    gal0511Dev and ChipDev like this.
  4. Offline

    97WaterPolo

    Skionz
    Great post, very interesting!
     
    Skionz likes this.
  5. Offline

    Skionz

    97WaterPolo Just made a tornado looking shape/thing after looking at your tornado plugin using the same helix logic :D
    [​IMG]
     
    ChipDev likes this.
  6. Offline

    97WaterPolo

    Skionz
    lol, I kinda forgot about that plugin :p
     
  7. Offline

    jensdeboom

    Skionz Fantastic tutorial! Am I able to do this with a repeating task (at 1-2 ticks) instead of a for loop so you can see the helix being created?
     
  8. Offline

    Skionz

    jensdeboom You could add an incrementing delay when you send the particle packets.
     
  9. Offline

    jensdeboom

    K thx.
     
  10. Offline

    d3v1n302418

    Skionz Nice post! Definitely going to use this in a plugin :D
     
    Skionz likes this.
  11. Offline

    Funergy

    Skionz
    Reached level: Pro. next level: Master
    Achievements for Master: use Reflection.

    Great tutorial :p
     
  12. Funergy Challenge accepted.
    Code:java
    1. public void createHelixWithReflection(Player player) throws Exception {
    2. Location loc = player.getLocation();
    3. int radius = 2;
    4. for (double y = 0; y <= 50; y += 0.05) {
    5. double x = radius * Math.cos(y);
    6. double z = radius * Math.sin(y);
    7. Object packet = getNMSClass(player, "PacketPlayOutWorldParticles").newInstance();
    8. packet = packet.getClass().getConstructor(String.class, float.class, float.class, float.class, float.class, float.class, float.class, float.class, int.class).newInstance("fireworksSpark", (float) (loc.getX() + x), (float) (loc.getY() + y), (float) (loc.getZ() + z), 0, 0, 0, 0, 1);
    9. for (Player online : Bukkit.getOnlinePlayers()) {
    10. Object nmsPlayer = online.getClass().getMethod("getHandle").invoke(online);
    11. Object playerConnection = nmsPlayer.getClass().getDeclaredField("playerConnection").get(nmsPlayer);
    12. playerConnection.getClass().getMethod("sendPacket", getNMSClass(online, "Packet")).invoke(playerConnection, packet);
    13. }
    14. }
    15. }
    16.  
    17. public Class<?> getNMSClass(Player player, String className) throws Exception {
    18. Field field = Bukkit.getServer().getClass().getDeclaredField("console");
    19. field.setAccessible(true);
    20. return (Class.forName(field.get(Bukkit.getServer()).getClass().getPackage().getName() + "." + className));
    21. }
     
    Funergy likes this.
  13. Offline

    Skionz

    DJSkepter bahh you beat me to it :( No fair I was at school
     
    DJSkepter and Funergy like this.
  14. Offline

    xTrollxDudex

    ...
     
    _Filip, Avygeil and Hawktasard like this.
  15. Offline

    Cirno

    rip performance.

    You might want to create all the packets ahead of time and then send it.
     
    MrShnig, rbrick, Hawktasard and 2 others like this.
  16. Skionz Don't worry, you still get the majority of the credit since you wrote the original thing. There's no way I could possibly know how to make a helix. Ever.

    Cirno Thanks for the tip, I'll try that next time :)
     
    Skionz likes this.
  17. Offline

    Funergy

  18. Offline

    xTrollxDudex

    I'm not kidding. Reflection is slow. Look at Cirno's comment.
     
  19. Offline

    Cirno

    rbrick likes this.
  20. Offline

    TheLexoPlexx

    Slikey did it this way:
    Code:
    package de.slikey.effectlib.effect;
     
    import de.slikey.effectlib.EffectManager;
    import de.slikey.effectlib.EffectType;
    import de.slikey.effectlib.util.ParticleEffect;
    import org.bukkit.Location;
     
    public class HelixLocationEffect extends LocationEffect {
        /**
        * Particle to form the helix
        */
        public ParticleEffect particle = ParticleEffect.FLAME;
     
        /**
        * Amount of strands
        */
        public int strands = 8;
     
        /**
        * Particles per strand
        */
        public int particles = 80;
     
        /**
        * Radius of helix
        */
        public float radius = 10;
     
        /**
        * Factor for the curves. Negative values reverse rotation.
        */
        public float curve = 10;
     
        /**
        * Rotation of the helix (Fraction of PI)
        */
        public double rotation = Math.PI / 4;
     
        public HelixLocationEffect(EffectManager effectManager, Location location) {
            super(effectManager, location);
            type = EffectType.REPEATING;
            period = 10;
            iterations = 8;
        }
     
        @Override
        public void onRun() {
            for (int i = 1; i <= strands; i++) {
                for (int j = 1; j <= particles; j++) {
                    float ratio = (float) j / particles;
                    double angle = curve * ratio * 2 * Math.PI / strands + (2 * Math.PI * i / strands) + rotation;
                    double x = Math.cos(angle) * ratio * radius;
                    double z = Math.sin(angle) * ratio * radius;
                    location.add(x, 0, z);
                    particle.display(location, visibleRange, 0, 0, 0, 0, 0);
                    location.subtract(x, 0, z);
                }
            }
        }
     
    }
    
    Full Code: https://github.com/Slikey/EffectLib
    Forum Topic: https://forums.bukkit.org/threads/e...-the-nice-way-text-image-in-particles.259879/
     
  21. Offline

    rbrick

    Simple math functions create amazing stuff.
     
    MrShnig and Skionz like this.
  22. Offline

    ChipDev

    This is why bukkit is so awesome.
    You are sitting in class. Geometry.. thinking "Im never going to use this.."
    well, bukkit is a great way to use cos and sin and other math stuff. and you are proud of it :p

    Cool! Do raidus+=0.1 and it will make a tornado :O

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 14, 2016
  23. Offline

    Skionz

  24. Offline

    ChipDev

    no.. ;P
    Code:java
    1. for(double y = 0; y <= 60; y += 0.1) {
    2. double x = l.getX() + (raidus * Math.cos(y));
    3. double z = l.getZ() + (raidus * Math.sin(y));
    4. raidus += 0.01;
    5. if(y >= 50){
    6. //other code :p
    7. }
    8. }
     
  25. Offline

    _Filip

    Cirno Where is the proof? Not meaning to start an argument, this is from non biased view point. The first solution is debunked in the comments of it. I know that reflection is slower, I'm just not sure that it is so much slower that it would really create that big of an effect.

    http://stackoverflow.com/a/547847
     
  26. Offline

    Cirno

    http://docs.oracle.com/javase/tutorial/reflect/index.html
    "Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications."

    Oracle themselves have stated that Reflection can be slow. It will typically be slow for the first couple iterations because the JIT needs to analyze it; but once that's done, your mileage may vary.

    I'm biased towards not using Reflection for several reasons:
    • As previously stated, it can be slow. With the amount of reflection being used within the loop that they made, you might as well just release multiple versions or use interfaces and then, on startup, generate a proper implementation class.
    • If you/someone else changes the variable/method signature, you pretty much screw up the entire code.
    • Environments are different. Some environments may use a security manager on top of Java, which is a major concern since the security manager can actually block reflection, along with other features of Java.
    • Might be compounded with the second point; it allows theoretically illegal code to execute without error. Because we're on Bukkit and that usually implies Minecraft (unless you're tampering with Bukkit; in that case, go ahead and tamper all the Simple* classes), NMS tends to be volatile in terms of field names. In 1.6.x, a field can be named "a" and have the type of int, and is used for, say, position. In 1.7.x, the variables type and name could be the same, but be completely used for another purpose.
    I will say that Reflection is fun toying with; you can toy with the integer cash and make 1+1 = 3 (and possibly screw up something as a result), but I don't think it belongs in an environment where performance is relatively important (considering the fact that Minecraft isn't exactly the "fastest server software".)
     
  27. Offline

    _Filip

    Cirno I'm sure people will find your post interesting. Thank you for this :)
     
  28. Offline

    feff890

    Skionz
    Always the exact same error on:
    ((CraftPlayer)online)
    Says CraftPlayer cannot be resolved to a type
    Pls help!! Anyone!
     
  29. feff890 You need to build against CraftBukkit
     
  30. Offline

    feff890

    Ok thanks! Now that it works this is really awesome.
    I was wondering if anyone knows how to make the shape where to rings cross over each other? Like an atom.
     
Thread Status:
Not open for further replies.

Share This Page