Skip to content

Instantly share code, notes, and snippets.

@ItsMichal
Created November 19, 2021 00:24
Show Gist options
  • Save ItsMichal/a186eaf2f3f17f2ada46b8f19fec2e16 to your computer and use it in GitHub Desktop.
Save ItsMichal/a186eaf2f3f17f2ada46b8f19fec2e16 to your computer and use it in GitHub Desktop.
Lane Defense - Serial Arduino Nano Game
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