Solved Circle particle math help

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

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

#1
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

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
#3
ShowbizLocket61 likes this.
4. Offline

mcdorli

X, he imagined a particle effect, like a circle rotated around 90 degrees on the z axis.

#4
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 :/

#5
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

#6
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){
}

public void spawnCircle(Player player){
final Location location = player.getLocation();
final double yaw = location.getYaw();
final double[] time = {0.0};
final double range = 30;

new BukkitRunnable(){
public void run(){
for(double i = 0; i < Math.PI*2; i++){
Location center = ...;
}

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 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();
}
}```

#8
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]));`

#10
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 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();
}
}```

#12
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

#14
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?

#16
17. Offline

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

#18
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.

I get that flat shape. Though, it it actually a little bit skewed upwards. Any help? Thanks!
(I'm trying to rotate 45 degrees)

#19
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

#21
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 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();
}
}
```

Produces this:

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

#23
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

#25
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 ? Thanks again man <3

#27
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) {`

#29
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.