microbit-samples: Added a suite of basic samples

Also introduced MicroBitSamples.h as a simple, cross IDE mechanism to choose
which sample to build.
master
Joe Finney 2016-04-08 16:52:09 +01:00
parent 7a8e36db3f
commit 8f9a0bcc83
11 changed files with 838 additions and 0 deletions

View File

@ -2,6 +2,10 @@
A collection of example programs using the micro:bit runtime.
The source folder contains a selection of samples demonstrating the capabilities and usage of the runtime APIs.
To select a sample, edit the `MicroBitSamples.h` file in the source folder and uncomment the line matching the
sample you wish to use. Please be sure to note that only one sample is selected at a time.
## Overview
The micro:bit runtime provides an easy to use environment for programming the BBC micro:bit in the C/C++ language, written by Lancaster University. It contains device drivers for all the hardware capabilities of the micro:bit, and also a suite of runtime mechanisms to make programming the micro:bit easier and more flexible. These range from control of the LED matrix display to peer-to-peer radio communication and secure Bluetooth Low Energy services. The micro:bit runtime is proudly built on the ARM mbed and Nordic nrf51 platforms.

View File

@ -0,0 +1,74 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_ACCELEROMETER_DEMO
MicroBit uBit;
//
// Scales the given value that is in the -1024 to 1024 range
// int a value between 0 and 4.
//
int pixel_from_g(int value)
{
int x = 0;
if (value > -750)
x++;
if (value > -250)
x++;
if (value > 250)
x++;
if (value > 750)
x++;
return x;
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
//
// Periodically read the accelerometer x and y values, and plot a
// scaled version of this ont the display.
//
while(1)
{
int x = pixel_from_g(uBit.accelerometer.getX());
int y = pixel_from_g(uBit.accelerometer.getY());
uBit.display.image.clear();
uBit.display.image.setPixelValue(x, y, 255);
uBit.sleep(100);
}
}
#endif

104
source/ButtonEvents.cpp Normal file
View File

@ -0,0 +1,104 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_BUTTON_EVENTS
MicroBit uBit;
//
// Print details of all events received to the serial port.
// Default settings are 115200 baud, 8N1 over the USB interface.
//
void onButton(MicroBitEvent e)
{
if (e.source == MICROBIT_ID_BUTTON_A)
uBit.serial.printf("BUTTON A: ");
if (e.source == MICROBIT_ID_BUTTON_B)
uBit.serial.printf("BUTTON B: ");
if (e.source == MICROBIT_ID_BUTTON_AB)
uBit.serial.printf("BUTTON A+B: ");
if (e.source == MICROBIT_ID_IO_P0)
uBit.serial.printf("TOUCH P0: ");
if (e.source == MICROBIT_ID_IO_P1)
uBit.serial.printf("TOUCH P1: ");
if (e.source == MICROBIT_ID_IO_P2)
uBit.serial.printf("TOUCH P2: ");
if (e.value == MICROBIT_BUTTON_EVT_DOWN)
uBit.serial.printf("DOWN");
if (e.value == MICROBIT_BUTTON_EVT_UP)
uBit.serial.printf("UP");
if (e.value == MICROBIT_BUTTON_EVT_CLICK)
uBit.serial.printf("CLICK");
if (e.value == MICROBIT_BUTTON_EVT_LONG_CLICK)
uBit.serial.printf("LONG_CLICK");
if (e.value == MICROBIT_BUTTON_EVT_HOLD)
uBit.serial.printf("HOLD");
if (e.value == MICROBIT_BUTTON_EVT_DOUBLE_CLICK)
uBit.serial.printf("DOUBLE_CLICK");
uBit.serial.printf("\n");
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
// Register to receive events when any buttons are clicked, including the A+B virtual button (both buttons at once).
uBit.messageBus.listen(MICROBIT_ID_BUTTON_A, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_B, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_BUTTON_AB, MICROBIT_EVT_ANY, onButton);
// Also register for touch events on P0, P1 and P2.
uBit.messageBus.listen(MICROBIT_ID_IO_P0, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_IO_P1, MICROBIT_EVT_ANY, onButton);
uBit.messageBus.listen(MICROBIT_ID_IO_P2, MICROBIT_EVT_ANY, onButton);
// Put the P0, P1 and P2 pins into touch sense mode.
uBit.io.P0.isTouched();
uBit.io.P1.isTouched();
uBit.io.P2.isTouched();
// We're done, so just enter a power efficient sleep while we wait for an event.
while (1)
uBit.sleep(10000);
}
#endif

