![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Minigame based on Nucleo F103RBSTM32F103RBT6 microcontroller with mBed Application shield
Dependencies: C12832 LM75B MMA7660 mbed
Fork of apps-shield-pots by
- One player - Apple to collect - Monster to avoid - 3 life - 5 ammo - Dynamic difficulty
Playability : Move with accelerometer Shoot with joystick Notifications with RBG LED/Speaker
4 applicatives view - Menu - Ingame - Pause (press fire 2 seconds) - Game over
Have fun
Revision 5:f11bddc1baf0, committed 2016-07-04
- Comitter:
- Laphaze
- Date:
- Mon Jul 04 11:20:37 2016 +0000
- Parent:
- 4:f0eb984c583d
- Commit message:
- Final commit
Changed in this revision
diff -r f0eb984c583d -r f11bddc1baf0 LM75B.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LM75B.lib Mon Jul 04 11:20:37 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/neilt6/code/LM75B/#7ac462ba84ac
diff -r f0eb984c583d -r f11bddc1baf0 MMA7660.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MMA7660.lib Mon Jul 04 11:20:37 2016 +0000 @@ -0,0 +1,1 @@ +http://developer.mbed.org/users/Sissors/code/MMA7660/#36a163511e34
diff -r f0eb984c583d -r f11bddc1baf0 main.cpp --- a/main.cpp Fri Aug 01 14:32:40 2014 +0000 +++ b/main.cpp Mon Jul 04 11:20:37 2016 +0000 @@ -1,19 +1,586 @@ +/* + _ _ _____ _ _ + / \ _ __ _ __ | | ___ | ___(_)_ __ __| | ___ _ __ + / _ \ | '_ \| '_ \| |/ _ \ | |_ | | '_ \ / _` |/ _ \ '__| + / ___ \| |_) | |_) | | __/ | _| | | | | | (_| | __/ | + /_/ \_\ .__/| .__/|_|\___| |_| |_|_| |_|\__,_|\___|_| + |_| |_| + + +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ + |Will you be able to get the most apple as possible before the monster hunt you down ?| + + |Tips| -> Shoot the monster with right/left joystick + -> Each 5 apple ate you level up and 2 ammo are added to your stock + -> Each 10 apple ate you gain 1 life + -> Pause the game by pressing Fire joystick 3 seconds + + |Warning| -> The monster is running faster each level + +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ +-+-+-+-+-+-+ +-+-+-+-+-+ + +*/ + #include "mbed.h" +#include "LM75B.h" #include "C12832.h" +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string> +#include <vector> +class Apple +{ + public: + float x; + float y; +}; + +class Player +{ + public: + float x; + float y; + int life; + int eatenApple; + int mobKilled; + int ammo; + bool firstSpawn; + + // Default class initialization + Player() : life(3), ammo (3), firstSpawn( true ) {} +}; + +class Monster +{ + public: + float x; + float y; + bool killed; + + Monster() : killed( false ) {} +}; + +class Game +{ + public: + bool started; + bool firstStart; + bool paused; + int level; + + // Default class initialization + Game() : started( true ), firstStart( true ), paused( false ), level (1) {} + + void RestartGame (){ + started = true; + level = 1; + } +}; + +// LCD initialization C12832 lcd(D11, D13, D12, D7, D10); +// Potentiometer AnalogIn pot1 (A0); AnalogIn pot2 (A1); -int main() +// RBG LED +DigitalOut red_led(D5); +DigitalOut blue_led(D8); +DigitalOut green_led(D9); + +// JOYSTICK +DigitalIn up(A2); +DigitalIn down(A3); +DigitalIn left(A4); +DigitalIn right(A5); +DigitalIn fire(D4); + +// Temperature Sensor +LM75B sensor(D14,D15); + +// Speaker +PwmOut spkr(D6); + +// Class initialization +Apple apple; +Player player; +Monster monster; +Game game; +std::vector<Apple> Apples; +std::vector<Monster> Monsters; + +/** setLight + Util method for switching LED color + + @param string color ColorName +*/ +void setLight (string color) +{ + if(color == "blue") + { + red_led = 1; + green_led = 1; + blue_led = 0; + } + else if(color == "red") + { + red_led = 0; + green_led = 1; + blue_led = 1; + } + else if(color == "transparent") + { + red_led = 1; + green_led = 1; + blue_led = 1; + } + else { + red_led = 1; + green_led = 0; + blue_led = 1; + } +} + +void PlayMusic () +{ + vector<int> sons; + spkr = 0.5; + sons.push_back(800); + sons.push_back(1100); + sons.push_back(400); + sons.push_back(1200); + sons.push_back(900); + int randomSound = rand() % 5; + int valueSound = sons.at(randomSound); + spkr.period(1.0/valueSound); + wait(0.03); + spkr = 0.0; +} +/** Shoot + Shooting Lazer, takes right or left parameter + + @param string position +*/ +void Shoot (string position) { - while(1) { - lcd.cls(); - lcd.locate(0,3); - lcd.printf("Pot 1 = %.2f", (float)pot1); - lcd.locate(0,14); - lcd.printf("Pot 2 = %.2f", (float)pot2); - wait(0.1); + if(player.ammo != 0) // Check if player have enough ammo + { + if(position == "right") // Right shoot ! + { + lcd.fillrect(player.x, player.y + 4, 127, player.y + 4, 1); // Display the laser ! + + int verifShootMonster = Monsters[0].y - player.y; + + if(verifShootMonster < 2 && player.x < Monsters[0].x) // Check if monster got hit + { + spkr.period(3.0/300); // Moskito crush sound ! :D + spkr=0.9; + wait(0.05); + spkr.period(3.0/500); + spkr=0.9; + player.mobKilled++; + Monsters[0].killed = true; // Monster is now hidden, to allow player to get the Apple safety + } + + player.ammo--; + } + if(position == "left") // Left shoot ! + { + lcd.fillrect(player.x - 5, player.y + 4, 0, player.y + 4, 1); // Display the laser ! + + int verifShootMonster = Monsters[0].y - player.y; + + if(verifShootMonster < 2 && player.x > Monsters[0].x) // Check if monster got hit + { + spkr.period(3.0/300); + spkr=0.9; + wait(0.05); + spkr.period(3.0/500); + spkr=0.9; + player.mobKilled++; + Monsters[0].killed = true; // Monster is now hidden, to allow player to get the Apple safety + } + player.ammo--; + } + } + else // Sorry, no ammo for the player :/ + { + spkr.period(4.0/500); + spkr=0.9; + } +} + +/** ColisionEffect + Action in case of collision with monster/apple + + @param string type +*/ +void ColisionEffect(string type) +{ + if(type == "apple") + { + player.eatenApple++; + setLight("green"); + + /* Resetting monster/apple to generate randomly the next ground */ + Apples.clear(); + Monsters.clear(); + + if(player.eatenApple % 10 == 0 && player.eatenApple > 9){ // Add 1 life each time player ate 10 apple + player.life++; + } + if(player.eatenApple % 5 == 0) // LEVEL UP :D + { + game.level++; + player.ammo += 2; + } + + } + else if (type == "monster") + { + wait(0.5); + setLight("red"); + spkr.period(1.0/300); + spkr = 0.9; + player.life--; + Monsters.clear(); + Apples.clear(); + + if(player.life <= 0) // End of the game if player's life is equal to 0 + { + game.started = false; + } } } + +// The monster is following horizontally and vertically the player. +void MonsterTrackingPlayer() +{ + if(Monsters[0].y > 14) // Teleport the monster at the top of the map + { + Monsters[0].y = 0; + } + else if(Monsters[0].y < 0) // Teleport the monster at the bottom of the map + { + Monsters[0].y = 13; + } + else if(Monsters[0].y >= 0 && Monsters[0].y < 15) // Following player, from left to right + { + if(Monsters[0].y > player.y) + { + Monsters[0].y -= static_cast <float> (rand()) / static_cast <float> (RAND_MAX); // Trying new rand method which is approximatively..Random :) + } + else + { + Monsters[0].y += static_cast <float> (rand()) / static_cast <float> (RAND_MAX); + } + } + + if(Monsters[0].x > 120) // Teleport player at the left of the map + { + Monsters[0].x = 0; + } + else if(Monsters[0].x < 0) // Teleport player at the right of the map // Unused in my case because monster's move are from left to right + { + Monsters[0].x = 120; + } + else if(Monsters[0].x >= 0 && Monsters[0].x < 121) // "Randomize" a bit the monster's move + { + Monsters[0].x += static_cast <float> (rand()) / static_cast <float> (RAND_MAX / game.level); // Monster's move is faster each level + } + + // Display the monster + lcd.locate(Monsters[0].x, Monsters[0].y); + lcd.printf("x"); +} + +// Display the start screen Menu +void PrintStartMenu() +{ + setLight("blue"); + lcd.fillrect(127, 0, 0, 0, 1); + lcd.locate(35, 2); + lcd.printf("Apple finder :D"); + + lcd.fillrect(127, 12, 0, 12, 1); + + lcd.locate(0, 13); + lcd.printf("Monster: X"); + + lcd.locate(55, 13); + lcd.printf("Apple: O"); + + lcd.locate(96, 13); + lcd.printf("You: +"); + + lcd.locate(0, 22); + lcd.printf("Presse fire to launch game !"); +} + +// Display the bottom stats ingame menu +void PrintBottomMenu() +{ + lcd.locate(0, 23); + lcd.fillrect(0, 30, 0, 30, 1); + lcd.printf("Apple: %d", player.eatenApple); + // Vertical divider + lcd.fillrect(42, 23, 42, 32, 1); + + lcd.locate(45, 23); + lcd.printf("LVL %d", game.level); + + // Vertical divider + lcd.fillrect(73, 23, 73, 32, 1); + + lcd.locate(79, 23); + lcd.printf("~%d", player.ammo); + + // Vertical divider + lcd.fillrect(92, 23, 92, 32, 1); + + lcd.locate(95, 23); + lcd.printf("Life: %d", player.life); +} + +// Display the Game Over screen Menu +void PrintGameOverMenu() +{ + lcd.fillrect(127, 0, 0, 0, 1); + lcd.locate(15, 2); + lcd.printf("Game OVER :/ LVL %d", game.level); + lcd.fillrect(127, 12, 0, 12, 1); + + lcd.locate(0, 13); + lcd.printf("Apple ate: %d", player.eatenApple); + + lcd.locate(70, 13); + lcd.printf("Mob killed: %d", player.mobKilled); + + lcd.locate(10, 22); + lcd.printf("Presse fire to restart"); +} + + +// Default thread +int main() +{ + + float verifXApple, verifYApple, verifXMonster, verifYMonster = 0.0; + int scrollPosition = 0; + int breakTimer = 0; + bool blinkEnd = true; + bool blinkScreenPause = true; + + // Sound off + spkr = 0.0; + + /* I'm using the temp sensor to generate random number that i'll pass as parameter for the srand fonction with time clock, it allows a different generation (and not random) number each appStart time */ + int randHack = int(sensor.temp() + 0.5); + srand(randHack); + + while(true) // Main thread + { + /* ------ */ + + PrintStartMenu(); + + /* ------ */ + + while(game.firstStart) // First Menu -- Explications + { + if(fire) // If user press fire, start the game ! + { + game.firstStart = false; + } + } + + // Play while player's alive + while(game.started == true) { + + spkr = 0.0; + lcd.cls(); // Initial screen clear + + while(game.paused == true) + { + PrintBottomMenu(); // Display the stats bottom menu + + blinkScreenPause = !blinkScreenPause; // Blink and invert the screen color, fun effect + + if(blinkScreenPause) // Black foreground + { + lcd.fillrect(127, 0, 0, 22, 1); + } + else // White foreground + { + lcd.fillrect(127, 0, 0, 22, 0); + } + + if(scrollPosition < 12) // Scrolling text vertically, and teleport it at the top if he reach the bottom limit + { + lcd.locate(32, scrollPosition); + lcd.printf("Game PAUSED"); + } + else + { + scrollPosition = 1; + lcd.locate(32, scrollPosition); + lcd.printf("Game PAUSED"); + } + + scrollPosition += 2; + + if(fire) // Resume pause + { + if(breakTimer >= 2) + { + game.paused = false; + breakTimer = 0; + } + else + { + breakTimer++; + } + } + + wait(0.5); + } + + if(player.firstSpawn == true) // Assign the player to default location, but seems little bit buggy due to the the potentiometer's value which is not reset to zero every time the system reboot. + { + setLight("green"); + player.x = 0; + player.y = 0; + } + else // Player positionning with potentiometer + { + player.x = (float)pot2 * 122; + player.y = (float)pot1 * 15; + } + + player.firstSpawn = false; + + // Random apple generation + if(Apples.size() == 0) + { + apple.x = rand() % 122; + apple.y = rand() % 15; + Apples.push_back(apple); + } + + // Random monster generation + if(Monsters.size() == 0) + { + monster.x = rand() % 122; + monster.y = rand() % 15; + + Monsters.push_back(monster); + } + + // Bottom map border + lcd.fillrect(0, 22, 128, 22, 1); + + // Colision Verification with apple + verifXApple = Apples[0].x - player.x; + verifYApple = Apples[0].y - player.y + 4.0; + + // Check collision with apple + if(verifXApple < 4 && verifXApple > -4 && verifYApple < 5 && verifYApple > -5) + { + ColisionEffect("apple"); + } + + // Verification colision with monster + verifXMonster = Monsters[0].x - player.x; + verifYMonster = Monsters[0].y - player.y + 4.0; + + // Check collision with monster + if(verifXMonster < 4 && verifXMonster > -4 && verifYMonster < 5 && verifYMonster > -5 && Monsters[0].killed == false) + { + ColisionEffect("monster"); + } + else + { + PlayMusic(); + } + + + /* ------ */ + + PrintBottomMenu(); + + /* ------ */ + + if(right) // Joystick event right/left + { + Shoot("right"); + } + if(left) + { + Shoot("left"); + } + + if(fire) + { + if(breakTimer >= 2) + { + game.paused = true; + breakTimer = 0; + } + else + { + breakTimer++; + } + } + + // Player positionning + lcd.locate(player.x, player.y); + lcd.printf("+"); + + // Apple positionning + lcd.locate(Apples[0].x, Apples[0].y); + lcd.printf("o"); + + if(Monsters[0].killed == false) + { + MonsterTrackingPlayer(); + } + + wait(0.15); + } + + lcd.cls(); // Clear screen before GameOverMenu + + while(game.started == false) // GameOver Menu + { + /* ------ */ + + PrintGameOverMenu(); + + /* ------ */ + + spkr = 0.0; + if(blinkEnd == true) // Making cool effect with light + { + blinkEnd = !blinkEnd; + setLight("red"); + } + else + { + blinkEnd = !blinkEnd; + setLight("transparent"); + } + + if(fire) // Start a new game + { + player.life = 3; + player.eatenApple = 0; + player.ammo = 1; + player.mobKilled = 0; + game.RestartGame(); + } + } + } +} + +// Wooh, you finished it ! \ No newline at end of file