mmiller5-Project-10

Don’t (or maybe do) get hit by the barrels!  Press any key to jump.

sketch

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!).

Leave a Reply