58
source/Greyscale.cpp Normal file
View File

@ -0,0 +1,58 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_GREYSCALE
MicroBit uBit;
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
// Enable per pixel rendering, with 256 level of brightness per pixel.
uBit.display.setDisplayMode(DISPLAY_MODE_GREYSCALE);
// Draw a rainbow brightness effect across the display
int value = 1;
for(int j = 0; j < 5; j++)
{
for(int i = 0; i < 5; i++)
{
uBit.display.image.setPixelValue(i,j,value);
value += 10;
}
}
// Nothing else to do, so enter a power efficient sleep.
while(1)
uBit.sleep(10000);
}
#endif

View File

@ -24,6 +24,9 @@ DEALINGS IN THE SOFTWARE.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_HELLO_WORLD
MicroBit uBit;
@ -40,3 +43,5 @@ int main()
// sit in the idle task forever, in a power efficient sleep.
release_fiber();
}
#endif

168
source/LogicGates.cpp Normal file
View File

@ -0,0 +1,168 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_LOGIC_GATES
#define LOGIC_MODE_NOT 1
#define LOGIC_MODE_AND 2
#define LOGIC_MODE_OR 3
#define LOGIC_MODE_OUTPUT 4
#define LOGIC_MODE_MIN 1
#define LOGIC_MODE_MAX 4
#define TOOL_SELECT_DELAY 1000
MicroBit uBit;
MicroBitImage NOT("\
0 0 1 0 0\n\
0 0 1 1 0\n\
1 1 1 1 1\n\
0 0 1 1 0\n\
0 0 1 0 0\n");
MicroBitImage AND("\
0 0 1 1 0\n\
1 1 1 1 1\n\
0 0 1 1 1\n\
1 1 1 1 1\n\
0 0 1 1 0\n");
MicroBitImage OR("\
0 0 0 1 0\n\
1 1 1 1 1\n\
0 0 0 1 1\n\
1 1 1 1 1\n\
0 0 0 1 0\n");
MicroBitImage OUTPUT_ON("\
0 1 1 1 0\n\
1 1 1 1 1\n\
1 1 1 1 1\n\
1 1 1 1 1\n\
0 1 1 1 0\n");
MicroBitImage OUTPUT_OFF("\
0 1 1 1 0\n\
1 0 0 0 1\n\
1 0 0 0 1\n\
1 0 0 0 1\n\
0 1 1 1 0\n");
int mode = LOGIC_MODE_NOT;
void onShake(MicroBitEvent)
{
// The micro:bit has been shaken, so move on to the next logic gate.
mode++;
// Wrap back to the start if necessary.
if (mode > LOGIC_MODE_MAX)
mode = LOGIC_MODE_MIN;
// Update the display to
switch (mode)
{
case LOGIC_MODE_NOT:
uBit.display.print(NOT);
break;
case LOGIC_MODE_AND:
uBit.display.print(AND);
break;
case LOGIC_MODE_OR:
uBit.display.print(OR);
break;
case LOGIC_MODE_OUTPUT:
uBit.display.print(OUTPUT_OFF);
break;
}
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
// Register to receive events when the micro:bit is shaken.
uBit.messageBus.listen(MICROBIT_ID_GESTURE, MICROBIT_ACCELEROMETER_EVT_SHAKE, onShake);
//
// Create a simple logic gate simulator, using the P0, P1 and P2 pins.
// The micro:bit can then be configured as an NOT / AND / OR gate, by shaking the device.
//
int output = 0;
// Our icons are drawn left to right, so rotate the display so the outputs point at the pins on the edge connector. :-)
uBit.display.rotateTo(MICROBIT_DISPLAY_ROTATION_270);
while (1)
{
// Check inputs and update outputs accordingly.
switch (mode)
{
int o1;
int o2;
case LOGIC_MODE_NOT:
output = uBit.buttonA.isPressed() ? 0 : !uBit.io.P0.getDigitalValue();
uBit.display.print(NOT);
break;
case LOGIC_MODE_AND:
o1 = uBit.buttonA.isPressed() || uBit.io.P0.getDigitalValue();
o2 = uBit.buttonB.isPressed() || uBit.io.P1.getDigitalValue();
output = o1 && o2;
break;
case LOGIC_MODE_OR:
output = uBit.buttonA.isPressed() || uBit.io.P0.getDigitalValue() || uBit.buttonB.isPressed() || uBit.io.P1.getDigitalValue();
break;
case LOGIC_MODE_OUTPUT:
if (uBit.io.P0.getDigitalValue())
uBit.display.print(OUTPUT_ON);
else
uBit.display.print(OUTPUT_OFF);
output = 0;
break;
}
// Update output pin value
uBit.io.P2.setDigitalValue(output);
// Perform a power efficient sleep for a little while. No need to run too quickly!
uBit.sleep(1000);
}
}
#endif

