Junk food game redux.

Screen Shot 2015-10-01 at 1.34.33 PM

This week’s assignment was to improve upon a previous project by cleaning up and rewriting some of the code for the project. I was excited to spend more time working on my junk food game I built with Jamie last week because there were still a number of things I thought I could improve.

Here’s the updated version of our game.

Before I’d done too much work on revising the code, Jamie told me she’d done some work and had (amazingly!) moved some things around and cleaned up a lot of the code we’d written last week. I added some cosmetic changes to the game, including a change in the animation that occurs when the mouth touches food.

Overall, here are some of the major things that were fixed in the new code:

 

  • One of the reasons the code from the original game was so long was because for each piece of food, we’d had to write code with directions. In the updated version, Jamie defined a new function so that each piece of food had a set of consistent parameters. The new function looked like this:

function Food(f, s, p, ip) {

For each piece of food, f = load the image, s = speed of fall, p = points if it hits the mouth (either +10 or -10) and ip = if you hit the poop. The function was defined at the end of the code after function setup() and function draw():

Screen Shot 2015-10-01 at 1.10.24 PM

In function setup() we’d already established what each of these parameters would be for each piece of food:

Screen Shot 2015-10-01 at 1.10.06 PM

That helped simplify the code considerably, since we could just write a general formula for the entire game rather than for each piece of food individually.

  • In the older version of the game, there was a slight jitter when you clicked the initial button. The jitter was fixed by changing the function from ‘mouseIsPressed’ to ‘mousePressed.’ This seemed to fix the problem altogether.
  • Last week, we struggled to change the final “end” screens so that the screen cleared once the game finished. When you win or when you eat the poop, there are two different screens that are displayed. Here’s what the screen looked like last week:

Screen Shot 2015-10-01 at 12.59.41 PM

We updated the code to fix the error (with some added vulgarity because this is just for fun anyway):

Screen Shot 2015-10-01 at 1.06.50 PM

I thought overall that we made some good improvements to the code without changing the structure of the game overall. I’ve got to give Jamie a lot of the credit for simplifying the code and giving a much stronger architecture to the game we had built. I really want to keep improving the game!

Junk food heaven. Or, my first game in p5.

Screen Shot 2015-09-24 at 1.49.33 PM

This week’s assignment for computational media was to build something that uses (1) a button or slider and (2) an algorithm for animation.

I immediately knew that however this project played out, I wanted it to involve both junk food and the Beach Boys.

Play the game here!

I was assigned to work with Jamie Ruddy. Jamie and I decided within the first 30 seconds of our conversation that we wanted to build a simple game using interactive elements and animation. Because both of us were drawn to the playful Japanese emojis that we use when we text, we designed a simple game in which the player moves a tongue that catches various pieces of food: hamburgers, apples, eggplant, etc. The player gains points for eating healthy food and loses points for eating junk food.

Here’s the initial sketch I drew:

IMG_2135

There were a lot of steps to build this game. First, we had to create a welcome screen that changed to the game screen once you clicked a button.

Screen Shot 2015-09-24 at 1.32.29 PM

Then, we had to create an assets library of PNG images to load into the game. Each piece of food would drop into the screen where the x-coordinate was random and the y-coordinate started at 0 and increased at each frame.

Screen Shot 2015-09-24 at 1.57.28 PM

Then came the most difficult step in the entire process. In order to animate the emojis and make them interact with one another, we had to create an object. This was a first for me, so I spent a lot of time reviewing the p5 reference library’s explanation of how to create an object.

Within the object, we created a function Food() that displayed each item of food, made it drop at a different rate than the other food, and then checked to see if it had touched the tongue. It also checked to see if the food had hit the bottom of the screen (y=height); if yes, then start the food again at the top of the screen (y = 0).

From there, we needed to ensure the score was increasing/decreasing based on which object the tongue touched. For instance, the apple would +10 and the hamburger would -10. Get to 50 points and you win.

Screen Shot 2015-09-24 at 1.23.28 PM

And for a bonus surprise: Eat the poop emoji and you just straight up lose the entire game (because, gross).

Screen Shot 2015-09-24 at 1.22.29 PM

To make the game more fun, I added the Beach Boys’ “Kokomo” to the sketch. It was simple to call the mp3 in the library by using the preload() function.

Screen Shot 2015-09-24 at 1.15.51 PM

Success! There’s a lot more I’d like to do with this game. For instance, I’d like there to be a location-based animation whenever the food hits the tongue  (right now the screen flashes white).

Here’s a video of how the game works:

 

 

Learning to animate in p5.

Screen Shot 2015-09-17 at 1.22.58 AM

Last week we drew static drawings from primitive shapes. This week we were assigned the task of animating our sketches in p5 using a set of new functions, including frameRate(), rotate(), and transform(), or new variables like mouseX and mouseY.

To complete the assignment, our sketch needed to contain: (1) One element that changed over time independent of the mouse; (2) One element controlled by the mouse; and (3) One element that’s different every time you run the sketch.

I’ve been a cyclist for a few years now. In Salt Lake City, where I lived for the past two years, I loved biking up into the canyon in the late afternoon before sunset. That experience was the inspiration behind my sketch this week, in which a bike rides into the mountains.

See my final sketch here.

Here was my initial sketch:

IMG_2029
I started planning out the sketch in Adobe Illustrator to get a better sense of the composition of the drawing.

mountain

My plan was to make the sun and its rays rotate in a circle independent of the mouse. That actually proved a lot more difficult than I’d anticipated. The action required me to use a new set of functions, including push(), transform(), rotate(), and pop(). Here are the lines of code I wrote that drew the sun:

push();
translate(350,100);
rotate (rads);

for (var d = 0; d < 10; d ++){
noStroke();
fill(206+d,188+d,122+d);
ellipse(0,0,175,175);

stroke(206+d,188+d,122+d);
strokeWeight(3);

for (var i = 0; i < 36; i ++) {
line(0,0,x,y);
rotate(PI/20);
}
pop ();

rads = rads + 1.57;

I started layering on primitive shapes for the mountains and bicycle using the beginShape() function I we learned in class. I decided to make the bicycle a different color every time you load the page by calling out var r, var g, and var b and then defining them in the setup:

r = 230;
g = random(100,200);
b = random(100,200);

Then the most difficult task lay ahead: Getting the bicycle to move at a variable speed controlled by the mouse. I tried a lot of different things, including making an object out of the bicycle using some new tricks we learned in Javascript, but ultimately this is the code that really worked out:

var speedX = 1;

var speedY = 1;

//bicycle

stroke(r,g,b,255);
strokeWeight(5);
noFill();

ellipse(225+speedX,520-speedY,100,100);
ellipse(400+speedX,490-speedY,100,100); 
ellipse(225+speedX,520-speedY,10,10); 
ellipse(400+speedX,490-speedY,10,10); 
quad(225+speedX,520-speedY,305+speedX,505-speedY,350+speedX,435-speedY,265+speedX,450-speedY); 
line(260+speedX,445-speedY,305+speedX,505-speedY); 
line(400+speedX,490-speedY,352+speedX,435-speedY); 
ellipse(305+speedX,505-speedY,30,30);
quad(250+speedX,450-speedY,245+speedX,440-speedY,275+speedX,440-speedY,275+speedX,445-speedY);

speedX+=map(mouseX,0,width,1,5); 
speedY+=0.15;

What’s happening above is that I’ve created two new variables, speedX and speedY, that will determine the velocity of the bike in relation to my mouse. The last two lines of code establish the range of values that the speed can be. When mouseX is high (i.e. it’s on the far right of the sketch), the bike moves more quickly.

Here’s a video of the animation.

Full code below.

var fr = 30;
var x = 1200;
var y = 0;
var rads = 0; // declare variable rads, angle at which sun will rotate
var speedX = 1; //declare variable speedX
var speedY = 1; //declare variable speedY
var r;
var g;
var b;
function setup() {
createCanvas(1100,600);
background(252,240,232);
r = 230;
g = random(100,200);
b = random(100,200);

}

function draw() {

//draw sun and rays and make them rotate.
push();
translate(350,100);
rotate (rads);

for (var d = 0; d < 10; d ++){
noStroke();
fill(206+d,188+d,122+d);
ellipse(0,0,175,175);

stroke(206+d,188+d,122+d);
strokeWeight(3);

for (var i = 0; i < 36; i ++) {
line(0,0,x,y);
rotate(PI/20);

}
}
pop ();

rads = rads + 1.57;

//mountains

//mountains layer three
stroke(136,167,173);
fill(136,167,173);
beginShape();
vertex(0,600);
vertex(0,400);
vertex(200,300);
vertex(300,350);
vertex(400,250);
vertex(500,325);
vertex(600,100);
vertex(750,200);
vertex(875,60);
vertex(1000,150);
vertex(1100,100);
vertex(1100,600);
endShape();

//mountains layer two
stroke(92,109,120,100);
fill(92,109,120,100);
beginShape();
vertex(0,600);
vertex(0,400);
vertex(275,375);
vertex(350,400);
vertex(425,375);
vertex(575,375);
vertex(800,200);
vertex(900,300);
vertex(1100,250);
vertex(1100,600);
endShape();

//mountains layer three
stroke(92,109,112,200);
fill(92,109,112,200);
beginShape();
vertex(0,600);
vertex(0,550);
vertex(500,400);
vertex(575,425);
vertex(600,400);
vertex(800,400);
vertex(875,300);
vertex(925,375);
vertex(1100,300);
vertex(1100,600);
endShape();

//mountains layer four
stroke(213,207,225,25);
fill(213,207,225,25);
triangle(0,600,1100,425,1100,600);

//bicycle

stroke(r,g,b,255);
strokeWeight(5);
noFill();

ellipse(225+speedX,520-speedY,100,100); //bike wheel
ellipse(400+speedX,490-speedY,100,100); //bike wheel
ellipse(225+speedX,520-speedY,10,10); //inner bike wheel
ellipse(400+speedX,490-speedY,10,10); //inner bike wheel
quad(225+speedX,520-speedY,305+speedX,505-speedY,350+speedX,435-speedY,265+speedX,450-speedY); //frame
line(260+speedX,445-speedY,305+speedX,505-speedY); //frame
line(400+speedX,490-speedY,352+speedX,435-speedY); //frame
ellipse(305+speedX,505-speedY,30,30); //frame
quad(250+speedX,450-speedY,245+speedX,440-speedY,275+speedX,440-speedY,275+speedX,445-speedY);

speedX+=map(mouseX,0,width,1,5); //x coordinate of the mouse determine speed of the bike
speedY+=0.15;
}

 

Portrait of a classmate with p5.js.

This week’s project was an exercise in patience because, to paraphrase the poet Mary Ruefle, I’m just a handmaiden with a broken urn when it comes to writing code. I felt like I learned a lot, though, and I’m slowly developing a process for these assignments.

In our first class, we were introduced to the basic functions in p5.js, function setup() and function draw(). Our assignment this week was to draw a portrait of one of our classmates using only primitive shapes in p5.js (translation: no complex shapes, no animation, no interactive elements).

Here’s a link to the final portrait.

My process was simple: (1) Sketch out the drawing in Illustrator; (2) Create a quick outline in p5.js; and (3) Code like hell.

I found it helpful before even writing a line of code to use Illustrator to make a sketch so I had a better sense of what kinds of shapes I’d be drawing. In terms of color, I used the site Coolors to generate the RGB values that matched the color scheme I envisioned.

Here’s my initial sketch and the outline of shapes I planned to use:

Sketch

Sketch---shapes

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

From there, I started coding.

Overall, I wanted the portrait to be symmetrical so I was doing a lot of math in my head to calculate some of the x and y coordinates for each shape that I drew. Just about all the shapes I drew were various combinations of quad(), rect(), ellipse(), triangle(), and line(). There was a lot of trial and error, since I was pretty much guessing at where different points would be on the canvas.

That proved to be a massive headache since I was constantly trying to remember which line of code corresponded to which shape in the drawing and which coordinate corresponded to which point on the shape. It’s no big deal when you have three shapes, but when you are drawing 30+ shapes it can get messy.

I found it helpful to organize my lines of code with some subheadings: //face, //hair, //shirt, etc. I think that in the future I will create a much more detailed system for labeling shapes in my code.

I quickly realized that the portrait I’d sketched out at the beginning of the project was going to be an ambitious undertaking with the limited tools that were available to me in p5.js (since we could only use functions that drew primitive shapes). It took me longer than I’d anticipated, but I found that I was able to add a lot of detail to the portrait despite these limitations.

Here’s a screenshot of the final portrait:

Portrait screenshot

Overall, the project was an excellent exercise in learning the basics of p5. Here’s my full code:

function setup() {
createCanvas(1000,1000);
background(132,220,207);
}

function draw() {

//shirt
stroke(33,131,128);
fill(33,131,128);
quad(50,450,80,350,420,350,450,450);
quad(80,350,190,300,310,300,420,350);
stroke(130,150,133);
fill(130,150,133);
triangle(190,300,290,400,220,395);
triangle(310,300,290,400,330,350);
stroke(60,132,131);
fill(60,132,131);
ellipse(232,382,10,10)
stroke(97,61,193);
fill(97,61,193);
quad(120,330,160,312,190,450,155,450);
quad(400,337,350,317,375,450,400,450);

//face
stroke(230,202,171);
fill(230,202,171);
triangle(190,300,310,300,290,400);
quad(190,300,200,270,300,270,310,300);
quad(180,230,320,230,280,300,220,300);
rect(180,160,140,70);
quad(180,160,320,160,300,90,200,90);

//hair
stroke(161,131,87);
fill(161,131,87);
quad(180,230,320,230,280,300,220,300);
triangle(180,230,180,190,199,230);
triangle(320,230,320,190,301,230);
quad(170,185,180,185,200,130,177,115);
quad(200,130,177,115,210,65,267,55);
quad(200,130,267,55,290,90,270,90);
quad(267,55,270,90,300,110,320,100);
triangle(270,90,250,110,260,90);
quad(300,110,320,100,330,140,310,150);
quad(310,150,330,140,320,185,315,185);
triangle(300,105,299,140,315,170);
triangle(200,130,196,155,180,175);
rect(207,149,23,4);
triangle(207,149,207,153,199,160);
rect(271,149,23,4);
triangle(294,149,294,153,303,160);

//face #2
stroke(230,202,171);
fill(230,202,171);
ellipse(175,185,26,50);
ellipse(325,185,26,50);
triangle(200,229,240,229,220,250);
triangle(300,229,260,229,280,250);
ellipse(250,260,33,11);

//facial features.
stroke(133,138,227,100);
strokeWeight(1.2)
fill(222,255,240);
quad(226,168,210,168,203,177,233,177);
quad(274,168,290,168,297,177,267,177);
stroke(86,88,87,190);
fill(86,88,87,190);
ellipse(223,172,8,7);
ellipse(287,172,8,7);
stroke(222,242,200);
fill(222,242,200);
ellipse(225,170,3,2);
ellipse(289,170,3,2);
stroke(133,138,227,0);
fill(133,138,227,110);
quad(203,177,233,177,226,181,210,181);
quad(297,177,267,177,274,181,290,181);
quad(243,230,259,230,267,223,235,223);
quad(267,223,235,223,242,218,260,218);
stroke(133,138,227,100);
strokeWeight(2.2);
line(258,217,258,163);
line(228,181,210,200);
line(272,181,290,200);
line(290,310,280,370);
line(230,313,260,350);

//hands
stroke(230,202,171);
fill(230,202,171);
rect(136,410,68,13);
rect(138,425,70,13);
rect(136,437,70,13);

//hair #2
stroke(161,131,87);
fill(161,131,87);
triangle(186,185,189,163,175,160);
triangle(314,185,311,163,325,160);
triangle(175,140,175,123,165,145);
triangle(210,67,190,79,210,75);
triangle(330,138,338,143,325,120)

//glasses
stroke(71,44,27,230);
strokeWeight(2.7);
noFill();
ellipse(217,175,44,24);
ellipse(284,175,44,24);
line(239,175,262,175);
line(195,175,182,170);
line(306,175,318,170);

}