Don’t (or maybe do) get hit by the barrels! Press any key to jump.
var clouds = [];
var barrels = [];
var ground = 320;
var character;
var spaceship = [];
var drop = [];
var gravity = .5;
var count = 0; //keeps track of time since last barrel was made
var ouch = 0; //opacity for Ouch! text
function setup() {
createCanvas(480, 480);
frameRate(48);
strokeWeight(0);
character = makeCharacter();
textAlign(CENTER);
initialClouds();
}
function draw() {
makeCharacter()
background(0, 100, 200);
//cloud stuff
stepClouds();
removeClouds();
addClouds();
//ground
midground();
//spaceship barrel drop stuff
stepDrop();
removeDrop();
//more ground
closerMidground();
fill(50, 35, 35);
rect(0, ground, width, height - ground);
//character stuff
stepCharacter();
//barrel stuff
stepBarrels();
removeBarrels();
addBarrels();
//spaceship stuff
stepSpaceship();
removeSpaceship();
addSpaceship();
//extra stuff
hit();
count += 1;
}
//cloudy-related stuff
function makeCloud() {
var cloud = {x: width + 50,
y: 80 + random(-50, 50),
scale: random(.8, 1.5),
tufts: floor(random(1, 7)),//chooses how many parts in cloud
tuftX: [random(-15, 15), random(-15, 15), random(-15, 15),
random(-15, 15), random(-15, 15), random(-15, 15),
random(-15, 15)], //parts in cloud have random location
tuftY: [random(-15, 15), random(-15, 15), random(-15, 15),
random(-15, 15), random(-15, 15), random(-15, 15),
random(-15, 15)],
speed: -.2,
move: cloudMove,
appearance: cloudAppearance}
return cloud;
}
function initialClouds() { //make clouds when script starts
for (var i = 0; i < random(5, 12); i ++) {
clouds.push(makeCloud());
clouds[i].x = random(width);
}
}
function cloudMove() {
this.x += this.speed * this.scale;
}
function cloudAppearance() {
fill(240, 100);
strokeWeight(0);
for(var i = 0; i < this.tufts; i ++) {
rect(this.x + this.tuftX[i], this.y + this.tuftY[i],
40 * this.scale, 20 * this.scale, 5 * this.scale);
}
}
function stepClouds() { //updates the cloud features to redraw them
for (var i = 0; i < clouds.length; i ++) {
clouds[i].move();
clouds[i].appearance();
}
}
function addClouds() { //spawns new clouds randomly
if (clouds.length <= 15 & random(0, 1) < .01) {
clouds.push(makeCloud());
}
}
function removeClouds() { //gets rid of clouds when off screen
var cloudsToKeep = [];
for (var i = 0; i < clouds.length; i ++) {
if (clouds[i].x + (40 * clouds[i].scale) + 15 > 0) {
cloudsToKeep.push(clouds[i]);
}
}
clouds = cloudsToKeep;
}
//character stuff
function makeCharacter() {
var character = {x: 50,
y: ground - 10,
yf: 0,
width: 10,
height: 10,
color: color(0),
jump: false,
move: characterJump,
appearance: characterAppearance,
collision: collision}
return character;
}
function characterJump() { //makes character move up and down when a key is pressed
if (this.jump == true) {
this.yf += gravity;
}
this.y += this.yf;
this.y = min(this.y, ground - this.height);
if (this.y == ground - this.height) {
this.jump = false;
}
if (keyIsPressed == true & this.jump == false) {
this.jump = true;
this.yf -= 10;
}
}
function characterAppearance() {
fill(this.color);
strokeWeight(1);
stroke(0, 150);
rect(this.x, this.y, this.width, this.height);
}
function stepCharacter() {
character.move();
character.appearance();
character.collision();
}
function collision() { //when character hits a barrel, change color and say Ouch!
for (var i = 0; i < barrels.length; i ++) {
if (dist(this.x, this.y,
barrels[i].x, barrels[i].y) <= barrels[i].radius ||
dist(this.x + this.width, this.y,
barrels[i].x, barrels[i].y) <= barrels[i].radius ||
dist(this.x, this.y + this.height,
barrels[i].x, barrels[i].y) <= barrels[i].radius ||
dist(this.x + this.width, this.y + this.height,
barrels[i].x, barrels[i].y) <= barrels[i].radius) {
this.color = barrels[i].color;
barrelHit(i);
}
}
}
//barrel stuff
function makeBarrel() {
var barrel = {x: width + 50,
y: ground - random(50, 150),
ySpeed: 0,
xSpeed: -3,
radius: 10,
color: color(random(0, 150), random(0, 150), random(0, 150)),
move: barrelMove,
appearance: barrelAppearance}
return barrel;
}
function barrelMove() {
this.x += this.xSpeed;
this.y += this.ySpeed;
this.y = min(ground - 10, this.y);
this.ySpeed += gravity;
if (this.y == ground - 10) {
this.ySpeed = -this.ySpeed * .82;
}
}
function barrelAppearance() {
fill(this.color);
strokeWeight(1);
stroke(0, 150);
ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
function stepBarrels() {
for (var i = 0; i < barrels.length; i ++) {
barrels[i].move();
barrels[i].appearance();
}
}
function addBarrels() {
if (random(0, 1) < .01 & count >= 48/*prevents from being too close*/) {
barrels.push(makeBarrel());
count = 0;
}
}
function removeBarrels() {
var barrelsToKeep = [];
for (var i = 0; i < barrels.length; i ++) {
if (barrels[i].x + 10 > 0) {
barrelsToKeep.push(barrels[i]);
}
}
barrels = barrelsToKeep;
}
function barrelHit(index) { //deletes hit barrels and says Ouch!
var barrelsToKeep = [];
for (var i = 0; i < barrels.length; i ++) {
if (i != index) {
barrelsToKeep.push(barrels[i]);
}
}
barrels = barrelsToKeep;
ouch = 255; //sets opacity for Ouch! to be visible
}
function hit() { //displays Ouch!
fill(255, 0, 0, ouch);
strokeWeight(0);
textSize(100);
text("Ouch!", 60, 100, width - 100, 200);
ouch -= 5;
}
//landscape elements
function midground() { //makes ground randomly according to noise
var terrainSpeed = 0.00005;
var terrainDetail = 0.005;
fill(50);
strokeWeight(0);
beginShape();
vertex(0, height);
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (millis() * terrainSpeed);
var y = map(noise(t), 0, 1, height / 4, ground);
vertex(x, y);
}
vertex(width, height);
endShape();
}
function closerMidground() { //makes ground randomly according to noise
var terrainSpeed = 0.0007;
var terrainDetail = 0.05;
fill(50, 80, 50);
strokeWeight(0);
beginShape();
vertex(0, height);
for (var x = 0; x < width; x++) {
var t = (x * terrainDetail) + (100000 + millis() * terrainSpeed);
var y = map(noise(t), 0, 1, height / 2, ground);
vertex(x, y);
}
vertex(width, height);
endShape();
}
//spaceship
function makeSpaceship() {
var spaceship = {x: -50,
y: random(50, 150),
speed: 0,
speedBoost: random(0, 500),
move: spaceshipMove,
appearance: spaceshipAppearance}
return spaceship;
}
function spaceshipMove() {
//movement speeds up and slows down according to noise
this.x += this.speed + .5 * (noise(millis() * .001 + this.speedBoost));
}
function spaceshipAppearance() {
strokeWeight(1);
fill(255, 200);
ellipse(this.x + 25, this.y - 5, 15, 15);
fill(150);
ellipse(this.x + 25, this.y, 50, 10);
}
function stepSpaceship() {
for (var i = 0; i < spaceship.length; i ++) {
spaceship[i].move();
spaceship[i].appearance();
addDrop(i); //spawns in barrel drops from ship
}
}
function addSpaceship() {
if (random(0, 1) < .0009 - (spaceship.length * .0003)) {
spaceship.push(makeSpaceship());
}
}
function removeSpaceship() {
var spaceshipToKeep = [];
for (var i = 0; i < spaceship.length; i ++) {
if (spaceship[i].x - 25 < width) {
spaceshipToKeep.push(spaceship[i]);
}
}
spaceship = spaceshipToKeep;
}
//spaceship barrel drop
function makeDrop(i) {
var drop = {x: spaceship[i].x + 27, //spawns at spaceship location
y: spaceship[i].y,
ySpeed: 0,
color: color(random(0, 160), random(0, 160), random(0, 160)),
radius: 3,
move: dropMove,
appearance: dropAppearance}
return drop;
}
function dropMove() {
this.y += this.ySpeed;
this.ySpeed += gravity / 5;
}
function dropAppearance() {
fill(this.color);
strokeWeight(.5);
stroke(0, 150);
ellipse(this.x, this.y, this.radius * 2, this.radius * 2);
}
function stepDrop() {
for (var i = 0; i < drop.length; i ++) {
drop[i].move();
drop[i].appearance();
}
}
function addDrop(i) {
if (random(0, 1) < .01) {
drop.push(makeDrop(i));
}
}
function removeDrop() {
var dropToKeep = [];
for (var i = 0; i < drop.length; i ++) {
if (drop[i].y < ground) {
dropToKeep.push(drop[i]);
}
}
drop = dropToKeep;
}
When thinking of generative landscapes, I started thinking about side-scrolling games, and so I decided to combine the two! Most of the objects are pretty basic — stuff gets introduced and moves across the screen — so I decided to add some complexity to each of the objects, giving them things like different numbers of components, bouncing, and spawning new objects. The part of this project I personally love the most is that when the character gets hit by a barrel, they become the same color as that barrel! I just think that’s so neat (and it’s also kinda sad, because clearly getting hit by the barrel hurts, but it’s so cool to watch!).