tag:blogger.com,1999:blog-33611506838095871412024-03-20T08:16:44.021+00:00GiggletronicsSon and Dad discover the BBC micro:bitGiggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.comBlogger12125tag:blogger.com,1999:blog-3361150683809587141.post-18302833221442756432016-09-13T13:31:00.000+01:002016-11-11T14:52:34.691+00:00How Big Can My Python Script Be?We all know that the micro:bit has limits. The specs (available either on <a href="https://en.wikipedia.org/wiki/Micro_Bit">WikiPedia</a> or the <a href="https://developer.mbed.org/platforms/Microbit/">ARMmbed</a> site) show that the memory limits are:<br />
<ul>
<li>16kB RAM
</li>
<li>256kB Flash </li>
</ul>
That sounds like a decent amount of memory - it's not in the gigabytes range of even your most modest modern PC or Mac, but for an embedded processor a total of 282kB is not too bad. So surely we can load massive Python scripts onto our micro:bits, right? Wrong. The hard limit for a Python script is just a snip under 8k. Try and copy a script file larger than that and it will fail. Why is that?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDBAdZ1W8Oz0gyCnhULBfiYMqahw5pGouDHCDV7To_SsI813Jmuj6mSJQdmBQUIkERUnsdVWbvUbqvxPIjm_eqBdxszV5PZdTVTWpqD-TK8Zu7GIyUvxW4J9PcaF5L6FHdwc3QpU0eOZ8/s1600/chip-1006008_640.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="213" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDBAdZ1W8Oz0gyCnhULBfiYMqahw5pGouDHCDV7To_SsI813Jmuj6mSJQdmBQUIkERUnsdVWbvUbqvxPIjm_eqBdxszV5PZdTVTWpqD-TK8Zu7GIyUvxW4J9PcaF5L6FHdwc3QpU0eOZ8/s320/chip-1006008_640.jpg" width="320" /></a></div>
<br />
<a name='more'></a><h2>
RAM vs Flash Memory</h2>
First of all, let's look at the two types of memory - normal Random Access Memory (or <a href="https://en.wikipedia.org/wiki/Random-access_memory">RAM</a>) and <a href="https://en.wikipedia.org/wiki/Flash_memory">Flash memory</a>. Normal RAM is super fast to access and can be read and written to as many times as you want. It does, however, loose everything when you remove power. Flash memory, on the other hand, retains it's memory even without power. Flash is also slower to read than normal RAM and is usually a little more work for a processor to write to. Flash memory is also limited in the number of times that you can write to it before it starts to degrade. Don't worry - the expected life time for most Flash memory is around 100,000 write cycles so it will take a very long time for your micro:bit's Flash to degrade. The upshot of this is that the two memory types are quite different, and your micro:bit uses them for different purposes. Flash memory is used like a disk drive - the program code is stored there and parts of it are read into the main RAM as needed. Main RAM is then used as the working memory for the processor - it will store dynamic data such as variables and the compiled Python script.<br />
<br />
<h2>
What Is Stored In Flash?</h2>
When you write a .hex file to the micro:bit, you're actually writing data to those 256kB of Flash RAM. Look back at <a href="http://giggletronics.blogspot.co.uk/2016/09/what-are-hex-files.html">our last article</a> and you'll see that this means that we're writing the MicroPython code and our actual Python script there. Let's take a look at the end of the dump file for a simple Python script again:<br />
<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;">DAT: 0x000350c0 000000000000000080000020764e0300 ........€.. vN..
DAT: 0x000350d0 78000400040488130100010001000101 x...............
DAT: 0x000350e0 0401000091160000913f0100b1550100 .........?...U..
DAT: 0x000350f0 155d010065160000 .]..e...
ELA: 0x00030000
DAT: 0x0003e000 4d50340066726f6d206d6963726f6269 MP4.from microbi
DAT: 0x0003e010 7420696d706f7274202a0a0a64697370 t import *..disp
DAT: 0x0003e020 6c61792e73686f77282748656c6c6f20 lay.show('Hello
DAT: 0x0003e030 576f726c6427290a0000000000000000 World').........
SLA: 0x00013a85
EOF:
</pre>
<br />
You can see the end of the MicroPython code followed by our script. The long hexadecimal number right after the DAT is the physical memory location that we are copying to. This means that our script is being copied to 0x3e000 or 253,952 decimal. The total amount of Flash memory is 256 * 1,024 or 262,144 bytes. Taking one away from the other we see that this gives us 8,192, or exactly 8 kB. Subtract the size of the header (MB plus two bytes for size = 4 bytes) and the null terminator at the end (1 more byte) and we get 8,187. From this we can surmise that the maximum size that our Python script can be is 8,187 bytes. We can easily test this by writing a script file that is 8 kB long (just fill the file with lots of comments until it's long enough) and trying to copy it to the micro:bit - it won't work.<br />
<br />
<h2>
8K Is All We've Got Then?</h2>
Well.. yes. And no. There are a few options open to us if we want to write larger Python scripts. The first is that we could recompile MicroPython (<a href="https://github.com/bbcmicrobit/micropython">it's open source</a>) after removing bits that we don't need. There would be a lot of space gained if we just removed the help text. With more space available we could set the start address of the Python script lower, giving us more space.<br />
<br />
Another option is a bit of a cheat but it's much easier. Consider the following code:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> A program to flash a heart image and then display a message</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #888888;"># Flash a heart 10 times</span>
<span style="color: #008800; font-weight: bold;">for</span> counter <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">10</span>):
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>HEART)
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.BLANK</span>)
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
<span style="color: #888888;"># Display a text message</span>
display<span style="color: #333333;">.</span>show(<span style="background-color: #fff0f0;">'Hello World'</span>)
</pre>
</div>
<br />
The Python script file for this code is 291 bytes long. Now consider this code which does <i>exactly the same thing</i>:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">10</span>):
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>HEART)
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>BLANK)
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
display<span style="color: #333333;">.</span>show(<span style="background-color: #fff0f0;">'Hello World'</span>)
</pre>
</div>
<br />
This time we're down to149 bytes just by removing the comments and the blank lines and converting spaces into tabs. Imagine the saving if we did this on a large script?<br />
<br />
This process is called <a href="https://en.wikipedia.org/wiki/Minification_(programming)">minification</a> and we can take it much further than this. The big downside of minifying your code is that it becomes very hard to read. However, we can easily write a tool to take our original script and automatically create a minified version. This way you never have to deal directly with the hard-to-read, minified code. In fact, we already have such a tool, and we'll give it to you in a future blog post.<br />
<br />
There are yet more ways to shoehorn more script code in. Maybe we'll come to those in a future blog post too.Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-127053571269543932016-09-06T14:10:00.003+01:002020-01-01T09:47:51.707+00:00What are .hex files?You must have come across .hex files by now. Every time you compile a program on the micro:bit website you end up with one. You copy it to your device and the program runs. Every time we post a project on this blog we include a .hex file. Every time you hit the Flash button in <a href="http://codewith.mu/">Mu</a> it silently and secretly creates a hex files and automatically copies it to your micro:bit. But what are .hex files, how do they work and why should we care about them?<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2xe1yNB36egZFE91gnSaDjuinssxIcyz4t001-j26z8GIm8NO-kHTsgpVL_1iF7wnd06RlwAGYnaakmmxqUALmpkCubx9J2sYyvOcoYUeF-r3iJSuObyMwAMQ5YlIMJIKFFOBUsbP3rY/s1600/hex.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi2xe1yNB36egZFE91gnSaDjuinssxIcyz4t001-j26z8GIm8NO-kHTsgpVL_1iF7wnd06RlwAGYnaakmmxqUALmpkCubx9J2sYyvOcoYUeF-r3iJSuObyMwAMQ5YlIMJIKFFOBUsbP3rY/s320/hex.png" width="287" /></a></div>
<h2>
<a name='more'></a>
The Intel HEX Format</h2>
The micro:bit's .hex format is actually not all that special, in fact the format was created by <a href="http://www.intel.com/">Intel</a> way back in 1988. Intel set out to define a simple format that they could use to load binary programs and data into their processors. They wanted it to be <a href="https://en.wikipedia.org/wiki/ASCII">ASCII</a> (human readable) rather than the hard-to-read binary that computers needed so they devised a simple way to encode the binary data as ASCII characters. They also defined the format to be able to specify where in the target device's memory the data should be stored and where the device should start executing the code from. Because the format was so simple it was easy for them to write code for their processors that would load and run one of these files. The format soon became a favourite and is now supported for everything from microprocessors to EPROM programmers to.. your micro:bit.<br />
<br />
<h2>
How Does It Work?</h2>
The format is straightforward, a sample line looks like this:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: yellow;"><span style="color: #f1c232;">:</span><span style="color: lime;">1</span></span><span style="color: lime;">0</span><span style="color: #0b5394;"><span style="color: #3d85c6;"><span style="color: blue;">47D0</span></span></span><span style="color: red;">00</span><span style="color: cyan;">1EE0019B201C013303990193FFF71AFB</span><span style="color: #999999;">94</span>
</pre>
Every character of the line (apart from the very first colon) represent one hexadecimal digit. Two hexadecimal digits make a single byte of data. Each line of the file follows the exact same format:<br />
<ul>
<li><span style="color: #f1c232;">Start code</span>. This is the : symbol at the start of the line.</li>
<li><span style="color: lime;">Byte count</span>. Two bytes to indicate how much data there will be in the data field.</li>
<li><span style="color: #0b5394;"><span style="color: #3d85c6;"><span style="color: blue;">Address</span></span></span>. Address to store the data at.</li>
<li><span style="color: red;">Record type</span>. What type of data is in this line.</li>
<li><span style="color: cyan;">Data</span>. The actual data. </li>
<li><span style="color: #999999;">Checksum</span>. A simple checksum that is used to ensure the integrity of the data. </li>
</ul>
We won't go into more detail than this here - if you want to know more then take at look at the <a href="https://en.wikipedia.org/wiki/Intel_HEX">Wikipedia entry</a> or, if you're having trouble sleeping, dive into <a href="http://www.interlog.com/~speff/usefulinfo/Hexfrmt.pdf">Intel's original specification document</a>.<br />
<br />
<h2>
What Does A MicroPython .hex File Look Like?</h2>
Let's write a simple Python script and compile it into a hex file. Here's the script:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
display<span style="color: #333333;">.</span>show(<span style="background-color: #fff0f0;">'Hello World'</span>)
</pre>
</div>
<br />
And here's resulting the .hex file.<br />
<a href="http://evilpaul.org/giggletronics/simple_script_1.hex">simple_script_1.hex</a><br />
<br />
The raw .hex file is not very exciting or readable, so here's an annotated version which shows what each line means:<br />
<a href="http://evilpaul.org/giggletronics/simple_script_1.dump">simple_script_1.dump</a><br />
<br />
Although there are lots of possible record types in the HEX format you'll only see four types used here:<br />
<ul>
<li>ELA. Short for Extended Segment Address. This tells the micro:bit where in memory to store the data</li>
<li>DAT. This is the actual data. You can see it in hexadecimal format as well as ASCII.</li>
<li>SLA. Start Linear Address. Tells the micro:bit where to start executing the code from.</li>
<li>EOF: A marker for end-of-file, meaning that there is no more data to follow.</li>
</ul>
Take a look through the file and you'll see lots of unreadable junk in there (this is generally the actual <a href="https://en.wikipedia.org/wiki/Machine_code">machine code</a> that the processor runs) as well as some readable text. The majority of the file is the Phython interpreter. If you look closely you'll see all the function and modules names, help text and error messages in there. But then.. right at the very bottom of the file you'll see what looks like the text for our script, and that's exactly what it is!<br />
<br />
Now, what happens if we write a different script?<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #888888;"># A slightly longer script this time..</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
display<span style="color: #333333;">.</span>show(<span style="background-color: #fff0f0;">'Goodbye World'</span>)
</pre>
</div>
<br />
<a href="http://evilpaul.org/giggletronics/simple_script_2.hex">simple_script_2.hex</a><br />
<br />
<a href="http://evilpaul.org/giggletronics/simple_script_2.dump">simple_script_2.dump</a><br />
<br />
Notice anything interesting in the dump file? Well, almost all of the file is exactly the same. In fact there are only a few lines of difference and those few lines are the ones that we already identified as containing the data for our script.<br />
<br />
Here's the end of the first script:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;">ELA: 0x00030000
DAT: 0x0003e000 4d50340066726f6d206d6963726f6269 MP4.from microbi
DAT: 0x0003e010 7420696d706f7274202a0a0a64697370 t import *..disp
DAT: 0x0003e020 6c61792e73686f77282748656c6c6f20 lay.show('Hello
DAT: 0x0003e030 576f726c6427290a0000000000000000 World').........
SLA: 0x00013a85
EOF:</pre>
And here's the second: <br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;">ELA: 0x00030000
DAT: 0x0003e000 4d505e0023204120736c696768746c79 MP^.# A slightly
DAT: 0x0003e010 206c6f6e676572207363726970742074 longer script t
DAT: 0x0003e020 6869732074696d652e2e0a0a66726f6d his time....from
DAT: 0x0003e030 206d6963726f62697420696d706f7274 microbit import
DAT: 0x0003e040 202a0a0a646973706c61792e73686f77 *..display.show
DAT: 0x0003e050 2827476f6f6462796520576f726c6427 ('Goodbye World'
DAT: 0x0003e060 290a0000000000000000000000000000 )...............
SLA: 0x00013a85
EOF:
</pre>
<br />
From this we can infer that the .hex for a micro:bit MicroPython script looks roughly like this:<br />
<ol>
<li>Code for the MicroPython interpreter</li>
<li>Instruction for where to store the script</li>
<li>The actual script data</li>
<li>Instruction for where to start running the code from</li>
<li>An end-of-file record</li>
</ol>
..and the only part that differs is part 3. What would happen if we copied parts 1, 2, 4 and 5 from a healthy donor .hex file and injected our own part 3? First we need to understand part 3 a little more.<br />
<br />
<h2>
How Does Our Script Become Hex?</h2>
Take a look at the part of the .hex file that contains our script:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;">DAT: 0x0003e000 4d50340066726f6d206d6963726f6269 MP4.from microbi
DAT: 0x0003e010 7420696d706f7274202a0a0a64697370 t import *..disp
DAT: 0x0003e020 6c61792e73686f77282748656c6c6f20 lay.show('Hello
DAT: 0x0003e030 576f726c6427290a0000000000000000 World').........</pre>
You can see that ahead of the script text are four mysterious looking bytes. What are they? Actually they're not all that scary. The first two bytes are the signature "MP" which, presumably, means MicroPython. The next two bytes turn out to be the length of the script that follows. These four bytes are checked by MicroPython when it compiles the script on the micro:bit and they must be exactly right. At the end of the script section you can also see that the data is padded with zeros. This probably isn't necessary - <a href="https://en.wikipedia.org/wiki/Null-terminated_string">it's likely that only the first zero is actually needed</a>.<br />
<br />
Now we know that to make our own part 3 we only need to prefix the script with "MP" and the two length bytes and zero terminate the script text.<br />
<br />
<h2>
So, Can We Make .hex Files Ourselves?</h2>
Now that we understand all parts of the .hex file it's pretty easy for us to create them ourselves. Copying parts from donor file is straightforward but it still might seem a little daunting to actually synthesise our own part 4 - we will need to fill in the record types, calculate checksums etc. for each line. But don't worry, because we've written a simple Python script to automate the process.<br />
<br />
Because we'll be using Python on our Windows/Mac/Linux/Whatever computer we'll need to download and install it first. We'll be using Python 2.7, so head over to <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a> and click on "Download Python 2.7.12". The last digit "12" may change over time as they release updates, but it's correct at the time of writing.<br />
<br />
Once you have Python installed you'll need to download the following two files into a new directory somewhere on your computer:<br />
<a href="http://evilpaul.org/giggletronics/make_hex.py">make_hex.py</a> <br />
<a href="http://evilpaul.org/giggletronics/python_base.hex">python_base.hex</a> < This is the "donor" file containing the MicroPython code<br />
<br />
Then create a Python script file in the same directory (call it "test.py") and paste the following code in it:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
display<span style="color: #333333;">.</span>show(<span style="background-color: #fff0f0;">'Hooray it works!'</span>)
</pre>
</div>
<br />
Now use the make_hex tool to make the .hex file. From the command line type:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #c8c8c8;">make_hex -i python_base.hex -s test.py -o test.hex</span></pre>
And, finally, copy the "test.hex" file onto your micro:bit. From the command line you can type:<br />
<pre style="background: #1e1e1e; color: gainsboro; font-family: Consolas; font-size: 13;"><span style="color: #c8c8c8;">copy test.hex g:</span>
</pre>
(substitute "g:" with wherever your micro:bit is located)<br />
<br />
You should see the yellow light flash for a short time and then the script should run and scroll the text message across the display.<br />
<br />
<h2>
Wrapping Up</h2>
In this post we learned what the .hex format is, where it came from and a little bit about how it works internally. We also learned how MicroPython uses .hex files. Armed with this knowledge we figured out how to create our own .hex files from raw Python scripts.<br />
<br />
Use this knowledge how you want. From now on we will probably be editing our code in a standard text editor and then creating and copying the .hex file to our micro:bit using our new tool. Up until now we've been using Mu. We do like Mu, and it's editor is pretty nice, but it's not a patch on other, more fully featured code editors.<br />
<br />Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-22519669333938277282016-09-01T13:10:00.002+01:002016-09-01T13:10:52.961+01:00Tilt MazeSon and I recently went off for a boy's weekend at the Grandparents. We knew that we'd be stuck on trains for a good few hours so we decided to take along the micro:bit so that we could embark upon our own <a href="http://trainjam.com/">Train Jam</a>. Son chose to work on a maze game where you have to navigate your way to the exit. He also wanted keys and doors to make it more of a challenge.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7_A-9jWn9yLR9s54nQfPRx4ssXku1qchyjZmgThNE1Z2pdRfFeC1CjebLG1K4wON1ECW-6ADeve1aARWAii7SmEwXW34ljaFiNIAqN63eq9XV4h7Rkdwl9n79QlMxr7hz1dm-uqHxgVs/s1600/tilt_maze.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj7_A-9jWn9yLR9s54nQfPRx4ssXku1qchyjZmgThNE1Z2pdRfFeC1CjebLG1K4wON1ECW-6ADeve1aARWAii7SmEwXW34ljaFiNIAqN63eq9XV4h7Rkdwl9n79QlMxr7hz1dm-uqHxgVs/s320/tilt_maze.jpg" width="240" /></a></div>
<br />
We thought it might be tough to make this a fun game on such a limited device so we decided to keep things simple. With only 25 red LEDs it was tough to think how we could show the various elements of the maze. We decided that:<br />
<ol>
<li>The player would be a very bright pixel and always in the middle of the screen. The rest of the maze would scroll around you.</li>
<li>Walls would be dim pixels.</li>
<li>Doors would be slowly flashing pixels.</li>
<li>Keys would be rapidly flashing pixels.</li>
<li>The exit would be flashing in some cool way that made it look enticing.</li>
</ol>
<a name='more'></a>Before we started on the actual game we knew that the movement mechanism would be important so to begin with we decided to prototype a couple of different control methods. We put a pixel in the middle of the LED display and tried different ways to move it around:<br />
<ol>
<li>Son's first idea was to tap the A button to move left and hold it to move down. Similarly, tapping the B button would move right while holding it would move up. This worked out pretty well and was very accurate but ultimately felt slow and sometimes we just got confused and moved in the wrong direction!</li>
<li>Next up we tried using the micro:bit's accelerometer as a tilt controller: tilt the unit up, down, left or right to move. We added a delay so that movement didn't repeat too quickly and we set a minimum tilt amount so that you didn't move around when you were holding the device level. This method worked pretty well but it was too easy to accidentally move when you didn't want to. We added a sensitivity setting which let us tweak how far you needed to tilt the micro:bit before movement was triggered but no setting felt right - they were either too sensitive (leading to accidental movement) or not sensitive enough (meaning that you had to tilt so far that you couldn't comfortably see the display).</li>
<li>Finally we tweaked the second method ever so slightly by adding a button press - you now had to tilt the micro:bit <i>and</i> press the A button to move. This felt much better. Not as satisfying as method 2 but much more accurate.</li>
</ol>
It's super important to prototype things wherever you can before starting on a big project. If we'd gone with our first method we might have been dissatisfied with the gameplay and not got around to finishing the project. To take it to an even further extreme - if we hadn't been able to make a satisfactory movement mechanic at all then there would have been little point in trying to build a fun game around it.<br />
<br />
The code is probably the most complex thing we've written so far. Here it is in full:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Tilt Maze</span>
<span style="color: #dd4422;"> Find the exit and escape the maze. Navigate the maze by tilting the micro:bit and pressing the A </span>
<span style="color: #dd4422;"> button. Collect keys to open the doors.</span>
<span style="color: #dd4422;"> Developed by http://giggletronics.blogspot.co.uk/</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #888888;"># Map definition. You can change this to change the game.</span>
<span style="color: #888888;"># Key:</span>
<span style="color: #888888;"># w = Wall</span>
<span style="color: #888888;"># s = Start position</span>
<span style="color: #888888;"># k = Key</span>
<span style="color: #888888;"># d = Door</span>
<span style="color: #888888;"># e = Exit</span>
<span style="color: #888888;"># Space = Location that player can walk on</span>
map_blocks <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">'wwwwwwwwwwwwwwwwww'</span>\
<span style="background-color: #fff0f0;">'w w k kw'</span>\
<span style="background-color: #fff0f0;">'w s d k w'</span>\
<span style="background-color: #fff0f0;">'w wwdwwwwwwwwww'</span>\
<span style="background-color: #fff0f0;">'w k w w'</span>\
<span style="background-color: #fff0f0;">'wwwwwwwwwwwwwwwwdw'</span>\
<span style="background-color: #fff0f0;">'w d w w'</span>\
<span style="background-color: #fff0f0;">'w e w w w'</span>\
<span style="background-color: #fff0f0;">'w w w w'</span>\
<span style="background-color: #fff0f0;">'w w w'</span>\
<span style="background-color: #fff0f0;">'wwwwwwwwwwwwwwwwww'</span>
map_width <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">18</span>
map_height <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">11</span>
<span style="color: #888888;"># A list of map blocks that should now be seen as clear spaces</span>
map_blocks_cleared <span style="color: #333333;">=</span> []
<span style="color: #888888;"># Player variables</span>
num_keys <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># This is how sensitive the input is. Higher numbers mean that you need to tilt the micro:bit </span>
<span style="color: #888888;"># further to move, lower numbers are move likely to trigger movement erroneously</span>
SENSITIVITY <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">200</span>
<span style="color: #888888;"># Some custom images</span>
BLANK <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'00000:00000:00000:00000:00000:'</span>)
KEY <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'00000:00099:99999:99099:99000:'</span>)
DOOR0 <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'99999:99999:99999:99999:99999:'</span>)
DOOR1 <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'99099:99099:99099:99099:99099:'</span>)
DOOR2 <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'90009:90009:90009:90009:90009:'</span>)
ALL_DOORS <span style="color: #333333;">=</span> [DOOR0, DOOR1, DOOR2, BLANK]
<span style="color: #888888;"># Validates that the map is correctly formatted. Halts on error</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">validate_map</span>():
<span style="color: #888888;"># Helper function to show an error message and halt</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_error</span>(error):
full_error <span style="color: #333333;">=</span> <span style="background-color: #fff0f0;">"MAP ERROR: "</span> <span style="color: #333333;">+</span> error
<span style="color: #008800; font-weight: bold;">print</span>(full_error)
display<span style="color: #333333;">.</span>scroll(full_error, loop<span style="color: #333333;">=</span><span style="color: #007020;">True</span>)
<span style="color: #888888;"># The map should contain width * height blocks</span>
map_size <span style="color: #333333;">=</span> <span style="color: #007020;">len</span>(map_blocks)
<span style="color: #008800; font-weight: bold;">if</span> map_size <span style="color: #333333;">!=</span> map_width <span style="color: #333333;">*</span> map_height:
show_error(<span style="background-color: #fff0f0;">'Map size is incorrect'</span>)
<span style="color: #888888;"># Count the special map blocks</span>
door_count <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
key_count <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
start_count <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(map_size):
block <span style="color: #333333;">=</span> map_blocks[i]
<span style="color: #008800; font-weight: bold;">if</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'w'</span> <span style="color: black; font-weight: bold;">or</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">' '</span> <span style="color: black; font-weight: bold;">or</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'e'</span>:
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'d'</span>:
door_count <span style="color: #333333;">=</span> door_count <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'k'</span>:
key_count <span style="color: #333333;">=</span> key_count <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'s'</span>:
start_count <span style="color: #333333;">=</span> start_count <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">else</span>:
show_error(<span style="background-color: #fff0f0;">'Unexpected map block </span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\'</span><span style="background-color: #fff0f0;">'</span> <span style="color: #333333;">+</span> block <span style="color: #333333;">+</span> <span style="background-color: #fff0f0;">'</span><span style="background-color: #fff0f0; color: #666666; font-weight: bold;">\'</span><span style="background-color: #fff0f0;"> found'</span>)
<span style="color: #888888;"># Raise an error if the special block counts are wrong</span>
<span style="color: #008800; font-weight: bold;">if</span> door_count <span style="color: #333333;">!=</span> key_count:
show_error(<span style="background-color: #fff0f0;">'Door and key counts do not match'</span>)
<span style="color: #008800; font-weight: bold;">if</span> start_count <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">1</span>:
show_error(<span style="background-color: #fff0f0;">'Map should contain exactly 1 start point'</span>)
<span style="color: #888888;"># Returns the map block at the given position</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">get_map_block</span>(x, y):
<span style="color: #888888;"># Clamp position</span>
map_x <span style="color: #333333;">=</span> <span style="color: #007020;">min</span>(<span style="color: #007020;">max</span>(x, <span style="color: #0000dd; font-weight: bold;">0</span>), map_width <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>)
map_y <span style="color: #333333;">=</span> <span style="color: #007020;">min</span>(<span style="color: #007020;">max</span>(y, <span style="color: #0000dd; font-weight: bold;">0</span>), map_height <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>)
block_number <span style="color: #333333;">=</span> map_x <span style="color: #333333;">+</span> map_y <span style="color: #333333;">*</span> map_width
<span style="color: #888888;"># Is this position still valid?</span>
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: black; font-weight: bold;">not</span> block_number <span style="color: black; font-weight: bold;">in</span> map_blocks_cleared:
<span style="color: #888888;"># Yes, return the block from the map</span>
<span style="color: #008800; font-weight: bold;">return</span> map_blocks[block_number]
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># No, it's been cleared so return an empty space</span>
<span style="color: #008800; font-weight: bold;">return</span> <span style="background-color: #fff0f0;">' '</span>
<span style="color: #888888;"># Returns the start x,y position on the map or 0,0 if it can't be found</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">find_start</span>():
<span style="color: #008800; font-weight: bold;">for</span> y <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(map_height):
<span style="color: #008800; font-weight: bold;">for</span> x <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(map_width):
<span style="color: #008800; font-weight: bold;">if</span> get_map_block(x, y) <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'s'</span>:
<span style="color: #008800; font-weight: bold;">return</span> x, y
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># Draws the current view of the world to the micro:bit display</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_world</span>(player_x, player_y):
<span style="color: #888888;"># Create a buffer to draw the map into</span>
screen <span style="color: #333333;">=</span> BLANK<span style="color: #333333;">.</span>copy()
<span style="color: #888888;"># Loop over each pixel in the buffer</span>
<span style="color: #008800; font-weight: bold;">for</span> y <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
map_y <span style="color: #333333;">=</span> player_y <span style="color: #333333;">+</span> y <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">2</span>
<span style="color: #008800; font-weight: bold;">for</span> x <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
map_x <span style="color: #333333;">=</span> player_x <span style="color: #333333;">+</span> x <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">2</span>
block <span style="color: #333333;">=</span> get_map_block(map_x, map_y)
<span style="color: #008800; font-weight: bold;">if</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'w'</span>:
<span style="color: #888888;"># Wall - Display as a solid pixel</span>
screen<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #0000dd; font-weight: bold;">4</span>)
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'d'</span>:
<span style="color: #888888;"># Door - Display as a slowly flashing pixel</span>
screen<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #0000dd; font-weight: bold;">4</span> <span style="color: #008800; font-weight: bold;">if</span> (running_time() <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">1000</span> <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">500</span>) <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'k'</span>:
<span style="color: #888888;"># Key - Display as a rapidly flashing pixel</span>
screen<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #0000dd; font-weight: bold;">8</span> <span style="color: #008800; font-weight: bold;">if</span> (running_time() <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">200</span> <span style="color: #333333;"><</span> <span style="color: #0000dd; font-weight: bold;">100</span>) <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'e'</span>:
<span style="color: #888888;"># Exit - Display as a super-fast flashing pixel</span>
screen<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #007020;">int</span>(running_time() <span style="color: #333333;">/</span> <span style="color: #0000dd; font-weight: bold;">50</span>) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">10</span>)
<span style="color: #888888;"># Overlay the player in the middle</span>
screen<span style="color: #333333;">.</span>set_pixel(<span style="color: #0000dd; font-weight: bold;">2</span>, <span style="color: #0000dd; font-weight: bold;">2</span>, <span style="color: #0000dd; font-weight: bold;">9</span>)
<span style="color: #888888;"># Copy to the micro:bit display</span>
display<span style="color: #333333;">.</span>show(screen)
<span style="color: #888888;"># Shows the number of keys held</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_keys</span>():
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">3</span>):
display<span style="color: #333333;">.</span>show([KEY, <span style="color: #007020;">str</span>(num_keys)])
<span style="color: #888888;"># Shows an animation for an opening door</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_door_opening</span>():
display<span style="color: #333333;">.</span>show(ALL_DOORS)
<span style="color: #888888;"># Collects the key at x,y</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">collect_key_at</span>(x, y):
<span style="color: #008800; font-weight: bold;">global</span> num_keys
<span style="color: #008800; font-weight: bold;">global</span> map_blocks_cleared
<span style="color: #888888;"># One more key for the player</span>
num_keys <span style="color: #333333;">=</span> num_keys <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #888888;"># Mark the door block as clear</span>
map_blocks_cleared<span style="color: #333333;">.</span>append(x <span style="color: #333333;">+</span> y <span style="color: #333333;">*</span> map_width)
<span style="color: #888888;"># Show the player how many keys they now hold</span>
show_keys()
<span style="color: #888888;"># Tries to open the door at x,y</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">try_to_open_door_at</span>(x, y):
<span style="color: #008800; font-weight: bold;">global</span> num_keys
<span style="color: #008800; font-weight: bold;">global</span> map_blocks_cleared
<span style="color: #008800; font-weight: bold;">if</span> num_keys <span style="color: #333333;">></span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># Player has enough keys... take one away</span>
num_keys <span style="color: #333333;">=</span> num_keys <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #888888;"># Mark the door block as clear</span>
map_blocks_cleared<span style="color: #333333;">.</span>append(x <span style="color: #333333;">+</span> y <span style="color: #333333;">*</span> map_width)
<span style="color: #888888;"># Show an animation of the door opening</span>
show_door_opening()
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># Player does not have enough keys.. show that</span>
show_keys()
<span style="color: #888888;"># Check that the map is correct</span>
validate_map()
<span style="color: #888888;"># Setup for game by placing the player at the start position</span>
player_x, player_y <span style="color: #333333;">=</span> find_start()
<span style="color: #888888;"># Main loop. We stay in this loop until the player reaches the exit</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
<span style="color: #888888;"># Try to move when the player presses the A button</span>
<span style="color: #008800; font-weight: bold;">if</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #888888;"># Read the accelerometer and use it to calculate a new player position</span>
acc_x <span style="color: #333333;">=</span> accelerometer<span style="color: #333333;">.</span>get_x()
acc_y <span style="color: #333333;">=</span> accelerometer<span style="color: #333333;">.</span>get_y()
new_x <span style="color: #333333;">=</span> player_x
new_y <span style="color: #333333;">=</span> player_y
<span style="color: #008800; font-weight: bold;">if</span> <span style="color: #007020;">abs</span>(acc_x) <span style="color: #333333;">></span> <span style="color: #007020;">abs</span>(acc_y):
<span style="color: #888888;"># X move is largest</span>
<span style="color: #008800; font-weight: bold;">if</span> acc_x <span style="color: #333333;"><</span> <span style="color: #333333;">-</span>SENSITIVITY:
new_x <span style="color: #333333;">=</span> player_x <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">elif</span> acc_x <span style="color: #333333;">></span> SENSITIVITY:
new_x <span style="color: #333333;">=</span> player_x <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># Y move is largest</span>
<span style="color: #008800; font-weight: bold;">if</span> acc_y <span style="color: #333333;"><</span> <span style="color: #333333;">-</span>SENSITIVITY:
new_y <span style="color: #333333;">=</span> player_y <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">elif</span> acc_y <span style="color: #333333;">></span> SENSITIVITY:
new_y <span style="color: #333333;">=</span> player_y <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #888888;"># Has the player moved?</span>
<span style="color: #008800; font-weight: bold;">if</span> new_x <span style="color: #333333;">!=</span> player_x <span style="color: black; font-weight: bold;">or</span> new_y <span style="color: #333333;">!=</span> player_y:
<span style="color: #888888;"># Yes. Which type of block are they trying to move on to?</span>
block <span style="color: #333333;">=</span> get_map_block(new_x, new_y)
<span style="color: #008800; font-weight: bold;">if</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'w'</span>:
<span style="color: #888888;"># Wall - Can't move here</span>
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'d'</span>:
<span style="color: #888888;"># Door - Try to open it</span>
try_to_open_door_at(new_x, new_y)
<span style="color: #888888;"># Clear button input</span>
button_a<span style="color: #333333;">.</span>was_pressed()
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'k'</span>:
<span style="color: #888888;"># Key - Collect it</span>
collect_key_at(new_x, new_y)
<span style="color: #888888;"># Clear button input</span>
button_a<span style="color: #333333;">.</span>was_pressed()
<span style="color: #008800; font-weight: bold;">elif</span> block <span style="color: #333333;">==</span> <span style="background-color: #fff0f0;">'e'</span>:
<span style="color: #888888;"># Exit - Break out of this function</span>
<span style="color: #008800; font-weight: bold;">break</span>
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># Space - Move the player here</span>
player_x <span style="color: #333333;">=</span> new_x
player_y <span style="color: #333333;">=</span> new_y
<span style="color: #888888;"># Show the map</span>
show_world(player_x, player_y)
<span style="color: #888888;"># Shows a message congratulating the playing on winning</span>
show_door_opening()
sleep(<span style="color: #0000dd; font-weight: bold;">1000</span>)
display<span style="color: #333333;">.</span>scroll(<span style="background-color: #fff0f0;">"Congratulations! You have escaped the maze!"</span>, loop<span style="color: #333333;">=</span><span style="color: #007020;">True</span>)
</pre>
</div>
<br />
There's one interesting thing about this project - we started to hit the limits of the micro:bit memory. We will expand on what this means (and how to scrounge more memory!) in a future post but suffice it to say that, for now, we worked our way around the limits. Probably the most interesting technique we used to save memory is the one that deals with changes to the map. The map is represented as an array of letters (which we call map blocks), so 'w' represents a wall block, 'k' is a key, ' ' is for a space that we can walk on etc.. When the player picks up a key we ned to erase it from the map. Python is great at this and we could have simply made a new copy of the map with the key removed, then swap the maps over. This would work, but requires (at least) twice as much memory - that's too much. The solution is quite neat - we never remove blocks from the map, meaning that we never need to copy the map! Instead we maintain a list (called map_blocks_cleared) of all the blocks that we've "erased". Whenever we try to read from the array of map blocks we first look in this list and if the block we're looking for is in there then we return ' ' instead of what's really there. We wrap all of this functionality up in get_map_block() so that's very easy to query map blocks.<br />
<br />
The Python and hex file are here:<br />
<a href="http://evilpaul.org/giggletronics/tilt_maze.py">tilt_maze.py</a><span id="goog_1315370778"></span><span id="goog_1315370779"></span><br />
<a href="http://evilpaul.org/giggletronics/tilt_maze.hex">tilt_maze.hex</a><br />
<br />
Don't forget that you can just copy the hex file to your device to run it. To play the game tilt the micro:bit in the direction you wish to move and press A. You're looking for the exit (a crazy flashing/strobing pixels) and you'll need to collect keys (rapidly flashing pixels) to open doors (slowly flashing pixels).<br />
<br />
Once you've completed the game, how about looking at the source code and figuring out how to make your own maze? Please share your creations in the comments if you do!Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-16141871074128455642016-08-16T21:47:00.000+01:002016-08-16T21:48:06.097+01:00Micro AlarmThis is our first hardware project - an alarm. It's (very) inspired by <a href="https://www.techwillsaveus.com/">Tech Will Save Us'</a> <a href="http://make.techwillsaveus.com/projects/microguardian">Micro Guardian</a>. The project is pretty simple, but it's a fun one to make. We set up the micro:bit with a connection between pins 0 and 3v using crocodile clips attached to two strips of copper tape. The copper tape goes across the seal of a jar, making a connection when it's closed and breaking it when it's open. We detect this in the code and, when the connection is broken, we output a pulse to pin 1 which has a buzzer connected to it (the other connection of the buzzer goes to GND). We also used some of MicroPython's built-in images to show the micro:bit asleep face when the connection is closed, and alternating between angry face and sword (Son was insistent that the micro:bit show you that it is both angry and ready to fight you) when open.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnBTyavDIBBVb78opOyoPJA-r58QuUgs5ido9cYf5F_h1v00bWnU_WhEzIGDk6nepJEIYFRfzrDPx-2N64XKwF43iX5xTxEkgzc_IjtQU5aHkHZLpGlQDfrcGlD7CEnsTQZArY0dmU3hU/s1600/micro_alarm_01.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhnBTyavDIBBVb78opOyoPJA-r58QuUgs5ido9cYf5F_h1v00bWnU_WhEzIGDk6nepJEIYFRfzrDPx-2N64XKwF43iX5xTxEkgzc_IjtQU5aHkHZLpGlQDfrcGlD7CEnsTQZArY0dmU3hU/s320/micro_alarm_01.JPG" width="240" /></a></div>
<!-- HTML generated using hilite.me --><br />
<a name='more'></a>We followed the first Tech Will Save Us' first step ('The Jar') to set up our jar - coincidentally we had exactly the same jar. We found their instructions and pictures a little bit unclear, so we'll mention that we bend the copper tape back on itself to make a loop to clip the crocodile clips onto:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6UzvTHpqct7sp2wXWAAKA-ABoM6kNMFBUNQXTDE1pEI7iWg1UQObFuwQNqgAe-_KrCZP8PnWf2_tKDjgg5djBCe6T5dYfsSSrf7C3E4y-H1jf0HUTBse5EEhO6jL-nVvrz9R1mjz2vDY/s1600/micro_alarm_03.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi6UzvTHpqct7sp2wXWAAKA-ABoM6kNMFBUNQXTDE1pEI7iWg1UQObFuwQNqgAe-_KrCZP8PnWf2_tKDjgg5djBCe6T5dYfsSSrf7C3E4y-H1jf0HUTBse5EEhO6jL-nVvrz9R1mjz2vDY/s320/micro_alarm_03.JPG" width="240" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jxl9kW8bfaZ9shrXfZgrcS6-ZqDrIz9Z6pE3SdKCwBY6wqy72spq7fGmC8LA9P1NcFNpIzmq8iZtUoE_cIrC41OkCsGHJ_fht2Z1woX5yhqlfMkZTXTrKn97DtTsmdBjFGYcE_l_iA8/s1600/micro_alarm_04.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0jxl9kW8bfaZ9shrXfZgrcS6-ZqDrIz9Z6pE3SdKCwBY6wqy72spq7fGmC8LA9P1NcFNpIzmq8iZtUoE_cIrC41OkCsGHJ_fht2Z1woX5yhqlfMkZTXTrKn97DtTsmdBjFGYcE_l_iA8/s320/micro_alarm_04.JPG" width="240" /></a></div>
<br />
<!-- HTML generated using hilite.me -->We also went for different wiring. Our wiring diagram looks like this:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAzypULpxpU2AndUNMVRNvKyu_Yky1UciPweKygd1dBuD_JrJWv7slTaKLkiMC1lvjcUwTPAB3jdYQNQnw3BF12mBXPaGwJQb02pmG40rEv6dXzZn1Aq38njvuYv5aOn71U7Xf1oHfKus/s1600/Untitled+drawing%25282%2529.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="97" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgAzypULpxpU2AndUNMVRNvKyu_Yky1UciPweKygd1dBuD_JrJWv7slTaKLkiMC1lvjcUwTPAB3jdYQNQnw3BF12mBXPaGwJQb02pmG40rEv6dXzZn1Aq38njvuYv5aOn71U7Xf1oHfKus/s320/Untitled+drawing%25282%2529.png" width="320" /></a></div>
<br />
And that looks like this when we wired it up for real on the micro:bit:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEies39Tt5aPC-QzgpA2ThpYyrlQ7cYyXgV0uLs28Pq2nRFH-yuIzatf0ctzkbNeng9GyO2_61Q2p2fD0X-UyTxh1UT1zQrUYa3H8bx5bBQUpjcNg7z9LIqtgu2u3fVXfo22qYYQE5JsWVE/s1600/micro_alarm_02.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEies39Tt5aPC-QzgpA2ThpYyrlQ7cYyXgV0uLs28Pq2nRFH-yuIzatf0ctzkbNeng9GyO2_61Q2p2fD0X-UyTxh1UT1zQrUYa3H8bx5bBQUpjcNg7z9LIqtgu2u3fVXfo22qYYQE5JsWVE/s320/micro_alarm_02.JPG" width="320" /></a></div>
<br />
<!-- HTML generated using hilite.me -->Here's our complete code:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Micro Alarm</span>
<span style="color: #dd4422;"> Inspired by http://make.techwillsaveus.com/projects/microguardian</span>
<span style="color: #dd4422;"> Makes the micro_bit into an alarm. Sets up a connection between pin 0 and 3v. When that </span>
<span style="color: #dd4422;"> connection is broken we trigger output on pin1, which should be connected to a buzzer.</span>
<span style="color: #dd4422;"> Developed by http://giggletronics.blogspot.co.uk/</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #888888;"># We define two variables that give more meaningful names to the micro:bit's IO pins</span>
contact <span style="color: #333333;">=</span> pin0
buzzer <span style="color: #333333;">=</span> pin1
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
<span style="color: #888888;"># Is the contact open(0) or closed(1)?</span>
<span style="color: #008800; font-weight: bold;">if</span> contact<span style="color: #333333;">.</span>read_digital() <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># Open - Make a beeping noise and show that the micro:bit is angry</span>
<span style="color: #888888;"># Turn buzzer on, show angry face and wait for 1/4 second</span>
buzzer<span style="color: #333333;">.</span>write_digital(<span style="color: #0000dd; font-weight: bold;">1</span>)
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>ANGRY)
sleep(<span style="color: #0000dd; font-weight: bold;">250</span>)
<span style="color: #888888;"># Turn buzzer off, show sword and wait for 1/4 second</span>
buzzer<span style="color: #333333;">.</span>write_digital(<span style="color: #0000dd; font-weight: bold;">0</span>)
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>SWORD)
sleep(<span style="color: #0000dd; font-weight: bold;">250</span>)
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># Closed - Show that the micro:bit is asleep</span>
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>ASLEEP)
</pre>
</div>
<br />
Python and hex files as per usual:<br />
<a href="http://evilpaul.org/giggletronics/micro_alarm.py">micro_alarm.py</a><br />
<a href="http://evilpaul.org/giggletronics/micro_alarm.py">micro_alarm.hex</a><a href="https://www.blogger.com/null"><span id="goog_915181991"></span><span id="goog_915181992"></span></a> Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-66981467078065683322016-08-08T22:31:00.000+01:002016-08-09T13:23:39.840+01:00SnakeHere's our second game, a version of the classic <a href="https://en.wikipedia.org/wiki/Snake_(video_game)">snake</a> game. A bit of a challenge to fit this onto a 5x5 display with only two buttons but we think we've managed it. Drive the snake around the screen using the A and B buttons to turn left and right. The aim is to eat the food (the flashing pixel) but your snake gets longer each time it eats something. Eventually your snake tail will be so long that you'll crash into it and it's game over!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVSz6Hl8vuF7DCq91A2v62v5lwiN5bQAjZyfRD6cJPxuCKxuJulVhVYORfvjRgM457l6KxyvMgT9eSuGU-LjfZkg-PDonY1uGSqE5oh8J1P1kS6Dx4xrhh3Lf_4rMsuhobzVdG1DnETe8/s1600/snake.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiVSz6Hl8vuF7DCq91A2v62v5lwiN5bQAjZyfRD6cJPxuCKxuJulVhVYORfvjRgM457l6KxyvMgT9eSuGU-LjfZkg-PDonY1uGSqE5oh8J1P1kS6Dx4xrhh3Lf_4rMsuhobzVdG1DnETe8/s320/snake.JPG" width="320" /></a></div>
<span id="goog_1620788119"></span><span id="goog_1620788120"></span><br />
<a name='more'></a>The code uses a list to store the snakes body. Each element in the list is itself a two element list with two entries: X and Y. Each update we draw the player's current position to the screen, push it to the front of the list and then pop the last position off and clear it. This makes it looks like the snake is slithering across the screen. The list starts out at one element long and each time we eat some food we push another, extra element to it - making the snake's body a little longer.<br />
<br />
We use another list of X/Y pairs, called directions, to tell us how to move from the current position to the next, based on player_direction. The variable player_direction is an index into that list, which is four elements long, so player_direction must be an integer between 0 and 3. We manage this using the modulus (written as '%') operator:<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"> <span style="color: #888888;"># Change direction if the player pressed a button</span>
<span style="color: #008800; font-weight: bold;">if</span> button_a<span style="color: #333333;">.</span>was_pressed():
player_direction <span style="color: #333333;">=</span> (player_direction <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">4</span> <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span>
<span style="color: #008800; font-weight: bold;">if</span> button_b<span style="color: #333333;">.</span>was_pressed():
player_direction <span style="color: #333333;">=</span> (player_direction <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span>
</pre>
</div>
<br />
Here is the complete listing:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Snake</span>
<span style="color: #dd4422;"> Steer the snake aroud the screen, eating food, which makes the snake's body grow longer and </span>
<span style="color: #dd4422;"> longer. Use the A and B buttons to change the snake's direction left and right. Game ends when </span>
<span style="color: #dd4422;"> the snake collides with it's own body.</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">random</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_titles</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show title image and wait for the A button to be pressed</span>
<span style="color: #dd4422;"> """</span>
display<span style="color: #333333;">.</span>show(Image<span style="color: #333333;">.</span>SNAKE)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">play_game</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Play a single round of the game and return the score achieved</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">find_empty_space</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Finds an empty space on the screen</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
x <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">4</span>)
y <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">4</span>)
<span style="color: #008800; font-weight: bold;">if</span> display<span style="color: #333333;">.</span>get_pixel(x, y) <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #008800; font-weight: bold;">return</span> [x, y]
<span style="color: #888888;"># Player's current position. Stored as a pair of x and y values in a list</span>
player_position <span style="color: #333333;">=</span> [<span style="color: #0000dd; font-weight: bold;">2</span>, <span style="color: #0000dd; font-weight: bold;">2</span>]
<span style="color: #888888;"># This will hold a list of x/y pairs for each segment of the snake's body</span>
player_position_stack <span style="color: #333333;">=</span> []
<span style="color: #888888;"># Players direction. Will be a number between 0 and 3</span>
player_direction <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># How to move in each of the four directions. One of these x/y pairs will be added to the </span>
<span style="color: #888888;"># player's position each frame to make them move</span>
directions <span style="color: #333333;">=</span> [
[<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>], <span style="color: #888888;"># up</span>
[<span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">0</span>], <span style="color: #888888;"># right</span>
[<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #333333;">+</span><span style="color: #0000dd; font-weight: bold;">1</span>], <span style="color: #888888;"># down</span>
[<span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">0</span>], <span style="color: #888888;"># left</span>
]
<span style="color: #888888;"># Clear the display and set the flag to put a piece of food down</span>
display<span style="color: #333333;">.</span>clear()
food_position <span style="color: #333333;">=</span> <span style="color: #007020;">None</span>
<span style="color: #888888;"># The main game loop. We break out if the snake crashes into it's own body</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
<span style="color: #888888;"># Draw player to the screen</span>
display<span style="color: #333333;">.</span>set_pixel(player_position[<span style="color: #0000dd; font-weight: bold;">0</span>], player_position[<span style="color: #0000dd; font-weight: bold;">1</span>], <span style="color: #0000dd; font-weight: bold;">9</span>)
<span style="color: #888888;"># Place a new piece of food if the flag is set</span>
<span style="color: #008800; font-weight: bold;">if</span> food_position <span style="color: #333333;">==</span> <span style="color: #007020;">None</span>:
food_position <span style="color: #333333;">=</span> find_empty_space()
<span style="color: #888888;"># Flash the food and slow down the game</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">4</span>):
display<span style="color: #333333;">.</span>set_pixel(food_position[<span style="color: #0000dd; font-weight: bold;">0</span>], food_position[<span style="color: #0000dd; font-weight: bold;">1</span>], <span style="color: #0000dd; font-weight: bold;">3</span> <span style="color: #008800; font-weight: bold;">if</span> i <span style="color: #333333;">&</span> <span style="color: #0000dd; font-weight: bold;">1</span> <span style="color: #008800; font-weight: bold;">else</span> <span style="color: #0000dd; font-weight: bold;">7</span>)
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
<span style="color: #888888;"># Push the player's position onto the stack</span>
player_position_stack<span style="color: #333333;">.</span>insert(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #007020;">list</span>(player_position))
<span style="color: #888888;"># Change direction if the player pressed a button</span>
<span style="color: #008800; font-weight: bold;">if</span> button_a<span style="color: #333333;">.</span>was_pressed():
player_direction <span style="color: #333333;">=</span> (player_direction <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">4</span> <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span>
<span style="color: #008800; font-weight: bold;">if</span> button_b<span style="color: #333333;">.</span>was_pressed():
player_direction <span style="color: #333333;">=</span> (player_direction <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span>
<span style="color: #888888;"># Move the player forward in the direction they are heading</span>
direction <span style="color: #333333;">=</span> directions[player_direction]
player_position[<span style="color: #0000dd; font-weight: bold;">0</span>] <span style="color: #333333;">=</span> (player_position[<span style="color: #0000dd; font-weight: bold;">0</span>] <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">5</span> <span style="color: #333333;">+</span> direction[<span style="color: #0000dd; font-weight: bold;">0</span>]) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">5</span>
player_position[<span style="color: #0000dd; font-weight: bold;">1</span>] <span style="color: #333333;">=</span> (player_position[<span style="color: #0000dd; font-weight: bold;">1</span>] <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">5</span> <span style="color: #333333;">+</span> direction[<span style="color: #0000dd; font-weight: bold;">1</span>]) <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">5</span>
<span style="color: #888888;"># What value is the pixel that the player is about to move to?</span>
value <span style="color: #333333;">=</span> display<span style="color: #333333;">.</span>get_pixel(player_position[<span style="color: #0000dd; font-weight: bold;">0</span>], player_position[<span style="color: #0000dd; font-weight: bold;">1</span>])
<span style="color: #008800; font-weight: bold;">if</span> value <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">9</span>:
<span style="color: #888888;"># 9 is the snake's own body colour, so break out of the main game loop</span>
<span style="color: #008800; font-weight: bold;">break</span>
<span style="color: #008800; font-weight: bold;">elif</span> value <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># 0 is background, so we don't need to do anything</span>
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #008800; font-weight: bold;">else</span>:
<span style="color: #888888;"># Anything else must be food</span>
<span style="color: #888888;"># Make the stack one element longer so that the snake body grows</span>
player_position_stack<span style="color: #333333;">.</span>insert(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #007020;">list</span>(player_position))
<span style="color: #888888;"># And clear the food position so that another one will be generated</span>
food_position <span style="color: #333333;">=</span> <span style="color: #007020;">None</span>
<span style="color: #888888;"># Pop the position off the end of the stack and clear it on the screen</span>
erase_position <span style="color: #333333;">=</span> player_position_stack<span style="color: #333333;">.</span>pop()
display<span style="color: #333333;">.</span>set_pixel(erase_position[<span style="color: #0000dd; font-weight: bold;">0</span>], erase_position[<span style="color: #0000dd; font-weight: bold;">1</span>], <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #888888;"># The score returned is the length of the snake's body</span>
<span style="color: #008800; font-weight: bold;">return</span> <span style="color: #007020;">len</span>(player_position_stack) <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_game_over</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show a game over screen</span>
<span style="color: #dd4422;"> """</span>
display<span style="color: #333333;">.</span>show([Image(), Image<span style="color: #333333;">.</span>SNAKE, Image(), Image<span style="color: #333333;">.</span>HEART, Image<span style="color: #333333;">.</span>HEART_SMALL, Image(), Image<span style="color: #333333;">.</span>SKULL, Image()])
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_score</span>(score):
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show score and wait for the A button to be pressed</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># Clear inputs</span>
button_a<span style="color: #333333;">.</span>was_pressed()
<span style="color: #888888;"># Show message and wait</span>
display<span style="color: #333333;">.</span>scroll(<span style="background-color: #fff0f0;">'Score: '</span> <span style="color: #333333;">+</span> <span style="color: #007020;">str</span>(score), wait <span style="color: #333333;">=</span> <span style="color: #007020;">False</span>, loop <span style="color: #333333;">=</span> <span style="color: #007020;">True</span>)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
show_titles()
score <span style="color: #333333;">=</span> play_game()
show_game_over()
show_score(score)
</pre>
</div>
<br />
<div align="center">
<video controls="" height="240" width="427">
<source src="http://evilpaul.org/giggletronics/snake.mp4" type="video/mp4"></source>
</video>
</div>
<br />
Note that it's not possible to complete the game - if you're good enough then you'll eventually run out of space, there will be nowhere to generate new food and the game will hang. Maybe you'd like to add the code to handle this case yourself? You'll need to ask yourself some questions:<br />
<ul>
<li>What is the maximum possible score?</li>
<li>What does completing the game mean - is it a certain score, a certain length of snake or is it when the screen is full?</li>
<li>How do you tell if the player has completed the game?</li>
<li>What will you do when the game is complete?</li>
</ul>
Here's the code (and the hex file) if you'd like to tinker:<br />
<a href="http://evilpaul.org/giggletronics/snake.py">snake.py</a><br />
<a href="http://evilpaul.org/giggletronics/snake.hex">snake.hex</a><br />
<br />
<br />Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-26371974712541884762016-08-05T14:53:00.001+01:002016-08-08T22:31:39.928+01:00Non-Flappy BirdHere we present our first micro:bit game - Non-Flappy Bird. We wanted to write a version of Flappy Bird, but on a 5x5 display there didn't feel like there was enough room for flapping. So instead of flapping, we made the A and B buttons move you left and right. Rows of lit pixels drop down the screen towards you and you'll need to dodge them. The game gets faster the more barriers you avoid.<br />
<br />
<div align="center">
<video controls="" height="240" width="427">
<source src="http://evilpaul.org/giggletronics/non_flappy_bird.mp4" type="video/mp4"></source>
</video>
</div>
<br />
<a name='more'></a>The code for this game is fairly simple, but there are is one interesting technique - we use an image as buffer for the horizontal barriers. Barriers are drawn directly to this buffer which is then copied directly to the screen and then the player overlaid at the bottom. The buffer is shifted down every few frames to give the illusion of movement. This buffer technique is great because we don't need to keep track of each barrier, we just draw it the buffer and forget about it. The alternative solution would be to remember each barrier's position and re-draw it every frame, which would be much more work.<br />
<br />
Here's the code:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Non-Flappy Bird</span>
<span style="color: #dd4422;"> Steer though the gaps in the barriers using the A and B buttons. The game gets faster the longer </span>
<span style="color: #dd4422;"> you play.</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">random</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_titles</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show titles and wait for the A button to be pressed</span>
<span style="color: #dd4422;"> """</span>
display<span style="color: #333333;">.</span>scroll(<span style="background-color: #fff0f0;">'Non-Flappy Bird - Press A To Start'</span>, wait <span style="color: #333333;">=</span> <span style="color: #007020;">False</span>, loop <span style="color: #333333;">=</span> <span style="color: #007020;">True</span>)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">play_game</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Play a single round of the game and return the score achieved</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># Create a screen sized image to use as a screen buffer. We draw the barriers to this screen </span>
<span style="color: #888888;"># and then copy it to the main screen every frame</span>
barrier_screen_buffer <span style="color: #333333;">=</span> Image(<span style="background-color: #fff0f0;">'00000:00000:00000:00000:00000:'</span>)
<span style="color: #888888;"># Player score and position</span>
player_x_position <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">2</span>
score <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># Variable to keep track of scrolling</span>
scroll_counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># Variables to keep track of barriers</span>
barrier_counter <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
total_barriers_created <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
<span style="color: #888888;"># Deal with scrolling. We update scrolling once every 4 updates, so the player gets four </span>
<span style="color: #888888;"># updates for each scroll</span>
scroll_counter <span style="color: #333333;">=</span> scroll_counter <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">if</span> scroll_counter <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span> <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># Scroll the barriers towards the player</span>
barrier_screen_buffer <span style="color: #333333;">=</span> barrier_screen_buffer<span style="color: #333333;">.</span>shift_down(<span style="color: #0000dd; font-weight: bold;">1</span>)
<span style="color: #888888;"># Deal with creating barriers. We create one barrier every 4 scrolls</span>
barrier_counter <span style="color: #333333;">=</span> barrier_counter <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #008800; font-weight: bold;">if</span> barrier_counter <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">4</span> <span style="color: #333333;">==</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># Draw a new barrier at the top of the barrier buffer</span>
gap_position <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">4</span>)
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #008800; font-weight: bold;">if</span> i <span style="color: #333333;">==</span> gap_position:
barrier_screen_buffer<span style="color: #333333;">.</span>set_pixel(i, <span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #008800; font-weight: bold;">else</span>:
barrier_screen_buffer<span style="color: #333333;">.</span>set_pixel(i, <span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">7</span>)
<span style="color: #888888;"># Increase score for every barrier</span>
score <span style="color: #333333;">=</span> score <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #888888;"># One more barrier created</span>
total_barriers_created <span style="color: #333333;">=</span> total_barriers_created <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>
<span style="color: #888888;"># Player movement</span>
<span style="color: #008800; font-weight: bold;">if</span> button_a<span style="color: #333333;">.</span>was_pressed():
player_x_position <span style="color: #333333;">=</span> <span style="color: #007020;">max</span>(player_x_position <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #008800; font-weight: bold;">if</span> button_b<span style="color: #333333;">.</span>was_pressed():
player_x_position <span style="color: #333333;">=</span> <span style="color: #007020;">min</span>(player_x_position <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">4</span>)
<span style="color: #888888;"># Draw the barriers to the screen</span>
display<span style="color: #333333;">.</span>show(barrier_screen_buffer)
<span style="color: #888888;"># Collision detection - See if the pixel at the position on the screen where the player is </span>
<span style="color: #888888;"># right now is turned on, if it is then there must be a barrier there</span>
<span style="color: #008800; font-weight: bold;">if</span> display<span style="color: #333333;">.</span>get_pixel(player_x_position, <span style="color: #0000dd; font-weight: bold;">4</span>) <span style="color: #333333;">!=</span> <span style="color: #0000dd; font-weight: bold;">0</span>:
<span style="color: #888888;"># Exit from the while loop</span>
<span style="color: #008800; font-weight: bold;">break</span>
<span style="color: #888888;"># Draw the player to the screen</span>
display<span style="color: #333333;">.</span>set_pixel(player_x_position, <span style="color: #0000dd; font-weight: bold;">4</span>, <span style="color: #0000dd; font-weight: bold;">9</span>)
<span style="color: #888888;"># Slow down the game. We use a short delay here. The delay gets slightly shorter with </span>
<span style="color: #888888;"># every barrier created</span>
sleep(<span style="color: #007020;">max</span>(<span style="color: #0000dd; font-weight: bold;">100</span> <span style="color: #333333;">-</span> total_barriers_created, <span style="color: #0000dd; font-weight: bold;">0</span>))
<span style="color: #888888;"># Finished. Return the score</span>
<span style="color: #008800; font-weight: bold;">return</span> score
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">show_score</span>(score):
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show score and wait for the A button to be pressed</span>
<span style="color: #dd4422;"> """</span>
display<span style="color: #333333;">.</span>scroll(<span style="background-color: #fff0f0;">'Score: '</span> <span style="color: #333333;">+</span> <span style="color: #007020;">str</span>(score), wait <span style="color: #333333;">=</span> <span style="color: #007020;">False</span>, loop <span style="color: #333333;">=</span> <span style="color: #007020;">True</span>)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
show_titles()
score <span style="color: #333333;">=</span> play_game()
show_score(score)
</pre>
</div>
<br />
And here are the source and hex files: <br />
<a href="http://evilpaul.org/giggletronics/non_flappy_bird.py">non_flappy_bird.py</a><br />
<a href="http://evilpaul.org/giggletronics/non_flappy_bird.hex">non_flappy_bird.hex</a><br />
<br />Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-79939789485765912542016-08-04T13:57:00.002+01:002016-08-04T14:07:04.099+01:00Custom Display ClearMicroPython has a simple built-in command to clear the display: display.clear(). The results are equally simple - it instantly turns off every LED on the display. We don't need to be limited to such a simplistic way of clearing the screen though, we can write our own exciting fades, wipes and dissolves.<br />
<br />
<div align="center">
<video controls="" height="240" width="427">
<source src="http://evilpaul.org/giggletronics/custom_display_clear.mp4" type="video/mp4"></source>
</video>
</div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<a name='more'></a>The program code below demonstrates a few different ways of clearing the screen. Press A to try each one in turn. Pressing B will cycle through a few different images so you can see how the clear looks with different source images. Each clear is written in it's own function, so hopefully you should be able to understand them without too much trouble. Try to use these as a basis for your own custom clear functions.<br />
<!-- HTML generated using hilite.me --><br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Custom Display Clear</span>
<span style="color: #dd4422;"> Demonstrate some different ways of clearing the micro:bit display. Pressing A will cycle through </span>
<span style="color: #dd4422;"> the different methods. Pressing B will change the image to be cleared.</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">random</span>
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">clear_fade</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Fade the display out</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># We need to do nine complete passes to ensure that everything is faded to 0</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">9</span>):
<span style="color: #888888;"># Go through all pixels on the display</span>
<span style="color: #008800; font-weight: bold;">for</span> x <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #008800; font-weight: bold;">for</span> y <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #888888;"># Get current pixel value</span>
value <span style="color: #333333;">=</span> display<span style="color: #333333;">.</span>get_pixel(x, y)
<span style="color: #888888;"># Fade it if it's not already 0</span>
display<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #007020;">max</span>(value <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>, <span style="color: #0000dd; font-weight: bold;">0</span>))
<span style="color: #888888;"># Slow down the fade</span>
sleep(<span style="color: #0000dd; font-weight: bold;">100</span>)
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">clear_wipe_down</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Wipe the image clear from top to bottom</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># Go through each line</span>
<span style="color: #008800; font-weight: bold;">for</span> y <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #888888;"># Set the entire line to 0</span>
<span style="color: #008800; font-weight: bold;">for</span> x <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
display<span style="color: #333333;">.</span>set_pixel(x, y, <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #888888;"># Slow down the wipe</span>
sleep(<span style="color: #0000dd; font-weight: bold;">250</span>)
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">clear_slide_down</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Slide the image off the bottom of the display</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># We need to do five complete passes to slide the whole image off the bottom </span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #888888;"># Process all rows</span>
<span style="color: #008800; font-weight: bold;">for</span> x <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">5</span>):
<span style="color: #888888;"># Process the bottom four pixels of each column</span>
<span style="color: #008800; font-weight: bold;">for</span> y <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">4</span>, <span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #333333;">-</span><span style="color: #0000dd; font-weight: bold;">1</span>):
<span style="color: #888888;"># Copy the pixel above into this pixel</span>
value <span style="color: #333333;">=</span> display<span style="color: #333333;">.</span>get_pixel(x, y <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>)
display<span style="color: #333333;">.</span>set_pixel(x, y, value)
<span style="color: #888888;"># Set the top pixel to 0</span>
display<span style="color: #333333;">.</span>set_pixel(x, <span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #888888;"># Slow down the wipe</span>
sleep(<span style="color: #0000dd; font-weight: bold;">250</span>)
<span style="color: #008800; font-weight: bold;">def</span> <span style="color: #0066bb; font-weight: bold;">clear_dissolve</span>():
<span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Dissolve the display</span>
<span style="color: #dd4422;"> """</span>
<span style="color: #888888;"># Make a list of all pixels</span>
pixels <span style="color: #333333;">=</span> <span style="color: #007020;">list</span>(<span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">25</span>))
<span style="color: #888888;"># Randomise the order by swapping random pairs of items lots of time</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> <span style="color: #007020;">range</span>(<span style="color: #0000dd; font-weight: bold;">50</span>):
a <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #007020;">len</span>(pixels) <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>)
b <span style="color: #333333;">=</span> random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #007020;">len</span>(pixels) <span style="color: #333333;">-</span> <span style="color: #0000dd; font-weight: bold;">1</span>)
swap <span style="color: #333333;">=</span> pixels[a]
pixels[a] <span style="color: #333333;">=</span> pixels[b]
pixels[b] <span style="color: #333333;">=</span> swap
<span style="color: #888888;"># Go through all of the pixels, one at a time, and turn them off</span>
<span style="color: #008800; font-weight: bold;">for</span> pixel <span style="color: black; font-weight: bold;">in</span> pixels:
<span style="color: #888888;"># Turn pixel off</span>
display<span style="color: #333333;">.</span>set_pixel(<span style="color: #007020;">int</span>(pixel <span style="color: #333333;">/</span> <span style="color: #0000dd; font-weight: bold;">5</span>), <span style="color: #007020;">int</span>(pixel <span style="color: #333333;">%</span> <span style="color: #0000dd; font-weight: bold;">5</span>), <span style="color: #0000dd; font-weight: bold;">0</span>)
<span style="color: #888888;"># Slow down the dissolve</span>
sleep(<span style="color: #0000dd; font-weight: bold;">50</span>)
<span style="color: #888888;"># All of the clear functions</span>
clear_functions <span style="color: #333333;">=</span> [
clear_fade,
clear_wipe_down,
clear_slide_down,
clear_dissolve,
]
clear_function_index <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># The test images</span>
test_images <span style="color: #333333;">=</span> [
Image<span style="color: #333333;">.</span>HEART,
Image<span style="color: #333333;">.</span>HAPPY,
Image(<span style="background-color: #fff0f0;">"99999:99999:99999:99999:99999"</span>),
Image(<span style="background-color: #fff0f0;">"99999:95559:95559:95559:99999"</span>),
Image(<span style="background-color: #fff0f0;">"13531:35753:57975:35753:13531"</span>),
]
test_image_index <span style="color: #333333;">=</span> <span style="color: #0000dd; font-weight: bold;">0</span>
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
display<span style="color: #333333;">.</span>show(test_images[test_image_index])
<span style="color: #008800; font-weight: bold;">if</span> button_a<span style="color: #333333;">.</span>was_pressed():
clear_functions[clear_function_index]()
sleep(<span style="color: #0000dd; font-weight: bold;">1000</span>)
clear_function_index <span style="color: #333333;">=</span> (clear_function_index <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #007020;">len</span>(clear_functions)
button_a<span style="color: #333333;">.</span>was_pressed()
<span style="color: #008800; font-weight: bold;">elif</span> button_b<span style="color: #333333;">.</span>was_pressed():
test_image_index <span style="color: #333333;">=</span> (test_image_index <span style="color: #333333;">+</span> <span style="color: #0000dd; font-weight: bold;">1</span>) <span style="color: #333333;">%</span> <span style="color: #007020;">len</span>(test_images)
</pre>
</div>
<br />
<a href="http://evilpaul.org/giggletronics/custom_display_clear.py">custom_display_clear.py</a><br />
<a href="http://evilpaul.org/giggletronics/custom_display_clear.hex">custom_display_clear.hex</a><br />
<br />Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-17362980620446393812016-08-03T21:44:00.001+01:002016-08-03T21:44:11.616+01:00Built-in ImagesThe micro:bit's MicroPython has a big list of built-in images - 63 to be precise. But what do they all look like? Well, here's a handy chart! And as a bonus, we've also included a test program that cycles through all the images on the micro:bit's display.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5_DP6e6lARra24xpxua3BxVwj4ytAcWE99Xt4VvXlAs-ZIbZgTnnLr5prxtyO4STGAPWnQA0K0QdDqV5e71lH2IUUp4HxV4khK1GDNKxypwoDXnBc4DZPhMrEpbGMTlAa0j5YeWyKeg/s1600/built_in_images.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgn5_DP6e6lARra24xpxua3BxVwj4ytAcWE99Xt4VvXlAs-ZIbZgTnnLr5prxtyO4STGAPWnQA0K0QdDqV5e71lH2IUUp4HxV4khK1GDNKxypwoDXnBc4DZPhMrEpbGMTlAa0j5YeWyKeg/s320/built_in_images.png" width="320" /></a></div>
<br />
<a name='more'></a>The code is pretty straight-forward - we store all the images in a big list and the iterate through them, showing each one to the screen and the waiting for a button press before going on to the next one.<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Show All Built In Images</span>
<span style="color: #dd4422;"> Show all built in images from the micro:bit library. Press the A button to switch to the next </span>
<span style="color: #dd4422;"> image in the list.</span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #888888;"># List containing all of the built im images</span>
all_images <span style="color: #333333;">=</span> [
Image<span style="color: #333333;">.</span>HEART,
Image<span style="color: #333333;">.</span>HEART_SMALL,
Image<span style="color: #333333;">.</span>DIAMOND,
Image<span style="color: #333333;">.</span>DIAMOND_SMALL,
Image<span style="color: #333333;">.</span>SQUARE,
Image<span style="color: #333333;">.</span>SQUARE_SMALL,
Image<span style="color: #333333;">.</span>HAPPY,
Image<span style="color: #333333;">.</span>SMILE,
Image<span style="color: #333333;">.</span>SAD,
Image<span style="color: #333333;">.</span>CONFUSED,
Image<span style="color: #333333;">.</span>ANGRY,
Image<span style="color: #333333;">.</span>ASLEEP,
Image<span style="color: #333333;">.</span>SURPRISED,
Image<span style="color: #333333;">.</span>SILLY,
Image<span style="color: #333333;">.</span>FABULOUS,
Image<span style="color: #333333;">.</span>MEH,
Image<span style="color: #333333;">.</span>YES,
Image<span style="color: #333333;">.</span>NO,
Image<span style="color: #333333;">.</span>CLOCK1,
Image<span style="color: #333333;">.</span>CLOCK2,
Image<span style="color: #333333;">.</span>CLOCK3,
Image<span style="color: #333333;">.</span>CLOCK4,
Image<span style="color: #333333;">.</span>CLOCK5,
Image<span style="color: #333333;">.</span>CLOCK6,
Image<span style="color: #333333;">.</span>CLOCK7,
Image<span style="color: #333333;">.</span>CLOCK8,
Image<span style="color: #333333;">.</span>CLOCK9,
Image<span style="color: #333333;">.</span>CLOCK10,
Image<span style="color: #333333;">.</span>CLOCK11,
Image<span style="color: #333333;">.</span>CLOCK12,
Image<span style="color: #333333;">.</span>ARROW_N,
Image<span style="color: #333333;">.</span>ARROW_NE,
Image<span style="color: #333333;">.</span>ARROW_E,
Image<span style="color: #333333;">.</span>ARROW_SE,
Image<span style="color: #333333;">.</span>ARROW_S,
Image<span style="color: #333333;">.</span>ARROW_SW,
Image<span style="color: #333333;">.</span>ARROW_W,
Image<span style="color: #333333;">.</span>ARROW_NW,
Image<span style="color: #333333;">.</span>TRIANGLE,
Image<span style="color: #333333;">.</span>TRIANGLE_LEFT,
Image<span style="color: #333333;">.</span>CHESSBOARD,
Image<span style="color: #333333;">.</span>PITCHFORK,
Image<span style="color: #333333;">.</span>XMAS,
Image<span style="color: #333333;">.</span>TARGET,
Image<span style="color: #333333;">.</span>TSHIRT,
Image<span style="color: #333333;">.</span>ROLLERSKATE,
Image<span style="color: #333333;">.</span>HOUSE,
Image<span style="color: #333333;">.</span>SWORD,
Image<span style="color: #333333;">.</span>UMBRELLA,
Image<span style="color: #333333;">.</span>RABBIT,
Image<span style="color: #333333;">.</span>COW,
Image<span style="color: #333333;">.</span>DUCK,
Image<span style="color: #333333;">.</span>TORTOISE,
Image<span style="color: #333333;">.</span>BUTTERFLY,
Image<span style="color: #333333;">.</span>GIRAFFE,
Image<span style="color: #333333;">.</span>SNAKE,
Image<span style="color: #333333;">.</span>SKULL,
Image<span style="color: #333333;">.</span>STICKFIGURE,
Image<span style="color: #333333;">.</span>PACMAN,
Image<span style="color: #333333;">.</span>GHOST,
Image<span style="color: #333333;">.</span>MUSIC_CROTCHET,
Image<span style="color: #333333;">.</span>MUSIC_QUAVER,
Image<span style="color: #333333;">.</span>MUSIC_QUAVERS,
]
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">for</span> i <span style="color: black; font-weight: bold;">in</span> all_images:
display<span style="color: #333333;">.</span>show(i)
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
display<span style="color: #333333;">.</span>clear()
</pre>
</div>
<br />
Here are the Python and hex files:<br />
<a href="http://evilpaul.org/giggletronics/show_all_built_in_images.py">show_all_built_in_images.py</a><br />
<a href="http://evilpaul.org/giggletronics/show_all_built_in_images.hex">show_all_built_in_images.hex</a>Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-82707518109127578972016-08-02T13:53:00.002+01:002016-08-02T13:53:36.577+01:00Electronic DieSo here's our first program - an electronic die. OK, so technically this is the second program - we went from the ultra-simplicity of "Hello, World" straight to here. The program's operation is pretty simple - every time you shake the micro:bit you get a new random number displayed on the screen in the image of a traditional six side die. We found that the shake gesture was pretty hit-and-miss so we made it that you can also press the A button to roll. We expected the gesture recognition to be better, so maybe we're doing it wrong? Suggestions welcome!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixS748LF5FRog4CwxVEcMVpEUnXqLuL44C_uZjNzDswm7VCHg9y_p463-N8PmNa3p-pi_BOQXtI9ktFwXSVV-WPzIeUfMvuOrwSwHbFYRjAKgflfzQq54wORrQnnnsNqOUJo56-HvVw48/s1600/IMG_0412%255B1%255D.JPG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEixS748LF5FRog4CwxVEcMVpEUnXqLuL44C_uZjNzDswm7VCHg9y_p463-N8PmNa3p-pi_BOQXtI9ktFwXSVV-WPzIeUfMvuOrwSwHbFYRjAKgflfzQq54wORrQnnnsNqOUJo56-HvVw48/s320/IMG_0412%255B1%255D.JPG" width="320" /></a></div>
<a name='more'></a><br />
The code is commented and hopefully it's pretty self explanatory. The basic overview is that we define six images, each one looking like the a face of a die. We then randomly display one of these images whenever we shake the micro:bit or press the A button. We added a couple of delays to a make the whole thing feel nicer - first of all we clear the display and leave a short delay after the shake/button to give the user a simple bit of feedback so that they know that they've activated the roll, the second delay is after the new roll has been displayed so that the user doesn't accidentally re-trigger another roll immediately. Finally, we added a couple of lines of code to clear the inputs. This might not seem important, but try taking it out and see what happens. Hint: notice what happens if you quickly double press the A button.<br />
<br />
Here's the code:<br />
<br />
<div style="background: #ffffff; border-width: 0.1em 0.1em 0.1em 0.8em; border: solid gray; overflow: auto; padding: 0.2em 0.6em; width: auto;">
<pre style="line-height: 125%; margin: 0;"><span style="color: #dd4422;">"""</span>
<span style="color: #dd4422;"> Electronic Die</span>
<span style="color: #dd4422;"> Roll an electronic die every time the micro:bit is shaken or the A button is pressed</span>
<span style="color: #dd4422;"> Developed by http://giggletronics.blogspot.co.uk/</span>
<span style="color: #dd4422;"> </span>
<span style="color: #dd4422;"> This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 </span>
<span style="color: #dd4422;"> International License. https://creativecommons.org/licenses/by-nc-sa/4.0/</span>
<span style="color: #dd4422;">"""</span>
<span style="color: #008800; font-weight: bold;">from</span> <span style="color: #0e84b5; font-weight: bold;">microbit</span> <span style="color: #008800; font-weight: bold;">import</span> <span style="color: #333333;">*</span>
<span style="color: #008800; font-weight: bold;">import</span> <span style="color: #0e84b5; font-weight: bold;">random</span>
<span style="color: #888888;"># Image definitions for the six sides of the die</span>
numbers <span style="color: #333333;">=</span> [
Image(<span style="background-color: #fff0f0;">"00000:00000:00900:00000:00000"</span>),
Image(<span style="background-color: #fff0f0;">"00009:00000:00000:00000:90000"</span>),
Image(<span style="background-color: #fff0f0;">"00009:00000:00900:00000:90000"</span>),
Image(<span style="background-color: #fff0f0;">"90009:00000:00000:00000:90009"</span>),
Image(<span style="background-color: #fff0f0;">"90009:00000:00900:00000:90009"</span>),
Image(<span style="background-color: #fff0f0;">"90009:00000:90009:00000:90009"</span>),
]
<span style="color: #888888;"># Main loop</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: #007020;">True</span>:
<span style="color: #888888;"># Display a random number</span>
display<span style="color: #333333;">.</span>show(numbers[random<span style="color: #333333;">.</span>randint(<span style="color: #0000dd; font-weight: bold;">0</span>, <span style="color: #0000dd; font-weight: bold;">5</span>)])
<span style="color: #888888;"># Wait half a second then clear inputs so that we don't immediately retrigger</span>
sleep(<span style="color: #0000dd; font-weight: bold;">500</span>)
accelerometer<span style="color: #333333;">.</span>was_gesture(<span style="background-color: #fff0f0;">"shake"</span>)
button_a<span style="color: #333333;">.</span>was_pressed()
<span style="color: #888888;"># Wait for a shake or a button press</span>
<span style="color: #008800; font-weight: bold;">while</span> <span style="color: black; font-weight: bold;">not</span> accelerometer<span style="color: #333333;">.</span>was_gesture(<span style="background-color: #fff0f0;">"shake"</span>) <span style="color: black; font-weight: bold;">and</span> <span style="color: black; font-weight: bold;">not</span> button_a<span style="color: #333333;">.</span>was_pressed():
<span style="color: #008800; font-weight: bold;">pass</span>
<span style="color: #888888;"># Clear display and pause to show user that we've acknowledged their input</span>
display<span style="color: #333333;">.</span>clear()
sleep(<span style="color: #0000dd; font-weight: bold;">500</span>)
</pre>
</div>
<br />
And here is the code as a text file (with Python's ".py" extension) and a ".hex" file. You can load the .py file into the micro:bit code editor, and you can flash the .hex file directly onto your micro:bit by dragging and dropping like you would with any other .hex file<br />
<br />
<a href="http://evilpaul.org/giggletronics/electronic_die.py">electronic_die.py</a><br />
<a href="http://evilpaul.org/giggletronics/electronic_die.hex">electronic_die.hex</a>Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-67936953398005892022016-07-29T14:11:00.000+01:002016-07-29T14:28:01.053+01:00Using MicroPython on the micro:bit<a href="https://github.com/bbcmicrobit/micropython">MicroPython</a> on the micro:bit is a great language. It may be a cut down version of <a href="https://www.python.org/">Python</a> 3 - missing many of the libraries that ship with the full-sized version of Python and some that are included are cut down somewhat - but it's a prefect match to the micro:bit. The only real problems that I've found so far revolve around using the BBC's online editor. It's good for what it is (getting you started) but three big limitations hit quite quickly:<br />
<ul>
<li>Flashing programs to the micro:bit is awkward. First you download the hex file from your browser, find where the browser stored it, open up the micro:bit drive, then you drag it to the micro:bit drive. Far too many steps.</li>
<li>Program errors are almost comically hard to trace as the micro:bit slowly scrolls the error messages across its tiny display.</li>
<li>Python programs are best developed in combination with access to the command line (which Python calls a <a href="https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop">REPL</a>). This allows you to try out commands and snippets of code without having to write a test program. If you've ever used BASIC on an old computer - that essentially what the REPL gives you. The default micro:bit IDE does not give you any way to access the REPL.</li>
</ul>
Luckily, there is a solution that solves all of these problems in a snip: <a href="http://codewith.mu/">Mu</a>.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzyc3vanYHrwmNigGo_1zTy0B_3faGjoQ9cCXK-SxelVijyjJ0PYHlcewjR2qwNa__81iIEUyUcQa-Z8DvE4LWfTu4WZslCNkw5k_b-x7gkcNGs0YaowSItbMgQxb3svlJsK2PjIpjxPA/s1600/mu.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="243" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjzyc3vanYHrwmNigGo_1zTy0B_3faGjoQ9cCXK-SxelVijyjJ0PYHlcewjR2qwNa__81iIEUyUcQa-Z8DvE4LWfTu4WZslCNkw5k_b-x7gkcNGs0YaowSItbMgQxb3svlJsK2PjIpjxPA/s320/mu.PNG" width="320" /></a></div>
<br />
<a name='more'></a><br />
Mu is a free, open source, cross platform <a href="https://en.wikipedia.org/wiki/Integrated_development_environment">IDE</a> for MicroPython on the micro:bit. It allows you to quickly and easily create and edit MicroPython programs and to flash them to your micro:bit for testing. You can also access the MicroPython REPL, giving you a command line and console output for the language. Finally, it allows you to manage files stored on the micro:bits local file system - something that we'll come to that much later on in our journey.<br />
<br />
With Mu installed you solve the big limitations:<br />
<ul>
<li>Flashing programs to the micro:bit is as straightforward as pressing the "Flash" button on the editor. </li>
<li>Program errors are reported in full to the REPL console, making debugging so much easier. You can also now use Python's print() command to send output to the console - and that makes debugging even easier still.</li>
<li>You can access the MicroPython "command line" via the REPL, meaning that you can poke around inside the micro:bit and prototype code much more quickly.</li>
</ul>
The programs we'll be showing on this blog will be developed using Mu. If you don't (or can't) use Mu then don't worry - they will work just as well if you load them into the BBC's own editor. In fact, we'll try not to even mention Mu again unless we really have to.<br />
<h2>
Installing Mu</h2>
The installation instructions for Mu are pretty simple, and are <a href="https://github.com/ntoll/mu">listed on the GitHub page</a>. If you're running Windows (like us) then you'll also need do download and install a small driver to be able to access the REPL. You'll still be able to flash programs to your micro:bit without it, but you'll be missing out on most of the fun that Mu provides. The link to the driver is given under the Windows specific install instructions for Mu, but I had some problems getting it to install. In the end I managed to get it to work by, 1) making sure that Mu was not running, and 2) connecting my micro:bit via USB, before 3) running the installer program.Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-69838060413802790862016-07-27T20:18:00.001+01:002016-07-28T18:04:18.090+01:00ArrivalBy mid-July it looked like the micro:bit should be available to buy, but every online shop was still showing them as out of stock. After a bit of a hunt, I found that <a href="https://shop.pimoroni.com/">Pimoroni</a> showed them as available to order. Being of the slightly suspicious type I sent them a message and quite quickly the reply came back "yes, we actually got them in stock". Brilliant! I hurriedly placed the order.<br />
<br />
A couple of days later a package arrived at our house. Nice work <a href="https://shop.pimoroni.com/">Pimoroni</a>! Son saw the package first (what with me being at work and him being at home on school holiday) and guessed that there was a micro:bit inside.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDx6ttKsYAJCGU6_1xCqwF7aPcCNZmd8GmUOte7hQKqXx8XNGBI7octKwJoJ7fJH6PoB1ovae8jUx27t8S6nwVz_7T-kBBhI32AFOKCMN2ofufBHdYht2CP63xe-rivbjD2fFSqjM0dsw/s1600/package.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhDx6ttKsYAJCGU6_1xCqwF7aPcCNZmd8GmUOte7hQKqXx8XNGBI7octKwJoJ7fJH6PoB1ovae8jUx27t8S6nwVz_7T-kBBhI32AFOKCMN2ofufBHdYht2CP63xe-rivbjD2fFSqjM0dsw/s320/package.png" width="320" /></a></div>
<br />
<a name='more'></a>He had to wait patiently for me to get home so that we could open it together. After we had opened it he confessed that he was "off the scale of excitedness".<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUsdAuEz3iWsaO1-wGQsU1HlTTUF-xGpneowLigKE3WXaNAXyD7_Qxnj2pf6C9F9r5hLUVz8xLUU-WXMCoXa3y6GgwHJoED0v7Dv2resmV07IYWT-p2ocFr1wDEHtG0-stCqzfDD-hqaQ/s1600/contents.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiUsdAuEz3iWsaO1-wGQsU1HlTTUF-xGpneowLigKE3WXaNAXyD7_Qxnj2pf6C9F9r5hLUVz8xLUU-WXMCoXa3y6GgwHJoED0v7Dv2resmV07IYWT-p2ocFr1wDEHtG0-stCqzfDD-hqaQ/s320/contents.png" width="320" /></a></div>
<br />
It took us about thirty seconds to get the micro:bit out and the battery plugged in and we were soon working our way through the built-in tutorial. About five minutes later we had our first Python script running and watched as the traditional "Hello, World" message scrolled across our tiny screen.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdRjP7Fy-TYxDWQPAv0FR5iCK2LM0Gs1JC6TstrkDMySG39zLSQvUAPT4ID8L4PBgMB7TcWiV_fb_99BWT9WmlcvYORsBjLP7wkhSs6qdDKwjlsc9pXd1EdwT6x0OyxmSamws5v-Pn8Lc/s1600/running.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjdRjP7Fy-TYxDWQPAv0FR5iCK2LM0Gs1JC6TstrkDMySG39zLSQvUAPT4ID8L4PBgMB7TcWiV_fb_99BWT9WmlcvYORsBjLP7wkhSs6qdDKwjlsc9pXd1EdwT6x0OyxmSamws5v-Pn8Lc/s320/running.png" width="320" /></a></div>
<br />
We have decided to write some programs, and to use Python as out language of choice. Over the course of this blog we will be posting our programs along with our general thoughts and processes regarding the BBC micro:bit.Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0tag:blogger.com,1999:blog-3361150683809587141.post-40722829047270209982016-07-25T22:19:00.001+01:002016-07-28T11:46:22.632+01:00Begin at the Beginning<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDCSHkUoK7VyplmDFsOYG3cziH5pNs0OLBCyTgEn1SJcPbf45wwcZyCSd4wNafNEbNqcFRZNRNETHyWL_lN1GYZwGZslNOsI98O6PiYoJdmgCTM5BJmH_gAPQe6XM8Cy319rx_ZZ0LFfw/s1600/micro-bit.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="179" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDCSHkUoK7VyplmDFsOYG3cziH5pNs0OLBCyTgEn1SJcPbf45wwcZyCSd4wNafNEbNqcFRZNRNETHyWL_lN1GYZwGZslNOsI98O6PiYoJdmgCTM5BJmH_gAPQe6XM8Cy319rx_ZZ0LFfw/s320/micro-bit.jpg" width="320" /></a></div>
<br />
I can't remember when we first heard about the BBC miro:bit, but it filled us both with excitement. I'm a software engineer who also dabbles in electronics, and Son is a school kid who likes to program in Scratch and who is also becoming interested in electronics. I wanted an to find an interesting platform that we could both to learn together. My wish list was something like:<br />
<a name='more'></a><br />
<ul>
<li>Easy to program - We both enjoy Scratch-like programming languages but I feel that they have their limits. Conversely, something like C or Java has too steep a learning curve. The micro:bit does support a number of "block languages", but it also works well with Python. We've both used Python before (me in my day job and Son has gone through a few tutorials) and it seems like the perfect compromise. Python is also an industry standard language and that makes it a useful thing to know.</li>
<li>Simple to deploy - I've played around with a few micro-controllers and, to be frank, they can be a pain to use. Most of the modern micro-controllers come on nice boards with dead-simple USB communication and well featured IDEs. The micro-bit definitely scores well here.</li>
<li>Limited, but not too limited - I firmly believe that limits breed creativity. Scratch was becoming difficult for us because our projects were staring to blossom out of all control and consequently many never got finished. I wanted a platform that was limited enough that it would be easy to conceive, create and debug complete programs in a very short amount of time. The BBC micro:bit seemed, once again, like a great compromise. Sure, I'd love a couple more buttons and a display bigger than 5x5 but then the scope for our programs would just get bigger. Better to stick with humble beginnings, knowing that we can extend it with external circuits at a later date.</li>
<li>Standalone - Must be something that can be easily run un-tethered. I want something that we can make portable toys and experiments with. I want something that we can run without having to lug extra kit around. The micro:bit with a battery pack does all of this well.</li>
<li>Cheap and sturdy - I want to have a piece of kit that we can take risks with, something that is strong enough to take a few knocks or incorrectly wired connections. I also want something that isn't expensive so that if we do manage to kill it then it's not the end of the world. I feel that risk taking is an important part of learning.</li>
</ul>
As you can see, the BBC micro:bit fits my list pretty sweetly. The only challenge for us then was how to get hold of one. They were being given out free to all year 7 UK school kids - but Son was too young for that. No-one that we asked could tell us when they were going to be available for the general public to buy. Maybe we should look at something else? Then we were lucky enough to get a hands-on demo at a Microsoft-led workshop at the brilliant Butlins Astonishing Family Science Weekend earlier in the year. We fell for the micro:bit all over again, and then suddenly it seemed like July was all but confirmed as the official release date. All we had to do now was to wait..<br />
<br />Giggletronicshttp://www.blogger.com/profile/08951318329608007280noreply@blogger.com0