March 30, 2010 12:45 AM
DIY hobo game controllers
by Shawn Wallace
These DIY game controllers are made from pennies and cigar boxes.
They are a sample controller for the Fluxly video game, a wizard duel where you have to build your own controller to compete. The interface for the game is implemented in Actionscript and compiled using Adobe's free mxmlc compiler.
This is the hardware block diagram:
And these are the services and software that are running on the computer side:
The serproxy serial proxy written in C can be found here.
A Perl version of the Flash socket policy server can be found here: flashpolicyd.pl.
The socket policy XML file looks like this:
<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
<site-control permitted-cross-domain-policies="master-only"/>
<allow-access-from domain="*" to-ports="5331" />
</cross-domain-policy>
The hardware is intended to be Arduino-compatible, so it is based on the Atmega8 line of microcontrollers. Here are the schematics for the controller:
and the base unit:
The SWF application in action:
Arduino code for the Base unit:
#
# Fluxly Base Unit
#
# Acts as a bridge between two controllers and a serial connection.
# Requests the state of each controller via I2C and forwards it
# to the computer.
#
#include <Wire.h>
byte state[6] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50};
void setup()
{
Wire.begin();
Serial.begin(57600);
}
void loop()
{
Wire.requestFrom(2, 6);
while(Wire.available())
{
byte c = Wire.receive();
state[int(c>>4)] = c;
}
Wire.requestFrom(3, 6);
while(Wire.available())
{
byte c = Wire.receive();
state[int(c>>4)] = state[int(c>>4)] | c;
}
for (int i=0; i < 6; i++) {
Serial.print(state[i],BYTE);
delay(10);
}
delay(10);
}
Arduino code for the controller:
#
# Fluxly Controller
#
# A super simple controller that polls a bunch of switches and sends a
# state table to the base unit over an I2C connection when asked.
#
#include <Wire.h>
#define player1 2
#define player2 3
#define maxButtons 12
#define left 0x01
#define right 0x02
#define jump 0x04
#define stabilize 0x08
#define windFromEast 0x11
#define windFromWest 0x12
#define quake 0x14
#define lessGravity 0x18
#define dropSmallBlocks 0x21
#define dropLargeBlocks 0x22
#define dropPlanks 0x24
#define conjureClouds 0x28
#define lightning 0x31
#define moreGravity 0x32
#define p2Left 0x34
#define p2Right 0x38
#define p2Jump 0x41
#define p2Stabilize 0x42
#define STATE_NSIZE (6)
uint8_t state[STATE_NSIZE] = { 0x00, 0x10, 0x20, 0x30, 0x40, 0x50};
byte buttons[maxButtons];
void setup() {
Serial.begin(9600);
Wire.begin(player2);
Wire.onRequest(requestEvent);
for (int i=0; i < maxButtons; i++) {
pinMode(i+2, INPUT);
buttons[i] = 0x00;
}
setButton(1, p2Left);
setButton(2, p2Stabilize);
setButton(3, p2Right);
setButton(4, p2Jump);
setButton(5, windFromEast);
setButton(6, windFromWest);
setButton(7, quake);
setButton(8, lessGravity);
setButton(9, dropSmallBlocks);
setButton(10, conjureClouds);
setButton(11, lightning);
setButton(12, moreGravity);
}
void setButton(int n, byte action) {
buttons[n-1] = action;
}
void checkButtons() {
for (byte i=0; i < 6; i++) {
state[i] = i<<4;
}
for (int i=0; i < maxButtons; i++) {
int index = buttons[i]>>4;
if (digitalRead(i+2) == LOW) {
state[index] = state[index] | buttons[i];
}
}
}
void loop() {
checkButtons();
delay(30);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.send(state, STATE_NSIZE);
}
Finally, an Actionscript class (ControllerInput) for handling the serial input:
package {
import flash.errors.*;
import flash.events.*;
import flash.net.Socket;
public class ControllerInput {
public var state:Array = new Array(32);
private var arduinoSocket:Socket;
private var input:int;
public function ControllerInput() {
for (var i:int=0; i<32; i++) {
state[i]=false;
}
openArduinoSocket();
}
private function openArduinoSocket():void {
//Create a socket connection to serproxy
arduinoSocket = new Socket("localhost",5331);
arduinoSocket.addEventListener(Event.CLOSE, closeHandler);
arduinoSocket.addEventListener(ProgressEvent.SOCKET_DATA, socketDataHandler);
}
private function closeHandler(event:Event):void {
// re-open socket if it gets closed accidentially
openArduinoSocket();
}
private function socketDataHandler(event:ProgressEvent):void {
var base_index:uint;
if (arduinoSocket.bytesAvailable >=6) {
for (var i:int=0; i<6; i++) {
input = arduinoSocket.readByte();
// place byte in state table
base_index = input >>4;
for (var j:int=0;j<0;j++) {
state[base_index+j] = (input >> j) & 0x01;
}
}
}
}
}
}
Puppet Master Final Project Page Updated
Shopbot Project - Modular Shelving
Diploma Completion Checklist Update - 08.14.2010
Unsuccessful Modela Troubleshooting - Partially Successful Switch to Roland Vinyl Cutter
Very Basic Beginner Assembly Tutorial III: How to Use Avrdude
Very Basic Beginner Assembly Tutorial II: How to Use Gavrasm to compile an .asm flie
Very Basic Assembly Tutorial I: Where to Get Gavrasm for the Mac OS
Complete and Working --> Modified Hello Echo + Button + FTDI v.2
Modified Hello Echo + Button + FTDI v.2 ---> In Progress
Modified Hello Echo + Button + FTDI v.1
Mantis Hardware / Software Trial Run
First 3D Scans - Modela Scan of Laughing Die and Shell
Interlocking Rings - 3D Printing
MakerBot Cupcake CNC- Assembling the Plastruder mk4 Spindle
Capacitive Sensing - PuppetMaster v.1-v.2
[Revised] Fab Academy Final Project Proposal: PuppetMaster
FabISB Round 2: Stuffing and Programming the Board
Making Programming, Connector and Serial Cables
Final Project Licencing and Distribution
Internet 0 / Zero - Milling, Stuffing & Setting Up the Boards
Spindle Assembly - Mantis Milling Machine
PuppetMaster Final Project Page
Encoded Building Materials with Computer Numerical Control Assembly
Final Project Plan: PuppetMaster Universal Remote
Final project: pinball machine themed on an unfinished opera by Dylan Thomas and Stravinsky
Electronics design and production
The Fabian: an Arduino-compatible, student-friendly board for Fab Labs
Super simple bootstrap 3-axis controller
Breadboard-friendly Attiny45 board
Using a GUI to Control Processing Output with ControlIP5, Firmata via Serial
My favorite python/GTK reference
Fab ISB - Round 1: Milling Out The Board
Completed TARDIS Cast | Working Light