final PVector normalX = new PVector(1, 0, 0); class ParticleSystem { ArrayList particles; PVector originVillain; PVector origin; float points; float previousPoints = 0; ParticleSystem() { originVillain = new PVector(0,-boxThickness/2 - cylinderHeight,0); particles = new ArrayList(); 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 (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(); 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; } }