tangible_game/ParticleSystem.pde
2020-10-08 20:15:00 +02:00

147 lines
5.6 KiB
Plaintext

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;
}
}