For my final project, I created a small game. I was inspired by the game many of us played as kids, with only one rule: don’t touch the lava! It’s a fun and simple game that I wanted to recreate in a digital format, to reflect on what we’ve learned this semester, and make something nostalgic and cheerful to combat the stress of year’s end.
To play the game, press any key to jump.
Your goal is to land atop each piece of furniture, and survive as long as you can. There’s some wiggle room (to make up for how kids will climb and latch onto furniture) but if you miss too many pieces of furniture, you’ll fall into the lava!
Stay alive as long as you can to rack up points. Boosters will give you 10 points each. Survive until 100 points to win!
*Don’t worry, it’s not meant to be a difficult game! As long as you pay attention, it should be a light-hearted, nostalgic experience.
Options to Play:
(I’ve posted these options, instead of embedding it, because this project requires the p5.play library from Molleindustria to work. p5.play is included in the downloads below.)
1. link to compressed zip file:finalproject_sofiasyjuco
2. link to download: https://www.dropbox.com/sh/emyra5s8hvgg71k/AADEDrgWffYkxI3NPN7VeSkHa?dl=0
//sofia syjuco //section A //smsyjuco@andrew.cmu.edu //final project var canvas;// variable for the canvas var pixelScale = 5;//size of the pixels var fontPixel;// font for the text var furniture;// variable for the furniture var furnitureList = [];// list to store all the furniture that appear var furnitureImage = [];// array to store all the furniture images var furnitureGroup = new Group();// group to store all the furniture for colliders var treasure;//variable for the treasure var treasureList = [];// list to store the treasure in var treasure_image;// variable for the treasure image var treasureGroup = new Group();// group to put all the treasure in for colliders //declare a variable for each animation var run_animation; var jump_animation; var character;// variable for the child character var dead = false;// variable to determine win state/lose state var points = 0;// variable to store the amount of points earned var floorHeight = 12;// variable for the height of the floor function preload(){ //load in the animations for the character sprite_sheet = loadSpriteSheet('assets/run_spritesheet.png', 12, 24, 2); run_animation = loadAnimation(sprite_sheet); sprite_sheet = loadSpriteSheet('assets/jump_spritesheet.png', 12, 24, 3); jump_animation = loadAnimation(sprite_sheet); // load in the image for the background bg_image = loadImage("assets/lava_background.png"); // load in images for furniture for (var i=1;i<4;i++){ furnitureImage[i] = loadImage("assets/furniture_"+[i]+".png"); } //load in image for treasure treasure_image = loadImage("assets/treasure_button.png"); // frame delays for the character's animations run_animation.frameDelay = 20; jump_animation.frameDelay = 20; // load in a pixel font fontPixel = loadFont("assets/Pixeled.ttf"); } function setup(){ canvas = createCanvas(80,50);// create the canvas //adjust how large the canvas appears to compensate for the pixel art's size canvas.style("width", width * pixelScale + "px"); canvas.style("height", height * pixelScale + "px"); noSmooth();// make sure it doesn't smooth down the pixel art createCharacter();// create a character createFurniture(25);// create a furniture to start with createFurniture(55);// create a second piece of furniture to start with createFurniture(85);// create a third piece of furniture to start with // need three pieces of furniture to start with, since it won't start generating //furniture until about a second into playing the game, so she'll die right away. } function createCharacter(){// this function stores information about your character character = createSprite(10, height - 32, 12, 24);// create a sprite character.setCollider("rectangle", 0, 12, 12, 1);// set the sprite's collider character.addAnimation('run', run_animation);// connect the animation character.addAnimation('jump', jump_animation);// connect the animation character.updatePosition = function(){// function to update character's position character.changeAnimation("run");//they should be running as a default if (character.overlap(treasureGroup) === true){// if the character hits treasure points +=10;// add ten points treasureList[0].remove();// remove the treasure from the storage list } if (character.overlap(furnitureGroup) === false){// if not touching furniture if (character.position.y < (height)){// if they're any higher than the lava character.position.y += 0.5;//have gravity kick in and they begin to fall } } // if the character is standing on the floor and they press a key if (keyIsPressed === true && character.overlap(furnitureGroup) === true){ character.position.y -= 10; // have them jump character.changeAnimation("jump");// change to the jump animation } } return character;// return character for this object to work } function createFurniture(startX){// function to create furniture //about every second (a little more, to give more space between furniture) if (frameCount%75===0){ furniture = createSprite(startX,height-(floorHeight/2),26,12);// create sprite furniture.addImage(furnitureImage[int(random(1,4))]);// attach image furnitureList.push(furniture);//put it in the list furnitureGroup.add(furniture);// put it in the collider group } return furniture; } function updatePlacement(furniture){ furniture.position.x -= 0.5;// move it to the left } function clearFurniture(){ var furnitureToKeep = [];// an array of furniture to keep for (var i = 0; i < furnitureList.length;i++){// go through the list if (furnitureList[i].position.x > -10){// if still on screen furnitureToKeep.push(furnitureList[i]);// put it in the to keep list } else {// otherwise furnitureGroup.remove(furnitureList[i]);//remove it from the collider group furnitureList[i].remove();// remove it from the list } } furnitureList = furnitureToKeep;//reassign all the ones we're keeping to the main list } function moveAndDisplayFurniture(){ for (var i = 0; i < furnitureList.length; i++){// for every furniture we've got updatePlacement(furnitureList[i]);// update their placement } } //----------------- function createTreasure(startX){//works much the same as furniture(see above) if (frameCount%120===0 && treasureList.length < 1){// every two seconds, spawn 1 treasure treasure = createSprite(startX,height/2,6,6);// create the sprite treasure.setCollider("rectangle", 0, 0, 12, 24);// set the collider to the character's size treasure.addImage(treasure_image);//connect the image treasureList.push(treasure);//add it to the list treasureGroup.add(treasure);// add it to the collider group } return treasure; } function updateTreasurePlacement(treasure){ treasure.position.x -= 0.5;// move it along with the furniture } function clearTreasure(){ var treasureToKeep = [];// array of treasure we're keeping for (var i = 0; i < treasureList.length;i++){// go through all the treasure if (treasureList[i].position.x > -10){// if they're on screen treasureToKeep.push(treasureList[i]);// put them in the to keep list } else {// otherwise treasureGroup.remove(treasureList[i]);// remove them from the collider group treasureList[i].remove();// remove them from the treasure list } } treasureList = treasureToKeep;// reassign treasure list to what we're keeping } function moveAndDisplayTreasure(){ for (var i = 0; i < treasureList.length; i++){// go through the treasure updatePlacement(treasureList[i]);// update their places } } function draw() { background(0);// create a background image(bg_image, 0, 0);// load in the background image character.updatePosition();// update the character's position every frame drawSprites();// draw the sprites // code for tracking the amount of points fill(255); noStroke(); textFont(fontPixel); textSize(5); text("points: "+ points, 37, 7); createFurniture(width);// create some furniture off screen moveAndDisplayFurniture();// make sure to move it clearFurniture();// clear it if it's off screen createTreasure(width);// create treasure off screen moveAndDisplayTreasure();// make sure to move it along with furniture clearTreasure();// clear if off screen if (character.position.y >= (height-floorHeight)){// if character touches lava dead = true;// they die } // adding points to player if (frameCount%60 === 0){// each second, give them one point points ++; } // Win state: If points are 100, then player wins game if (points > 100){ background(10,210,10,70); text("You Win!", 2,height/2); noLoop(); } //lose state: if they fall in the lava, game over if (dead === true){ background(210,10,10,50); text("You fell in the lava!",2,height/2); noLoop(); } }]]>
In this last Looking Outwards, I looked through projects in the infinite-runner and side-scrolling genres of games. These would be especially interesting and relevant to my final project, because I intend to create a kind of infinite-runner/side-scroller game.
The first project that I was inspired by was the game Canabalt by Adam Saltzman for the Experimental Game Project. I thought this game was very interesting because, while thematically it’s a pretty simple game, its aesthetics and strict color scheme make it a very visually appealing game, and add a sense of drama. I really admire the way that art can not only just make a game look ‘good’, but it can actually play such a deciding role in whether the game’s experience itself is good. The graphics don’t have to be hyper-realistic, it’s all in the artistic sensibilities of the artist. The only thing I think that was overlooked was adding more appeal and interest to the game itself – jumping over buildings as a suit-clad office worker looks alright, but quickly loses luster.
http://www.swordandsworcery.com/
The second project I looked to for inspiration was Sword and Sworcery, by Superbrothers. It’s not an infinite runner, but it is a very beautifully created side-scroller. I really admire the art of it, how nostalgic it is even when it isn’t exactly what retro games used to look like – it still retains some feeling of the past. I want to use Sword and Sworcery as an art inspiration for my project, and study it for how I can incorporate visuals into my side-scrolling game. As my project will be a game that many will remember from childhood, I want its art to suggest something nostalgic and fond memories.
Both of these projects are very different in terms of what kind of games they are, and what the user experience is, but I think that I can learn a lot from the both of them in order to create the kind of game that I’m imagining.
]]>For my final project, I’d like to propose making an interactive game with the skills we’ve learned this semester. I want to base this game off the game children sometimes play at home, where they pretend the floor is lava and they try to jump on furniture to keep off the floor.
The game would be a side-scroller, where you play as a child jumping through their house and avoiding the lava floor. Furniture will be randomly generated and scroll in from the right (there will be different kinds, like sofas, desks, chairs, cabinets… etc.) The longer you survive, the more points you rack up. Grabbing objects and power-ups will also increase your point total, and power-ups can give you speed or jump boosts.
I think this project is within scope, and encapsulates many of the ideas that we’ve learned this semester.
Sketch of what the game’s layout would look like.
//Sofia Syjuco
//section A
//smsyjuco@andrew.cmu.edu
// Assignment - 11- c
var turtle1;// create a turtle
function setup(){
createCanvas(700,400);// create a canvas
turtle1 = makeTurtle(width/2,height/2);// make the first turtle
}
function draw(){
background(235,100,210,10); // fill the background with white
turtle1.penDown();// start drawing
turtle1.setColor(255); //set the color to white
turtle1.setWeight(5);// weight to 6
turtle1.turnToward(mouseX, mouseY, 30);// turn the turtle towards the mouse
turtle1.forward(1);// move the turtle forward
}
//-----------------------------------------------------------------------------
function turtleLeft(d){this.angle-=d;}function turtleRight(d){this.angle+=d;}
function turtleForward(p){var rad=radians(this.angle);var newx=this.x+cos(rad)*p;
var newy=this.y+sin(rad)*p;this.goto(newx,newy);}function turtleBack(p){
this.forward(-p);}function turtlePenDown(){this.penIsDown=true;}
function turtlePenUp(){this.penIsDown = false;}function turtleGoTo(x,y){
if(this.penIsDown){stroke(this.color);strokeWeight(this.weight);
line(this.x,this.y,x,y);}this.x = x;this.y = y;}function turtleDistTo(x,y){
return sqrt(sq(this.x-x)+sq(this.y-y));}function turtleAngleTo(x,y){
var absAngle=degrees(atan2(y-this.y,x-this.x));
var angle=((absAngle-this.angle)+360)%360.0;return angle;}
function turtleTurnToward(x,y,d){var angle = this.angleTo(x,y);if(angle< 180){
this.angle+=d;}else{this.angle-=d;}}function turtleSetColor(c){this.color=c;}
function turtleSetWeight(w){this.weight=w;}function turtleFace(angle){
this.angle = angle;}function makeTurtle(tx,ty){var turtle={x:tx,y:ty,
angle:0.0,penIsDown:true,color:color(128),weight:1,left:turtleLeft,
right:turtleRight,forward:turtleForward, back:turtleBack,penDown:turtlePenDown,
penUp:turtlePenUp,goto:turtleGoTo, angleto:turtleAngleTo,
turnToward:turtleTurnToward,distanceTo:turtleDistTo, angleTo:turtleAngleTo,
setColor:turtleSetColor, setWeight:turtleSetWeight,face:turtleFace};
return turtle;}
I spent a long time tinkering with the turtle trying to figure out exactly how to turn it towards the mouse, and it was such a relief to discover it was actually pretty simple! From there it was just tweaking certain numbers and values, and trying to get an interesting result.
]]>Metallophone
Changxi Zheng
http://www.cs.columbia.edu/~cxz/publications/metallophone.pdf
A work in the area of music that I found particularly interesting was the new musical instrument developed by Changxi Zheng. It’s called the “zoolophone,” a metallophone where each bar is shaped like a different animal. But the stylized shapes of the instrument aren’t nearly the most interesting thing about it, nor what I admire most. Zheng used computational design to create each bar, instead of painstakingly carving out each bar so that they vibrate perfectly. The computer tests and retests each bar, so that there is even less room for error, and when struck with a mallet, actually produces three notes (or a full chord).
I don’t know much about the algorithms used by Zheng to generate this work, but it’s really cool to think that, outside the intricate programming to carve out each piece, from this course we’ve been taught enough to know that the process beyond that is probably something along the lines of ‘if’ statements and continually testing until it works!
The artist’s sensibilities manifest in the final form by making each bar into a stylized animal shape – which is pretty incredible to think about, given instruments usually use regular bar shapes because it’s so difficult to get the sounds right with irregular shapes.
]]>
http://www.liaworks.com/theprojects/elements-an-android-experiment/
LIA
ELEMENTS an Android Experiment
2015
LIA’s project “Elements an Android Experiment” is a very interesting application that she developed for Android. It takes what the device can see through its camera, and creates an entirely unique pattern on the screen of the device. Each time the camera shifts, the pattern changes. I really admire the way that this makes art portable, and in the hands of any user. Through it is the artist herself that makes this experience possible, it gives the viewer agency, and the ability to look at the world through a new perspective.
I couldn’t find where LIA studied, or what specifically she studied, but her CV does say that she lives and works in Vienna, and has been producing work since 1995. Her work consists of programming, and she identifies her medium as “code.” She uses programming as a way to let the viewer experience her art on a “subconscious” level.
]]>//Sofia Syjuco
//section A
//smsyjuco@andrew.cmu.edu
// Assignment - 10-c
var boats = [];// create an array to store the boats
function setup(){
createCanvas(600,400,100);// create a canvas
background(230);// set the background color
for (var i = 0;i<5;i++){ // for loop to populate the array with boats
var fb = random(2*width);
boats[i] = makeBoat(fb);
}
frameRate(10);// frame rate at 10 fps
}
function draw(){
noStroke(); // no strokes around shapes
//bottom layer of ocean
push();
fill(100,150,255,80);
rect(0,200,600,150);
pop();
callMoveAndDisplayBoats();// call the function to update boats on screen
addNewBoat();// add new boats
clearBoat();// clear boats when they pass the left edge of the screen
push();
//top layer of ocean
fill(50,150,255,90);
rect(0,300,600,100);
pop();
}
function makeBoat(startLocationX){// main boat function, stores all the important information
var boat = {x: startLocationX,
display: boatDisplay,
move: boatMove,
speed: -1.0 * random(0.75,2),
sailColorR: round(random(0,255)),
sailColorG: round(random(0,255)),
sailColorB: round(random(0,255)),
boatHeight: 50,
boatWidth: 100,
}
return boat;
}
function boatDisplay(){// this function displays the boat, holds the code to draw it basically
push();
arc(this.x,290,this.boatWidth,this.boatHeight,0,PI,CHORD);
fill(this.sailColorR,this.sailColorG, this.sailColorB);
triangle(this.x-50,220,this.x-50,280,this.x+40,280);
pop();
}
function boatMove(){// keeps boats moving by adding the "speed" to the x value each time
this.x += this.speed;
}
function addNewBoat(){// adds new boats to the array depending on a probability of 0.001
var newBoatChance = 0.001;
if (random(0,1)< newBoatChance){
boats.push(makeBoat(width));
}
}
function clearBoat(){// clear boats away once they pass screen edge
var boatsToKeep = [];// by constantly putting acceptable boats into a new array of "to keep" boats
for (var i = 0; i<boats.length; i++){// check with each loop
if (boats[i].x > 0){// if the boat x is greater than screen edge
boatsToKeep.push(boats[i]); // put it in the "too keep" pile, basically
}
}
boats = boatsToKeep; // assign the boats to keep to boats
}
function callMoveAndDisplayBoats(){ // this function contains the instructions to move and display boats
for (var i = 0;i<boats.length;i++){
boats[i].move();
boats[i].display();
}
}
When I saw the prompt was generative landscape, I really wanted to make something to do with ships. I thought it could be interesting to vary the type of hulls and sails and such, but time constraints narrowed my process down to something else: making a regatta. I liked the idea of still having random boats, with sails different colors, but instead of making that the main random aspect of the piece, the speed of the boats was the focus. So that watching them pass becomes more of an activity, and less a passive perusal of what colors are currently on the screen.
]]>Look Good In
Shannon Case Looking Outwards
Anna Powell-Smith
Look Good In
In looking through previous Looking Outwards posts, I found Shannon Case’s post on Anna Powell-Smith, a web developer. Shannon links to a website that Powell-Smith designed, which gathers shoes that are being sold all over the UK, and places them in one repository that can easily be searched through, with filters that range from the ordinary (size or price), to the more creative (style, color, toe, heel, back).
I think that the cited project is really quite interesting, and I very much respect Anna Powell-Smith for her work. But I disagree with Shannon that this a project to admire. While it is a change of power dynamic from usually male-created capitalistic ways of selling women products, it is simply a website that links to more things to further perpetuate our consumer society.
]]>var portraitPhoto; // variable to store the photo link
var colorAtPixel; // variable to store the color
var ellipseSize = 20; // variable to store the ellipse size
function preload(){
portraitPhoto = loadImage("http://i.imgur.com/sn5iIEZ.jpg"); //load in the portrait photo
}
function setup() {
createCanvas(800,800); // create a canvas at the photo's dimensions
portraitPhoto.loadPixels(); // load in the pixels for the photo
}
function draw() {
background(255);// draw in a background
noStroke(); // no strokes around shapes
for(var r = 0;r<=width+1;r+=ellipseSize){ // go through all the rows of pixels
for(var c = 0;c<=height+1;c+=ellipseSize){ // go through all the columns of pixels
colorAtPixel = portraitPhoto.get(r,c); // check what the color is in the photo
fill (colorAtPixel); // fill it with that color
ellipse(r,c,ellipseSize,ellipseSize); // draw a circle
}
}
noLoop();//just run draw once
}
I was very intrigued by the work of Danny Rozin, and how just that simple repetition of shapes could still manage to convey human features – but I wanted to work with color, not with shadows. So I tried to develop something that is in keeping with the simplicity of Rozin’s style, but incorporates colors to make the portrait more recognizably human.
]]>Mimi Son studied at the Copenhagen Institute of Interaction Design for Interaction Design, and got her MA in Interaction Design from the Landsdown Centre of Middlesex University in London. She is both a teacher, of Interactive Storytelling at Kaywon School of Art and Design, and an art director at her own studio, Kimchi and Chips.
I really admire Son for her work. As a woman excelling in the fields of both art and technology, she’s created some incredible works and has gained recognition for it. I really admire her tenacity to gain such a breadth of education in such a specialized topic, teach it, and create her own studio.
Son has a natural charisma when she presents. She makes jokes, is charmingly self-deprecating, and creates a good relationship between her and her audience. I think I can really learn from her techniques, and work to cultivate a atmosphere of interest and humor in my presentations.