Simple game

Revision:
0:c0ff9a7daaac
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Apr 13 16:20:53 2016 +0000
@@ -0,0 +1,210 @@
+/*
+The MIT License (MIT)
+Copyright (c) 2016 British Broadcasting Corporation.
+This software is provided by Lancaster University by arrangement with the BBC.
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the "Software"),
+to deal in the Software without restriction, including without limitation
+the rights to use, copy, modify, merge, publish, distribute, sublicense,
+and/or sell copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
+*/
+
+/* The letter game....
+
+   This simple game demonstrates the use of:
+   1) The random function
+   2) Events on the message bus to handle button presses
+   3) Driving the display for both characters, numbers and animations.
+   4) The system timer
+   
+   The start of the game will be preceeded by the following message:
+   "Get Ready.."
+   and then a small animation showing shrinking boxes.
+   Once the game starts a random letter from A-Z will be displayed on the screen.
+   If it is a consonant then you press the right button.
+   If it is a vowel then you press the left button.
+   You must press the corresponding button within the time period for the current level.
+   Each time you level up, the time to respond decreases. When you level up the shrinking
+   box animation will be displayed again.
+   
+   The initial allowed time is defined as INITIAL_LIMIT.
+   The amount by which the time allowed decreases at each level is defined by SPEEDUP.
+   The point at which a level up occurs is defined as LEVEL_UP.
+    
+*/
+
+#include "MicroBit.h"
+#include <stdio.h>
+
+void level_up();
+void start();
+void game_over();
+void display_letter();
+void check_press(unsigned long delay);
+void onButtonA(MicroBitEvent e);
+void onButtonB(MicroBitEvent e);
+
+
+MicroBit uBit;
+
+#define INITIAL_LIMIT  2000 //ms
+#define SPEEDUP         200 //ms
+#define LEVEL_UP         20  // level/speed up each time score accumulates by this amount
+
+typedef enum 
+{
+    NONE,
+    VOWEL,
+    CONSONANT,
+    LATE_PRESS
+} Letter_type;
+
+Letter_type buttonPress = NONE;
+Letter_type type = NONE;
+unsigned long time_val;
+unsigned long limit;
+unsigned score = 0;
+
+void level_up()
+{
+    MicroBitImage outer("255,255,255,255,255\n255,0,0,0,255\n255,0,0,0,255\n255,0,0,0,255\n255,255,255,255,255\n");
+    uBit.display.print(outer, 0, 0);
+    uBit.sleep(200);
+    MicroBitImage middle("0,0,0,0,0\n0,255,255,255,0\n0,255,0,255,0\n0,255,0,255,0\n0,0,0,0,0\n");
+    uBit.display.print(middle, 0, 0);
+    uBit.sleep(200);
+    MicroBitImage inner("0,0,0,0,0\n0,0,0,0,0\n0,0,255,0,0\n0,0,0,0,0\n0,0,0,0,0\n");
+    uBit.display.print(inner, 0, 0); 
+    uBit.sleep(200);
+    uBit.display.print(middle, 0, 0);
+    uBit.sleep(200);
+    uBit.display.print(outer, 0, 0);    
+    uBit.sleep(200);
+    uBit.display.clear();
+    uBit.sleep(300);
+}
+
+void start()
+{
+    score = 0;
+    limit = INITIAL_LIMIT;
+    uBit.display.clear();
+    uBit.display.scroll("GET READY...", 100);
+    uBit.sleep(500);
+    level_up();
+    uBit.sleep(500);
+    display_letter();
+}
+
+void game_over()
+{
+    char val[5];
+    uBit.display.clear();
+    uBit.display.scroll("GAME OVER!", 100);
+    uBit.display.scroll("SCORE = ");
+    sprintf(val,"%u", score);
+    uBit.display.scroll(val, 100);
+}
+
+
+void display_letter()
+{
+    // random number from 65 - 90 ie ASCII A-Z
+    char letter = uBit.random(26) + 65;
+    
+    switch(letter)
+    {
+       case 'A':
+       case 'E':
+       case 'I':
+       case 'O':
+       case 'U': 
+          type = VOWEL;
+          break;
+          
+       default:
+           type = CONSONANT;
+    }
+
+    uBit.display.printChar(letter,500);
+    //uBit.sleep(limit);
+    uBit.display.clear();
+    time_val = uBit.systemTime();
+}
+
+void check_press(unsigned long delay)
+{
+    if (buttonPress == type && delay <= limit)
+    {
+        score++;            
+        if ((score % LEVEL_UP) == 0 && limit > SPEEDUP)
+        {
+            // Increase speed
+            limit -= SPEEDUP;    
+            level_up();
+        }
+        buttonPress = NONE;
+        display_letter();
+    }
+    else
+    {
+        game_over();            
+        uBit.sleep(1000);
+        start();
+    }
+    
+}   
+
+void onButtonA(MicroBitEvent e)
+{
+    if (e.value == MICROBIT_BUTTON_EVT_CLICK)
+    {
+        unsigned long delay = uBit.systemTime() - time_val;
+        buttonPress = VOWEL;
+        check_press(delay);
+    }
+}
+
+void onButtonB(MicroBitEvent e)
+{
+    if (e.value == MICROBIT_BUTTON_EVT_CLICK)
+    {
+        unsigned long delay = uBit.systemTime() - time_val;
+        buttonPress = CONSONANT;
+        check_press(delay);
+    }
+ 
+}
+
+
+int main()
+{
+    
+    // Initialise the micro:bit runtime.
+    uBit.init();
+    
+    // Set up button event handlers
+    uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButtonB);
+    uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButtonA);
+    
+    start();
+    while(1)
+    {            
+        uBit.sleep(100);
+    }
+
+    // If main exits, there may still be other fibers running or registered event handlers etc.
+    // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
+    // sit in the idle task forever, in a power efficient sleep.
+    release_fiber();
+}
\ No newline at end of file