class Player { private Particle p, peg; private float radius, eyeRadius, speed, suckRadius, blowRadius, nmef; boolean up, right, down, left, suck, blow; // for keyboard control private boolean sucking, blowing, bounced; private int suckCnt, blowCnt; private Vector blowRings; private color c, g; Player () { p = phys.makeParticle(1, width/2, height/2, 0); peg = phys.makeParticle(1, width/2, height/2, 0); peg.makeFixed(); radius = playerSize; eyeRadius = radius*0.38f; suckRadius = blowRadius = radius*4; speed = playerSpeed; up = right = down = left = false; suckCnt = blowCnt = 0; blowRings = new Vector(5, 5); c = playerColor; g = playerGlow; nmef = 0.1f; } void keyMove() { if ( !(bounced && isMoving()) ) { bounced = false; float v = speed/mass(); if ( up ) { p.setVelocity(vx(), -v, 0); } if ( down ) { p.setVelocity(vx(), v, 0); } if ( left ) { p.setVelocity(-v, vy(), 0); } if ( right ) { p.setVelocity(v, vy(), 0); } } keepOnScreen(); peg.moveTo(x(), y(), 0); } void move(float x, float y) { if ( !(bounced && isMoving()) ) { bounced = false; p.setVelocity(x/mass(), y/mass(), 0); } keepOnScreen(); peg.moveTo(x(), y(), 0); } private void keepOnScreen() { if ( x() < radius ) { p.moveTo(radius, y(), 0); addVelocity(30/mass(), 0); } else if ( x() > width - radius ) { p.moveTo(width - radius, y(), 0); addVelocity(-30/mass(), 0); } if ( y() < radius ) { p.moveTo(x(), radius, 0); addVelocity(0, 30/mass()); } else if ( y() > height - radius ) { p.moveTo(x(), height - radius, 0); addVelocity(0, -30/mass()); } } void addVelocity(float x, float y) { p.addVelocity(x, y, 0); bounced = true; } void setMass(float m) { p.setMass(constrain(m, 1, 3)); } void setSuckRadius(float r) { suckRadius = r; } void setBlowRadius(float r) { blowRadius = r; } void reset() { p.moveTo(width/2, height/2, 0); peg.moveTo(width/2, height/2, 0); sucking = false; blowing = false; } void interact(Pulser puls) { float d = dist(x(), y(), puls.x(), puls.y()); float vx = (puls.x() - x())/d; float vy = (puls.y() - y())/d; if ( sucking && d < suckRadius + puls.radius() ) { puls.attach(); } if ( puls.isAttached() && !sucking ) { puls.detach(); if ( puls.mood() == VORACIOUS ) puls.setVelocity(vx*50, vy*50); else puls.setVelocity(vx*10, vy*10); } if ( isBlowing() && d < blowRadius() + puls.radius() ) { puls.setVelocity(blowStrength*vx, blowStrength*vy); puls.setMood(HAPPY); } } void interact(Deathskull nme) { // actual distance float d = dist(x(), y(), nme.x(), nme.y()); // minimum allowed distance float md = radius + nme.radius(); // unit vector pointing towards the enemy float vx = (nme.x() - x())/d; float vy = (nme.y() - y())/d; if ( sucking && d < suckRadius + nme.radius() ) nme.setVelocity(-vx*nmef, -vy*nmef); if ( isBlowing() && d < blowRadius() + nme.radius() ) nme.setVelocity(vx*nmef, vy*nmef); if ( d < md ) { p.moveTo(nme.x() - vx*md, nme.y() - vy*md, 0); nme.addVelocity(vx*nmef, vy*nmef); } } void interact(Sucker nme) { // actual distance float d = dist(x(), y(), nme.x(), nme.y()); // minimum allowed distance float md = radius + nme.radius(); // unit vector pointing towards the enemy float vx = (nme.x() - x())/d; float vy = (nme.y() - y())/d; if ( sucking && d < suckRadius + nme.radius() ) nme.setVelocity(-vx*nmef, -vy*nmef); if ( isBlowing() && d < blowRadius() + nme.radius() ) nme.setVelocity(vx*nmef, vy*nmef); if ( d < md ) { p.moveTo(nme.x() - vx*md, nme.y() - vy*md, 0); nme.addVelocity(vx*nmef, vy*nmef); } } void interact(Blower nme) { // actual distance float d = dist(x(), y(), nme.x(), nme.y()); // minimum allowed distance float md = radius + nme.radius(); // unit vector pointing towards the enemy float vx = (nme.x() - x())/d; float vy = (nme.y() - y())/d; if ( sucking && d < suckRadius + nme.radius() ) nme.setVelocity(-vx*nmef, -vy*nmef); if ( isBlowing() && d < blowRadius() + nme.radius() ) nme.setVelocity(vx*nmef, vy*nmef); if ( d < md ) { p.moveTo(nme.x() - vx*md, nme.y() - vy*md, 0); nme.addVelocity(vx*nmef, vy*nmef); } } void interact(PickUp pick) { float d = dist(x(), y(), pick.x(), pick.y()); if ( sucking && d < suckRadius + pick.radius() ) pick.attach(); } void suck(boolean b) { if ( !blowing && b ) sucking = true; else sucking = false; } void keySuck() { suck(suck); } boolean isSucking() { return sucking; } void blow(boolean b, boolean c) { if ( !blowing && b ) { if ( c ) blowRings.add(new Ring(1024, color(255, 0, 0, 120))); else blowRings.add(new Ring(blowRadius, color(255))); } blowing = b; } void keyBlow(boolean c) { blow(blow, c); } void spawnRing() { blowRings.add(new Ring(blowRadius, color(255))); } boolean isBlowing() { return blowRings.size() > 0; } boolean isMoving() { return (abs(vx()) > 2f || abs(vy()) > 2f); } float radius() { return radius; } float suckRadius() { return suckRadius; } float blowRadius() { float blrad = 0; for (int i = 0; i < blowRings.size(); i++) { float tmp = ((Ring)blowRings.get(i)).radius(); if ( tmp < blowRadius ) { blrad = tmp; break; } } return blrad; } float mass() { return p.mass(); } float x() { return p.position().x(); } float y() { return p.position().y(); } float vx() { return p.velocity().x(); } float vy() { return p.velocity().y(); } void render() { noFill(); stroke(c); pushMatrix(); translate(x(), y()); // suck waves if ( sucking ) { float rad = constrain(suckRadius * cos((suckCnt%30)*PI/60), radius, suckRadius); octa(rad); suckCnt++; } else suckCnt = 0; // blow waves for (int i = 0; i < blowRings.size(); i++) { Ring tmp = (Ring)blowRings.get(i); if ( tmp.finished ) { blowRings.remove(i); i--; } else { tmp.update(); tmp.render(); } } // the player if ( drawGlow ) { float radI = radius; float radO = radius; float eRadI = eyeRadius; float eRadO = eyeRadius; for (int i = 1; i < 10; i++) { radI *= 0.97f; eRadI *= 0.97f; radO *= 1.03f; eRadO *= 1.03f; stroke(red(g), green(g), blue(g), 200f/i); octa(radI); octa(radO); diamond(eRadI, -radius*0.5f, radius*0.1f); diamond(eRadO, radius*0.5f, radius*0.1f); triangle(radI*-0.5625, radI*0.55, radI*0.5626, radI*0.55, 0, radI*0.8f); triangle(radO*-0.5625, radO*0.55, radO*0.5626, radO*0.55, 0, radO*0.8f); } fill(255, 255, 190, 50); ellipse(-radius*0.5f, radius*0.1f, eyeRadius*0.4f, eyeRadius*0.4f); ellipse(radius*0.5f, radius*0.1f, eyeRadius*0.4f, eyeRadius*0.4f); } noFill(); stroke(c); octa(radius); // left eye diamond(eyeRadius, -radius*0.5f, radius*0.1f); plus(eyeRadius, -radius*0.5f, radius*0.1f); cross(eyeRadius*0.5f, -radius*0.5f, radius*0.1f); // right eye diamond(eyeRadius, radius*0.5f, radius*0.1f); plus(eyeRadius, radius*0.5f, radius*0.1f); cross(eyeRadius*0.5f, radius*0.5f, radius*0.1f); // mouth triangle(radius*-0.5625, radius*0.55, radius*0.5626, radius*0.55, 0, radius*0.8f); popMatrix(); } class Ring { boolean finished; private float radius, endRadius, step; private color col; Ring(float r, color c) { radius = playerSize; endRadius = r; step = 10; col = c; } float radius() { return radius; } void update() { radius += step; } void render() { stroke(col); octa(radius); if ( radius >= endRadius ) finished = true; } } }