Extra Arduino Game

Assignment:

This week we were given the option of creating a game with the Arduino and I decided to continue with my favorite Processing game thus far, my F1 simulator. I wanted to make a controller that would be integrated into the game.

 

Game Controller:

There are three main inputs in a car (a simplified automatic one anyways), steering, gas, and acceleration. My game already had these inputs but steering was in essence binary (full left, neutral, full right). I decided that analog input could make for much more fun steering and in addition to gas/brake buttons I could make a F1 car controller.

For the steering I used the potentiometer. I had to rework all my code for how the car was steered as it was no longer left or right, but rather any value from full left to full right and anywhere in-between. I ended up checking which way the potentiometer was facing and mapping the annual acceleration of the car off of this.

I also added a brake and gas button. These were super easy to implement as they behaved exactly the same as if I was pressing the up or down arrow in the keyboard controls so all I had to was change to binary values if they were on or off.

Finally I wanted something a bit extra than just inputs, also outputs that could make the player feel more like they were in a car. I decided to add two LEDs, a green one that would light up when pressing the gas, and a red one that would light up when braking, or flash when the car crashed like hazard lights. This allowed me to try the no delay blinking code as well.

Circuit

Code

Arduino Code

const int brakeLed = 5;
const int forwardLed = 4;
const int forwardButton = 2;
const int brakeButton = 3;
const int sensorPin = A0;

int forward = 0;
int brake = 0;
int crash = 0;
long timer = 0;
int timerLength = 500;
bool onOff = false;

void setup() {
  Serial.begin(9600);
  Serial.println("0,0");
  pinMode(brakeLed, OUTPUT);
  pinMode(forwardLed, OUTPUT);
  pinMode(forwardButton, INPUT);
  pinMode(brakeButton, INPUT);
}

void loop() {
  while (Serial.available()) {
    forward = Serial.parseInt();
    brake = Serial.parseInt();
    crash = Serial.parseInt();
    if (Serial.read() == '\n') {
      if (crash) {
        if (millis() > timer) {
          onOff = !onOff;
          digitalWrite(brakeLed, onOff);
        digitalWrite(forwardLed, LOW);
          timer = millis() + timerLength;
        }
      }
      else{
        digitalWrite(forwardLed, forward);
        digitalWrite(brakeLed, brake);
      }
      int forwardToggle = digitalRead(forwardButton);
      delay(1);
      int brakeToggle = digitalRead(brakeButton);
      delay(1);
      int steeringInput = analogRead(sensorPin);
      delay(1);
      Serial.print(forwardToggle);
      Serial.print(',');
      Serial.print(brakeToggle);
      Serial.print(',');
      Serial.println(steeringInput);
    }
  }
}

Processing Code

import processing.sound.*;

//======= Global variables ========
int gameMode = 0; //0 is main menu, 1 select your car, 2 running game, 3 crash, 4 controls menu, 5 credits
Team teams[] = new Team[10];
int teamSelector = 0;  //Which team from array is selected
int[][] teamDict = {{7, 0, 7, 0, 0}, {8, 1, 8, 0, 1}, {5, 2, 5, 0, 2}, {4, 3, 4, 0, 3}, {0, 4, 0, 0, 4}, {2, 5, 2, 1, 0}, {1, 6, 1, 1, 1}, {6, 7, 6, 1, 2}, {9, 8, 9, 1, 3}, {3, 9, 3, 1, 4}}; //Dictonary containing index of car sprite, associated team image sprite index, team name index, menu row, menu col

//====== Team Selection Menu Variables
PImage teamMenuImg;


//====== Trak Menu Variables
//  PImage track[][] = new PImage[10][10];  //For tile system
//float tileWidth = 2560;  //For tile system
PImage map;
float trackScale = 1; //What percent of original size should track be drawn

//====== Main Game Variables
float rotation = PI;  //Current angle
float speed = 0;  //Current speed
float maxSpeed = 500;  //Max speed on the track
float sandMaxSpeed = 20;  //Max speed off the track
float posX = -4886.6123;  //0,0 is top left of track , values increase negative as they are reversed
float posY = -1254.3951;

float acceleration = 5;  //How fast the car speeds up on track
float sandAcceleration = 1;  //How fast the car speeds up in sand
float brakeDeacceleration = 10;  //How quick the car stops when braking on track
float coastDeacceleration = 2;  //How quick the car stops when no power
float sandDeacceleration = 15;  //How quick the car stops in sand
float angularAcceleration = PI/20;  //How fast the car turns
boolean reverse = false;

float carScale = 0.3; //What percent of original size should car be drawn

//Keyboard inputs
boolean forward = false;
boolean brake = false;
boolean left = false;
boolean right = false;

