For this week project I took inspiration from my one of my previous weekly assignments where I made a device where a user could record a Morse code message and could play it back.
One issue with that project is that a user must know Morse code first. I personally don’t know Morse code but I find the idea to be pretty cool.
For my assignment this week I made a setup where you could interact with processing via the buttons on the breadboard to input a dashes and dot and you could press enter to check if your input was correct.
The user would press the blue button to input a dot and the yellow button to input a dash. The corresponding would be displayed on the processing window. Once the user is satisfied with the input they can press the red button to check if the input is correct. If the input is correct a green light would flash on the breadboard, if not a red light would flash. Once the enter button is pressed a new letter is displayed and the input is cleared.
int led1 = 3;
int led2 = 2;
int enter = 8;
int dot = 9;
int dash = 10;
int buttonDelay = 400;
int wrong = 7;
int correct = 6;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(led1,OUTPUT);
pinMode(led2,OUTPUT);
pinMode(enter,INPUT);
pinMode(dot,INPUT);
pinMode(dash,INPUT);
pinMode(wrong,OUTPUT);
pinMode(correct,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
if (digitalRead(dot)==1){
// send a 1 to processing
Serial.write(1);
digitalWrite(led1,HIGH);
delay(buttonDelay);
digitalWrite(led1,LOW);
}
else if(digitalRead(dash)==1){
// send a 2 to processing
Serial.write(2);
digitalWrite(led1,HIGH);
digitalWrite(led2,HIGH);
delay(buttonDelay);
digitalWrite(led1,LOW);
digitalWrite(led2,LOW);
}
else if(digitalRead(enter)==1){
Serial.write(3);
delay(buttonDelay);
}
if (Serial.available()>0){
int data = Serial.read();
if (data == 100){
digitalWrite(wrong,HIGH);
delay(100);
digitalWrite(wrong,LOW);
} else if(data == 101){
digitalWrite(correct,HIGH);
delay(100);
digitalWrite(correct,LOW);
}
}
}
/*
* 1 for dot
* 2 for dash
* 3 for enter
*/
Every room in the dollhouse will have a variety of either physical interactions (lights, sounds), virtual tasks (that will be displayed on the computer), or a mixture of both. The goal of the game is to be able to interact with the dollhouse, but also to finish all the tasks set in place. The user will be able to complete the tasks on processing and this will be reflected on the dollhouse. We would also like to integrate a display on the dollhouse to display the progress as well display a message when the game is won.
When I was thinking about what to make for this week’s assignment I was came across a clip from The Big Bang Theory where Sheldon was playing the Theremin.
I theremin is the musical instrument that makes sound based on how electromagnetic fields produced by two antennae are altered by the hand movements between the two.
To mimic this I initially tried to use a Ultrasonic sensor to alter the sound. While this worked it only altered the sound based on the distance of the object[hand] from the sensor, the sound was altered based on only one direction.
I then used a LDR to do the same thing. This allowed me to change the sound by moving a light source around the LDR. This allowed me control the sounds by movement of the light source both horizontally and vertically.
I also added a button that multiplies the value of the photoresistor by 2 when pushed once and then the function gets disabled when pushed again. This yields a siren like effect when the button is repeatedly pushed.
For this week project I took inspiration from the problem that a lot of people face while parking. This being that it can be really difficult to park close to a wall especially for new drivers. Newer cars are often fitted parking sensors which makes beeping sounds to alert the drivers about there distance from an object. Older cars however do not have this feature so it can often be a challenge to park cars especially for newer drivers.
For my adaptation of the parking sensor I used an ultrasonic sensor to the determine the distance of the sensor to an object in front of it. Then using the equation of a line I determine the rate at which the led should blink. The led will blink with an interval of 800ms if the object is more than 25cm away or it will blink with an interval of 100ms if the object is less than 5cm away. The interval between 5cm and 25cm will be calculated using the equation of the line given below:
interval = 35*distance -75
A button can be used to put the device in parking mode. When the device goes into parking mode the ultrasonic sensor is activated and sound waves are emitted. The time taken for these sound waves to come back determines the distance. The distance is then used to calculate the interval.
// echo produces a pulse when reflected signal is received
// the reflected signal is the one that is sent by the trig pin
int trigPin = 10;
int echoPin = 9;
int statusLedPin = 2;
int prevState = LOW;
int button = 4;
int warningPin = 5;
float distance = 10;
bool parking = false;
int delayMS = 0;
int interval = 500;
unsigned long prevTime = 0;
int warningState = LOW;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(statusLedPin, OUTPUT);
pinMode(button, INPUT);
pinMode(warningPin, OUTPUT);
}
void loop() {
changeState();
parkingState();
if (parking) {
distance = getDistance();
calculateDelay();
blinkLed();
// Serial.println(delayMS);
}
if (!parking && warningState == HIGH) {
warningState = LOW;
digitalWrite(warningPin, warningState);
}
}
float getDistance() {
digitalWrite(trigPin, LOW); // no signal is sent
delayMicroseconds(2);
digitalWrite(trigPin, HIGH); // after 2ms a signal is sent
delayMicroseconds(10);
digitalWrite(trigPin, LOW); // signal is not sent after 10 ms
// read the time taken for the pulse to return
float duration = pulseIn(echoPin, HIGH);
// calculate the distance
return duration * 0.034 / 2;
}
void changeState() {
if (digitalRead(button) == HIGH && prevState == LOW) {
// if (parking) {
// parking = false;
// } else if (!parking) {
// parking = true;
// }
//refactor
parking = !parking;
}
prevState = digitalRead(button);
}
void parkingState() {
if (parking) {
digitalWrite(statusLedPin, HIGH);
// digitalWrite(warningPin, LOW);
} else if (!parking) {
digitalWrite(statusLedPin, LOW);
// digitalWrite(warningPin, HIGH);
}
}
void calculateDelay() {
if (distance >= 5 && distance <= 25) {
delayMS = (int) 35 * distance - 75;
} else if (distance < 5) {
delayMS = 100;
} else if (distance > 25) {
delayMS = 800;
}
}
void blinkLed() {
Serial.println("calling");
unsigned long currTime = millis();
if (currTime - prevTime >= delayMS) {
prevTime = currTime;
if (warningState == LOW) {
warningState = HIGH;
} else {
warningState = LOW;
}
digitalWrite(warningPin, warningState);
}
}
For my project this week, I decided to make a communication system using a series of LEDs and buttons and the ability for you to record your own message in
…
wait for it
….
MORSE CODE
and then play it back as many times as you’d like.
When the Arduino first starts up, the Arduino will flash SOS denoted by:
…—…
and then will wait for actions.
You can record your own message by pressing the blue button. When red led lights up it means that it will record a message when you push buttons. When you push the red button it will flash two green leds and will record a dash, when you push the yellow button it will flash one green led and will record a dot.
You can stop the recording by pushing the blue button, the red led will turn off.
You can play back the message that you just recorded pushing the green button. This will turn on the blue led indicating that you are now in playback mode and will flash the message you just recorded.
You can push the green button as many times as you want to playback the record message.
// use static array to store the recorded codes
int message[500];
int messageSize = 0;
int sos[9] = {0, 0, 0, 1, 1, 1, 0, 0, 0};
int playSos = true;
//pins
int dashPin = 12;
int dotPin = 11;
int recordStopPin = 10;
int playPin = 9;
//one led is dot
//two leds are dash
int led1Pin = 3;
int led2Pin = 2;
int recordPin = 4;
int playingLedPin = 5;
//flags
bool record = false;
bool isPlaying = false;
void setup() {
Serial.begin(9600);
pinMode(dashPin, INPUT);
pinMode(dotPin, INPUT);
pinMode(recordStopPin, INPUT);
pinMode(playPin, INPUT);
pinMode(led1Pin, OUTPUT);
pinMode(led2Pin, OUTPUT);
pinMode(recordPin, OUTPUT);
pinMode(playingLedPin, OUTPUT);
// play(sos, 9);/
}
void loop() {
readPin();
if (record) {
digitalWrite(recordPin, HIGH);
} else {
digitalWrite(recordPin, LOW);
}
if (isPlaying) {
digitalWrite(playingLedPin, HIGH);
play(message, messageSize);
} else {
digitalWrite(playingLedPin, LOW);
}
if (playSos) {
play(sos, 9);
playSos = false;
}
}
// register a dash
void registerDash() {
addDigit(1);
}
// register a dot
void registerDot() {
addDigit(0);
}
// add the digit to the array
void addDigit(int add) {
message[messageSize] = add;
Serial.println(message[messageSize]);
messageSize++;
}
//
void readPin() {
if (digitalRead(dashPin) == HIGH && !isPlaying) {
if (record) {
registerDash();
}
digitalWrite(led1Pin, HIGH);
digitalWrite(led2Pin, HIGH);
delay(500);
digitalWrite(led1Pin, LOW);
digitalWrite(led2Pin, LOW);
}
if (digitalRead(dotPin) == HIGH && !isPlaying) {
if (record) {
registerDot();
}
digitalWrite(led1Pin, HIGH);
delay(500);
digitalWrite(led1Pin, LOW);
}
if (digitalRead(recordStopPin) == HIGH && !isPlaying) { //set recording state
Serial.println("record/stop");
record = !record;
delay(500);
}
if (digitalRead(playPin) == HIGH && !record) {
Serial.println("play");
isPlaying = !isPlaying;
delay(500);
}
}
int play(int arr[], int arrSize) {
for (int i = 0; i < arrSize; i++) {
if (arr[i] == 1) {
digitalWrite(led1Pin, HIGH);
digitalWrite(led2Pin, HIGH);
delay(500);
digitalWrite(led1Pin, LOW);
digitalWrite(led2Pin, LOW);
}
if (arr[i] == 0) {
digitalWrite(led1Pin, HIGH);
delay(500);
digitalWrite(led1Pin, LOW);
}
delay(500);
}
isPlaying = false;
return 0;
}
//notes
// -1 is invalid
// 0 is a dot
// 1 is a dash
// first button is for registering a dash
// second button is for registering a dot
// third button is to record
// forth button is to play the saved recording
From my last about the midterm until now, time for submission I had to change a few things. The biggest change was how the game would operate. Initially the plan was to have the shooter in the middle of the screen and have a pointer that would change location based on the location of the mouse in the window, however I changed this to have the shooter moving from side to side as a not to have the user/player switch between the mouse and the keyboard for now the player can play the entirely from the keyboard.
Objective of the game
Try to get as many points as possible while keeping the number of cases as low as possible within 2 minutes/
Game Operation
The keys used for the operation of the game are:
1,2,3,m, space bar and the left and right arrow keys.
The space bar will shoot the fighting tool that is currently selected, this can seen in the shooter icon. Keys 1,2 and 3 can be used to switch between the fighting tools when you’re in “fight” mode. Keys 1,2 and 3 can be used to buy more fighting tools when you are in buy mode. You can switch modes by pressing the m button.
The difference between the fighting tool is number of points you get when you shoot the virus down and the speed of the fighting tool.
Speed of Handwash < Speed of face mask < Speed of face shield.
Shooting the virus down with a handwash will get you 1 points, shooting it down with facemask will get you 3 points and the shield will get you 5 points.
You can use the points to buy more tools. Buying more handwash will cost 1 point, face masks cost 2 points/mask, and face shields cost 3 points/shield.
The number of cases will go up if the virus goes below the window.
import processing.sound.*;
//create new game
Game game;
// arrayList to store corona virus images
ArrayList <CoronaVirus> coronaList;
ArrayList <Fighter> activeFighters;
//sound files
SoundFile error;
SoundFile scaryBg;
SoundFile collision;
SoundFile newCase;
//image
PImage virus;
// misc vars
String errorMessage = "";
void setup() {
size(1280, 720);
game = new Game(); //init game
coronaList = new ArrayList<CoronaVirus>(0);
activeFighters = new ArrayList<Fighter>(0);
for (int i=0; i<4; i++) {
coronaList.add(new CoronaVirus());
}
virus = loadImage("virus.png");
error = new SoundFile(this, "error.mp3");
scaryBg = new SoundFile(this, "scaryBg.mp3");
collision = new SoundFile(this, "collide.mp3");
newCase = new SoundFile(this, "dead.mp3");
}
void draw() {
if (game.state==-2) {
startScreen();
}
else if (game.state==0 || game.state==1) {
background(211, 211, 211); // clear background to avoid trails
game.drawGameStats(); // show the game statistics
game.shooter(); // draw the shooter
displayError(); //display error messages
displayCost(); // display cost of buying
playBGMusic(); // play background music
updateCorona(); // update the position and display the virus
moveFighters(); //move the fighting tools on the screen
checkCollisions(); //check for collision
checkCoronaPosition(); // check for off screen viruses
checkFighterPosition(); // check for off screen fighting tool
newViruses(); // generate new viruses
game.moveShooter(); // move the shooter
game.updateTime(); // countdown time
}
else if (game.state==-1) {
gameOver();
}
}
import processing.sound.*;
//create new game
Game game;
// arrayList to store corona virus images
ArrayList <CoronaVirus> coronaList;
ArrayList <Fighter> activeFighters;
//sound files
SoundFile error;
SoundFile scaryBg;
SoundFile collision;
SoundFile newCase;
//image
PImage virus;
// misc vars
String errorMessage = "";
void setup() {
size(1280, 720);
game = new Game(); //init game
coronaList = new ArrayList<CoronaVirus>(0);
activeFighters = new ArrayList<Fighter>(0);
for (int i=0; i<4; i++) {
coronaList.add(new CoronaVirus());
}
virus = loadImage("virus.png");
error = new SoundFile(this, "error.mp3");
scaryBg = new SoundFile(this, "scaryBg.mp3");
collision = new SoundFile(this, "collide.mp3");
newCase = new SoundFile(this, "dead.mp3");
}
void draw() {
if (game.state==-2) {
startScreen();
}
else if (game.state==0 || game.state==1) {
background(211, 211, 211); // clear background to avoid trails
game.drawGameStats(); // show the game statistics
game.shooter(); // draw the shooter
displayError(); //display error messages
displayCost(); // display cost of buying
playBGMusic(); // play background music
updateCorona(); // update the position and display the virus
moveFighters(); //move the fighting tools on the screen
checkCollisions(); //check for collision
checkCoronaPosition(); // check for off screen viruses
checkFighterPosition(); // check for off screen fighting tool
newViruses(); // generate new viruses
game.moveShooter(); // move the shooter
game.updateTime(); // countdown time
}
else if (game.state==-1) {
gameOver();
}
}
class Fighter {
int type = -1; // 0 is handwash, 1 is mask, 2 is shield
int speed = -1;
int positionX = -1;
int positionY = -1;
PImage img;
//methods
//update position
void updatePosition() {
positionY -= speed;
showFighter();
}
void fighterImage() {
//println(type);
switch(type) {
case 0:
{ // handwash
img = loadImage("handwash.png");
speed = 3;
break;
}
case 1:
{ // facemask
img = loadImage("mask.png");
speed = 5;
break;
}
case 2:
{ // faceshield
img = loadImage("shield.png");
speed = 7;
break;
}
}
}
void showFighter() {
image(img, positionX, positionY, 30, 30);
}
}
class Game {
// attributes
int points = 0;
int cases = 0;
int state = -2; // 0->shooting | 1-> buying | -1 -> gameOver | -2-> game not started
int fightingTool = 0; // 0-handwash, 1-mask, 2-shield
int time = 120;
PImage maskImg = loadImage("mask.png");
PImage handwashImg = loadImage("handwash.png");
PImage shieldImg = loadImage("shield.png");
int timeDisplay = 0;
int shooterPosition = width/2;
int shooterDirection = 0;
float shooterSpeed = 2;
// fighting tools
// handwash attr
int handwash = 20;
// facemask attr
int masks = 14;
// faceshield attr
int shields = 6;
//methods
void incrementPoints(int type) {
if (type == 0) {
points += 1;
} else if (type == 1) {
points += 3;
} else if (type == 2) {
points += 5;
}
}
void incrementCases() {
cases+=1;
}
void incrementMasks() {
masks+=1;
}
void decrementMasks() {
masks-=1;
}
void incrementShields() {
shields+=1;
}
void decrementShields() {
shields-=1;
}
void incrementHandwash() {
handwash+=1;
}
void decrementHandwash() {
handwash-=1;
}
void decrementFighters(){
switch(fightingTool){
case 0:{
decrementHandwash();
break;
}
case 1:{
decrementMasks();
break;
}
case 2:{
decrementShields();
break;
}
}
}
void changeState() {
//println("changing state");
if (state==0) {
state=1;
} else if (state==1) {
state=0;
}
}
void updateTime() {
if (time==0) {
state=-1;
}
if (frameCount%60==0 && state!=-1) {
time-=1;
if (timeDisplay==0) {
timeDisplay = 1;
} else if (timeDisplay==1) {
timeDisplay=0;
}
}
if (points==0 && handwash==0 && masks==0 && shields==0){
state=-1;
}
}
void drawGameStats() {
textSize(12);
color(0, 0, 0);
imageMode(CENTER);
pushStyle();
//draw handwash
image(handwashImg, 70, 30, 30, 30); //150,30,30,30
text(handwash+" x", 25, 30);//110,30
// draw mask
image(maskImg, 150, 30, 30, 30);
text(masks+" x", 110, 30);
// draw faceshield
image(shieldImg, 230, 30, 30, 30);
text(shields+" x", 190, 30);
popStyle();
//display time
pushStyle();
textSize(30);
if (timeDisplay==1) {
fill(0, 0, 0);
text(time, width-100, height-30);
} else if (timeDisplay==0) {
fill(255, 255, 0);
text(time, width-100, height-30);
}
popStyle();
// game mode
pushStyle();
int rectWidth = 100;
int rectHeight = 30;
int cornerRadius = 10;
noFill();
rect(width/2-rectWidth/2, 20, rectWidth, rectHeight, cornerRadius, cornerRadius, cornerRadius, cornerRadius);
if (state==0) {
pushStyle();
textAlign(CENTER);
textSize(25);
fill(255, 255, 0);
text("FIGHT", width/2, 45);
popStyle();
} else if (state==1) { //display buy
pushStyle();
textAlign(CENTER);
textSize(25);
fill(0, 255, 0);
text("BUY", width/2, 45);
popStyle();
} else if (state==-1) { //display gameover
pushStyle();
textAlign(CENTER);
textSize(18);
fill(255, 0, 0);
text("Game Over", width/2, 43);
popStyle();
}
popStyle();
//display points
pushStyle();
fill(0, 0, 0);
textSize(25);
text(points+" points", width-300, 45);
text(cases+" cases", width-150, 45);
popStyle();
}
void drawFightingTool(int x, int y, int imgWidth, int imgHeight) {
pushStyle();
imageMode(CENTER);
if (fightingTool==0) { // draw handwash
image(handwashImg, x, y, imgWidth, imgHeight);
} else if (fightingTool == 1) { //draw mask
image(maskImg, x, y, imgWidth, imgHeight);
} else if (fightingTool == 2) { //draw shield
image(shieldImg, x, y, imgWidth, imgHeight);
}
popStyle();
}
void changeFightingTool(int tool) {
fightingTool = tool;
//println(fightingTool);
}
void shooter() {
pushStyle();
fill(255, 255, 255);
circle(shooterPosition, height, 100);
game.drawFightingTool(shooterPosition, height-20, 40, 40);
popStyle();
}
void moveShooter() {
if (shooterSpeed<=2) {
shooterDirection=0;
shooterSpeed=2.1;
}
if (shooterSpeed>2) {
shooterPosition += shooterDirection*shooterSpeed;
}
}
}
// to interact with game
void keyPressed() {
//println(keyCode);
switch(keyCode) {
case 32:
{ // space bar pressed need to create a new fighter add to list and reduce the number from game class
if (game.fightingTool==0 && game.handwash>0) {//check number of handwash
Fighter tempFighter = new Fighter();
tempFighter.type = game.fightingTool;
tempFighter.positionX = game.shooterPosition;
tempFighter.positionY = height-30;
tempFighter.fighterImage();
activeFighters.add(tempFighter);
game.decrementFighters();
} else if (game.fightingTool==1 && game.masks>0) {//check number of masks
Fighter tempFighter = new Fighter();
tempFighter.type = game.fightingTool;
tempFighter.positionX = game.shooterPosition;
tempFighter.positionY = height-30;
tempFighter.fighterImage();
activeFighters.add(tempFighter);
game.decrementFighters();
} else if (game.fightingTool==2 && game.shields>0) {//check number of shields
Fighter tempFighter = new Fighter();
tempFighter.type = game.fightingTool;
tempFighter.positionX = game.shooterPosition;
tempFighter.positionY = height-30;
tempFighter.fighterImage();
activeFighters.add(tempFighter);
game.decrementFighters();
}
break;
}
case 37:
{ //move left
game.shooterDirection = -1;
if (game.shooterSpeed<10) {
game.shooterSpeed*=1.1;
}
break;
}
case 39:
{ //move right
game.shooterDirection = 1;
if (game.shooterSpeed<10) {
game.shooterSpeed*=1.1;
}
break;
}
case 49:
{ //handwash
if (game.state==0) {
game.changeFightingTool(0);
} else if (game.state==1) { //buy more handwash
if (game.points>=1) { //check if you have enough points
game.points-=1;
game.handwash+=1;
} else {
triggerErrorSound();
errorMessage = "Not Enough Points";
}
}
break;
}
case 50:
{ //facemask
if (game.state==0) {
game.changeFightingTool(1);
} else if (game.state==1) { //buy more masks
if (game.points>=2) { //check if you have enough points
game.points-=2;
game.masks+=1;
} else {
triggerErrorSound();
errorMessage = "Not Enough Points";
}
}
break;
}
case 51:
{ //faceshield
if (game.state==0) {
game.changeFightingTool(2);
} else if (game.state==1) { //buy more handwash
if (game.points>=3) { //check if you have enough points
game.points-=3;
game.shields+=1;
} else {
triggerErrorSound();
errorMessage = "Not Enough Points";
}
}
break;
}
case 77:
{
game.changeState();
break;
}
default:
{
triggerErrorSound();
errorMessage = "Invalid Control";
break;
}
}
}
void keyReleased() {
if (keyCode==37 || keyCode==39) {
game.shooterSpeed = 0.8;
}
}
void flashMessage(String msg, color c, int size, int hOffset) {
pushStyle();
fill(c);
textSize(size);
text(msg, 10, height-hOffset);
popStyle();
}
void triggerErrorSound() {
if (!error.isPlaying()) {
error.play();
}
}
void updateCorona() {
for (int i=0; i<coronaList.size(); i++) {
coronaList.get(i).updatePosition(height);
coronaList.get(i).dispVirus();
}
}
void displayError() {
if (error.isPlaying()) // // display error message
{
color errorColor = color(255, 0, 0); // color of error message
flashMessage(errorMessage, errorColor, 15, 25); // display error message
}
}
void displayCost() {
if (game.state==1) { // display cost of buying more items
String msg = "Handwash 1 Facemask 2 Faceshield 3"; // message string
color c = color(53, 50, 56); // color of message
flashMessage(msg, c, 18, 10); // display message
}
}
void playBGMusic() {
if (!scaryBg.isPlaying()) { // play bgMusic
scaryBg.play();
}
}
void moveFighters() {
//activeFighters
for (int i=0; i<activeFighters.size(); i++) {
activeFighters.get(i).updatePosition();
}
}
void checkCollisions() {
//println("checking collision");
// two for loops. Check as virus against each fighter
// if collision rem both fighter and virus from arraylist
// increment point accordingly
// if fighter above screen remove from array list
// if virus below screen increment cases and rem from arraylist
for (int i=0; i<coronaList.size(); i++) {
println(coronaList.size());
CoronaVirus tC = coronaList.get(i);
int size = tC.size;
//println(size);
for (int j=0; j<activeFighters.size(); j++) {
Fighter tF = activeFighters.get(j);
if (tF.positionX>tC.positionX && tF.positionX<tC.positionX+size) { // this mean the fighter is within the image
if (tF.positionY>tC.positionY && tF.positionY<tC.positionY+size) { // this means the fighter is within the image
coronaList.remove(i);
activeFighters.remove(j);
game.incrementPoints(tF.type);
if (!collision.isPlaying()){
collision.play();
}
game.points+=1;
}
}
}
}
}
void checkCoronaPosition(){
for(int i=0;i<coronaList.size();i++){
CoronaVirus tC = coronaList.get(i);
if (tC.positionY>height){
game.cases+=1;
if(!newCase.isPlaying()){
newCase.play();
}
coronaList.remove(i);
}
}
}
void checkFighterPosition(){
for(int i=0;i<activeFighters.size();i++){
Fighter tF = activeFighters.get(i);
if (tF.positionY<0){
activeFighters.remove(i);
}
}
}
void newViruses(){
if (frameCount%7==0 && frameCount%9==0 && frameCount%4==0){
coronaList.add(new CoronaVirus());
}
}
void gameOver(){
// this should display the previous game stats
background(110,125,171);
int size = 50;
pushStyle();
textSize(24);
int moveItemsHorizontal = 100;
image(game.handwashImg,width/2-120+moveItemsHorizontal,height/2-240,size,size);
text(game.handwash,width/2-80+moveItemsHorizontal,height/2-230);
image(game.maskImg,width/2-120+moveItemsHorizontal,height/2-160,size,size);
text(game.masks,width/2-80+moveItemsHorizontal,height/2-150);
image(game.shieldImg,width/2-120+moveItemsHorizontal,height/2-80,size,size);
text(game.masks,width/2-80+moveItemsHorizontal,height/2-70);
textSize(32);
textAlign(CENTER);
text("Points "+game.points,width/2,height/2+30);
text("Cases "+game.cases,width/2,height/2+80);
popStyle();
restartButton();
}
void restartButton(){
int buttonYPosition = 200;
int rectWidth = 250;
int rectHeight = 70;
pushStyle();
rectMode(CENTER);
fill(9,129,74);
if (mouseX>width/2-rectWidth/2 && mouseX<width/2+rectWidth/2 && mouseY>height/2+buttonYPosition-rectHeight/2 && mouseY<height/2+buttonYPosition+rectHeight/2){
fill(9,160,74);
if (mousePressed){
resetGame();
fill(9,100,74);
}
}
rect(width/2,height/2+buttonYPosition,rectWidth,rectHeight,30);
textAlign(CENTER);
fill(0,0,0);
textSize(40);
text("RESTART",width/2,height/2+buttonYPosition+15);
popStyle();
}
void resetGame(){
game = new Game();
coronaList = new ArrayList<CoronaVirus>(0);
activeFighters = new ArrayList<Fighter>(0);
game.state = 0;
for (int i=0; i<4; i++) {
coronaList.add(new CoronaVirus());
}
}
void startScreen(){
background(110,125,171);
image(virus,20,20,500,500);
instructions();
startButton();
}
void startButton(){
int moveButton = 85;
int buttonYPosition = 200;
int rectWidth = 250;
int rectHeight = 70;
pushStyle();
rectMode(CENTER);
fill(9,129,74);
if (mouseX>width/2-rectWidth/2 && mouseX<width/2+rectWidth/2 && mouseY>height/2+buttonYPosition-rectHeight/2+moveButton && mouseY<height/2+buttonYPosition+rectHeight/2+moveButton){
fill(9,160,74);
if (mousePressed){
game.state=0;
fill(9,100,74);
}
}
rect(width/2,height/2+buttonYPosition+moveButton,rectWidth,rectHeight,30);
textAlign(CENTER);
fill(0,0,0);
textSize(40);
text("START",width/2,height/2+buttonYPosition+15+moveButton);
popStyle();
}
void instructions(){
// Title
pushStyle();
String title = "Pandemic";
fill(178,103,0);
stroke(178,103,0);
strokeWeight(3);
textAlign(CENTER);
textSize(48);
text(title,width/2,60);
popStyle();
//objective heading
pushStyle();
String objective = "Objective";
fill(0,0,0);
textAlign(LEFT);
textSize(32);
text(objective,width/2,150);
popStyle();
//objective text
pushStyle();
String objectiveText = "Try to get your points as high as possible while keeping the number of the cases as low as possible";
fill(0,0,0);
textAlign(LEFT);
textSize(18);
text(objectiveText,width/2+50,180, width/2-70,250);
popStyle();
//instruction heading
pushStyle();
String instruction = "Instructions";
fill(0,0,0);
textAlign(LEFT);
textSize(32);
text(instruction,width/2,280);
popStyle();
//objective text
String line1 = "1. Move the shooter across the screen by using the left and right arrow keys.\n";
String line2 = "2. The icon shown in the shooter will be what you will be shooting down the virus with.\n";
String line3 = "3. Shooting the virus down with different tools will yield different points.\n";
String line4 = "4. The tools which yield greater points are also more expensive to acquire.\n";
String line5 = "5. You can choose the tool that you’re fighting with by pressing 1,2 or 3. 1 will select the handwash, 2 will select facemask and 3 will select a face shield.\n";
String line6 = "6. You can acquire more tools by pressing m to go into buying mode and then pressing 1,2 or 3 to acquire more tools. A hand wash will cost 1 point, a face mask will cost 2 points and a face shield will cost 3 points.\n";
String line7 = "7. Number of cases will increase is the virus goes below the screen.";
pushStyle();
String instructionText = line1+line2+line3+line4+line5+line6+line7;
fill(0,0,0);
textAlign(LEFT);
textSize(15);
text(instructionText,width/2+50,300, width/2-70,700);
popStyle();
}
The game is about fighting COVID-19 by the use of your fighting tools [handwash, facemask, and faceshield] the COVID-19 cells will fall from the top of the screen and if you shoot them, you get points but the number of fighting tools decrease. If the cells reaches the bottom of the screen the number of cases go up. The objective of the game is to keep the number of cases as low as possible.
For the midterm project the progress so far has been planning the game on paper. As seen below. As of right now on processing the code consists of a game class file and a main file.
The game class file will encapsulate all the game state and will be responsible for displaying the game stats and and updating them. The game class attributes are:
points
cases
handwash
masks
shields
state
fightTool
time
And the icons
The game class methods are:
increment points
reduce points
increment cases
increment masks
decrement masks
increment shields
decrement shields
increment handwash
decrement handwash
change state
update time
drawGameStats
The icons for use in the game were downloaded from flaticon as seen below
class Game {
// attributes
int points = 0;
int cases = 0;
int handwash = 20;
int masks = 14;
int shields = 6;
int state = 0; // 0->shooting 1-> buying -1 -> gameOver
int fightingTool = 0; // 0-handwash, 1-mask, 2-shield
int time = 120;
PImage maskImg = loadImage("mask.png");
PImage handwashImg = loadImage("handwash.png");
PImage shieldImg = loadImage("shield.png");
int timeDisplay = 0;
//methods
void incrementPoints() {
if (fightingTool == 0) {
points += 1;
} else if (fightingTool == 1) {
points += 3;
} else if (fightingTool == 2) {
points += 5;
}
}
void reducePoints(int fightingTool) {
if (state==1) {
if (fightingTool == 1) {
}
}
}
void incrementCases() {
cases+=1;
}
void incrementMasks() {
masks+=1;
}
void decrementMasks() {
masks-=1;
}
void incrementShields() {
shields+=1;
}
void decrementShields() {
shields-=1;
}
void incrementHandwash() {
handwash+=1;
}
void decrementHandwash() {
handwash-=1;
}
void changeState() {
if (state==0) {
state=1;
} else if (state==1) {
state=0;
}
}
void updateTime() {
if (time==0) {
state=-1;
}
if (frameCount%60==0 && state!=-1) {
time-=1;
if (timeDisplay==0) {
timeDisplay = 1;
} else if (timeDisplay==1) {
timeDisplay=0;
}
}
}
void drawGameStats() {
color(0, 0, 0);
imageMode(CENTER);
// draw mask
image(maskImg, 70, 30, 30, 30);
text(masks+" x", 25, 30);
//draw handwash
image(handwashImg, 150, 30, 30, 30);
text(handwash+" x", 110, 30);
// draw faceshield
image(shieldImg, 230, 30, 30, 30);
text(shields+" x", 190, 30);
//display time
pushStyle();
textSize(30);
if (timeDisplay==1) {
fill(0, 0, 0);
text(time, width-100, height-30);
} else if (timeDisplay==0) {
fill(255, 255, 0);
text(time, width-100, height-30);
}
popStyle();
// game mode
pushStyle();
int rectWidth = 100;
int rectHeight = 30;
int cornerRadius = 10;
noFill();
rect(width/2-rectWidth/2, 20, rectWidth, rectHeight, cornerRadius, cornerRadius, cornerRadius, cornerRadius);
if (state==0) {
pushStyle();
textAlign(CENTER);
textSize(25);
fill(255, 0, 0);
text("FIGHT", width/2, 45);
popStyle();
}
popStyle();
//display points
pushStyle();
fill(0,0,0);
textSize(25);
text(points+" points", width-300,45);
text(cases+" cases", width-150,45);
popStyle();
}
}
For this week assignment I was completely out of ideas. So I decided to manipulate the pixel of an image. I load the picture and then in different functions I manipulate each individual pixel of the image.
There are five different manipulations that can take place:
Inverting the RGB values of each pixel
Inverting the R values of each pixel
Inverting the G values of each pixel
Inverting the B values of each pixel
Swapping the pixels in the array
Exagerating the each RGB value with the same random number
Each of the different functions are mapped to keys 1-6 on the keyboard and pressing any other key would reload the original image.
Pressing different keys in different combinations will yield different outcomes.
Advanced Implementation
I tried to add another level of complexity to the sketch by inverting the pixels which in a circular distance of the mouse cursor.
I was able to figure the logic on paper but the logic when translated to code was not.
I would like to pursue this further and implement this logic
PImage img;
int counter = 0;
int KeyCode = -1;
void setup() {
size(1280, 720);
img = loadImage("scene.jpg");
image(img, 0, 0, width, height);
//noLoop();
}
void draw() {
//if (mouseX>0 && mouseX<width && mouseY>0 && mouseY<height) {
// negativeMousePosition();
//}
}
void keyPressed() {
float sinVal = radians(180);
println(sin(sinVal),cos(radians(180)));
if (keyCode==49) { //1
invertRGB();
KeyCode = 49;
} else if (keyCode==50) { //2
invertR();
KeyCode = 50;
} else if (keyCode==51) { //3
invertG();
KeyCode = 51;
} else if (keyCode==52) { //4
invertB();
KeyCode = 52;
} else if (keyCode==53) { //5
swapPixels();
KeyCode = 53;
} else if (keyCode == 54) { //6
exagerate();
KeyCode = 54;
} else { //anything else
drawOriginal();
KeyCode = -1;
}
}
//void mouseDragged(){
// negativeMousePosition();
//}
void invertRGB() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
for (int i=0; i<width*height; i++) {
int r = (int)red(pixels[i]); //get red value
int g = (int) green(pixels[i]); // get green value
int b = (int) blue(pixels[i]); //get blue value
color c = color(255-r, 255-g, 255-b); // take the complement of the rgb values
pixels[i] = c; //set the new color value
}
updatePixels(); //update the pixels on screen
}
void invertR() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
for (int i=0; i<width*height; i++) {
int r = (int)red(pixels[i]); //get red value
int g = (int) green(pixels[i]); // get green value
int b = (int) blue(pixels[i]); //get blue value
color c = color(255-r, g, b); // take the complement of the rgb values
pixels[i] = c; //set the new color value
}
updatePixels(); //update the pixels on screen
}
void invertG() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
for (int i=0; i<width*height; i++) {
int r = (int)red(pixels[i]); //get red value
int g = (int) green(pixels[i]); // get green value
int b = (int) blue(pixels[i]); //get blue value
color c = color(r, 255-g, b); // take the complement of the rgb values
pixels[i] = c; //set the new color value
}
updatePixels(); //update the pixels on screen
}
void invertB() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
for (int i=0; i<width*height; i++) {
int r = (int)red(pixels[i]); //get red value
int g = (int) green(pixels[i]); // get green value
int b = (int) blue(pixels[i]); //get blue value
color c = color(r, g, 255-b); // take the complement of the rgb values
pixels[i] = c; //set the new color value
}
updatePixels(); //update the pixels on screen
}
void drawOriginal() {
image(img, 0, 0, width, height);
}
void swapPixels() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
//println(pixels[1]);
//println(pixels[width*height-2]);
for (int i=0; i<(width*height)/2; i++) {
int temp;
temp = pixels[i];
pixels[i] = pixels[width*height-1-i];
pixels[width*height-1-i] = temp;
}
updatePixels();
//println(pixels[1]);
}
void exagerate() {
//img = loadImage("scene.jpg");
//image(img, 0, 0, width, height);
loadPixels();
for (int i=0; i<width*height; i++) {
int r = (int)red(pixels[i]); //get red value
int g = (int) green(pixels[i]); // get green value
int b = (int) blue(pixels[i]); //get blue value
int randomR = (int) random(255);
int randomG = (int) random(255);
int randomB = (int) random(255);
color c = color((r+randomR), (g+randomG), (b+randomB)); // take the complement of the rgb values
pixels[i] = c; //set the new color value
}
updatePixels(); //update the pixels on screen
}
For this week’s assignment I decided to use that was being collected by the running app that I am using to track my running progress. The app records the distance per run, walking pace, running pace and the average pace.
For this assignment I took the average pace per run [given in minutes/km] and point plotted it against the days.
The data was between 0 and 9 so I have to get that data in the range such that I could plot it on the screen. For this I used the following formula
data*(maxDrawableHeight)/9.
This gave me the height of the points from the axis but since the drawing points are given from top left corner going down I inverted this by subtracting this from the drawable height.
Table data;
float[] numericData;
float [] plotData;
int numCols;
int axisOffset = 100;
void setup() {
size(1000, 500);
loadData();
dataTransformation();
drawAxes();
drawGrid();
printLabels();
plotPoints();
noLoop();
}
void draw() {
}
void drawAxes() {
axisOffset = 50;
pushStyle();
strokeWeight(2);
//y axis
line(axisOffset, 0, axisOffset, height-axisOffset);
//x-axis
line(0+axisOffset, height-axisOffset, width, height-axisOffset);
popStyle();
}
void loadData() {
data = loadTable("data.csv");
TableRow row = data.getRow(0);
numCols = row.getColumnCount();
numericData = new float[numCols];
for (int i=0; i<numCols; i++) {
numericData[i] = Float.parseFloat(row.getString(i));
}
//println();
}
void printData() {
for (int i=0; i<numericData.length; i++)
{
print(numericData[i] + " | ");
}
println();
}
void drawGrid()
{
// data will be in the range of 0 < 9*(height-axisOffset)
pushStyle();
stroke(0,0,0,40);
// for drawing Horizontal grid lines
float xLineGap = (height-axisOffset)/9;
for (float y=height-axisOffset; y>=0; y=y-xLineGap){
line(axisOffset,y,width,y);
}
//println(numCols);
float yLineGap = (width-axisOffset)/numCols;
for (float x=axisOffset+yLineGap;x<=width; x+=yLineGap)
{
line(x,0,x,height-axisOffset);
}
popStyle();
}
void dataTransformation(){
// data will be in the range of 0 < 9*(height-axisOffset)
//transform the data
plotData = new float[numCols];
for(int i=0;i<numCols;i++)
{
plotData[i] = numericData[i]*(height-axisOffset)/9;
}
//println(plotData);
}
void plotPoints(){
float yLineGap = (width-axisOffset)/numCols;
for(int i=0;i<numCols;i++){
strokeWeight(6);
float yCoord = height-(plotData[i]+axisOffset+yLineGap);
//println(plotData[i]);
point(axisOffset+yLineGap+(yLineGap)*i,yCoord);
}
}
void printLabels(){
//title
fill(0,0,0);
textSize(20);
textAlign(CENTER);
String title = "Graph Of Average Pace [minutes/km] Against Run Days";
text(title,width/2, height-(axisOffset/5));
//x-axis labels
float yLineGap = (width-axisOffset)/numCols;
for(int i=0;i<numCols;i++)
{
text(i+1,axisOffset+yLineGap+(yLineGap)*i, height-(axisOffset*3/5));
}
//y-axis labels
float xLineGap = (height-axisOffset)/9;
int text = 0;
for(float y=height-axisOffset; y>=0; y=y-xLineGap)
{
text(text,axisOffset-10,y);
text++;
//println(text);
}
for (float y=height-axisOffset; y>=0; y=y-xLineGap){
line(axisOffset,y,width,y);
}
}
For this weeks assignment I decided to recreate a game that I played alot with my siblings when power was out during hurricanes seasons in a digital. I decided to make the game tic-tac-toe however instead of uses X’s and O’s I decided that each piece will be a square box that it will be filled in each of the spots. The reason for this was utilize the entire canvas that processing provide.
I utilized a snapping motion to determine where the player was currently
was and the piece would be put should the player click the mouse button.
For the object oriented portion of the game all of the game logic is encapsulated in a game class. The game class uses a 2D-array to store the “pieces” either as a 0 for red, 1 for green or a -1 for empty. This array is used during the entire time that the game is in session to render the pieces as well do various logic work. For instance, if the value is not -1 then the piece should not be played. The game class also used this array to check the winning condition of the game.\\
void setup() {
size(1000, 1000);
}
//global variables
float boxWidth = 1000/3;
Game myGame = new Game();
int turn = 0; //0 is red, 1 is green
boolean gameRunning = true;
String gameWonBy = "";
int piecesIn = 0;
void draw() {
background(255, 255, 255);
if (gameRunning == true)
{
cursorHover();
}
board();
myGame.colorPieces();
myGame.checkWin();
pushStyle();
textSize(32);
textAlign(CENTER);
//fill(255, 255, 255);
fill(0, 0, 0);
if (gameWonBy == "Red") {
text("This game was won by red", width/2, height/2);
//println("should display text");
} else if (gameWonBy == "Green") {
text("This game was won by green", width/2, height/2);
//println("should display text");
} else if (gameWonBy == "Tie") {
text("This game ended in a tie", width/2, height/2);
//println("should display text");
}
popStyle();
}
//functions
void board() {
pushStyle();
strokeWeight(3);
//first vertical line
line(width/3, 0, width/3, height);
//second vertical line
line(2* width/3, 0, 2*width/3, height);
//first horizontal line
line(0, height/3, width, height/3);
//second horizontal line
line(0, 2*height/3, width, 2*height/3);
popStyle();
}
void cursorHover() {
//make the light green/red box over the position
if (turn%2==0)
{
fill(255, 0, 0, 180);
} else if (turn%2==1) {
fill(0, 255, 0, 180);
}
//origin of the hover box
int[] origin = getIndices();
//draw the position
rect(origin[1]*boxWidth, origin[0]*boxWidth, boxWidth, boxWidth);
}
void mouseClicked() {
myGame.updatePosition(getIndices());
//myGame.printPositions();
}
int[] getIndices() {
int[] indices = new int[2];
//x is index 0, y is index 1
indices[0] = floor(mouseY/boxWidth);
indices[1] = floor(mouseX/boxWidth);
return indices;
}
//classes
class Game {
int[][] positions = new int[3][3];
Game() {
for (int i=0; i<positions.length; i++) {
for (int j=0; j<positions[i].length; j++) {
positions[i][j]=-1;
}
}
}
void updatePosition(int[] indices) {
if (gameRunning)
{
if (positions[indices[0]][indices[1]] == -1) {
positions[indices[0]][indices[1]] = turn%2;
turn=turn+1;
piecesIn+=1;
}
}
}
void printPositions() {
for (int i=0; i<positions.length; i++) {
for (int j=0; j<positions[i].length; j++) {
//print(positions[i][j]+" ");
}
//println();
}
//println();
}
void colorPieces() {
for (int i=0; i<positions.length; i++) {
for (int j=0; j<positions[i].length; j++) {
//if position is 0 then color the position red
if (positions[j][i]==0) {
pushStyle();
fill(255, 0, 0);
rect(i*boxWidth, j*boxWidth, boxWidth, boxWidth);
popStyle();
}
//if position is 1 then color the position green
else if (positions[j][i]==1) {
pushStyle();
fill(0, 255, 0);
rect(i*boxWidth, j*boxWidth, boxWidth, boxWidth);
popStyle();
}
}
}
}
void checkWin() {
//tie check
if (piecesIn == 9 && gameRunning==true) {
gameRunning = false;
gameWonBy = "Tie";
//println("Tie");
}
//row check
for (int i=0; i<3; i++) {
if (positions[i][0]==0 && positions[i][1]==0 && positions[i][2]==0) {
gameRunning = false;
gameWonBy = "Red";
//println("gameWonBy Red");
} else if (positions[i][0]==1 && positions[i][1]==1 && positions[i][2]==1) {
gameRunning = false;
gameWonBy = "Green";
//println("gameWonBy Green");
}
}
// column check
for (int i=0; i<3; i++) {
if (positions[0][i]==0 && positions[1][i]==0 && positions[2][i]==0) {
gameRunning = false;
gameWonBy = "Red";
//println("gameWonBy Red");
} else if (positions[0][i]==1 && positions[1][i]==1 && positions[2][i]==1) {
gameRunning = false;
gameWonBy = "Green";
//println("gameWonBy Green");
}
}
// diagonal check y=-x
if (positions[0][0]==0 && positions[1][1]==0 && positions[2][2]==0) {
gameRunning = false;
gameWonBy = "Red";
//println("gameWonBy Red");
} else if (positions[0][0]==1 && positions[1][1]==1 && positions[2][2]==1) {
gameRunning = false;
gameWonBy = "Green";
//println("gameWonBy Green");
}
// diagonal check y=x
if (positions[0][2]==0 && positions[1][1]==0 && positions[2][0]==0) {
gameRunning = false;
gameWonBy = "Red";
//println("gameWonBy Red");
} else if (positions[0][2]==1 && positions[1][1]==1 && positions[2][0]==1) {
gameRunning = false;
gameWonBy = "Green";
//println("gameWonBy Green");
}
}
}