66
source/MicroBitSamples.h Normal file
View File

@ -0,0 +1,66 @@
/*
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.
*/
#ifndef MICROBIT_SAMPLES_H
#define MICROBIT_SAMPLES_H
//
// Uncomment ONE of the following #defines to select which sample to build.
// Afterwards, save this file and build the project. The resulting HEX
// file will contain your chosen sample.
//
//
// Introductory examples using the uBit object.
//
//#define MICROBIT_SAMPLE_HELLO_WORLD
//#define MICROBIT_SAMPLE_ACCELEROMETER_DEMO
//#define MICROBIT_SAMPLE_BUTTON_EVENTS
//#define MICROBIT_SAMPLE_SIMPLE_ANIMATION
#define MICROBIT_SAMPLE_GREYSCALE
//#define MICROBIT_SAMPLE_LOGIC_GATES
//#define MICROBIT_SAMPLE_SNAKE
//
// Examples using MicroBitRadio.
//
// n.b. you MUST disable the BLE stack to run these samples.
// Do this by setting "#define MICROBIT_BLE_ENABLED 0" in your MicroBitConfig.h file.
//
// For yotta based environments this file is located at:
// "yotta_modules/microbit-dal/inc/core/MicroBitConfig.h"
//
// For project compiling on mbed.org, it is located at:
// "microbit/microbit-dal/inc/core/MicroBitConfig.h"
//
//#define MICROBIT_SAMPLE_SIMPLE_RADIO_TX
//#define MICROBIT_SAMPLE_SIMPLE_RADIO_RX
#endif

View File

@ -0,0 +1,45 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_SIMPLE_ANIMATION
MicroBit uBit;
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
// Setup a simple triangular waveform.
MicroBitImage img("1 0 0 0 0 0 0 0 0 1\n0 1 0 0 0 0 0 0 1 0\n0 0 1 0 0 0 0 1 0 0\n0 0 0 1 0 0 1 0 0 0\n0 0 0 0 1 1 0 0 0 0\n");
while(1)
uBit.display.scroll(img, 80, -1);
}
#endif

56
source/SimpleRadioRx.cpp Normal file
View File

@ -0,0 +1,56 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_SIMPLE_RADIO_RX
MicroBit uBit;
void onData(MicroBitEvent)
{
ManagedString s = uBit.radio.datagram.recv();
if (s == "1")
uBit.display.print("A");
if (s == "2")
uBit.display.print("B");
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
uBit.messageBus.listen(MICROBIT_ID_RADIO, MICROBIT_RADIO_EVT_DATAGRAM, onData);
uBit.radio.enable();
while(1)
uBit.sleep(1000);
}
#endif

52
source/SimpleRadioTx.cpp Normal file
View File

@ -0,0 +1,52 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_SIMPLE_RADIO_TX
MicroBit uBit;
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
uBit.radio.enable();
while(1)
{
if (uBit.buttonA.isPressed())
uBit.radio.datagram.send("1");
else if (uBit.buttonB.isPressed())
uBit.radio.datagram.send("2");
uBit.sleep(100);
}
}
#endif

206
source/Snake.cpp Normal file
View File

