// This program displays a game of cup pong.
// The 'characters' are the ball, cups, table, and water in the cups.
// When the ball bounces on different surfaces (on the floor, into a cup, etc.),
// it produces different sounds.
// One side wins when all of the cups are empty
//(or just a few if you change the 'win' variable in the draw function).
// sounds:
var watercup;
var emptycup;
var bouncefloor;
var throwing;
var gameover;
// objects:
var cup; // will have fields for cx, cy, and boolean isFull
var ball; // will have fields for x, y, dx, dy, and functions
// arrays:
var leftCups = [];
var rightCups = [];
function preload() {
watercup = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/pong-sounds-with-liquid.wav");
bouncefloor = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/bouncing-ping-pong-ball.wav");
throwing = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/throwing-paper-in-trash.wav");
gameover = loadSound("https://courses.ideate.cmu.edu/15-104/f2021/wp-content/uploads/2021/11/ending.wav");
}
// makes a cup object, always full to begin
function makeCup(cx, cy) {
cup = {x:cx, y:cy, isFull: true, drawc: drawCup};
return(cup);
}
// makes a ball object
function makeBall(cx, cy, dirx, diry) {
ball = {x:cx, y:cy,
dx:dirx, dy:diry,
drawb: drawBall,
throwb: throwBall,
resetb: resetBall,
leftright: true};
return(ball);
}
function setup() {
createCanvas(480, 300);
frameRate(35); // high framerate is better for this program
useSound();
rectMode(CENTER);
// fill cup arrays:
// set x and y positions to create pyramid shape.
// the if statements create the rows for the pyramid
for (var i=0; i<10; i++) {
if (i<4) {
lcup = makeCup(width/10+10, (i*20)+120);
rcup = makeCup(9*width/10-10, (i*20)+120);
}
else if (i<7) {
lcup = makeCup(width/10+30, (i*20)+50);
rcup = makeCup(9*width/10-30, (i*20)+50);
}
else if (i<9) {
lcup = makeCup(width/10+50, i*20);
rcup = makeCup(9*width/10-50, i*20);
}
else {
lcup = makeCup(width/10+70, height/2);
rcup = makeCup(9*width/10-70, height/2);
}
leftCups.push(lcup);
rightCups.push(rcup);
}
// create ping pong ball
let dy = random(-4, 4);
ball = makeBall(5, height/2, 5, dy);
}
function soundSetup() { // setup for audio generation
watercup.setVolume(0.5);
bouncefloor.setVolume(0.5);
throwing.setVolume(0.5);
gameover.setVolume(0.5);
}
function draw() {
background(133, 94, 66);
// draw the table
drawTable();
// draw the cups
for (var c=0; c<leftCups.length; c++) {
leftCups[c].drawc();
rightCups[c].drawc();
}
// draw the ball
ball.drawb();
// throw the ball
ball.throwb();
// check for winner
let checkl = 0;
let checkr = 0;
for (l=0; l<leftCups.length; l++) {
if (leftCups[l].isFull == false) { checkl+=1 }
}
for (r=0; r<rightCups.length; r++) {
if (rightCups[r].isFull == false) { checkr+=1 }
}
// when one side wins, display text and play sound
// change 'win' value to see game over sooner:
let win = 10;
if (checkl == win|| checkr == win) {
gameover.play();
textAlign(CENTER, CENTER);
textSize(25);
fill(0);
rect(width/2, height/2, width/2, 50, 10);
fill(255);
text('Game Finished!', width/2, height/2);
noLoop();
}
}
// draws a green table with offwhite diagonal lines:
function drawTable() {
let linescol = color(250, 250, 225);
let tcol = color(0, 100, 100);
strokeWeight(7);
stroke(linescol);
fill(tcol);
rect(width/2, height/2, 4*width/5, 4*height/5);
line(width/10, height/10, 9*width/10, 9*height/10);
line(width/10, 9*height/10, 9*width/10, height/10);
}
// draws individual cups based on x and y fields:
function drawCup() {
let diam = 20;
fill(200, 0, 0); // red cup
stroke(255);
strokeWeight(2);
circle(this.x, this.y, diam);
// if the cup hasnt been hit, it has water in it:
if (this.isFull == true) {
noStroke();
fill(0, 0, 200); // blue water
circle(this.x, this.y, diam/2);
}
}
// draws the ball
function drawBall() {
stroke(0);
strokeWeight(.5);
fill(250);
circle(this.x, this.y, 10);
}
//throws the ball
function throwBall() {
if (this.leftright==true) { // going left to right
if (this.x < width/2) {
this.x += this.dx;
this.y -= this.dy;
} else {
this.x += this.dx;
this.y += (1.5*this.dy);
}
// remove the water if the ball goes into a full cup and reset ball placement
// play water cup noise if cup is hit
for (var j=0; j<rightCups.length; j++) {
if (dist(rightCups[j].x, rightCups[j].y, this.x, this.y)<=7 &
rightCups[j].isFull==true) {
watercup.play();
rightCups[j].isFull = false;
this.resetb();
}
}
} else { // going right to left
if (this.x > width/2) {
this.x -= this.dx;
this.y -= this.dy;
}
else {
this.x -= this.dx;
this.y += (1.5*this.dy);
}
// same code to remove water from hit cup
for (var j=0; j<leftCups.length; j++) {
if (dist(leftCups[j].x, leftCups[j].y, this.x, this.y)<=7 &
leftCups[j].isFull==true) {
watercup.play();
leftCups[j].isFull = false;
this.resetb();
}
}
}
// no cups are hit, reset the ball position & play floor bounce track
if (this.x > width || this.x < 0 ) {
this.resetb();
bouncefloor.play();
}
}
//resets the ball to the next players starting position
function resetBall() {
this.leftright = -this.leftright;
if (this.leftright == true) {this.x=10}
else {this.x =width-10}
this.y = height/2;
this.dy = random(-4, 4);
// plays a 'whoosh' track for each throw
throwing.play();
}
I chose to make a program that displays a game of water pong. The sounds I use are a ‘whoosh’ noise when a ball is thrown, a ‘clink’ sound if the ball goes into a full cup, a bouncing pingpong ball noise if the ball does not go into any full cups, and a bell noise if there is a winner. My code is randomized in a way that every game will be slightly different.