diff --git a/LeagueHalloween2/LeagueHalloween2.pde b/LeagueHalloween2/LeagueHalloween2.pde new file mode 100644 index 0000000..2ac902e --- /dev/null +++ b/LeagueHalloween2/LeagueHalloween2.pde @@ -0,0 +1,154 @@ +/* + * Run the code and see if you can figure out how to change the pumpkins + * in different ways. + * + * *Hint* Look in the code in the draw() and mouseWheel() methods. + * + * Use the following pumpkin methods to customize your pumpkin panel! + * pumpkin.setSize() + * pumpkin.setPumpkinColor() + * pumpkin.bounce() + * pumpkin.setBounceHeight() + * pumpkin.spin() + * pumpkin.spinSpinSpeed() + * pumpkin.explode() + * pumpkin.explodeColor() + * pumpkin.explodeRandomColor() + * pumpkin.stop() + * pumpkin.reset() + * pumpkin.moveRight() + * pumpkin.moveLeft() + * panel.addPumpkin() + */ +int numPanels = 5; +int panelWidth; +Panel[] panels; +color[] bgColors; + +final color RED = #FF0000; +final color BLUE = #0000FF; +final color GREEN = #00FF00; +final color YELLOW = #FFFF00; +final color PURPLE = #800080; +final color ORANGE = #FFA500; + +color[] colors = { + RED, + BLUE, + GREEN, + YELLOW, + PURPLE, + ORANGE +}; + +void setup() { + size(1200, 800); + initializePanels(colors); +} + +void draw() { + for ( int i = 0; i < panels.length; i++ ) { + Panel panel = panels[i]; + + for ( Pumpkin pumpkin : panel.pumpkins ) { + + /* + * If mouse is hovering over a panel... + */ + if ( i == mouseX / panelWidth ) { + pumpkin.bounce(); + + if ( mousePressed ) { + /* + * When the mouse is pressed... + */ + + } + + if ( keyPressed ) { + /* + * When a key is pressed... + */ + + } + } + } + + panel.draw(); + } +} + +void mouseWheel(MouseEvent event) { + + /* + * event.getCount() returns < 0 if scrolled up (away from the user) + * event.getCount() returns > 0 if scrolled down (toward the user) + */ +} + +void initializePanels(color[] colors) { + panelWidth = width / numPanels; + bgColors = new color[numPanels]; + panels = new Panel[numPanels]; + + for ( int i = 0; i < bgColors.length; i++ ) { + bgColors[i] = colors[i % colors.length]; + } + + for ( int i = 0; i < numPanels; i++ ) { + panels[i] = new Panel(i * panelWidth, panelWidth, bgColors[i]); + } +} + +class Panel { + int x, y, w, h; + color bgColor; + PImage bg; + PGraphics pg; + ArrayList pumpkins; + + public Panel(int x, int w, color bgColor) { + this.x = x; + this.y = 0; + this.w = w; + this.h = height; + this.bgColor = bgColor; + this.pg = createGraphics(w, h); + this.bg = createImage(pg.width, pg.height, ARGB); + + pumpkins = new ArrayList(); + addPumpkin(pg.width / 2, 150); + + for (int i = 0; i < bg.pixels.length; i++) { + float a = map(i, 0, bg.pixels.length, 0, 255 + 100); + bg.pixels[i] = color(red(bgColor), green(bgColor), blue(bgColor), a); + } + } + + void addPumpkin(int x, int size) { + Pumpkin pumpkin = new Pumpkin(x, bgColor, pg); + pumpkin.setSize(size); + pumpkin.setBounceHeight(int(random(10, height/20))); + this.pumpkins.add(pumpkin); + } + + void addPumpkinRandomSize(int x) { + addPumpkin(x, int(random(10, 200))); + } + + void draw() { + pg.beginDraw(); + + pg.fill(255); + pg.rect(0, 0, pg.width, pg.height); + pg.image(bg, 0, 0); + + for ( Pumpkin pumpkin : this.pumpkins ) { + pumpkin.draw(); + } + + pg.endDraw(); + + image(pg, x, y); + } +} diff --git a/LeagueHalloween2/Pumpkin.pde b/LeagueHalloween2/Pumpkin.pde new file mode 100644 index 0000000..bad1e83 --- /dev/null +++ b/LeagueHalloween2/Pumpkin.pde @@ -0,0 +1,354 @@ +public class Pumpkin { + private final int STILL = 0; + private final int BOUNCE = 1 << 0; + private final int SPIN = 1 << 1; + private final int EXPLODE = 1 << 2; + private int state = STILL; + + protected int x; + protected int y; + private int spinSpeed = 5; + private int xSpeed = 0; + private int angleDeg = 0; // facing east + private int bounceHeight = 30; + private int bounceSpeed = 0; + private int gravity = 1; + private int floorY; + private int pumpkinColor; + private int sizePixels = 150; + private int glowColor; + private int greenStemColor = #2EA22C; + + protected PGraphics pg = null; + ArrayList particles; + + public Pumpkin( int x, int pumpkinColor, PGraphics pg ) { + this.x = x; + this.floorY = height - 15; + this.y = floorY - (sizePixels / 2); + this.pg = pg; + this.glowColor = pumpkinColor; + this.pumpkinColor = color(0); + this.particles = new ArrayList(); + } + + /* + * Set new pumpkin size + */ + public void setSize(int newSize) { + this.sizePixels = newSize; + this.y = floorY - (sizePixels / 2); + } + + /* + * Change the color of your pumpkin + */ + public void setPumpkinColor( int newColor ) { + this.pumpkinColor = newColor; + } + + /* + * Make the pumpkin spin + */ + void spin() { + if ( (this.state & EXPLODE) == 0 ) { + println("spin"); + this.state |= SPIN; + } + } + + /* + * Set how fast the pumpkin spins + */ + void setSpinSpeed(int newSpeed) { + this.spinSpeed = newSpeed; + } + + /* + * Make the pumpkin EXPLODE! + */ + void explode() { + explodeColor(color(0)); + } + void explodeRandomColor() { + explodeColor(color(random(255), random(255), random(255))); + } + void explodeColor(color c) { + if ( (this.state & EXPLODE) == 0) { + particles.clear(); + + for ( int i = 0; i < this.sizePixels * 20; i+=10 ) { + /* + * Apparently my first impression on solving this is pretty naive + * because the general distribution of a random point inside a circle + * has a greater density of points at larger radii, so that's why + * it's sqrt(random(0, 1)) and not just random(0, 1) :D + */ + //float randomRadius = (this.sizePixels / 2) * random(0, 1); + float randomRadius = (this.sizePixels / 2) * sqrt(random(0, 1)); + + float random_angle_rad = 2 * PI * random(0, 1); + float randomX = this.x + (randomRadius * cos(random_angle_rad)); + float randomY = this.y + (randomRadius * sin(random_angle_rad)); + Particle p = new Particle(randomX, randomY, c); + particles.add(p); + } + + // Size of 0 makes the pumpkin shape disappear + this.sizePixels = 0; + this.state |= EXPLODE; + } + } + + /* + * Make the pumpkin bounce + */ + public void bounce() { + this.state |= BOUNCE; + } + + /* + * Set how high the pumpkin bounces + */ + public void setBounceHeight( int newHeightInPixels ) { + this.bounceHeight = newHeightInPixels; + this.y = newHeightInPixels; + } + + /* + * Stop the pumpkin from moving or bouncing + */ + public void stop() { + this.state = STILL; + this.xSpeed = 0; + } + + /* + * Regererate a new pumpkin! + */ + public void reset() { + this.setSize(int(random(100, 600))); + this.setBounceHeight(int(random(10, height/20))); + this.stop(); + } + + /* + * Have the pumpkin move to the right + */ + public void moveRight( int speed ) { + this.xSpeed = speed; + } + + /* + * Have the pumpkin move to the left + */ + public void moveLeft( int speed ) { + this.xSpeed = -speed; + } + + /* + * Draw the pumpkin! + */ + public void draw() { + pg.push(); + + int savedX = x, savedY = y; + + if ( (this.state & BOUNCE) != 0 ) { + updateBounce(); + } + if ( (this.state & EXPLODE) != 0 ) { + updateExplode(); + } + + // Spin must be the last if check because the x/y coordinates + // and coordiante system are modified when rotate() is called + if ( (this.state & SPIN) != 0 ) { + pg.pushMatrix(); + savedX = this.x; + savedY = this.y; + updateSpin(); + } + + drawPumpkinShape(); + + if ( (this.state & SPIN) != 0 ) { + pg.popMatrix(); + this.x = savedX; + this.y = savedY; + } + + // Call here so the shadow doesn't potentially rotate + drawShadow(); + + pg.pop(); + } + + private void updateBounce() { + + if ( bounceSpeed < bounceHeight ) { + bounceSpeed += gravity; + } + + y += bounceSpeed; + + if ( this.y > floorY - (sizePixels/2) ) { + this.y = floorY - (sizePixels/2); + + if ( (state & BOUNCE) != 0 ) { + bounceSpeed = -bounceSpeed; + } + } + + this.x += xSpeed; + + if ( this.x > pg.width + this.sizePixels ) { + this.x = 0 - this.sizePixels; + } + if ( this.x < 0 - this.sizePixels ) { + this.x = pg.width + this.sizePixels; + } + } + + private void updateSpin() { + pg.translate(x, y); + pg.rotate(radians(this.angleDeg)); + this.angleDeg += this.spinSpeed; + this.x = 0; + this.y = 0; + } + + private void updateExplode() { + for ( Particle p : particles ) { + p.update(); + p.draw(); + } + } + + private void drawShadow() { + float scaleFactor = sizePixels / 150.0; + float w = (150 * scaleFactor * y) / height; + float h = (10 * scaleFactor * y) / height; + pg.ellipse(x, floorY, w, h); + } + + private void drawPumpkinShape() { + if ( this.sizePixels == 0 ) { + return; + } + + float scaleFactor = sizePixels / 150.0; + + // Black outline + pg.ellipseMode(CENTER); + pg.stroke(0); + pg.strokeWeight(2); + + // Draw top stem + pg.fill(0); + pg.rect(x - (10.0 * scaleFactor), y - (sizePixels/2) - (20 * scaleFactor), 15 * scaleFactor, 20 * scaleFactor); + + // Draw body + pg.fill(pumpkinColor); + pg.ellipse(x, y, sizePixels, sizePixels); + + // Set flickering glow color + pg.fill(glowColor, random(200) + 50 ); + + // Draw eyes + pg.triangle(x - (30 * scaleFactor), y - (20 * scaleFactor), x - (20 * scaleFactor), y, x - (40 * scaleFactor), y); + pg.triangle(x + (30 * scaleFactor), y - (20 * scaleFactor), x + (20 * scaleFactor), y, x + (40 * scaleFactor), y); + pg.triangle(x, y, x + (10 * scaleFactor), y + (20 * scaleFactor), x - (10 * scaleFactor), y + (20 * scaleFactor)); + + // Draw mouth + pg.arc(x, y + (30 * scaleFactor), 80 * scaleFactor, 80 * scaleFactor, 0, PI, 0); + pg.line(x - (40 * scaleFactor), y + (30 * scaleFactor), x + (40 * scaleFactor), y + (30 * scaleFactor)); + + // Draw tooth + pg.fill(this.pumpkinColor); + pg.rect(x + (10 * scaleFactor), y + (30 * scaleFactor), 10 * scaleFactor, 15 * scaleFactor); + + // Clear the top outline of the tooth + pg.strokeWeight(3); + pg.stroke(this.pumpkinColor); + pg.fill(this.pumpkinColor); + pg.line(x + (12 * scaleFactor), y + (30 * scaleFactor), x + (17 * scaleFactor), y + (30 * scaleFactor)); + } + + class Particle { + float newX; + float oldX; + float newY; + float oldY; + float dir; + float magnitude; + float xVelocity; + float yVelocity; + float size; + float gravity; + int particleColor; + boolean isSparkle = false; + + public Particle(float x, float y) { + initialize(x, y); + } + public Particle( float x, float y, int particleColor ) { + initialize(x, y); + this.particleColor = particleColor; + } + + public Particle( float x, float y, int particleColor, float minSize, float maxSize ) { + initialize(x, y); + this.particleColor = particleColor; + this.size = random(minSize, maxSize); + } + + void initialize(float x, float y) { + newX = x; + oldX = newX; + newY = y; + oldY = newY; + + // radiate particles 360 degree from center + dir = random(0, TWO_PI); + + // Blast radius so the particle falls within the screen width + float fireworkWidth = float(width) / (1.7 * width); + magnitude = fireworkWidth * random(10.1, 25); + xVelocity = magnitude * cos(dir); + yVelocity = magnitude * sin(dir); + + + size = random(1, 10); + gravity = 0.2; + particleColor = #FFFFFF; + } + + void draw() { + pg.push(); + + // Draw a line from the old location to the new location + pg.strokeWeight(this.size); + if ( isSparkle ) { + float red = red(this.particleColor) - random(50); + float green = green(this.particleColor) - random(50); + float blue = blue(this.particleColor) - random(50); + pg.stroke(red, green, blue, random(255)); + } else { + pg.stroke(this.particleColor); + } + pg.line(oldX, oldY, newX, newY); + + pg.pop(); + } + + void update() { + // Calculate new X and Y, set old X and Y + oldX = newX; + oldY = newY; + newX += xVelocity; + newY += yVelocity; + yVelocity += gravity; + } + } +}