-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathParticleSystem.pde
More file actions
146 lines (131 loc) · 5.61 KB
/
ParticleSystem.pde
File metadata and controls
146 lines (131 loc) · 5.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
final PVector normalX = new PVector(1, 0, 0);
class ParticleSystem {
ArrayList<PVector> particles;
PVector originVillain;
PVector origin;
float points;
float previousPoints = 0;
ParticleSystem() {
originVillain = new PVector(0,-boxThickness/2 - cylinderHeight,0);
particles = new ArrayList<PVector>();
setupVillain();
}
//#############################################
//------------SETUP OF THE VILLAIN------------
//#############################################
void setupVillain() {
points = 0;
robotnik = loadShape("robotnik.obj");
robotnik.scale(50);
robotnik.rotateX(PI);
texture = loadImage("robotnik.png");
robotnik.setTexture(texture);
}
//#############################################
// Main method that will add and adjacent cylinder to the whole system
//#############################################
void addParticle() {
PVector center;
int numAttempts = 100;
for(int i=0; i<numAttempts; i++) {
// Pick a cylinder and its center.
int index = int(random(particles.size()));
center = particles.get(index).copy();
// Try to add an adjacent cylinder.
float angle = random(TWO_PI);
center.x += sin(angle) * 2*cylinderBaseSize;
center.z += cos(angle) * 2*cylinderBaseSize;
if(checkPosition(center)) {
particles.add(new PVector(center.x , 0, center.z));
points -= 1;
break;
}
}
}
//#############################################
// Check if a position is available, i.e.
// - would not overlap with particles that are already created
// (for each particle, call checkOverlap())
// - is inside the board boundaries
//#############################################
boolean checkPosition(PVector center) {
boolean result = true;
pushMatrix();
translate(width/2, height/2);
if ( (center.x > (boxLength/2 - cylinderBaseSize)) || (center.x < - boxLength/2 + cylinderBaseSize) || (center.z > (boxLength/2 - cylinderBaseSize)) || (center.z < - boxLength/2 + cylinderBaseSize) ) result = false;
for(PVector v : particles)
if (checkOverlap(v, center)) result = false;
popMatrix();
return result;
}
//#############################################
// Check if a particle with center c1 and another particle with center c2 overlap.
//#############################################
boolean checkOverlap(PVector c1, PVector c2) {
double distance = sqrt((c1.x - c2.x)*(c1.x - c2.x) + (c1.z - c2.z)*(c1.z - c2.z));
return distance < 2*cylinderBaseSize;
}
//#############################################
// Do the following two things :
// - Add a new cylinder at a regular time interval
// - Move the bad guy so that it always faces the movement of the ball
//#############################################
void run() {
playable_sphere.checkCylinderCollision();
if(frameCount % 30 == 0 ) {
addParticle(); //interval set to 0.5 seconds
}
// Rotation of the villain according to the position of the ball
float sphereZ = playable_sphere.location().z - originVillain.copy().z;
float sphereX = playable_sphere.location().x - originVillain.copy().x;
float posNormZ = normalX.copy().normalize().z;
float posNormX = normalX.copy().normalize().x;
float angleVillain = (float) Math.atan2(sphereX*posNormZ - sphereZ*posNormX, sphereX*posNormX + sphereZ*posNormZ);
normalX.x = playable_sphere.location().x - originVillain.x;
normalX.z = playable_sphere.location().z - originVillain.z;
normalX.y = playable_sphere.location().y - originVillain.y;
robotnik.rotateY(angleVillain);
}
//#############################################
// Draw the position of the cylinder in the square top view box
//#############################################
void particleTopView() {
topView.noStroke();
for (int i = 0; i < particles.size(); ++i){
PVector particle_vector = particles.get(i);
float ellipseX = (particle_vector.x + boxLength/2) * square_for_score/boxLength;
float ellipseY = (particle_vector.z + boxLength/2) * square_for_score/boxLength;
float ellipseDim = (2*cylinderBaseSize) * square_for_score/boxLength;
if(i==0){
topView.fill(colorVillainTopView);
topView.ellipse(ellipseX, ellipseY, ellipseDim, ellipseDim);
} else {
topView.fill(defaultCylinderColour);
topView.ellipse(ellipseX, ellipseY, ellipseDim, ellipseDim);
}
}
}
}
//#############################################
// Checks if we can add a cylinder given a x and y coordinates
//#############################################
boolean canAddCylinder(float x, float y) {
return !( (x > (width/2 + boxLength/2 - cylinderBaseSize)) || (x < width/2 - boxLength/2 + cylinderBaseSize) || (y > (height/2 + boxLength/2 - cylinderBaseSize)) || (y < height/2 - boxLength/2 + cylinderBaseSize) );
}
//#############################################
// Set up the origin of the villain in order to place it on the board.
//#############################################
void addCenterOfVillain() {
//when a new origin is set, remove all the cylinders and add a new cylinder at the origin
particle_system.particles.clear();
particle_system.previousPoints = particle_system.points;
particle_system.points = 0;
scores = new ArrayList<Float>();
if(canAddCylinder(mouseX, mouseY)){
PVector origin = new PVector(mouseX - width/2 , 0 , mouseY - height/2); //origin in upper left corner
particle_system.particles.add(origin);
particle_system.origin = origin;
} else {
particle_system.origin = null;
}
}