Fab Academy at AS220 Labs

March 30, 2010 12:45 AM

DIY hobo game controllers

by Shawn Wallace

IMG_0285.jpg

These DIY game controllers are made from pennies and cigar boxes.

IMG_0287.JPG

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:

figure1.png

And these are the services and software that are running on the computer side:

figure2.png

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:

FluxlyBoard.png

and the base unit:

FluxlyBase.png

The SWF application in action:

3_aaafluxly2-thumb-600x600-3468.jpg

3_aaafluxly-1-thumb-600x600-3465.jpg

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;
            }
        } 
     }
    }
  }
}

Return to front

Older articles