@ -0,0 +1,206 @@
/*
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.
*/
#include "MicroBit.h"
#include "MicroBitSamples.h"
#ifdef MICROBIT_SAMPLE_SNAKE
#define SNAKE_EMPTY 0
#define SNAKE_UP 1
#define SNAKE_LEFT 2
#define SNAKE_RIGHT 3
#define SNAKE_DOWN 4
#define SNAKE_FRAME_DELAY 350
#define GROWTH_SPEED 3
struct Point
{
int x;
int y;
};
MicroBit uBit;
Point head; // Location of the head of our snake.
Point tail; // Location of the tail of our snake.
Point food; // Location of food.
MicroBitImage map(5,5);
void place_food()
{
int r = uBit.random(24);
int x = 0; int y = 0;
while (r > 0)
{
x = (x+1) % 5;
if (x == 0)
y = (y+1) % 5;
if(map.getPixelValue(x,y) == SNAKE_EMPTY)
r--;
}
food.x = x;
food.y = y;
}
void snake()
{
Point newHead; // Calculated placement of new head position based on user input.
int hdirection; // Head's direction of travel
int tdirection; // Tail's direction of travel
int snakeLength; // number of segments in the snake.
int growing; // boolean state indicating if we've just eaten some food.
int score;
// Start in the middle of the screen.
tail.x = tail.y = 2;
head.x = head.y = 2;
snakeLength = 1;
growing = 0;
score = 0;
map.clear();
uBit.display.image.setPixelValue(head.x, head.y, 255);
// Add some random food.
place_food();
while (1)
{
// Flash the food is necessary;
uBit.display.image.setPixelValue(food.x, food.y, uBit.systemTime() % 1000 < 500 ? 0 : 255);
int dx = uBit.accelerometer.getX();
int dy = uBit.accelerometer.getY();
newHead.x = head.x;
newHead.y = head.y;
if (abs(dx) > abs(dy))
{
if(dx < 0)
{
hdirection = SNAKE_LEFT;
newHead.x = newHead.x == 0 ? 4 : newHead.x-1;
}
else
{
hdirection = SNAKE_RIGHT;
newHead.x = newHead.x == 4 ? 0 : newHead.x+1;
}
}
else
{
if(dy < 0)
{
hdirection = SNAKE_UP;
newHead.y = newHead.y == 0 ? 4 : newHead.y-1;
}
else
{
hdirection = SNAKE_DOWN;
newHead.y = newHead.y == 4 ? 0 : newHead.y+1;
}
}
int status = map.getPixelValue(newHead.x, newHead.y);
if (status == SNAKE_UP || status == SNAKE_DOWN || status == SNAKE_LEFT || status == SNAKE_RIGHT)
{
uBit.display.scroll("GAME OVER! SCORE: ");
uBit.display.scroll(score);
return;
}
// move the head.
map.setPixelValue(head.x, head.y, hdirection);
uBit.display.image.setPixelValue(newHead.x, newHead.y, 255);
if (growing == GROWTH_SPEED)
{
growing = 0;
snakeLength++;
}
else
{
// move the tail.
tdirection = map.getPixelValue(tail.x,tail.y);
map.setPixelValue(tail.x, tail.y, SNAKE_EMPTY);
uBit.display.image.setPixelValue(tail.x, tail.y, 0);
// Move our record of the tail's location.
if (snakeLength == 1)
{
tail.x = newHead.x;
tail.y = newHead.y;
}
else
{
if (tdirection == SNAKE_UP)
tail.y = tail.y == 0 ? 4 : tail.y-1;
if (tdirection == SNAKE_DOWN)
tail.y = tail.y == 4 ? 0 : tail.y+1;
if (tdirection == SNAKE_LEFT)
tail.x = tail.x == 0 ? 4 : tail.x-1;
if (tdirection == SNAKE_RIGHT)
tail.x = tail.x == 4 ? 0 : tail.x+1;
}
}
// Update our record of the head location and away we go!
head.x = newHead.x;
head.y = newHead.y;
// if we've eaten some food, replace the food and grow ourselves!
if (head.x == food.x && head.y == food.y)
{
growing++;
score++;
place_food();
}
uBit.sleep(SNAKE_FRAME_DELAY);
}
}
int main()
{
// Initialise the micro:bit runtime.
uBit.init();
// Insert your code here!
uBit.display.scroll("SNAKE v1.0");
while(1)
snake();
}
#endif