//Sound
SoundFile accSound;
float accSoundAmp = 0;
float soundRate = 0.5;

//Timing
int passedTime;  //How long has passed since saved time mark
int savedTime;  //Savea time to start timer
boolean activeTimer = false; //Set to false, becomes active when crossing start line or false if reversed over
int bestTime = -1;

//Menu files
PImage controls;
PImage credits;

//Main menu variables  
  int numButtons = 3;
  int activeButton = 0; // 0 for start, 1 for controls, 2 for credits
  int buttonWidth = 200;
  int buttonHeight = 100;
  int buttonSpacing = 50;
  int buttonYOffset = 100;
  String buttonContent[] = {"Start Game","Controls","Credits"};
  float buttonX;
  float buttonY;
  
//Arduino game control variables
import processing.serial.*;
Serial myPort;
boolean crash = false;

void setup() {
  fullScreen();

  //Set up the team array
  //=======================================================================================
  PImage[] carSprites;
  PImage[] teamSprites;
  String[] nameArray = {"McLaren F1 Team", 
    "Scuderia AlphaTauri Honda", 
    "Mercedes-AMG Petronas F1 Team", 
    "ROKiT Williams Racing", 
    "Haas F1 Team", 
    "BWT Racing Point F1 Team", 
    "Scuderia Ferrari", 
    "Alfa Romeo Racing ORLEN", 
    "Aston Martin Red Bull Racing", 
    "Renault F1 Team"
  };
  //Alfa Romeo, Red Bull, Racing Point, Haas, Mclaren, Mercedes, AlphaTauri, Ferrari, Renault, Williams

  //Set sprite sheets
  carSprites = getCarSpriteSheet("SpriteSheetCars.png");  //Load the car sprite sheet into sprites
  teamSprites = getTeamSpriteSheet("Teams.png");  //Load the team sprite sheet into sprites

  //Set teams array with appropiate info
  for (int i = 0; i < 10; i++) {
    Team newTeam = new Team();
    newTeam.setName(nameArray[teamDict[i][2]]);  //Set team name
    newTeam.setCarImg(carSprites[teamDict[i][0]]);  //Set team img
    newTeam.setTeamImg(teamSprites[teamDict[i][1]]);  //Set team car img
    teams[i] = newTeam;
  }

  //=======================================================================================

  //Load menu imgs
  teamMenuImg = loadImage("Teams.png");
  controls = loadImage("Controls.png");
  credits = loadImage("Credits.png");

  //=======================================================================================

  //Load map
  map = loadImage("Track.png");

  //=======================================================================================
  //Load sound
  accSound = new SoundFile(this, "acc.wav");
  accSound.loop();
  accSound.amp(accSoundAmp);
  accSound.rate(soundRate);
  
  //Start lap timer
  savedTime = millis();
  
  //Start serial communication with controller
  String portname=Serial.list()[1];
  myPort = new Serial(this,portname,9600);
  myPort.clear();
  myPort.bufferUntil('\n');
}

void draw() {
  //Main Gamemode Control selector
  switch(gameMode) {
  case 0:
    mainMenu();
    break;
  case 1:
    teamMenu();
    break;
  case 2:
    runGame();
    break;
  case 3:
    crash();
    break;
  case 4:
    controls();
    break;
  case 5:
    credits();
    break;
  }
}


//When all game cariables need to be reset to start status
void resetVariables(){
  accSound.amp(0);
  forward = brake = right = left = false;
  activeTimer = false;
  speed = 0;
  gameMode = 0;
  posX = -4886.6123;  //0,0 is top left of track , values increase negative as they are reversed
  posY = -1254.3951;
  rotation = PI;
  crash = false;
}


void serialEvent(Serial myPort){
  String s=myPort.readStringUntil('\n');
  s=trim(s);
  if (s!=null){
    println(s);
    int values[]=int(split(s,','));
    if (values.length==3){
      if(values[0] == 1 && values[1] == 1){
        forward = false;
        brake = false;
      }
      else if (values[0] == 1){
        forward = true;
      }
      else if (values[1] == 1){
        brake = true;
      }
      else if (values[0] == 0 && values[1] == 0){
        forward = false;
        brake = false;
      }
      
      
      int steering = values[2];
      //Turn left
      if(steering > 1023/2){
        left = true;
        right = false;
        angularAcceleration = map(values[2],1023/2,1023,0, PI/20);
      }
      else if(steering < 1023/2){
        left = false;
        right = true;
        angularAcceleration = map(values[2],1023/2,0,0, PI/20);
      }
    }
  }
  println(crash);
  myPort.write(int(forward)+","+int(brake)+","+int(crash)+"\n");
}

 

Results

Leave a Reply