Sunday, 1 March 2015

Ultrasonic Elephant Cheese-puff Game using Raspberry Pi and Scratch

In two previous posts I've written how my kids and I used an ultra sonic sensor, Raspberry Pi and Scratch to make a press up counter and a cuddly toy theft alarm.  One deficiency in those projects was that the Scratch/GPIO capability could only take an ultra-sonic measurement every one second.  In particular, for the press up counter I had to do the press ups REALLY slowly to get them to count. Too much like hard work!

A bit more investigation on Simple Si's epic Scratch/GPIO site showed that he has created a capability using an "UltraDelay" variable which means you can take a reading every 0.2 seconds.  So this means you can many more measurements and so, racking my brains to think what we could do with this, I had the idea of making the Scratch cat levitate by moving my hand up and down over the ultra sonic sensor.  A extension of this was to create a Scratch game, using the sensor to control a sprite's position.

Here's what we came up with:

  • Have a sprite moving across the screen from right to left at random heights.  When it reaches the left hand side of the screen it returns to the right hand side and re-starts at a new height.
  • Have a sprite that moves up and down the screen based upon the position of your hand over the sensor.  If this sprite touches the right to left sprite then you score points.
  • Have this happening for a fixed period of time and then have the final score read out at the end.

Here's the code for the right to left sprite:

So a very simple block of code:
  • Start when g (for game) is pressed.
  • Set the initial position of the sprite as x=200, y=-100.  This is on the right edge of the screen towards the bottom.
  • Loop 600 times.  
  • For each loop, move the x position of the sprite by -13 steps. 
  • If the sprite gets to an x position of -180 (left hand side of the screen) then move it back to the right hand side of the screen but at a random height that is somewhere between -200 (bottom of screen) and 200 (top).
There was some excellent learning to be had just in this short block of code:
  • x and y coordinates on the screen.
  • Loops, and changing the loop variable to get the game time we needed.
  • Experimenting with the number of steps to move the sprite by for each loop.  The final value of -13 was found to be just the right number to make the game challenging but not too challenging.
  • An if statement and an action taken should the statement be true.

Which leaves the (slightly more complex) code for the second sprite:
Here we:
  • Again start by pressing g.
  • Set the UltraDelay variable to 0.  This means a reading is available every 0.2 seconds.
  • Set a HitCount variable to 0, this was incremented when the sprites touch.
  • Set the sprite to it's initial position.  x = -100 is left of centre meaning there's time to move the sprite into position to hit the right to left sprite.
  • Go into a loop with 600 iterations, the same as for the other sprite.
  • Broadcast for an ultrasonic measurement.
  • Get the response and then set the y position of the sprite to be (value * 10) - 200.  Having -200 meant that when the value is very low (or zero) the sprite moves to the bottom of the screen.  Having * 10 means that 40cm worth of hand movement over the sensor can translate to 400 steps of movement of the sprite.
  • A check to see of the sprite is touching the right-left sprite.  If it is then increment a variable to count the number of touches and play a pop sound.
  • When the main 600 iterations are done, go into a loop that reads out the final score.

So in doing this we learnt:
  • About setting and incrementing variables
  • About maths statements, taking one value and transposing it to another.
  • The simple concept of taking a real world value and turning this into an on-screen analogue.

Which left the important task of choosing the sprite icons.  For this we used:
  • A bowl of cheese puffs for the right to left sprite.
  • An elephant for the up and down sprite.

You ask why?  I say why not!!!

Here's the game in action:

Future improvements:
  • A high score feature.
  • Having only one point scored when the sprites touch (should be able to use a simple boolean for this).