import processing.core.*; import processing.xml.*; import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.io.*; import java.net.*; import java.text.*; import java.util.*; import java.util.zip.*; import java.util.regex.*; public class Reflection2 extends PApplet { /** * Non-orthogonal Collision with Multiple Ground Segments * by Ira Greenberg. * * Based on Keith Peter's Solution in * Foundation Actionscript Animation: Making Things Move! */ Orb orb; PVector velocity; float gravity = .05f, damping = 0.8f; int segments = 40; Ground[] ground = new Ground[segments]; float[] peakHeights = new float[segments+1]; public void setup(){ size(640, 200); smooth(); orb = new Orb(50, 50, 3); velocity = new PVector(.5f, 0); // Calculate ground peak heights for (int i=0; i width-orb.r){ orb.x = width-orb.r; velocity.x *= -1; velocity.x *= damping; } else if (orb.x < orb.r){ orb.x = orb.r; velocity.x *= -1; velocity.x *= damping; } } public void checkGroundCollision(Ground groundSegment) { // Get difference between orb and ground float deltaX = orb.x - groundSegment.x; float deltaY = orb.y - groundSegment.y; // Precalculate trig values float cosine = cos(groundSegment.rot); float sine = sin(groundSegment.rot); /* Rotate ground and velocity to allow orthogonal collision calculations */ float groundXTemp = cosine * deltaX + sine * deltaY; float groundYTemp = cosine * deltaY - sine * deltaX; float velocityXTemp = cosine * velocity.x + sine * velocity.y; float velocityYTemp = cosine * velocity.y - sine * velocity.x; /* Ground collision - check for surface collision and also that orb is within left/rights bounds of ground segment */ if (groundYTemp > -orb.r && orb.x > groundSegment.x1 && orb.x < groundSegment.x2 ){ // keep orb from going into ground groundYTemp = -orb.r; // bounce and slow down orb velocityYTemp *= -1.0f; velocityYTemp *= damping; } // Reset ground, velocity and orb deltaX = cosine * groundXTemp - sine * groundYTemp; deltaY = cosine * groundYTemp + sine * groundXTemp; velocity.x = cosine * velocityXTemp - sine * velocityYTemp; velocity.y = cosine * velocityYTemp + sine * velocityXTemp; orb.x = groundSegment.x + deltaX; orb.y = groundSegment.y + deltaY; } class Ground { float x1, y1, x2, y2; float x, y, len, rot; // Default constructor Ground(){ } // Constructor Ground(float x1, float y1, float x2, float y2) { this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; x = (x1+x2)/2; y = (y1+y2)/2; len = dist(x1, y1, x2, y2); rot = atan2((y2-y1), (x2-x1)); } } class Orb{ float x, y, r; // Default constructor Orb() { } Orb(float x, float y, float r) { this.x = x; this.y = y; this.r = r; } } static public void main(String args[]) { PApplet.main(new String[] { "Reflection2" }); } }