Anna Bridge / microbit-letter-game
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002 The MIT License (MIT)
00003 Copyright (c) 2016 British Broadcasting Corporation.
00004 This software is provided by Lancaster University by arrangement with the BBC.
00005 Permission is hereby granted, free of charge, to any person obtaining a
00006 copy of this software and associated documentation files (the "Software"),
00007 to deal in the Software without restriction, including without limitation
00008 the rights to use, copy, modify, merge, publish, distribute, sublicense,
00009 and/or sell copies of the Software, and to permit persons to whom the
00010 Software is furnished to do so, subject to the following conditions:
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00014 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00015 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
00016 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00017 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
00018 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
00019 DEALINGS IN THE SOFTWARE.
00020 */
00021 
00022 /* The letter game....
00023 
00024    This simple game demonstrates the use of:
00025    1) The random function
00026    2) Events on the message bus to handle button presses
00027    3) Driving the display for both characters, numbers and animations.
00028    4) The system timer
00029    
00030    The start of the game will be preceeded by the following message:
00031    "Get Ready.."
00032    and then a small animation showing shrinking boxes.
00033    Once the game starts a random letter from A-Z will be displayed on the screen.
00034    If it is a consonant then you press the right button.
00035    If it is a vowel then you press the left button.
00036    You must press the corresponding button within the time period for the current level.
00037    Each time you level up, the time to respond decreases. When you level up the shrinking
00038    box animation will be displayed again.
00039    
00040    The initial allowed time is defined as INITIAL_LIMIT.
00041    The amount by which the time allowed decreases at each level is defined by SPEEDUP.
00042    The point at which a level up occurs is defined as LEVEL_UP.
00043     
00044 */
00045 
00046 #include "MicroBit.h"
00047 #include <stdio.h>
00048 
00049 void level_up();
00050 void start();
00051 void game_over();
00052 void display_letter();
00053 void check_press(unsigned long delay);
00054 void onButtonA(MicroBitEvent e);
00055 void onButtonB(MicroBitEvent e);
00056 
00057 
00058 MicroBit uBit;
00059 
00060 #define INITIAL_LIMIT  2000 //ms
00061 #define SPEEDUP         200 //ms
00062 #define LEVEL_UP         20  // level/speed up each time score accumulates by this amount
00063 
00064 typedef enum 
00065 {
00066     NONE,
00067     VOWEL,
00068     CONSONANT,
00069     LATE_PRESS
00070 } Letter_type;
00071 
00072 Letter_type buttonPress = NONE;
00073 Letter_type type = NONE;
00074 unsigned long time_val;
00075 unsigned long limit;
00076 unsigned score = 0;
00077 
00078 void level_up()
00079 {
00080     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");
00081     uBit.display.print(outer, 0, 0);
00082     uBit.sleep(200);
00083     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");
00084     uBit.display.print(middle, 0, 0);
00085     uBit.sleep(200);
00086     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");
00087     uBit.display.print(inner, 0, 0); 
00088     uBit.sleep(200);
00089     uBit.display.print(middle, 0, 0);
00090     uBit.sleep(200);
00091     uBit.display.print(outer, 0, 0);    
00092     uBit.sleep(200);
00093     uBit.display.clear();
00094     uBit.sleep(300);
00095 }
00096 
00097 void start()
00098 {
00099     score = 0;
00100     limit = INITIAL_LIMIT;
00101     uBit.display.clear();
00102     uBit.display.scroll("GET READY...", 100);
00103     uBit.sleep(500);
00104     level_up();
00105     uBit.sleep(500);
00106     display_letter();
00107 }
00108 
00109 void game_over()
00110 {
00111     char val[5];
00112     uBit.display.clear();
00113     uBit.display.scroll("GAME OVER!", 100);
00114     uBit.display.scroll("SCORE = ");
00115     sprintf(val,"%u", score);
00116     uBit.display.scroll(val, 100);
00117 }
00118 
00119 
00120 void display_letter()
00121 {
00122     // random number from 65 - 90 ie ASCII A-Z
00123     char letter = uBit.random(26) + 65;
00124     
00125     switch(letter)
00126     {
00127        case 'A':
00128        case 'E':
00129        case 'I':
00130        case 'O':
00131        case 'U': 
00132           type = VOWEL;
00133           break;
00134           
00135        default:
00136            type = CONSONANT;
00137     }
00138 
00139     uBit.display.printChar(letter,500);
00140     //uBit.sleep(limit);
00141     uBit.display.clear();
00142     time_val = uBit.systemTime();
00143 }
00144 
00145 void check_press(unsigned long delay)
00146 {
00147     if (buttonPress == type && delay <= limit)
00148     {
00149         score++;            
00150         if ((score % LEVEL_UP) == 0 && limit > SPEEDUP)
00151         {
00152             // Increase speed
00153             limit -= SPEEDUP;    
00154             level_up();
00155         }
00156         buttonPress = NONE;
00157         display_letter();
00158     }
00159     else
00160     {
00161         game_over();            
00162         uBit.sleep(1000);
00163         start();
00164     }
00165     
00166 }   
00167 
00168 void onButtonA(MicroBitEvent e)
00169 {
00170     if (e.value == MICROBIT_BUTTON_EVT_CLICK)
00171     {
00172         unsigned long delay = uBit.systemTime() - time_val;
00173         buttonPress = VOWEL;
00174         check_press(delay);
00175     }
00176 }
00177 
00178 void onButtonB(MicroBitEvent e)
00179 {
00180     if (e.value == MICROBIT_BUTTON_EVT_CLICK)
00181     {
00182         unsigned long delay = uBit.systemTime() - time_val;
00183         buttonPress = CONSONANT;
00184         check_press(delay);
00185     }
00186  
00187 }
00188 
00189 
00190 int main()
00191 {
00192     
00193     // Initialise the micro:bit runtime.
00194     uBit.init();
00195     
00196     // Set up button event handlers
00197     uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButtonB);
00198     uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButtonA);
00199     
00200     start();
00201     while(1)
00202     {            
00203         uBit.sleep(100);
00204     }
00205 
00206     // If main exits, there may still be other fibers running or registered event handlers etc.
00207     // Simply release this fiber, which will mean we enter the scheduler. Worse case, we then
00208     // sit in the idle task forever, in a power efficient sleep.
00209     release_fiber();
00210 }