Created
November 19, 2021 00:24
-
-
Save ItsMichal/a186eaf2f3f17f2ada46b8f19fec2e16 to your computer and use it in GitHub Desktop.
Lane Defense - Serial Arduino Nano Game
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const conWidth = 800; | |
const conHeight = 450; | |
let serial; | |
let latestData = "waiting for data"; | |
class Drawable { | |
constructor(){ | |
} | |
drawSelf(){ | |
} | |
valid(){ | |
} | |
} | |
class Lane extends Drawable { | |
constructor(x,y, w, h){ | |
super(); | |
this.x = x; | |
this.y = y; | |
this.w = w; | |
this.h = h; | |
this.maxhp = 50; | |
this.hp = this.maxhp; | |
this.pellets = []; | |
this.enemies = []; | |
this.colors = [100, 200]; | |
this.active = false; | |
this.gun = new Gun(this); | |
this.spawner = new Spawner(this); | |
} | |
drawSelf(){ | |
fill(this.colors[((this.active) ? 1: 0)]); | |
noStroke(); | |
rect(this.x, this.y, this.w, this.h); | |
this.gun.drawSelf(); | |
this.spawner.drawSelf(); | |
fill("green"); | |
rect(this.x, this.y+this.h+25, map(this.hp, 0, this.maxhp, 0, this.w), 10); | |
//Draw pellets | |
for(let i = 0; i < this.pellets.length; i++){ | |
if(this.pellets[i].valid()){ | |
this.pellets[i].drawSelf(); | |
}else{ | |
console.log("Removed pellet"); | |
this.pellets.splice(i,1); | |
} | |
} | |
//Draw enemies and do collision | |
for(let i = 0; i < this.enemies.length; i++){ | |
//Collision | |
for(let j = 0; j < this.pellets.length; j++){ | |
let enemyLowY = this.enemies[i].y + this.enemies[i].d/2; | |
let pelletHighY = this.pellets[j].y - this.pellets[j].d/2; | |
if(enemyLowY > pelletHighY){ | |
console.log("Collision detected"); | |
this.pellets.splice(j, 1);//Remove pellet | |
this.enemies[i].damage(1.1); | |
} | |
} | |
if(this.enemies[i].valid()){ | |
this.enemies[i].drawSelf(); | |
}else{ | |
this.enemies.splice(i,1); | |
} | |
} | |
} | |
select(val){ | |
this.active = val; | |
this.gun.select(val); | |
} | |
damage(hp){ | |
this.hp -= hp; | |
} | |
valid(){ | |
return true; | |
} | |
} | |
class Spawner extends Drawable { | |
constructor(lane){ | |
super(); | |
this.x = lane.x; | |
this.y = 0; | |
this.w = lane.w; | |
this.hs = [10,20]; | |
this.h = 10; | |
this.lane = lane; | |
this.colors = [color(255,0,255), color(255,100,255)]; | |
this.spawning = false; | |
} | |
drawSelf(){ | |
noStroke(); | |
fill(this.colors[((this.spawning) ? 1: 0)]); | |
rect(this.x, this.y, this.w, this.h); | |
let spawnChoice = Math.floor(random(500)); | |
if(spawnChoice == 1 && this.lane.enemies.length < 5){ | |
this.lane.enemies.push(new Enemy(this, random(1,3))); | |
} | |
} | |
valid(){ | |
return true; | |
} | |
} | |
class Enemy extends Drawable { | |
constructor(spawner, hp){ | |
super(); | |
this.maxhp = hp; | |
this.hp = hp; | |
this.d = 40 + (10 * hp); | |
this.x = spawner.x + spawner.w/2 + random(-5,5); | |
this.y = spawner.y; | |
this.vy = (6 - (this.hp))/6; | |
this.spawner = spawner; | |
this.destroyed = false; | |
} | |
drawSelf(){ | |
noStroke(); | |
stroke(0); | |
fill(255,0,255); | |
circle(this.x, this.y, this.d); | |
fill(255,0,0); | |
rect(this.x-this.d/2, this.y - this.d, this.d, 10); | |
fill(0,255,0); | |
rect(this.x-this.d/2, this.y - this.d, map(this.hp, 0, this.maxhp, 0, this.d), 10); | |
this.y += this.vy * (deltaTime / 50); | |
} | |
damage(hp){ | |
this.hp -= hp; | |
if(this.hp <= 0){ | |
this.destroyed = true; | |
} | |
} | |
valid(){ | |
if(this.destroyed){ | |
return false; | |
} | |
if(this.y > this.spawner.lane.h + this.spawner.lane.y){ | |
this.spawner.lane.damage(this.hp); | |
return false; | |
} | |
return true; | |
} | |
} | |
class Gun extends Drawable { | |
constructor(lane){ | |
super(); | |
this.x = lane.x; | |
this.y = lane.y + lane.h; | |
this.w = lane.w; | |
this.hs = [10,20]; | |
this.h = 10; | |
this.lane = lane; | |
this.colors = [color(255,0,0), color(255,100,100)]; | |
this.selected = false; | |
} | |
drawSelf(){ | |
fill(this.colors[((this.selected) ? 1: 0)]); | |
noStroke(); | |
rect(this.x, this.y, this.w, this.h); | |
} | |
fire(){ | |
this.lane.pellets.push(new Pellet(this)); | |
} | |
select(val){ | |
this.selected = val; | |
this.h = this.hs[((val) ? 1 : 0)]; | |
} | |
valid(){ | |
return true; | |
} | |
collision(obj){ | |
return false; | |
} | |
} | |
class Pellet extends Drawable { | |
constructor(gun){ | |
super(); | |
this.d = 50; | |
this.x = gun.x + gun.w/2; | |
this.y = gun.y - this.d/2; | |
this.vy = -4; | |
this.destroyed = false; | |
} | |
drawSelf(){ | |
stroke(0); | |
fill(255,0,0); | |
circle(this.x, this.y, this.d); | |
this.y += this.vy * (deltaTime / 50); | |
} | |
collide(){ | |
this.destroyed = true; | |
} | |
valid(){ | |
if(this.destroyed){ | |
return false; | |
} | |
if(this.y < 10){ | |
return false; | |
} | |
return true; | |
} | |
} | |
let objects =[]; | |
let laneSwitchObj = []; | |
let laneIndex = 0; | |
function setup() { | |
createCanvas(conWidth, conHeight); | |
//Create lanes | |
objects.push(new Lane(0,0, 150, 400)) | |
objects.push(new Lane(200,0, 150, 400)) | |
objects.push(new Lane(400,0, 150, 400)) | |
//Create spawner for lanes | |
laneSwitchObj[0] = [objects[0]]; | |
laneSwitchObj[1] = [objects[1]]; | |
laneSwitchObj[2] = [objects[2]]; | |
updateActiveLane(); | |
switchLane(false); | |
objects[1].gun.fire(); | |
objects.forEach((obj)=>console.log(obj)) | |
serial = new p5.SerialPort(); | |
serial.list(); | |
serial.open('/dev/tty.usbmodem11201'); | |
serial.on('connected', serverConnected); | |
serial.on('list', gotList); | |
serial.on('data', gotData); | |
serial.on('error', gotError); | |
serial.on('open', gotOpen); | |
serial.on('close', gotClose) | |
} | |
function switchLane(left){ | |
let delta = (left) ? -1 : 1; | |
laneIndex += delta; | |
if(laneIndex < 0){ | |
laneIndex = 0; | |
}else if(laneIndex >= laneSwitchObj.length){ | |
laneIndex = laneSwitchObj.length-1; | |
} | |
updateActiveLane(); | |
} | |
function updateActiveLane(){ | |
for(let i = 0; i < laneSwitchObj.length; i++){ | |
laneSwitchObj[i].forEach((laneObj) => { | |
laneObj.select(i == laneIndex); | |
}); | |
} | |
} | |
function fireInActiveLane(){ | |
laneSwitchObj[laneIndex][0].gun.fire(); | |
} | |
function draw() { | |
background(240); | |
// console.log(objects); | |
// let testlane = new Lane(200, 0, 100, 400); | |
// testlane.drawSelf(); | |
// console.log(testlane); | |
//Draw all objects | |
for(let i = 0; i < objects.length; i++){ | |
let obj = objects[i]; | |
if(obj.valid()){ | |
obj.drawSelf(); | |
}else{ | |
console.log("Removed "+ typeof obj); | |
objects.splice(i,1); | |
} | |
} | |
} | |
function keyPressed(){ | |
if(keyCode == LEFT_ARROW){ | |
switchLane(true); | |
}else if(keyCode == RIGHT_ARROW){ | |
switchLane(false); | |
}else if(keyCode == 32 ){ | |
fireInActiveLane(); | |
} | |
} | |
function serverConnected() { | |
print("Connected to Server"); | |
} | |
function gotList(thelist) { | |
print("List of Serial Ports:"); | |
for (let i = 0; i < thelist.length; i++) { | |
print(i + " " + thelist[i]); | |
} | |
} | |
function gotOpen() { | |
print("Serial Port is Open"); | |
} | |
function gotClose(){ | |
print("Serial Port is Closed"); | |
latestData = "Serial Port is Closed"; | |
} | |
function gotError(theerror) { | |
print(theerror); | |
} | |
function gotData() { | |
let currentString = serial.readLine(); | |
trim(currentString); | |
if (!currentString) return; | |
console.log(currentString); | |
if(currentString == "LEFT"){ | |
switchLane(true); | |
}else if(currentString == "RIGHT"){ | |
switchLane(false); | |
}else if(currentString == "FORWARD"){ | |
fireInActiveLane(); | |
} | |
latestData = currentString; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment