Solved Circle particle math help

Discussion in 'Plugin Development' started by HeavyMine13, Jan 18, 2016.

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

    HeavyMine13

    Hey! So I am trying to create an effect in which a "circle/ring" made of particle would shoot to the direction the player is looking. Any ideas on how I can achieve this? Thanks in advance!

    Note: I am just at the surface of calculus, so don't expect me to be Mr. Genius :p Thanks again!

    Note 2: I have the basic method of the "shoot" system, I just can't get a circle to appear(I'm bad at vectors), so I have no "set of points" where particles should spawn! Thanks again!
     
  2. Offline

    ShowbizLocket61

    @HeavyMine13
    Here's how you would do it straight to the positive-z direction:
    Make x and y functions of z, your "time". You need a radius, say 1.
    You want to make a circle, in which x would go from -1 to 1 and back. Sound familar? Yup, a sine wave.
    Code:
    Math.sin(time)*radius;
    The y would go from 0 to 1 to -1 and back to 0. Sound familar? Yup, a cosine wave.
    Code:
    Math.cos(time)*radius;
    Now just stick all of that into a bukkit scheduler, and place particles at x,y,z.

    You should have learned this in precalc :p

    Now for the hard part: rotating the circle to fit the direction.
    Use your direction vector to find the center of the circle.
    Now, you want to rotate this circle along the x axis according to the yaw. Keep in mind that yaw is in degrees. The change in x from the center would be your unrotated x multiplied by the cosine of the yaw.
    Code:
    Math.sin(time) * radius * Math.cos(Math.PI/180 * location.getYaw())
    Then spawn a particle at center.getX()+x, center.getY()+y, center.getZ();
     
    Last edited: Jan 18, 2016
    ChipDev and HeavyMine13 like this.
  3. Offline

    ChipDev

    Thanks for simplifying that down! We're learning how an increase means a gain which adds, not calc :3
    (I've only wondered how to implement yaw into the circle) ;)

    Wait, does the
    Code:
    Math.sin(time) * radius * Math.cos(Math.PI/180 * location.getYaw())
    fit into the X, Y, or Z?

    @ShowbizLocket61
     
    Last edited: Jan 18, 2016
    ShowbizLocket61 likes this.
  4. Offline

    mcdorli

    X, he imagined a particle effect, like a circle rotated around 90 degrees on the z axis.
     
    HeavyMine13 likes this.
  5. Offline

    HeavyMine13

    I'm sorry but I still don't really understand that much. Not the math, but how to translate it into my code :/
     
  6. Offline

    mcdorli

    He pretty much said what you need to know. Here comes in logic. You need to do the formula mentioned above, to get the x and y coordinates, angle needs to be in radians (360 degrees is 2*PI radians), and you get angle, by pretty much using a for loop, and adding a small amount every time the for loop runs, like have an angle variable, and inside the for loop do angle += 2*Math.PI / detail, where detail is how many times the for loop runs. A higher detail means more detailed circle, but don't go crazy with it, 180 is pretty much okay
     
  7. Offline

    ShowbizLocket61

    @HeavyMine13
    I showed you how to get the x, y, and z of each particle on a circle at a time.
    Create a bukkit scheduler, and in every 5 ticks spawn a circle.
    I wrote some partial code for you down here. Make sure you understand it, and write center and spawnParticle yourself.
    Code:
    public double xPos(double time, double radius, double yaw){
    	return Math.sin(time) * radius * Math.cos(Math.PI/180 * yaw);
    }
    
    public double yPos(double time, double radius){
    	return Math.cos(time)*radius;
    }
    
    public void spawnCircle(Player player){
    final Location location = player.getLocation();
    final double yaw = location.getYaw();
    final double[] time = {0.0};
    final double radius = 1;
    final double range = 30;
    
    new BukkitRunnable(){
    	public void run(){
    		for(double i = 0; i < Math.PI*2; i++){
    			Location center = ...;
    			spawnParticle(xPos(time[0], radius, yaw)+center.getX(), yPos(time[0], radius)+center.getY(), center.getZ());
    		}
    		
    		time[0] += 0.1;
    		if(time[0] >= range)
    			this.cancel();
    	}
    }
    }
     
    HeavyMine13 likes this.
  8. Offline

    HeavyMine13

    So like this?

    Code:
      public void spawnCircle(Player player) {
            final Location location = player.getLocation();
            final double yaw = location.getYaw();
            final double[] time = {0.0};
            final double radius = 1;
            final double range = 30;
    
            new BukkitRunnable() {
                public void run() {
                    for (double i = 0; i < Math.PI * 2; i++) {
                        Location center = location.add(0, 1.5, 0);
                        Location n = new Location(center.getWorld(), xPos(time[0], radius, yaw) + center.getX(), yPos(time[0], radius) + center.getY(), center.getZ());
                        ParticleEffect.REDSTONE.display(0, 0, 0, 0, 1, n, 30);
                    }
    
                    time[0] += 0.1;
                    if (time[0] >= range)
                        this.cancel();
                }
            }.runTaskTimer(this, 0, 1);
        }
     
  9. Offline

    ShowbizLocket61

    @HeavyMine13
    You're almost there!
    Some things to take care of: the add() method also adds to the original location. Don't use it, create a new location instead. Create center outside of the for loop, the loop makes the circle. You should make center dependent on the player's direction. Use location.getDirection(), which returns an unit vector of the direction, and multiply it by the time and add it to the original location for your new center :) Everything else is great.
     
    HeavyMine13 likes this.
  10. Offline

    HeavyMine13

    Sorry I'm taking a lot of your time but I am trying my best to learn both OOP and Math ahead of my level <3 I have this before the for loop:
    Code:
    Location center = location.add(location.getDirection().multiply(time[0]));
     
  11. Offline

    ShowbizLocket61

    @HeavyMine13
    Remember, you don't want to add it to location itself. Do this:
    Code:
    Vector vec = location.getDirection().multiply(time[0]);
    Location center = new Location(location.getWorld(), location.getX()+vec.getX(), location.getY()+vec.getY(), location.getZ()+vec.getZ));
     
  12. Offline

    HeavyMine13

    So this is my code atm. They particle goes forward in a wave pattern(Like a sine graph for visual representation):

    Code:
     public void spawnCircle(Player player) {
            final Location location = player.getLocation();
            final double yaw = location.getYaw();
            final double[] time = {0.0};
            final double radius = 1;
            final double range = 30;
    
            new BukkitRunnable() {
                public void run() {
                    Vector vec = location.getDirection().multiply(time[0]);
                    Location center = new Location(location.getWorld(), location.getX() + vec.getX(), location.getY() + vec.getY(), location.getZ() + vec.getZ());
                    for (double i = 0; i < Math.PI * 2; i++) {
                        Location n = new Location(center.getWorld(), xPos(time[0], radius, yaw) + center.getX(), yPos(time[0], radius) + center.getY(), center.getZ());
                        ParticleEffect.REDSTONE.display(0, 0, 0, 0, 1, n, 30);
                    }
    
                    time[0] += 0.1;
                    if (time[0] >= range)
                        this.cancel();
                }
            }.runTaskTimer(this, 0, 1);
        }
     
  13. Offline

    ShowbizLocket61

    @HeavyMine13
    Are you saying it's not working? The code looks fine to me. :/
     
  14. Offline

    mcdorli

    You use i++ int he for loop, that means it only going to run 6 times. You should get into trigonometry, before attempting to make this
     
  15. Offline

    ShowbizLocket61

    @mcdorli
    6 times is enough to give the visual shape of a circle of radius 1. Of course, the more the better, but he took that from me.
     
    HeavyMine13 likes this.
  16. Offline

    HeavyMine13

    Thanks a lot. 1) I just bought trigo books and will start asap!
    2) Please, any idea how to fix this before I start trigonometry?
     
  17. Offline

    ShowbizLocket61

  18. Offline

    HeavyMine13

    @ShowbizLocket61
    It is creating a forward moving line moving up and down sometimes other times like a helix instead of a circle
     
  19. Offline

    ChipDev

    Well, I'm trying to graph this in grapher, and I took a screenshot.
    Remember, Z = Y in minecraft, but thats really all that matters.
    [​IMG]
    I get that flat shape. Though, it it actually a little bit skewed upwards. Any help? Thanks!
    (I'm trying to rotate 45 degrees)
     
  20. Offline

    ShowbizLocket61

    @ChipDev
    It should look like that. Since z and y are interchanged in minecraft, it would an upright circle moving along.
     
  21. Offline

    mcdorli

    @ChipDev It's not skewed, it's just rotated around one of the axis, If they were some sort of perspective in that program, then it would look like it os rotated around. @ShowbizLocket61 you probably move the cebter while you spawn new ones
     
  22. Offline

    ShowbizLocket61

    @ChipDev @mcdorli @HeavyMine13
    Haha, found it. The variable i should have been passed to the pos functions, not time[0].
    Code:
    for (double i = 0; i < Math.PI * 2; i++) {
        Location n = new Location(center.getWorld(), xPos(i, radius, yaw) + center.getX(), yPos(i, radius) + center.getY(), center.getZ());
        ParticleEffect.REDSTONE.display(0, 0, 0, 0, 1, n, 30);
    }
    
     
  23. Offline

    HeavyMine13

    @ShowbizLocket61

    This:
    Code:
        public void spawnCircle(Player player) {
            final Location location = player.getLocation();
            final double yaw = location.getYaw();
            final double[] time = {0.0};
            final double radius = 1;
            final double range = 30;
    
            new BukkitRunnable() {
                public void run() {
                    Vector vec = location.getDirection().multiply(time[0]);
                    Location center = new Location(location.getWorld(), location.getX() + vec.getX(), location.getY() + vec.getY(), location.getZ() + vec.getZ());
                    for (double i = 0; i < Math.PI * 2; i++) {
                        Location n = new Location(center.getWorld(), xPos(i, radius, yaw) + center.getX(), yPos(i, radius) + center.getY(), center.getZ());
                        ParticleEffect.REDSTONE.display(0, 0, 0, 0, 1, n, 30);
                    }
    
                    time[0] += 0.1;
                    if (time[0] >= range)
                        this.cancel();
                }
            }.runTaskTimer(this, 0, 1);
        }
    

    Produces this:

    http://i.imgur.com/8hXEOpR.png
    http://i.imgur.com/3FTsz00.png
     
  24. Offline

    ShowbizLocket61

    @HeavyMine13
    hahaha I guess 6 isn't enough then. Make it 18! Change i++ to i+=Math.pi*/9
     
    HeavyMine13 likes this.
  25. Offline

    HeavyMine13

    */? lol
    Important thing: THANKSSSSSSSSSSSSSSSSS
     
  26. Offline

    ShowbizLocket61

    @HeavyMine13
    No problem. I assume it works? Great! It's been a pleasure helping you. :)
     
  27. Offline

    HeavyMine13

    SO is it Pi/9 or Pi*9 :p? Thanks again man <3
     
  28. Offline

    ShowbizLocket61

    @HeavyMine13
    The angle is going from 0, to 2pi. If you want it to make 18 particles per circle, you would have to increment 1/18 of (2PI-0), which equals 2PI/18 = PI/9.
     
  29. Offline

    HeavyMine13

    Didn't work very well, came up with this(opinion?):
    Code:
    for (double i = 0; i < 360;  i+=3) {
     
  30. Offline

    ShowbizLocket61

    @HeavyMine13
    That's in degrees. The Math.sin() function takes in radians. You could use that, but you have to multiply i by Math.PI/180 to convert it to radians.
     
Thread Status:
Not open for further replies.

Share This Page