///////////////////////////
// Jumping Square //
// Object Oriented toy //
// By: Nicolas Olivieri //
///////////////////////////
// No objective, just jump around the screen
// and enjoy the pretty lights that run away from you!
//
// W = Jump
// A = Left
// D = Right
Floor floor;
Background gradBG;
Player player;
SetPlatforms platforms;
Particle p;
ParticleSystem ps;
Keyboard keyboard = new Keyboard();
void setup() {
// Initialize screen
size(800, 600, P2D);
// Create the background
gradBG = new Background();
// Create the floor
floor = new Floor();
// Create the platforms
platforms = new SetPlatforms();
// Create the player
player = new Player();
// Create the particle system
ps = new ParticleSystem();
// Generate the spikes
floor.generateBigSpikes();
floor.generateSmallSpikes();
// Generate the platforms
platforms.generatePlatforms();
// Generate the particles
ps.generateParticles(player.location);
}
void draw() {
frameRate(60);
// Make sure particles don't go off the screen
ps.constrainParticle(player.location);
MPAFP();
// Move the player
player.runInput();
player.move();
player.constrainPlayer();
gradBG.drawBG();
ps.drawParticles();
floor.drawFloor();
platforms.drawPlatforms();
player.drawPlayer();
}
// Move particles away from player
void MPAFP() {
float playerCenterX = player.location.x + player.size / 2;
float playerCenterY = player.location.y + player.size / 2;
for (int i = 0; i < ps.psRandom.length; i++) {
float distX = abs(playerCenterX - ps.psRandom[i].location.x);
float distY = abs(playerCenterY - ps.psRandom[i].location.y);
if (distX < 50 && distY < 50) {
ps.psRandom[i].velocity.x = -player.velocity.x * 1.5;
ps.psRandom[i].velocity.y = player.velocity.y * 1.5;
}
}
}
// Needed to keep track of multiple keys being pressed at the same time
void keyPressed() {
keyboard.onPressed(keyCode);
}
void keyReleased() {
keyboard.onReleased(keyCode);
}
class Background {
public void drawBG() {
// Background
pushMatrix();
beginShape();
// Top left
fill(50);
vertex(0, 0);
// Top right
fill(50);
vertex(800, 0);
// Bot right
fill(30);
vertex(800, 600);
// Bot left
fill(30);
vertex(0, 600);
endShape();
popMatrix();
fill(0, 40);
triangle(-100, height, 100, 150, 280, height);
triangle(100, height, 300, 60, 450, height);
triangle(300, height, 450, 300, 600, height);
}
}public class Floor {
// Big Spikes
private Spike[] bigSpikes = new Spike[20];
// Small Spikes
private Spike[] smallSpikes = new Spike[100];
public void generateBigSpikes() {
// Generates the big spikes in the array
for (int i = 0; i < bigSpikes.length; i++)
bigSpikes[i] = new Spike();
// Generates the big spike conditions for every spike in the array
for (int i = 0; i < bigSpikes.length; i++) {
bigSpikes[i].spikeX = random(0, width);
bigSpikes[i].gradStart = color(255, 0, 0);
bigSpikes[i].gradEnd = color(60, 0, 0);
bigSpikes[i].spikeY = 600;
bigSpikes[i].spikeSize = random(35, 60);
bigSpikes[i].spikeHalfSize = bigSpikes[i].spikeSize / 2;
}
}
public void generateSmallSpikes() {
// Generates the small spikes in the array
for (int i = 0; i < smallSpikes.length; i++)
smallSpikes[i] = new Spike();
// Generates the small spike conditions for every spike in the array
for (int i = 0; i < smallSpikes.length; i++) {
smallSpikes[i].spikeX = random(0, width);
smallSpikes[i].gradStart = color(20);
smallSpikes[i].gradEnd = color(5);
smallSpikes[i].spikeY = 600;
smallSpikes[i].spikeSize = random(10, 25);
smallSpikes[i].spikeHalfSize = smallSpikes[i].spikeSize / 1.5;
}
}
// Draw the floor
public void drawFloor() {
// Loop through the array and draw the spikes randomly
for (int i = 0; i < bigSpikes.length; i++)
bigSpikes[i].display();
for (int i = 0; i < smallSpikes.length; i++)
smallSpikes[i].display();
// Floor line
pushMatrix();
beginShape();
fill(30);
vertex(0, 535);
fill(30);
vertex(0, 536);
fill(100);
vertex(150, 536);
fill(100);
vertex(650, 536);
fill(30);
vertex(800, 536);
fill(30);
vertex(800, 535);
fill(100);
vertex(150, 535);
fill(100);
vertex(650, 535);
endShape();
popMatrix();
}
}// Keyboard keyCode values (from processing wiki)
int KEY_A = 65;
int KEY_D = 68;
int KEY_W = 87;
int KEY_S = 83;
class Keyboard {
private boolean states[] = new boolean[256];
public Keyboard() {
for (int i = 0; i < states.length; i++)
states[i] = false;
}
public void onPressed(int _keyCode) {
//assert(_keyCode > 0 && _keyCode < states.length);
states[_keyCode] = true;
}
public boolean isKeyDown(int _keyCode) {
//assert(_keyCode > 0 && _keyCode < states.length);
return states[_keyCode];
}
public void onReleased(int _keyCode) {
//assert(_keyCode > 0 && _keyCode < states.length);
states[_keyCode] = false;
}
public boolean isKeyUp(int _keyCode) {
//assert(_keyCode > 0 && _keyCode < states.length);
return !states[_keyCode];
}
}class Particle {
PVector location;
PVector velocity;
PVector acceleration;
float particleSize;
color particleStroke;
color particleFill;
float w;
float h;
float fadeStroke = 100;
float fadeFill = 150;
// Update location of the particle and fade the floor particles
void updateParticles() {
if (location.y <= height) {
fadeStroke -= 10;
fadeFill -= 5;
}
velocity.add(acceleration);
location.add(velocity);
velocity.limit(3.5);
}
public void display() {
drawParticle(particleSize, particleStroke, particleFill, location.x, location.y, w, h);
}
// Draw the particle
void drawParticle(float sW, color s, color f, float x, float y, float w, float h) {
strokeWeight(sW);
stroke(s);
fill(f);
ellipse(x, y, w, h);
}
}class ParticleSystem {
// Particles that are randomly moving around in the background
// of the scene
Particle[] psRandom = new Particle[20];
// Particles that are on the floor
Particle[] psFloor = new Particle[40];
// Particles that follow the player
Particle[] psPlayer = new Particle[20];
float offset;
// Generates the particles conditions for every particle in the array
void generateParticles(PVector playerPos) {
// Initialize random particles
for (int i = 0; i < psRandom.length; i++) {
psRandom[i] = new Particle();
psRandom[i].location = new PVector(random(100, 500), height);
psRandom[i].particleFill = color(181, 14, 14, 50);
psRandom[i].acceleration = new PVector(0, 0);
psRandom[i].velocity = new PVector(0, 0);
}
// Initialize particles on the floor
for (int i = 0; i < psFloor.length; i++) {
psFloor[i] = new Particle();
psFloor[i].location = new PVector(random(0, width), random(height, 700));
psFloor[i].particleSize = 2;
psFloor[i].w = 5;
psFloor[i].h = 6;
psFloor[i].acceleration = new PVector(0, random(-0.01, -0.02));
psFloor[i].velocity = new PVector(0, -2);
}
// Initialize particles following player
for (int i = 0; i < psPlayer.length; i++) {
psPlayer[i] = new Particle();
psPlayer[i].location = new PVector(random(0, 50), playerPos.y + random(0, 50));
psPlayer[i].particleSize = 1;
psPlayer[i].w = 5;
psPlayer[i].h = 6;
psPlayer[i].acceleration = new PVector(0, random(-0.1, -0.2));
psPlayer[i].velocity = new PVector(0, -2);
}
}
// Generates the particles conditions that need to
// be in draw for every particle in the array
void drawParticles() {
for (int i = 0; i < psRandom.length; i++) {
psRandom[i].acceleration = PVector.random2D();
psRandom[i].particleSize = sin(frameCount * 0.7) * 5;
psRandom[i].particleStroke = color(255, 0, 0, sin(frameCount * 0.2) * 40);
psRandom[i].w = 8 + sin(frameCount * 0.06) * 3;
psRandom[i].h = 8 + sin(frameCount * 0.06) * 3;
psRandom[i].updateParticles();
psRandom[i].display();
}
for (int i = 0; i < psFloor.length; i++) {
psFloor[i].particleFill = color(10, psFloor[i].fadeFill);
psFloor[i].particleStroke = color(255, 0, 0, psFloor[i].fadeStroke);
psFloor[i].updateParticles();
psFloor[i].display();
}
for (int i = 0; i < psPlayer.length; i++) {
psPlayer[i].particleFill = color(10, psPlayer[i].fadeFill);
psPlayer[i].particleStroke = color(180, 133, 0, psPlayer[i].fadeStroke);
psPlayer[i].updateParticles();
offset = psPlayer[i].location.x;
psPlayer[i].location.x = player.location.x + offset;
psPlayer[i].display();
psPlayer[i].location.x = offset;
}
}
void constrainParticle(PVector playerPos) {
// Locks random prticles within the screen
for (int i = 0; i < psRandom.length; i++) {
if (psRandom[i].location.x >= width)
psRandom[i].location.x = -8;
if (psRandom[i].location.x <= -8)
psRandom[i].location.x = width;
if (psRandom[i].location.y >= height)
psRandom[i].location.y = -8;
if (psRandom[i].location.y <= -8)
psRandom[i].location.y = height;
}
// Reset the floor particles when they hit the ground
for (int i = 0; i < psFloor.length; i++) {
if (psFloor[i].location.y <= 533 + psFloor[i].h) {
psFloor[i].location.y = height;
psFloor[i].fadeStroke = 100;
psFloor[i].fadeFill = 150;
psFloor[i].velocity.y = -2;
}
}
// Reset the player particles depending on their distance away from the player
for (int i = 0; i < psPlayer.length; i++) {
float distY = abs(playerPos.y - psPlayer[i].location.y);
if (distY >= 100) {
psPlayer[i].location.y = playerPos.y + random(0, 50);
psPlayer[i].fadeStroke = 100;
psPlayer[i].fadeFill = 150;
psPlayer[i].velocity.y = -2;
}
}
}
}class Platform {
PVector location,
velocity,
acceleration;
float endPos; // End position of platform
Platform() {
velocity = new PVector(2, 2);
acceleration = new PVector(0.06, 0.06);
}
void drawPlatform() {
// Platform
noStroke();
pushMatrix();
beginShape();
// Top left
fill(0);
vertex(location.x, location.y);
// Top right
fill(0);
vertex(location.x + 70, location.y);
// Bot right
fill(180, 18, 93, 70);
vertex(location.x + 70, location.y + 25);
// Bot left
fill(180, 18, 93, 70);
vertex(location.x, location.y + 25);
endShape();
popMatrix();
// Gives a stroke to the platform
strokeWeight(1);
stroke(255);
noFill();
rect(location.x - 1, location.y - 1, 72, 27);
// Handle
stroke(5);
strokeWeight(3);
line(location.x + 35, location.y + 28, location.x + 35, location.y + 45);
// Blinking light
fill(180, 18, 93, 70);
stroke(30);
strokeWeight(1);
ellipseMode(CENTER);
ellipse(location.x + 35, location.y + 45, sin(frameCount * 0.06) * 20, sin(frameCount * 0.06) * 20);
}
// Move the platform up on start up
void movePlatform() {
location.y -= velocity.y;
velocity.y += acceleration.y;
if (location.y <= endPos) {
velocity.y = 0;
acceleration.y = 0;
}
}
// Is the player colliding with a platform
public boolean collides() {
if (player.location.y < location.y + 25 && player.size + player.location.y > location.y &&
player.location.x < location.x + 70 && player.location.x + player.size > location.x) {
return true;
}
return false;
}
}class Player {
PVector location,
velocity,
acceleration;
float ground;
float gravity,
size;
float playerSpeed,
jumpSpeed,
jumpGravityReduction;
boolean jumping;
Player() {
size = 50;
ground = 533;
gravity = 4;
playerSpeed = 2.5;
jumpSpeed = 19;
jumpGravityReduction = 0.25;
jumping = false;
location = new PVector(width / 2, ground - size);
velocity = new PVector(0, 0);
acceleration = new PVector(0, 0);
}
void runInput() {
// Recalculate input velocity
acceleration.x = 0;
acceleration.y = 0;
if (keyboard.isKeyDown(KEY_A)) {
acceleration.x -= 8;
} else if (keyboard.isKeyDown(KEY_D)) {
acceleration.x += 8;
}
if (keyboard.isKeyDown(KEY_W) && !jumping) {
jumping = true;
velocity.y = -jumpSpeed;
}
}
void move() {
// Apply gravity
if (velocity.y < gravity) {
float actualGravity = gravity;
if (jumping)
actualGravity *= jumpGravityReduction;
velocity.y += actualGravity;
// Clamp gravity
if (velocity.y > gravity)
velocity.y = gravity;
}
// Check if the movement is making us collide with something
boolean currentlyColliding = false;
for (int i = 0; i < platforms.platforms.length; i++) {
Platform p = platforms.platforms[i];
boolean doesCollide = p.collides();
if (doesCollide) {
currentlyColliding = true;
break;
}
}
// Does moving down make us hit something
float velY = velocity.y + acceleration.y;
location.y += velY;
boolean collidingBottom = false;
for (int i = 0; i < platforms.platforms.length; i++) {
Platform p = platforms.platforms[i];
boolean doesCollide = p.collides();
if (!currentlyColliding && doesCollide) {
// Make sure the player doesn't go through the object
collidingBottom = velY < 0;
if (!collidingBottom) {
location.y = p.location.y - size - 1;
jumping = false; // Reset jumping because we're hitting a platform
}
break;
}
}
float velX = velocity.x + acceleration.x;
location.x += velX;
for (int i = 0; i < platforms.platforms.length; i++) {
Platform p = platforms.platforms[i];
boolean doesCollide = p.collides();
if (!currentlyColliding && doesCollide && !collidingBottom) {
boolean collidingLeft = velX > 0;
if (collidingLeft) {
location.x = p.location.x - size - 1;
} else {
location.x = p.location.x + 70 + 1;
}
break;
}
}
}
void drawPlayer() {
stroke(255, 132, 0);
strokeWeight(1);
fill(50);
rect(location.x, location.y, size, size);
noStroke();
fill(255, 132, 0, 100);
rect(location.x + 10, location.y + 10, size - 20, size - 20);
fill(50);
rect(location.x + 15, location.y + 15, size - 30, size - 30);
}
// Constrain the player to the screen
void constrainPlayer() {
if (location.x >= width) {
location.x = 0 - size + 1;
}
if (location.x <= 0 - size) {
location.x = width;
}
if (location.y + (velocity.y + acceleration.y) > ground - size) {
location.y = ground - size;
jumping = false;
}
}
}class SetPlatforms {
Platform[] platforms = new Platform[7];
public void generatePlatforms() {
// Sets random positions for the platforms
for (int i = 0; i < platforms.length; i++) {
platforms[i] = new Platform();
platforms[i].endPos = random(60, 450);
platforms[i].location = new PVector(random(10, width - 80), height + 1);
}
// Ensure that each platform is spaced out from all other platforms
for (int i = 0; i < platforms.length; i++) {
boolean finished = false;
int attempts = 0; // safety to make sure the loop doesn't run infinitely
while (!finished) {
attempts++;
finished = true;
for (int j = 0; j < platforms.length; j++) {
// don't try and space the platform out from itself
if (j == i)
continue;
float distX = abs(platforms[j].location.x - platforms[i].location.x);
float distY = abs(platforms[j].location.y - platforms[i].location.y);
if (distY < 45 && distX < 75) {
// platform is too close; re-generate, try again.
finished = false;
platforms[i].location = new PVector(random(10, width - 80), height + 1);
// break out of the for loop and start checking over again
break;
}
}
// Perhaps there's a better way of doing this?
// Preventing an infinite loop
if (attempts > 500000) {
//println("Quite unlucky!");
break;
}
}
}
}
void drawPlatforms() {
// Draw and update the platforms in the array
for (int i = 0; i < platforms.length; i++) {
platforms[i].movePlatform();
platforms[i].drawPlatform();
}
}
}public class Spike {
public color gradStart,
gradEnd;
public float spikeX,
spikeY,
spikeSize,
spikeHalfSize;
public void display() {
drawGradientSpike(spikeX, spikeY, spikeX + (spikeHalfSize / 2), spikeY - spikeSize,
spikeX + spikeHalfSize, spikeY, gradStart, gradEnd);
}
// Draws the gradient spike
void drawGradientSpike(float x1, float y1, float x2, float y2, float x3, float y3, color color1, color color2) {
noStroke();
pushMatrix();
beginShape();
// top of triangle
fill(color1);
vertex(x2, y2);
// bottom left
fill(color2);
vertex(x1, y1);
// bottom right
vertex(x3, y3);
endShape();
popMatrix();
}
}