Freeduino Games
Freeduino Truck Lane
Go from the Freeduino Spring Training LCD activity to a game!
Need a Freeduino, a 10K pot, and a 16x2 LCD and a solderless breadboard. Follow all steps in 4th Inning. Now, pull the middle pot pin out of the LCD. Just connect that LCD pin to ground. (It's the third pin from the end of the LCD) This should give you a high contrast display. We need to use the pot for steering! Connect the middle pot pin instead to Analog Input pin 1 of your Freeduino. We didn't add a speaker, just used pin 13 to light up the onboard green LED if you "crash" in the game. If you want to use a speaker, connect it to a PWM pin like digital 3, 5 or 6 and adjust the code accordingly.
Here's the code, cut and paste this into Arduino and install it to your board. Play away. To play again, press the Freeduino's reset button.
Much more including videos at the game's original site [1]. We've changed the pinouts in the code to match what we did in the Freeduino Spring Training LCD activity.
Can you modify the code to make a game that rewards crashing? For example, scoot around catching falling "coins," and see how many you can collect within a certain time. Then, make them fall faster and faster! This would be a fun way to learn more about what the code is doing.
/* Simple Car game for a 16x2 LCD display You can use any Hitachi HD44780 compatible LCD. Modified for LVL1 Spring Training LCD Activity, Originally from @TheRealDod, Nov 25, 2010 There's a "steering wheel" potentiometer on analog input 1, and a led on pin 13 Enjoy, */ #include <LiquidCrystal.h> // LiquidCrystal display // You can use any Hitachi HD44780 compatible. Wiring explained at // http://www.arduino.cc/en/Tutorial/LiquidCrystal LiquidCrystal lcd(7, 8, 9, 10, 11, 12); // Steering wheel potentiometer const int POTPIN = 1; const int MAXPOT = 800; // no need to turn the wheel all the way to 1023 :) // Piezo speaker const int SPEAKERPIN = 13;//you can see the led flash when u crash const int RANDSEEDPIN = 0; // an analog pin that isn't connected to anything const int MAXSTEPDURATION = 300; // Start slowly, each step is 1 millisec shorter. const int MINSTEPDURATION = 150; // This is as fast as it gets const int NGLYPHS = 6; // the glyphs will be defined starting from 1 (not 0), // to enable lcd.print() of null-terminated strings byte glyphs[NGLYPHS][8] = { // 1: car up { B00000, B01110, B11111, B01010, B00000, B00000, B00000, B00000} // 2: car down ,{B00000, B00000, B00000, B00000, B01110, B11111, B01010, B00000} // 3: truck up ,{B00000, B11110, B11111, B01010, B00000, B00000, B00000, B00000} // 4: truck down ,{B00000, B00000, B00000, B00000, B11110, B11111, B01010, B00000} // 5: crash up ,{B10101, B01110, B01110, B10101, B00000, B00000, B00000, B00000} // 6: crash down ,{B00000, B00000, B00000, B10101, B01110, B01110, B10101, B00000} }; const int NCARPOSITIONS = 4; // Each position is mapped to a column of 2 glyphs // Used to make sense when I had a 5th position // where car or crash was drawn as 2 glyphs // (can't do that since 0 terminates strings), // so it's kinda silly now, but it ain't broke :) const char BLANK=32; char car2glyphs[NCARPOSITIONS][2] = { {1,BLANK},{2,BLANK},{BLANK,1},{BLANK,2} }; char truck2glyphs[NCARPOSITIONS][2] = { {3,BLANK},{4,BLANK},{BLANK,3},{BLANK,4} }; char crash2glyphs[NCARPOSITIONS][2] = { {5,BLANK},{6,BLANK},{BLANK,5},{BLANK,6} }; const int ROADLEN = 15; // LCD width (not counting our car) int road[ROADLEN]; // positions of other cars char line_buff[2+ROADLEN]; // aux string for drawRoad() int road_index; int car_pos; // Off-the-grid position means empty column, so MAXROADPOS // determines the probability of a car in a column // e.g. 3*NCARPOSITIONS gives p=1/3 const int MAXROADPOS = 3*NCARPOSITIONS; int step_duration; int crash; // true if crashed unsigned int crashtime; // millis() when crashed const int CRASHSOUNDDURATION = 250; const char *INTRO1="Trucks ahead,"; const char *INTRO2="Drive carefully"; const int INTRODELAY = 2000; void setup() { crash = crashtime = road_index = 0; step_duration = MAXSTEPDURATION; line_buff[1+ROADLEN] = '\0'; // null terminate it randomSeed(analogRead(RANDSEEDPIN)); for (int i=0; i<NGLYPHS; i++) { lcd.createChar(i+1,glyphs[i]); } for (int i=0; i<ROADLEN; i++) { road[i]=-1; } pinMode(SPEAKERPIN,OUTPUT); analogWrite(SPEAKERPIN,0); // to be on the safe side lcd.begin(16,2); getSteeringWheel(); drawRoad(); lcd.setCursor(1,0); lcd.print(INTRO1); lcd.setCursor(1,1); lcd.print(INTRO2); delay(INTRODELAY); } void loop() { unsigned long now = millis()-INTRODELAY; if (!crash) { getSteeringWheel(); crash = (car_pos==road[road_index]); } if (crash) { if (!crashtime) { crashtime=now; drawRoad(); // Game over text // (keep first 2 "crash" columns intact) lcd.setCursor(2,0); lcd.print("Crashed after"); lcd.setCursor(2,1); lcd.print(now/1000); lcd.print(" seconds."); } if ((now-crashtime)<CRASHSOUNDDURATION) { analogWrite(SPEAKERPIN,random(255)); // white noise } else { analogWrite(SPEAKERPIN,0); // dramatic post-crush silence :) } delay(10); // Wait a bit between writes } else { int prev_pos = road[(road_index-1)%ROADLEN]; int this_pos = random(MAXROADPOS); while (abs(this_pos-prev_pos)<2) { // don't jam the road this_pos = random(MAXROADPOS); } road[road_index] = this_pos; road_index = (road_index+1)%ROADLEN; drawRoad(); delay(step_duration); if (step_duration>MINSTEPDURATION) { step_duration--; // go faster } } } void getSteeringWheel() { car_pos = map(analogRead(POTPIN),0,1024,0,NCARPOSITIONS); } void drawRoad() { for (int i=0; i<2; i++) { if (crash) { line_buff[0]=crash2glyphs[car_pos][i]; } else { line_buff[0]=car2glyphs[car_pos][i]; } for (int j=0; j<ROADLEN; j++) { int pos = road[(j+road_index)%ROADLEN]; line_buff[j+1] = pos>=0 && pos<NCARPOSITIONS ? truck2glyphs[pos][i] : BLANK; } lcd.setCursor(0,i); lcd.print(line_buff); } }
Freeduino Whack-A-Mole
Coming soon, Freeduino [Whack-A-Mole!][2] We need 5-way joysticks for this one. It will introduce the Arduino Serial Monitor.
Others
What games can you make from a Freeduino, LCD, one pot, one 5-way joystick, some LEDs, a temperature sensor, a light sensor and maybe a piezo speaker?
Advanced
You are also allowed to use the Serial Monitor in combination with Processing or the like, to do stuff on your computer's display. The Freeduino should be the game engine.