/* Created by Sean Braithwaite October 1st, 2015 Introduction to Computation - Straight Outta Compt'tation series OmniNOMNOMicon Ascention is a game about eating food by moving the mouse close to it to get a score greater than your friends and therefore become better members of society There are a great deal of reusable original functions in this program */ //Global variables for memory-reliant variables... would've made some classes and objects but we haven't covered that quite yet. //environment related global int shapeConstant = 0; color foreGround; color backGroundColor; color tertiaryGround; //character related globals int characterChosen = -1; //-1 for none, 0 for character 1, 1 for character 2 float characterX; float speed; int characterWidth = 35; int characterHeight = 400; //GUI GLOBALS float timeLeft = 0; long highScore = 0; long score = 0; //colours int minRed = 11; int maxRed = 22; int minGreen = 50; int maxGreen = 180; int minBlue = 100; int maxBlue = 180; int R = (int)random(minRed, maxRed); int G = (int)random(minGreen, maxGreen); int B = (int)random(minBlue, maxBlue); color themeColour = color(R, G, B); color themeColourSecondary = color(R-10, G-10, B-10); color themeColourTertiary = color (R-30, G-30, B-10); //collectable related globals float fruitYOne; float fruitOneWidth = 25; float fruitOneHeight = 25; color fruitColourOne = themeColour; float fruitXOne; float fruitVelocityOne = 0; char fruitOneLetter; float fruitYTwo; float fruitTwoWidth = 25; float fruitTwoHeight = 25; color fruitColourTwo = themeColourSecondary; float fruitXTwo; float fruitVelocityTwo = 0; float fruitYThree; float fruitThreeWidth = 25; float fruitThreeHeight = 25; color fruitColourThree = themeColourTertiary; float fruitXThree; float fruitVelocityThree = 0; //food speed float ascentionSpeed = 3; //incrementation of background standard int backgroundTextureYCycle = 0; int backgroundWidth = 20; int backgroundHeight = 20; //open new window, print out basic instructions to console void setup() { print("Welcome to Omninomnomicon Ascention - Created by Sean Braithwaite - October 2015\n\nMouse over the food as it falls from the waterfall to prolong your miserable existence\n"); size(400, 400); frameRate(60); } //some issue with spawning collectibles? //main loop void draw() { //show menu whilst a player is not chosen, otherwise show the gamespace if (characterChosen==-1) { showMainMenu(); } else { textureBackground(themeColour, themeColourSecondary, themeColourTertiary, backgroundWidth, backgroundHeight, 0, 0, shapeConstant, 3, 3, #E7EDDF, #D4E0C3); //showGround(); showTrees(); makeFruit(ascentionSpeed); showGUI(); drawCharacter(); globalTicker(); //print(score + "\n"); } } //Create a tiled background with one of four shapes; colours and weights are user defined as are the widths and heights of the shapes. //There is also an additional 'impact' effect which I used as the moons reflection and to reveal falling food //shape 0 is rect //shape 1 is ellipse //shape 2 is diamond //shape 3 is triangle void textureBackground(color colourOne, color colourTwo, color backGroundColor, int pixelWidth, int pixelHeight, int strokeWeightAmount, color strokeColour, int shape, int impactX, int impactY, color impactOne, color impactTwo) { //set up the background accroding to user input and standardize shape input and characteristics background(backGroundColor); rectMode(CORNER); ellipseMode(CORNER); noStroke(); fill(0); rect(0, 0, 400, 50); //set up colours and stroke patterns stroke(strokeColour); if (strokeWeightAmount>0) strokeWeight(strokeWeightAmount); else noStroke(); //set up tiling variable. Will be used to determine which colour is used on a shape boolean everyOther = false; //build a horizontal row, then move down for (int y = 50; y < height; y+=pixelHeight) { for (int x = 0; x < width; x+=pixelWidth) { //change 'tile' colours based upon mouse location //if the mouse is close if (mouseX<=x+pixelWidth*impactX && mouseX>x && mouseY>y && mouseY<=y+pixelHeight*impactY) { if (everyOther) { fill(impactOne); } else { fill(impactTwo); } //if the mouse is not close } else { if (everyOther) { fill(colourOne); } else { fill(colourTwo); } } //draw the requested shape if (shape == 0) rect(x, y, pixelWidth, pixelHeight); else if (shape == 1) ellipse(x, y, pixelWidth, pixelHeight); else if (shape == 2) quad(x, y+pixelHeight/2, x+pixelWidth/2, y, x+pixelWidth, y+pixelHeight/2, x+pixelWidth/2, y+pixelHeight); else if (shape == 3) triangle(x, y, x+pixelWidth, y, x, y+pixelHeight); else print("Unrecognized input '" + shape + "' for shape command in textureBackground function...\nRefer to textureBackground documentation...\nPrinting aborted...\n\n"); //reverse used colour everyOther=!everyOther; } //move background y+=backgroundTextureYCycle; everyOther=!everyOther; } //increment background backgroundTextureYCycle++; if (backgroundTextureYCycle>pixelHeight) backgroundTextureYCycle = 0; } //set temporary colour each time a new game is started void startGame() { //set colour standards R = (int)random(minRed, maxRed); G = (int)random(minGreen, maxGreen); B = (int)random(minBlue, maxBlue); themeColour = color(R, G, B); themeColourSecondary = color(R-10, G-10, B-10); themeColourTertiary = color (R+10, G+10, B+10); //reset timeLeft timeLeft = 370; } //choose a random character in the range of a-z char randChar() { return (char)random(65, 90); } //perform cleanup operations on game end void endGame() { //choose a new shape for the main menu and next game shapeConstant = (int)random(0, 4); //Show score and highscore as well as analysis and breakdown print ("GAME OVER\nSCORE: " + score + "\n"); if (score>highScore) { print ("You beat the highscore of " + highScore + " by " + (score-highScore) + " for a grand total of " + score + ". Nice job!\n\n"); highScore = score; } else if (score==highScore) print (" You tied for highscore!\n\n"); else print ("You were " + (highScore-score) + " points off of the highscore!\n\n"); //perform consistency cleanup and reset any residual elements characterChosen = -1; score = 0; backgroundWidth = (int)random(5, 50); backgroundHeight = (int)random(5, 50); fruitYOne=height+fruitOneHeight; fruitYTwo=height+fruitTwoHeight; fruitYThree=height+fruitThreeHeight; ascentionSpeed = 3; showMainMenu(); } //check for proximity of objects void globalTicker() { //for object one if (mouseProximityDetection(fruitXOne, fruitYOne, fruitOneWidth, fruitOneHeight)) { timeLeft+=40; print("You ate some food!\n+100 points - +timer\n\n"); //soft reset, no need to access other functions, will be dealt with in next frame fruitYOne=height+fruitOneHeight; //increment score and speed based on item collection score+=100; score*=1.01; ascentionSpeed += 0.01; } /* //for object two if (mouseProximityDetection(fruitXTwo, fruitYTwo, fruitTwoWidth, fruitTwoHeight)) { timeLeft+=50; print("You ate some food!\n+100 points - +timer\n\n"); //soft reset, no need to access other functions, will be dealt with in next frame fruitYTwo=height+fruitTwoHeight; //increment score and speed based on item collection score+=100; score*=1.01; ascentionSpeed += 0.01; } //for object three if (mouseProximityDetection(fruitXThree, fruitYThree, fruitThreeWidth, fruitThreeHeight)) { timeLeft+=50; print("You ate some food!\n+100 points - +timer\n\n"); //soft reset, no need to access other functions, will be dealt with in next frame fruitYThree=height+fruitThreeHeight; //increment score and speed based on item collection score+=100; score*=1.01; ascentionSpeed += 0.01; } */ if (timeLeft <= 0) { endGame(); } else { timeLeft-=1; } } //display the GUI void showGUI() { rectMode(CORNER); //TIMELEFT ASSOCIATED WITH FRAMERATE timeLeft = constrain(timeLeft, 0, 370); //draw inner timer portion; changes based upon time remaining to visually indicate approaching death strokeWeight(0); fill(#D32929); rect(15, 15, timeLeft, 10); //draw timer cover stroke(255); strokeWeight(3); noFill(); rect(15, 15, 370, 10); } //behind/ foreground void showTrees() { //draw rocks noStroke(); fill(#C6C6C6); triangle(0, 0, 0, height, 75, height); triangle(width, 0, width, height, width-75, height); rectMode(CORNER); //draw back trees fill(#83CB6D); rect (10-mouseX/10, 0, 30, height); rect(90-mouseX/10, 0, 20, height); rect(150-mouseX/10, 0, 30, height); rect(180-mouseX/10, 0, 20, height); rect(250-mouseX/10, 0, 40, height); rect(350-mouseX/10, 0, 10, height); //draw forward trees fill(#70AA5E); rect(-10-mouseX/5, 0, 40, height); rect(60-mouseX/5, 0, 30, height); rect (130-mouseX/5, 0, 30, height); rect(180-mouseX/5, 0, 40, height); rect(270-mouseX/5, 0, 20, height); rect(360-mouseX/5, 0, 60, height); rect(455-mouseX/5, 0, 30, height); } //draw ground void showGround() { fill(random(110, 140)); rectMode(CORNER); rect(0, 380, 400, 20); } //shows menu with buttons for starting game and changing options void showMainMenu() { //Keep the texture in greys so as to visually indicate a session is not on textureBackground(#C6C6C6, #B9B9B9, #ADADAD, backgroundWidth, backgroundHeight, 0, 0, shapeConstant, 0, 0, 0, 0); rectMode(CORNER); //next behind menus showTrees(); //menu locations int buttonOneX = 50; int buttonOneY = 250; int buttonOneW = 100; int buttonOneH = 100; int buttonTwoX = 250; int buttonTwoY = 250; int buttonTwoW = 100; int buttonTwoH = 100; int optionsX = 175; int optionsY = 275; int optionsW = 50; int optionsH = 50; //draw the options button and control it fill(#E8E8E8); stroke(#DEDEDE); strokeWeight(5); rect (15, 50, 370, 40); //billboard 60 //draw title drawChar('O', 27, 60, 3, themeColour); drawChar('M', 52, 60, 3, themeColour); drawChar('N', 77, 60, 3, themeColour); drawChar('I', 102, 60, 3, themeColour); drawChar('N', 127, 60, 3, themeColour); drawChar('O', 152, 60, 3, themeColour); drawChar('M', 177, 60, 3, themeColour); drawChar('N', 202, 60, 3, themeColour); drawChar('O', 227, 60, 3, themeColour); drawChar('M', 252, 60, 3, themeColour); drawChar('I', 277, 60, 3, themeColour); drawChar('C', 302, 60, 3, themeColour); drawChar('O', 327, 60, 3, themeColour); drawChar('N', 352, 60, 3, themeColour); //set up shape standards, draw options button fill(#E8E8E8); stroke(#DEDEDE); strokeWeight(5); rect (optionsX, optionsY, optionsW, optionsH); stroke(#D4D4D4); strokeWeight(5); ellipse(optionsX+15, optionsY+15, 20, 20); //determine if mouse is close to button and if it is change appearance to encourage clicking if (mouseX >= optionsX && mouseX <= optionsX+optionsW && mouseY > optionsY && mouseY < optionsY+optionsH) { //draw depressed button stroke(#DEDEDE); fill(#CBCBCB); rect(optionsX, optionsY, optionsW, optionsH); noStroke(); fill(#E8E8E8); rect (optionsX+10, optionsY+10, optionsW-12, optionsH-12); //draw depressed center stroke(#D4D4D4); strokeWeight(5); ellipse(optionsX+25, optionsY+25, 20, 20); //change global shape for patterning if the button is pressed if (mousePressed && mouseX >= optionsX && mouseX <= optionsX+optionsW && mouseY > optionsY && mouseY < optionsY+optionsH) { backgroundWidth = (int)random(5, 50); backgroundHeight = (int)random(5, 50); if (shapeConstant >= 0 && shapeConstant <= 2) shapeConstant++; else shapeConstant = 0; } } //draw the first character button fill(245); stroke(255); strokeWeight(5); rect(buttonOneX, buttonOneY, buttonOneW, buttonOneH); //draw center of character button one stroke(#D4D4D4); strokeWeight(5); fill(#ED1388); ellipse(buttonOneX+25, buttonOneY+25, 50, 50); //draw the second character button fill(245); stroke(255); strokeWeight(5); rect(buttonTwoX, buttonTwoY, buttonTwoW, buttonTwoH); //draw center of character button two stroke(#D4D4D4); strokeWeight(5); fill(#155DCE); ellipse(buttonTwoX+25, buttonTwoY+25, 50, 50); //control character button one //determine if mouse is close to button and if it is change appearance to encourage clicking if (mouseX >= buttonOneX && mouseX <= buttonOneX+buttonOneW && mouseY > buttonOneY && mouseY < buttonOneY+buttonOneH) { //draw depressed button fill(235); stroke(255); strokeWeight(5); rect(buttonOneX, buttonOneY, buttonOneW, buttonOneH); fill(245); noStroke(); rect(buttonOneX+10, buttonOneY+10, buttonOneW-12, buttonOneH-12); //draw center of button depressed stroke(#D4D4D4); strokeWeight(5); fill(#ED1388); ellipse(buttonOneX+35, buttonOneY+35, 50, 50); //if the button is pressed, choose the corresponding character and start the game if (mousePressed && mouseX >= buttonOneX && mouseX <= buttonOneX+buttonOneW && mouseY > buttonOneY && mouseY < buttonOneY+buttonOneH) { characterChosen = 1; startGame(); } } //control character button two //determine if mouse is close to button and if it is change appearance to encourage clicking if (mouseX >= buttonTwoX && mouseX <= buttonTwoX+buttonTwoW && mouseY > buttonTwoY && mouseY < buttonTwoY+buttonTwoH) { //draw depressed button fill(235); stroke(255); strokeWeight(5); rect(buttonTwoX, buttonTwoY, buttonTwoW, buttonTwoH); fill(245); noStroke(); rect(buttonTwoX+10, buttonTwoY+10, buttonTwoW-12, buttonTwoH-12); //draw depressed center of character button two stroke(#D4D4D4); strokeWeight(5); fill(#155DCE); ellipse(buttonTwoX+35, buttonTwoY+35, 50, 50); //if the button is pressed, choose the corresponding character and start the game if (mousePressed && mouseX >= buttonTwoX && mouseX <= buttonTwoX+buttonTwoW && mouseY > buttonTwoY && mouseY < buttonTwoY+buttonTwoH) { characterChosen = 0; startGame(); } } } //draw the chosen character void drawCharacter() { rectMode(CENTER); //determine character movement; incremement speed based on mouse-to-character location if (characterX == mouseX) { } else if (characterX > mouseX+characterWidth/2) { speed-=0.7; } else if (characterX < mouseX-characterWidth/2) { speed+=0.7; } else { speed*=0.5; } //block character from exceeding max speed speed = constrain(speed, -20, 20); //move character characterX+=speed; //block character from leaving screen, display character; is performed after movement so as to not allow the character to move outside of the boundary for 1 frame characterX = constrain(characterX, 0, width-characterWidth); //set up variables for a characters' colours color colourMain = 0; color colourSecondary = 0; color colourTertiary = 0; //colour character 1 or 2 accordingly if (characterChosen == 1) { colourTertiary = #F52A96; colourMain = #ED1388; colourSecondary = #D11177; } else if (characterChosen == 0) { colourTertiary = #2A79F5; colourMain = #155DCE; colourSecondary = #0B50BC; } //draw the character strokeWeight(1); fill(0); boolean everyOther = false; //pattern the character dynamically for (int x = 0; x < characterWidth; x+=5) { for (int y = 0; y < characterHeight; y+=5) { //set shape colours stroke(colourTertiary); if (everyOther) { fill(colourMain); } else { fill(colourSecondary); } //draw shape and swap colours rect(characterX+x, mouseY+y, 5, 5); everyOther=!everyOther; } everyOther=!everyOther; } } //proximity code; determines if the mouse is within the ||4 cornered|| area of a shape boolean mouseProximityDetection(float x, float y, float w, float h) { if (mouseX >= fruitXOne && mouseX <= x+w && mouseY > y && mouseY < y+h) return true; else return false; } //Create new copies of the fruit if they do not exist or have expired void makeFruit(float ascentionSpeed) { strokeWeight(5); //determine if the fruit is within the gamespace still, if not, refresh it, otherwise increment its height if (fruitYOne > height+fruitOneHeight) { //give new co-ordinates fruitYOne = 0; fruitXOne = random(25, 350); } else { //increment fruit y location, choose colour for spawn fruitYOne+=(fruitVelocityOne + ascentionSpeed); fill(themeColour); stroke(themeColour + 20); drawFish(fruitXOne, fruitYOne, fruitOneWidth, fruitOneHeight); } /* if (fruitYTwo > height+fruitTwoHeight) { //give new co-ordinates fruitYTwo = 0; fruitXTwo = random(25, 350); } else { //increment fruit y location, choose colour for spawn fruitYTwo+=(fruitVelocityTwo + ascentionSpeed); fill(themeColourSecondary); stroke(themeColourSecondary + 20); drawFish(fruitXTwo, fruitYTwo, fruitTwoWidth, fruitTwoHeight); } if (fruitYThree > height+fruitThreeHeight) { //give new co-ordinates fruitYThree = 0; fruitXThree = random(25, 350); } else { //increment fruit y location, choose colour for spawn fruitYThree+=(fruitVelocityThree + ascentionSpeed); fill(themeColourTertiary); stroke(themeColourTertiary + 20); drawFish(fruitXThree, fruitYThree, fruitThreeWidth, fruitThreeHeight); } */ } //draw a fish to the screen at the provided coordinates void drawFish(float fruitX, float fruitY, float fruitWidth, float fruitHeight) { triangle(fruitX+fruitWidth, fruitY+fruitHeight-15, fruitX+fruitWidth+10, fruitY+5, fruitX+fruitWidth+10, fruitY+fruitHeight-10); ellipse(fruitX, fruitY, 30, 20); noStroke(); fill(255); ellipse(fruitX+10, fruitY+8, 5, 5); } //Draws a char on screen w/ a standardized size at a location designated by users //with a user-defined weight and colour //Should prioritize vowels to front to speed process, less common characters at the end void drawChar(char letterRequested, int x, int y, int strokeWeightAmount, color strokeColour) { stroke(strokeColour); strokeWeight(strokeWeightAmount); if (letterRequested == 'W' || letterRequested == 'w') { line(x, y, x, y+20);//leftmost vert line(x+10, y+10, x, y+20);//middleleft diag line(x+10, y+10, x+20, y+20);//middleright diag line(x+20, y, x+20, y+20);//right vert } else if (letterRequested == 'E' || letterRequested == 'e') { line(x, y, x+20, y);//upper hori line(x, y+10, x+10, y+10);//mid hori line(x, y+20, x+20, y+20);//lower hori line(x, y, x, y+20);//left vert } else if (letterRequested == 'B' || letterRequested == 'b') { line(x, y, x+15, y);//upper hori line(x, y+10, x+20, y+10);//mid hori line(x, y+20, x+20, y+20);//lower hori line(x, y, x, y+20);//left vert line(x+15, y, x+15, y+10);//upper right vert line(x+20, y+10, x+20, y+20);//lower right vert } else if (letterRequested == 'L' || letterRequested == 'l') { line(x, y, x, y+20);//vert line(x, y+20, x+20, y+20);//hori } else if (letterRequested == 'C' || letterRequested == 'c') { line(x, y, x+20, y);//upper hori line(x, y+20, x+20, y+20);//lower hori line(x, y, x, y+20);//left vert } else if (letterRequested == 'O' || letterRequested == 'o' || letterRequested == 'D' || letterRequested == 'd' ) { line(x, y, x+20, y);//upper hori line(x, y, x, y+20);//left vert line(x, y+20, x+20, y+20);//lower hori line(x+20, y, x+20, y+20);//right vert } else if (letterRequested == 'M' || letterRequested == 'm') { line(x, y, x, y+20);//left vert line(x+20, y, x+20, y+20);//right vert line(x, y, x+10, y+10);//middleleft diag line(x+20, y, x+10, y+10);//middleright diag } else if (letterRequested == 'T' || letterRequested == 't') { line(x, y, x+20, y);//upper hori line(x+10, y, x+10, y+20);//mid vert } else if (letterRequested == 'S' || letterRequested == 's') { line(x, y, x+20, y);//upper hori line(x, y, x, y+10);//left vert line(x, y+10, x+20, y+10);//mid hori line(x+20, y+10, x+20, y+20);//right vert line(x, y+20, x+20, y+20);//lower hori } else if (letterRequested == 'H' || letterRequested == 'h') { line(x, y, x, y+20);//left vert line(x+20, y, x+20, y+20);//right vert line(x, y+10, x+20, y+10);//middle hori } else if (letterRequested == 'R' || letterRequested == 'r') { line(x, y, x, y+20);//left vert line(x, y, x+20, y);//top hori line(x, y+10, x+20, y+10);//mid hori line(x+20, y, x+20, y+10);//right vert line(x, y+10, x+20, y+20);//leg } else if (letterRequested == 'I' || letterRequested == 'i') { line(x, y, x+20, y);//upper hori line(x, y+20, x+20, y+20);//lower hori line(x+10, y, x+10, y+20);//mid vert } else if (letterRequested == 'A' || letterRequested == 'a') { line(x, y, x, y+20);//left vert line(x+20, y, x+20, y+20);//right vert line(x, y, x+20, y);//upper hori line(x, y+10, x+20, y+10);//lower hori } else if (letterRequested == 'N' || letterRequested == 'n') { line(x, y, x, y+20);//left vert line(x+20, y, x+20, y+20);//right vert line(x, y, x+20, y+20);//mid diag } else if (letterRequested == 'U' || letterRequested == 'u') { line(x, y, x, y+20);//left vert line(x, y+20, x+20, y+20);//lower hori line(x+20, y, x+20, y+20);//right vert } else if (letterRequested == 'P' || letterRequested == 'p') { line(x, y, x, y+20);//left vert line(x, y, x+20, y);//upper hori line(x, y+10, x+20, y+10);//lower hori line(x+20, y, x+20, y+10);//right vert } else if (letterRequested == 'Q' || letterRequested == 'q') { line(x, y, x+20, y);//upper hori line(x, y, x, y+20);//left vert line(x, y+20, x+20, y+20);//lower hori line(x+20, y, x+20, y+20);//right vert line(x+20, y+20, x+10, y+10);//diag } else if (letterRequested == 'F' || letterRequested == 'f') { line(x, y, x+20, y);//upper hori line(x, y+10, x+10, y+10);//mid hori line(x, y, x, y+20);//left vert } else if (letterRequested == 'J' || letterRequested == 'j') { line (x+20, y, x+20, y+20);//right vert line(x, y+20, x+20, y+20);//lower hori line(x, y+10, x, y+20);//left vert } else if (letterRequested == 'K' || letterRequested == 'k') { line(x, y, x, y+20);//left vert line (x, y+10, x+20, y);//upper vert line(x, y+10, x+20, y+20);//lower diag } else if (letterRequested == 'V' || letterRequested == 'v') { line (x, y, x+10, y+20);//left diag line(x+20, y, x+10, y+20);//right diag } else if (letterRequested == 'X' || letterRequested == 'x') { line (x, y, x+20, y+20);//left diag line(x+20, y, x, y+20);//right diag } else if (letterRequested == 'Y' || letterRequested == 'y') { line(x, y, x+10, y+10);//left diag line(x+10, y+10, x+20, y);// right diag line(x+10, y+10, x+10, y+20);//mid } else if (letterRequested == 'Z' || letterRequested == 'z') { line(x, y, x+20, y);//upper flat line(x, y+20, x+20, y+20);//lower flat line(x+20, y, x, y+20);//diag } else { print("Character '" + letterRequested + "' not found...\n aborting printing process...\n\n"); } }