Description
We all (most of us) have played the popular game of Pocket Tanks. For those who dont know about it, it’s a two player turn based game where one player controls the velocity and the angle at which his/her tank will shoot so as to land a hit on the opponent’s tank. I thought of an interesting way in which pocket tanks can be played. I used a potentiometer to control the angle of the nozzle and the force sensor to decide the velocity with which one is supposed to hit the other tank. The harder you press on the force sensor , the further the shot goes. I mapped the values of the potentiometer from 0 to 180 and the values of the FSR from 0 to 100.
Materials
- Arduino
- 1 Force Sensitive Resistor (FSR)
- 1 Potentiometer
- 1 10 KΩ resistor
Code
Arduino
const int fsrPin = 0;
const int potPin = 1;
void setup() {
// Still need to set a baud rate, even for USB.
Serial.begin(9600);
// Poteniometer analogue pin is an input.
pinMode(potPin, INPUT);
pinMode(fsrPin, INPUT);
}
void loop() {
int velocity = map(analogRead(fsrPin),0,1023,0,100);
int angle = map(analogRead(potPin),0,1023,0,180);
Serial.print(String(velocity) +'a'+ String(angle)+' ');
delay(50);
}
Processing
//importing processing libraries
import processing.serial.*;
// Change this to the portname your Arduino board
String portname = "COM5"; // or "COM5"
//defining custom font
PFont mono;
//defingin position values for the two tanks
int xpos1, ypos1, xpos2, ypos2, xpos, ypos, distance = 0, angleX, angleY;
int velocity = 50, velocity1 = 50, velocity2 = 50; //saves velocity and angles for each person
int angle = 90, angle1 = 90, angle2 = 90;
int fuel1 = 50, fuel2 = 50, fuel = 50;
int tS = 15; //tank size
float bS = .1; //ball size
boolean player1Turn = true, shoot = false, gameEnd = false, loopOne = true, moveTank = false;
float ballX, ballY;
float vx, vy, grav = 9.8, t = 0;
int win1 = 0, win2 = 0; //counts the wins for each person
int btnMoveRed = 255, btnMoveGreen = 255,btnMoveBlue = 255; //change the color of the move button when clicked
int btnSSR = 255, btnSSG = 255,btnSSB = 255, btnSmallR = 37, btnSmallG = 116,btnSmallB = 169,btnMedB = 255, btnMedR = 255, btnMedG = 255,btnBigB = 255, btnBigR = 255, btnBigG = 255; //change color of gamemode buttons
Serial myPort;
//Built on the base program provided by
/* OpenProcessing Tweak of *@*http://www.openprocessing.org/sketch/374777*@* */
//Jarod Searle
void setup() {
size(1000, 800);
smooth();
do {
xpos1 = int(random(1000));
ypos1 = 600;
xpos2 = int(random(1000));
ypos2 = 600;
distance = abs(xpos2 - xpos1);
} while(distance < 75);
textSize(13);
stroke(0);
mono = createFont("segoeui.ttf",32);
textFont(mono);
// List all the available serial ports:
printArray(Serial.list());
// Open the port you are using at the rate you want:
myPort = new Serial(this, Serial.list()[0], 9600);
//buffering each input till the delimiter for easy read
myPort.bufferUntil(' ');
}
void draw() {
//drawing the various elements in the game
textSize(13);
background(236,236,236);
fill(0);
line(0, 600, 1000, 600);
fill(22, 160, 133);
ellipse(xpos1, ypos1, tS, tS); //player 1 = red
text("Player 1 Color", 50, 650);
text("Fuel: " + fuel1, 50, 670);
text("Player 1 Wins: " + win1, 700, 125);
fill(214,69,65);
ellipse(xpos2, ypos2, tS, tS); //player 2 = blue
text("Player 2 Color", 825, 650);
text("Fuel: " + fuel2, 825, 670);
text("Player 2 Wins: " + win2, 700, 145);
fill(0);
text("Velocity: " + velocity + " m/s", 440, 690);
text("Angle: " + angle + " degrees", 440, 710);
text("Controls: Use the potentiometer to adjust the angle, and the FSR to adject the velocity, Spacebar to shoot", 280, 730);
text("NOTE - to hit the other player, the shot must land within their circle.", 300, 60);
text("This means that the shot can technically go through the upper half of the other player.", 250, 80);
fill(btnMoveRed, btnMoveGreen, btnMoveBlue);
rect(50, 690, 150, 75);
fill(0);
textSize(30);
text("MOVE", 80, 740);
fill(btnSSR, btnSSG, btnSSB);
rect(20, 100, 100, 50);
fill(btnSmallR, btnSmallG, btnSmallB);
rect(140, 100, 100, 50);
fill(btnMedR, btnMedG, btnMedB);
rect(260, 100, 100, 50);
fill(btnBigR, btnBigG, btnBigB);
rect(380, 100, 100, 50);
fill(0);
textSize(13);
text("Super Small", 30, 130);
text("Small", 170, 130);
text("Medium", 285, 130);
text("Big", 420, 130);
if (player1Turn == true) { //Player 1's turn
if (loopOne == true) {
velocity = velocity1; //saves the previous turn's velocity and angle
angle = angle1;
xpos = xpos1;
ypos = ypos1;
fuel = fuel1;
}
loopOne = false;
velocity1 = velocity;
angle1 = angle;
xpos1 = xpos;
ypos1 = ypos;
fuel1 = fuel;
//defining the trajectory
angleX = int(xpos - velocity * cos(angle * (3.14/180))); //velocity * the rest will make the line longer for more power
angleY = int(ypos - velocity * sin(angle * (3.14/180)));
line(xpos, ypos, angleX, angleY);
if (shoot == true) {
loopOne = true;
shot();
textSize(30);
//code to check if the trajectory of the tank shot hits the other tank
if ((ballX >= xpos2 - tS / 2 && ballX <= xpos2 + tS / 2) && (ballY >= ypos2 - tS)) {
text("PLAYER 1 WINS", 350, 300);
gameEnd = true;
fill(255);
rect(420, 350, 100, 50);
fill(0);
text("RESET", 430, 380);
win1 += 1;
}
else {
text("CLICK TO CONTINUE", 350, 300);
player1Turn = false;
noLoop();
}
}
}
else if (player1Turn == false) { //Player 2's turn
if (loopOne == true) {
velocity = velocity2;
angle = angle2;
xpos = xpos2;
ypos = ypos2;
fuel = fuel2;
}
loopOne = false;
velocity2 = velocity;
angle2 = angle;
xpos2 = xpos;
ypos2 = ypos;
fuel2 = fuel;
angleX = int(xpos - velocity * cos(angle * (3.14/180)));
angleY = int(ypos - velocity * sin(angle * (3.14/180)));
line(xpos, ypos, angleX, angleY);
if (shoot == true) {
loopOne = true;
shot();
textSize(30);
//code to check if the trajectory of the tank shot hits the other tank
if ((ballX >= xpos1 - tS / 2 && ballX <= xpos1 + tS / 2) && (ballY >= ypos1 - tS)) {
text("PLAYER 2 WINS", 350, 300);
gameEnd = true;
fill(255);
rect(420, 350, 100, 50);
fill(0);
text("RESET", 430, 380);
win2 += 1;
}
else {
text("CLICK TO CONTINUE", 350, 300);
player1Turn = true;
noLoop();
}
}
}
if (gameEnd == true) {
noLoop();
}
}
void shot() { //will shoot the ball, gets rid of code up above
do {
vx = velocity * cos(angle * (3.14/180));
vy = velocity * sin(angle * (3.14/180));
t += .02;
ballX = xpos -(vx * t);
ballY = ypos -(vy * t - (grav/2)*t*t);
fill(0);
ellipse(ballX, ballY, bS, bS);
} while (!(ballY > 600));
}
void resetButtons() {
btnSSR = 255;
btnSSG = 255;
btnSSB = 255;
btnSmallR = 255;
btnSmallG = 255;
btnSmallB = 255;
btnMedR = 255;
btnMedG = 255;
btnMedB = 255;
btnBigR = 255;
btnBigG = 255;
btnBigB = 255;
}
// called whenever serial data arrives
void serialEvent(Serial p) {
while (myPort.available() > 0) {
//reading the buffer until ' ' which is the delimiter
String inString = myPort.readStringUntil(' ');
//the two values of the sensors are separated by 'a'
String nums[] = inString.split("a");
velocity = int(nums[0]);
nums[1] = trim(nums[1]);
angle = int(nums[1]);
printArray(nums);
}
}
void keyPressed() {
if (key == CODED) {
if (keyCode == RIGHT) {
if (moveTank == true && fuel > 0) {
xpos += 1;
fuel -= 1;
}
}
else if (keyCode == LEFT) {
if (moveTank == true && fuel > 0) {
xpos -= 1;
fuel -= 1;
}
}
}
else if (keyCode == ' ')
shoot = true;
}
void mousePressed() {
if (shoot == true && gameEnd == false) {
shoot = false;
t = 0;
moveTank = false;
loop();
btnMoveGreen = 255;
btnMoveRed = 255;
btnMoveBlue = 255;
}
else if (gameEnd == true) {
if (mouseX >= 420 && mouseX <= 520 && mouseY >= 350 && mouseY <= 400) {
do {
xpos1 = int(random(1000));
xpos2 = int(random(1000));
distance = abs(xpos2 - xpos1);
} while(distance < 75);
angle1 = 90;
angle2 = 90;
velocity1 = 50;
velocity2 = 50;
fuel1 = 50;
fuel2 = 50;
textSize(13);
shoot = false;
gameEnd = false;
loopOne = true;
t = 0;
if (win1 > win2)
player1Turn = false;
else if (win2 > win1)
player1Turn = true;
else {
int x = int(random(2));
if (x == 1)
player1Turn = true;
else
player1Turn = false;
}
loop();
}
}
else if (mouseX >= 50 && mouseX <= 200 && mouseY >= 690 && mouseY <= 765) { //move button
if (moveTank == false) {
moveTank = true;
btnMoveGreen = 116;
btnMoveRed = 37;
btnMoveBlue = 169;
}
else {
moveTank = false;
btnMoveGreen = 255;
btnMoveRed = 255;
btnMoveBlue = 255;
}
}
else if (mouseX >= 20 && mouseX <= 120 && mouseY >= 100 && mouseY <= 150) { //super small
resetButtons();
btnSSR = 37;
btnSSG = 116;
btnSSB = 169;
tS = 5;
}
else if (mouseX >= 140 && mouseX <= 240 && mouseY >= 100 && mouseY <= 150) {
resetButtons();
btnSmallR = 37;
btnSmallG = 116;
btnSmallB = 169;
tS = 15;
}
else if (mouseX >= 260 && mouseX <= 360 && mouseY >= 100 && mouseY <= 150) {
resetButtons();
btnMedR = 37;
btnMedG = 116;
btnMedB = 169;
tS = 100;
}
else if (mouseX >= 380 && mouseX <= 480 && mouseY >= 100 && mouseY <= 150) {
resetButtons();
btnBigR = 37;
btnBigG = 116;
btnBigB = 169;
tS = 200;
}
}