Catching fallen stars(Taiwanese Version)
INSPIRATION:
There is a Taiwanese myth about catching fallen stars to make a wish come true. I intend to create a game that consists of a traditional Taiwanese bamboo woven basket and white stars falling from the night sky.
RULES:
The way to win is to collect 66 stars (white). The players would lose one life if hit by fallen satellite remains (red). They have three lives in total and loses the game when all three lives are wasted. However, players can catch Taiwanese street food (green) to restore lost lives.
OBJECTS:
- Background: import an image of the Taiwanese famous night sky of lanterns
- Sound: Background music – summer night time in Taiwanese mountains
- Object behavior:
- Stars: falling with medium speed
- Satellite: falling with extremely fast speed
- Food: falling with extremely low speed
STORYBOARD:
- MENU (START)
- STORY
- RULES
- GAME
- Restart
- win
- lose
CHALLENGES:
-
- The hardest part was the collision detection. It was hard to wrap my head around the logic. For the satellite remains, player lives should have decrement one when one satellite hits, but for some reason, perhaps the boundary setting or the collision content, player lives decrease ridiculously fast. However, sometimes it works perfectly. I am still in the process of figuring it out.
- Slight mistake: not clarifying how to play the game (what key to press)
CODES:
1. Main Function
PImage sky; PImage stinkyTofu; PImage sausage; PImage oysterOmlette; //another variable name to create another object Fall [] fallStars; Fall [] fallGood; Fall [] fallBad; import processing.sound.*; SoundFile bgMusic; //SoundFile winMusic; //SoundFile loseMusic; //setup the basket int stage; float basketWidth = 100; float basketHeight = 50; float X = 384; float Y = 723; color basketColor = color(188, 123, 25); int lives = 3; int stars = 0; boolean goLeft = false; boolean goRight = false; void setup() { size (1024, 768); bgMusic = new SoundFile (this, "/Users/chi-tingtsai/Downloads/summer night.mp3"); bgMusic.loop(); //winMusic = new SoundFile (this, "/Users/chi-tingtsai/Documents/Processing/Intro_to_IM_Midterm_ver2/data/win.mp3"); //loseMusic = new SoundFile (this, "/Users/chi-tingtsai/Documents/Processing/Intro_to_IM_Midterm_ver2/data/lose.mp3"); stage = 0; //setup the falling objects fallStars = new Fall[10]; for (int k=0; k<fallStars.length; k++) { fallStars[k] = new Fall(random(width), 0, random(2, 7), color(255)); } fallGood = new Fall[5]; for (int i=0; i<fallGood.length; i++) { fallGood[i] = new Fall(random(width), 0, random(1, 5), color(94, 240, 134)); } fallBad = new Fall[15]; for (int l=0; l<fallBad.length; l++) { fallBad[l] = new Fall(random(width), 0, random(6, 10), color(234, 83, 131)); } } //EXECUTION void draw () { if (stage == 0) { menu(); } if (stage == 3) { playGame(); } } void keyReleased() { goLeft = false; goRight = false; if (key == ' ' && stage == 0) { stage = 1; story(); } else if (key == ' ' && stage == 1) { stage = 2; rules(); } else if (key == ' ' && stage == 2) { stage = 3; } else if (key == ' ' && stage == 3) { for (int k=0; k<fallStars.length; k++) { fallStars[k].restart(); } for (int i=0; i<fallGood.length; i++) { fallGood[i].restart(); } for (int l=0; l<fallBad.length; l++) { fallBad[l].restart(); } } }
2. MENU FUNCTION:
color frame = color(237, 168, 17); void menu() { background(color(99, 144, 130)); fill(255); textAlign(CENTER); PFont F = createFont("PatuaOne-Regular", 1); //explain how to start textFont(F, 30); text("Press Space Bar to Begin Game", width/2, height*3/4); //explain this game textFont(F, 50); text("CATCHING FALLEN STARS\n(TAIWANESE VERSION)", width/2, height/2-50); //frame noStroke(); rectMode(CENTER); fill(frame); rect(width/2, 10, width, 20); rect(width/2, height-10, width, 20); rect(10, height/2, 20, height); rect(width-10, height/2, 20, height); }
3. STORY:
int rectWidth = width/10; int rectHeight = height/10; float bg, up, mid, down; void story() { background(color(99, 144, 130)); fill(255); textAlign(CENTER); PFont F = createFont("PatuaOne-Regular", 1); //explain how to start textFont(F, 50); text("STORY", width/2, height/4); textFont(F, 30); text("A long time ago,\nDeep in the mountains of Yu and Ali,\nThere was a lake called Sun Moon Lake.\nRumor has it that if you collected enough fallen stars\nDuring Mid Autumn Festival,\nYour fears will disipate,\nInsecurities will calm,\nAnd peace will shine on you.", width/2, height/2-120); //frame noStroke(); rectMode(CENTER); fill(frame); rect(width/2, 10, width, 20); rect(width/2, height-10, width, 20); rect(10, height/2, 20, height); rect(width-10, height/2, 20, height); //Next to Rules textFont(F, 40); text("Press Space Bar to Continue", width/2, height*3/4+75); }
4. RULES:
int size = 200; void rules() { stinkyTofu = loadImage("stinkytofu.jpeg"); stinkyTofu.resize(size, size); sausage = loadImage("sausage.jpeg"); sausage.resize(size, size); oysterOmlette = loadImage("oysteromlette.jpeg"); oysterOmlette.resize(size-30, size-30); background(color(99, 144, 130)); fill(255); textAlign(CENTER); PFont F = createFont("PatuaOne-Regular", 1); //display images of food image(stinkyTofu, 30, 30); image(sausage, 784, 30); image(oysterOmlette, width-200, height - 200); //explain how to play textFont(F, 50); text("RULES", width/2, height/4); textFont(F, 30); text("The way to win is to catch 66 stars(white)\nwith you bamboo woven basket\nYou have three lives in total.\nYou lose one life if hit by a satellite (red).\nYou lost the game when all lives are wasted.\nHowever, you can catch Taiwanese street food(green)\nto restore lost lives.", width/2, height/2-60); //frame noStroke(); rectMode(CENTER); fill(frame); rect(width/2, 10, width, 20); rect(width/2, height-10, width, 20); rect(10, height/2, 20, height); rect(width-10, height/2, 20, height); }
5. PLAY GAME:
void playGame() { sky = loadImage("pinxi sky lantern.jpeg"); sky.resize(width, height); PFont F = createFont("PatuaOne-Regular", 1); noStroke(); //background background (255); image (sky, 0, 0); //objects start falling for (int k=0; k<fallStars.length; k++) { fallStars[k].runFall(); } for (int i=0; i<fallGood.length; i++) { fallGood[i].runFall(); } for (int l=0; l<fallBad.length; l++) { fallBad[l].runFall(); } //different kinds of collision for (int i=0; i<fallStars.length; i++) { fallStars[i].starcollision(); } for (int k=0; k<fallGood.length; k++) { fallGood[k].goodcollision(); } for (int l=0; l<fallBad.length; l++) { fallBad[l].badcollision(); } //player basket rectMode(CENTER); fill(basketColor); rect(X, Y, basketWidth, basketHeight); if (goLeft == true) { X -= 15; } if (goRight == true) { X += 15; } if (stars == 66 && stage == 3) { background(color(99, 144, 130)); textFont(F, 80); fill(255); text("Congratulations! You have done it!", width/2, height/2); textFont(F, 50); text("Have you found your peace?\nOr even more chaotic?\nhehe)", width/2, height/2-50); textFont(F, 30); text("Press Space Bar to Restart", width/2, height/2+50); } if (lives == 0 && stage == 3) { background(color(99, 144, 130)); textFont(F, 80); fill(255); text("Game Over...", width/2, height/2); textFont(F, 50); text("Awwww... Press Space Bar to Restart?", width/2, height/2+50); } //show lives to player textSize(24); fill(color(90, 167, 247)); text("LIVES:", width -120, height - 50); text(lives, width - 60, height - 50); //show lives to player fill(color(255)); text("STARS:", 90, 60); text(stars, 160, 60); //frame noStroke(); rectMode(CENTER); fill(frame); rect(width/2, 10, width, 20); rect(width/2, height-10, width, 20); rect(10, height/2, 20, height); rect(width-10, height/2, 20, height); } void keyPressed() { if (keyCode == LEFT) { goLeft = true; } else if (keyCode == RIGHT) { goRight = true; } if (X <= basketWidth/2 + 10) { goLeft = false; X = basketWidth/2; } if (X >= width - basketWidth/2 - 10) { goRight = false; X = width - basketWidth/2; } }
6. CLASS for Fallen Objects:
//VARIABLE boolean goodtouch = false; boolean badtouch = false; boolean startouch = false; class Fall { float posX, posY; float objectWidth; float objectHeight; color fallColor; float speed; //CONSTRUCTER Fall(float _posX, float _posY, float _speed, color _colorFall) { posX = _posX; posY = _posY; objectWidth = objectHeight = 20; fallColor = _colorFall; speed = _speed; } //FUNCTIONALITY void runFall() { colorFall(); beginFall(); } void colorFall() { fill(fallColor); noStroke(); rect(posX, posY, objectWidth, objectHeight); } void beginFall() { posY += speed; if (posY > height+objectHeight/2) { posY = -objectHeight/2; reset(); } } void reset() { posX = random(0, width); } void goodcollision() { if (posY + (objectHeight+basketHeight)/2 > Y && posY - (objectHeight+basketHeight)/2 < Y && posX - (objectHeight+basketHeight)/2 < X && posX + (objectHeight+basketHeight)/2 > X && !goodtouch) { goodtouch = true; lives ++; } if (posY > height && goodtouch ==true) { goodtouch = false; } if (lives > 3) { lives = 3; } } void badcollision() { if (posY + (objectHeight+basketHeight)/2 > Y && posY - (objectHeight+basketHeight)/2 < Y && posX - (objectHeight+basketHeight)/2 < X && posX + (objectHeight+basketHeight)/2 > X && !badtouch) { badtouch =true; lives --; } if (posY > height && badtouch ==true) { badtouch = false; } if (lives < 0) { lives = 0; } } void starcollision() { if (posY + (objectHeight+basketHeight)/2 > Y && posY - (objectHeight+basketHeight)/2 < Y && posX - (objectHeight+basketHeight)/2 < X && posX + (objectHeight+basketHeight)/2 > X && !startouch) { startouch = true; stars ++; } if (posY > height && startouch ==true) { startouch = false; } } void restart() { stage = 3; lives = 3; stars = 0; posY = 0; } }