xxxxxxxxxx
275
const MAX_LIVES = 3;
const BUGSPEED = 0.3;
const HERO_SPEED = 1;
const HERO_REACH = 5;
const SPAWN_RATE = 25; // each x turns a wave spawns
// multiples of 4 (should be multiples of amount of players)
const AMT_BUG_PER_WAVE_MAX = 16;
const AMT_BUG_PER_WAVE_MIN = 4;
const MAX_BUGS = 12;
var game;
var SHOW_VECTOR = true;
function setup() {
createCanvas(400, 400);
game = new Game();
}
class Bug {
constructor(x, y, dx, dy) {
this.pos = createVector(x, y);
this.speed = createVector(dx, dy);
}
update() {
this.pos.add(this.speed);
}
draw() {
circle(this.pos.x, this.pos.y, 5);
}
}
class Hero {
constructor(x, y) {
this.pos = createVector(x, y);
this.speed = createVector(0, 0);
}
draw() {
circle(this.pos.x, this.pos.y, 10);
// if (SHOW_VECTOR) { line(this.pos.x, this.pos.y, this.pos.x+this.speed.x, this.pos.y+this.speed.y)}
}
update(bugs) {
var hero = this.pos;
if (bugs.length > 0) {
var [[bi, bestBug], _d] = bugs.reduce(
function (best, curr) {
var [[i, best_bug], best_d] = best;
var new_d = curr.pos.dist(hero);
if (new_d < best_d) {
return [[i + 1, curr], new_d];
}
return best;
},
[[0, bugs[0]], bugs[0].pos.dist(hero)]
);
var direction = p5.Vector.sub(bestBug.pos, hero);
line(hero.x, hero.y, bestBug.pos.x, bestBug.pos.y);
direction.setMag(HERO_SPEED);
if (this.pos.dist(bestBug.pos) < HERO_REACH) {
bugs.splice(bi, 1);
}
hero.add(direction);
this.speed.x = direction.x;
this.speed.y = direction.y;
}
return bugs;
}
}
class Player {
constructor(hp, mana) {
this.hp = hp;
this.mana = mana;
}
}
class STRATEGY_RandomStrategy {
playRound(game, index) {
const heros = game.heroes[index];
for (const h of heros) {
var newTarget = createVector(random(0, width), random(0, height));
// text('random', h.pos.x, h.pos.y)
var newdir = p5.Vector.sub(newTarget, h.pos);
newdir.setMag(HERO_SPEED);
h.pos.add(newdir);
}
}
}
class STRATEGY_ClosestToBase {
playRound(game, index) {
const heros = game.heroes[index];
const bugs = game.bugs;
var [bx, by] = game.bases[index]
const baseVector = createVector(bx, by);
var sorted_bugs = bugs.sort((a,b)=> a.pos.dist(baseVector) > b.pos.dist(baseVector));
for (const [i,h] of heros.entries()) {
if (i >= sorted_bugs.length) break;
var newTarget = sorted_bugs[i].pos
if (newTarget.dist(h.pos) < HERO_REACH) {
bugs.splice(i, 1)
}
var newdir = p5.Vector.sub(newTarget, h.pos);
newdir.setMag(HERO_SPEED);
h.pos.add(newdir);
}
}
}
class STRATEGY_ClosestToBaseInterCept {
playRound(game, index) {
const heros = game.heroes[index];
const bugs = game.bugs;
var [bx, by] = game.bases[index]
const baseVector = createVector(bx, by);
var sorted_bugs = bugs.sort((a,b)=> a.pos.dist(baseVector) > b.pos.dist(baseVector));
for (const [i,h] of heros.entries()) {
if (i >= sorted_bugs.length) break;
const bug = sorted_bugs[i]
var nt; // new target
if (bug.pos.dist(h.pos) <= HERO_REACH) {
nt = bug.pos;
bugs.splice(i, 1)
} else {
var heading = p5.Vector.sub(bug.pos, h.pos);
var bugfuture = p5.Vector.add(bug.pos, bug.speed)
var failsafe = 0
do {
bugfuture.add(bug.speed);
var newHeading = p5.Vector.sub(bugfuture, h.pos);
failsafe++;
// print(`${heading.mag()} ${newHeading.mag()}`)
point(bugfuture.x, bugfuture.y)
} while (heading.mag() < newHeading.mag() && failsafe < 55)
nt = bugfuture // new target
line(nt.x, nt.y, h.pos.x, h.pos.y)
}
var newdir = p5.Vector.sub(nt, h.pos);
newdir.setMag(HERO_SPEED);
h.pos.add(newdir);
}
}
}
class Game {
constructor() {
this.bases = [
[0, 0],
[width, 0],
[width, height],
[0, height],
];
this.heroes = this.bases.map(([x, y]) => [
new Hero(x, y),
new Hero(x, y),
new Hero(x, y),
]);
this.players = this.bases.map(() => new Player(MAX_LIVES, 0));
this.turn = 0;
this.bugs = [];
this.strategies = [new STRATEGY_RandomStrategy(), new STRATEGY_ClosestToBase(), new STRATEGY_ClosestToBaseInterCept()];
}
spawnBugs() {
const c = createVector(width / 2, height / 2);
var amt_to_spawn = random(AMT_BUG_PER_WAVE_MIN, AMT_BUG_PER_WAVE_MAX);
if (amt_to_spawn + this.bugs.length > MAX_BUGS) {
amt_to_spawn = MAX_BUGS - this.bugs.length;
}
for (var i = 0; i < amt_to_spawn; i++) {
for (const [dx, dy] of [
[1, height],
[width, 1],
[0, 1],
[1, 0],
]) {
var x = constrain(random(0,400) * dx, 0, 400);
var y = constrain(random(0,400) * dy, 0, 400);
var v = p5.Vector.sub(c, createVector(x, y));
v.setMag(BUGSPEED);
var b = new Bug(x, y, v.x, v.y);
this.bugs.push(b);
}
}
}
update() {
this.updateBugs();
// this.updateHeroes();
for (var i = 0; i < this.bases.length; i++) {
this.strategies[i % this.strategies.length].playRound(this, i);
}
if (this.turn % SPAWN_RATE == 0 && this.bugs.length < MAX_BUGS) {
this.spawnBugs();
}
this.turn++;
}
updateHeroes() {
for (const heroes of this.heroes) {
for (const h of heroes) {
this.bugs = h.update(this.bugs);
}
}
}
drawHeroes() {
const colorsets = [[0,0,255],[255,255,255], [255,0,0],[0,255,0]];
for (const [i,heroes] of this.heroes.entries()) {
push();
const [r,g,b] = colorsets[i];
fill(r,g,b);
for (const h of heroes) {
h.draw();
}
pop();
}
}
updateBugs() {
var to_delete = [];
for (const [i, b] of this.bugs.entries()) {
b.update();
if (
b.pos.x > width + 5 ||
b.pos.x < 0 - 5 ||
b.pos.y > height + 5 ||
b.pos.y < 0 - 5
) {
to_delete.push(i);
}
}
for (const i of to_delete) {
this.bugs.splice(i, 1);
}
}
drawBugs() {
for (const b of this.bugs) {
b.draw();
}
}
draw() {
this.drawBugs();
this.drawHeroes();
}
}
function draw() {
background(220);
game.update();
game.draw();
}