xxxxxxxxxx
549
//Core Game
let font;
let stage = 0;
let not_started = true;
let stages = ["Title", "Instructions1", "Instructions2", "Game", "GameOver"];
let numStages = 4;
let sessionTimer;
let gameTimer;
let gameTimerEnd;
let timeofLastDeath = 0;
let numLives = 4;
let numBacteria = 5;
let score = 0;
//Lists
let bacteria = [];
let lives = [];
let bullets = [];
let boosts = [];
let nets = [];
let bombs = [];
//White Blood Cell Properties
let wbx;
let wby;
let wbr;
//Bacteria Properties
let bx;
let by;
let br;
let bspeed;
let speedfactor = 1;
//Bullet Properties
let bulletx;
let bullety;
let bulletr;
let bulletspeed;
let numBullets = 1;
//Powerup #1 - Vitamin Boost (Produce more antibody bullets) (Z)
let boostcost = 15;
let boosttime = 10;
let boostfactor = 3;
let lastboosttime;
let booststartscore = -15;
let maxboosts = 5;
let boosticonx;
let boosticony;
let boosticonw;
//Powerup #2 - Neutrophil Extracellular Trap (Slows down all bacteria) (X)
let netcost = 20;
let nettime = 10;
let netfactor = 0.5;
let lastnettime;
let netstartscore = -20;
let maxnets = 5;
let neticonx;
let neticony;
let neticonw;
//Powerup #3 - Complement Bomb (Clears Screen of all Bacteria) (C)
let bombcost = 40;
let bombtime = 20;
let lastbombtime;
let bombstartscore = -30;
let maxbombs = 2;
let bombiconx;
let bombicony;
let bombiconw;
//Colors
let restartbuttoncolor = "green";
let titlebuttoncolor = "mediumorchid";
let buttonhovercolor = "rgba(237,20,61,0.5)";
//Buttons
let restartbutton;
let titlebutton;
//images
let titleimg;
let bgimg = [];
let bgy = 0;
let wbcsprite;
let bacspritesheet;
let bacsprites = [];
let bulletsprite;
let boosticon;
let neticon;
let bombicon;
//sounds+music
let titleMusic;
let gametheme;
let ecg;
let ecgPlayed = false;
let shotsound;
function preload() {
font = loadFont("assets/fonts/ConcertOne-Regular.ttf");
//icons and sprites
boosticon = loadImage("assets/images/boost.png");
neticon = loadImage("assets/images/net.png");
bombicon = loadImage("assets/images/bomb.png");
wbcsprite = loadImage("assets/images/wbc.png");
bacspritesheet = loadImage("assets/images/bacteria.png");
bulletsprite = loadImage("assets/images/antibody.png");
//backgrounds
titleimg = loadImage("assets/images/dalle.jpg")
bgimg = [loadImage("assets/images/capillary.png"), loadImage("assets/images/capillary.png")];
//music+sound
titleMusic = loadSound("assets/sound/title.mp3")
gametheme = loadSound("assets/sound/gametheme.mp3")
shot = loadSound("assets/sound/laser.mp3");
ecg = loadSound("assets/sound/ekg.mp3");
//Sanity Check
console.log("Assets Preloaded Successfully");
}
function setup() {
cnv = createCanvas(windowWidth, windowHeight);
sessionTimer = millis();
textFont(font);
for (let x = 0; x < 2; x++){
bacsprites[x] = bacspritesheet.get(x * bacspritesheet.width / 2, 0, bacspritesheet.width/2, bacspritesheet.height);
}
}
function draw() {
// check if player has lives
if (stages[stage] == "Title") {
drawTitle();
} else if (
stages[stage] == "Instructions1" ||
stages[stage] == "Instructions2"
) {
drawInstructions();
} else if (stages[stage] == "Game") {
drawGame();
} else if (stages[stage] == "GameOver") {
drawGameOver();
}
}
// Reset Game State
function reset() {
score = 0;
gameTimer = millis();
frameStart = 0;
gameOver = false;
bacteria = [];
lives = [];
bullets = [];
boosts = [];
nets = [];
bombs = [];
speedfactor = 1;
lastboosttime = gameTimer;
booststartscore = -15;
lastnettime = gameTimer;
netstartscore = -20;
lastbombtime = gameTimer;
bombstartscore = -30;
boosticonx = (11 / 12) * width;
boosticony = (1 / 4) * height;
boosticonw = (1 / 8) * height;
neticonx = (11 / 12) * width;
neticony = (2 / 4) * height;
neticonw = (1 / 8) * height;
bombiconx = (11 / 12) * width;
bombicony = (3 / 4) * height;
bombiconw = (1 / 8) * height;
var boost = new Boost(
boostfactor,
boosttime,
boosticonx,
boosticony,
boosticonw,
boosticon
);
boosts.push(boost);
var net = new Net(netfactor, nettime, neticonx, neticony, neticonw, neticon);
nets.push(net);
var bomb = new Bomb(bombtime, bombiconx, bombicony, bombiconw, bombicon);
bombs.push(bomb);
wbx = 5 / 12 * width;
wby = height - height / 10;
wbr = height / 15;
for (let i = 0; i < numLives; i++) {
var immune = new ImmuneCell(wbx, wby, wbr, wbcsprite);
lives.push(immune);
}
for (let i = 0; i < numBacteria; i++) {
bx = int(random((2 * width) / 15, (5 / 6) * width - (2 * width) / 15));
by = -height / 40;
br = height / 40;
bspeed = int(speedfactor * random(height / 400, height / 200));
var bacGen = new Bacteria(bx, by, br, bspeed, bacsprites);
bacteria.push(bacGen);
}
frameofLastDeath = 0;
ecgPlayed = false;
}
// Trigger game state change on mouse click
function mousePressed() {
if (stages[stage] != "Game" && stages[stage] != "GameOver") {
stage = (stage + 1) % 5;
}
//reset after completing instructions
if (stages[stage] == "Game" && (millis()-gameTimer < 100 || not_started)) {
reset();
not_started = false;
}
}
function keyPressed() {
if (stages[stage] == "Game") {
//SPACEBAR
if (keyCode == 32) {
shot.play();
if (int((millis() - lastboosttime) / 1000) > boosttime) {
numBullets = 1;
}
for (let i = 1; i <= numBullets; i++) {
bulletx =
lives[0].x +
lives[0].r * 0.25 * (-2 * pow(-1, i) * i + pow(-1, i) - 1);
bullety = lives[0].y;
bulletr = height / 100;
bulletspeed = height / 20;
var bullet = new Bullet(
bulletx,
bullety,
bulletr,
bulletspeed,
bulletsprite
);
bullets.push(bullet);
}
}
//Z
if (keyCode == 90) {
if (boosts.length > 1) {
if (int((millis() - lastboosttime) / 1000) > boosttime) {
numBullets = boostfactor;
lastboosttime = millis();
boosts.pop();
}
}
}
//X
if (keyCode == 88) {
if (nets.length > 1) {
if (int((millis() - lastnettime) / 1000) > nettime) {
speedfactor = netfactor;
for (let i = 0; i < bacteria.length; i++) {
bacteria[i].moveY = max(height/400, speedfactor * bacteria[i].moveY);
}
lastnettime = millis();
nets.pop();
}
}
}
}
//C
if (keyCode == 67) {
if (bombs.length > 1) {
if (int((millis() - lastbombtime) / 1000) > bombtime) {
score += bacteria.length;
bacteria = [];
lastbombtime = millis();
bombs.pop();
}
}
}
}
//Title Screen
function drawTitle() {
ecg.stop();
clear();
imageMode(CENTER);
image(titleimg, width/2, height/2, min(3*height/4, 2*width/3), 2*height/3);
textSize(48);
textAlign(CENTER, CENTER);
fill("green");
text("IMMUNE DEFENDERS!", width / 2, height / 10);
fill("midnightblue");
textSize(24);
text("Click anywhere to continue", width / 2, (9 * height) / 10);
//Music
if (!titleMusic.isPlaying()){
titleMusic.playMode("restart");
titleMusic.setVolume(1);
titleMusic.play();
titleMusic.setLoop(true);
}
}
//Instructions Panel
function drawInstructions() {
ecg.stop();
clear();
if (stages[stage] == "Instructions1") {
textAlign(CENTER, CENTER);
fill("black");
textSize(36);
text("MISSION BREIFING", width / 2, height / 10);
textSize(24);
text("B-Cell Recruit #742, report for duty!\nThe body is under attack by invasive bacteria,\nand only you have the right antibodies!\n You need to do your duty as a Plasma Cell right now!\nNot to worry, you have the latest technology to assist you.\n\n\nUse Arrow or 'A' and 'D' keys to move the white blood cell.\nUse SPACEBAR to shoot antibodies to collect antigen points.\nAntigen Points can be used to gain special abilities in battle.\nYour goal is to survive as long as possible,\nuntil reinforcements arrive.", width/2, height/2)
text("Click to Continue", width/2, 9*height/10);
} else if (stages[stage] == "Instructions2") {
textSize(24);
textAlign(CENTER, CENTER);
fill("black");
text("Use the Z key to activate a Vitamin C boost,\nwhich allows you to shoot more antibodies in one go.\nThis move costs 15 antigens, and the effect lasts for\n10 seconds.\n\n\nUse the X key to activate Neutrophil Extracellular Traps (NETs)\nthat can slow bacteria down.\nThis move costs 20 antigens, and the effect lasts for\n10 seconds.\n\n\nUse the C key to activate Complement Bomb,\nwhich eliminates all bacteria currently on the screen\nin a finishing move.\nThis killer move costs 30 antigens, and has a cooldown\nof 20 seconds.", width / 2, height / 2);
}
}
//Game screen
function drawGame() {
ecg.stop();
titleMusic.stop();
clear();
background("firebrick");
imageMode(CORNER);
tint (255, 255);
image(bgimg[0], 0, bgy, 5/6 * width, height);
image(bgimg[1], 0, -height+bgy, 5/6 * width, height);
bgy = (bgy + 1) % height
// diplay, movement, collision of bacteria
for (let i = 0; i < bacteria.length; i++) {
bacteria[i].display();
bacteria[i].move();
// invincibility frames
if (millis() - timeofLastDeath > 1500) {
// bacteria dying on contact with cell
if (bacteria[i].collide(lives[0])) {
bacteria.splice(i, 1);
//immune cell dying on contact (if more than 1 life left)
if (lives.length > 1) {
lives.splice(0, 1);
} else {
gameTimerEnd = int((millis() - gameTimer) / 1000);
stage = 4;
}
timeofLastDeath = millis();
}
}
}
// check when bacteria leave the screen (separate loop for logic purpose)
for (let i = 0; i < bacteria.length; i++) {
if (bacteria[i].wallCollide()) {
bacteria.splice(i, 1);
}
}
// immune cell display and indication of i-frames
if (millis() - timeofLastDeath > 1500) {
lives[0].display(255);
} else {
lives[0].display(0.6 * 255);
}
//bullet display,, movement and collision
for (let i = 0; i < bullets.length; i++) {
bullets[i].display();
bullets[i].move();
//Delete bullet and bacterium, and add score when killing bacteria
for (let j = 0; j < bacteria.length; j++) {
if (bullets.length > i) {
//length condition added as parameter changes before draw() function is next called
if (bullets[i].collide(bacteria[j])) {
bullets.splice(i, 1);
bacteria.splice(j, 1);
score++;
}
}
}
//Delete when bullets fly off-screen
if (bullets.length > i) {
//length condition added as parameter changes before draw() function is next called
if (bullets[i].wallCollide()) {
bullets.splice(i, 1);
}
}
}
//immune cell movement control
if (keyIsDown(LEFT_ARROW) || keyIsDown(65)) {
if (lives[0].x > (2 * width) / 15) {
lives[0].x -= 10;
}
}
if (keyIsDown(RIGHT_ARROW) || keyIsDown(68)) {
if (lives[0].x < (5 / 6) * width - (2 * width) / 15) {
lives[0].x += 10;
}
}
if ((frameCount - frameStart) % 120 == 0) {
for (let i = 0; i < numBacteria; i++) {
bx = int(random((2 * width) / 15, (5 / 6) * width - (2 * width) / 15));
by = -height / 40;
br = height / 40;
bspeed = int(speedfactor * random(height / 400, height / 200));
var bacGen = new Bacteria(bx, by, br, bspeed, bacsprites);
bacteria.push(bacGen);
}
}
//Score Display
textAlign(LEFT, CENTER);
textSize(16);
fill(255);
text("Antigens: " + score, 2*width / 20, height / 10);
//Lives Display
textAlign(LEFT, CENTER);
textSize(16);
fill(255);
text("Lives Remaining: " + lives.length, 2*width / 20, height / 20);
//Game Timer
textAlign(RIGHT, CENTER);
textSize(16);
fill(255);
text(
"Time Survived: " + str(int((millis() - gameTimer) / 1000)),
(99 * width) / 100,
height / 20
);
//Powerups
//Boost Powerup
if (boosts.length <= maxboosts && score - booststartscore >= boostcost) {
var boost = new Boost(
boostfactor,
boosttime,
boosticonx,
boosticony,
boosticonw,
boosticon
);
boosts.push(boost);
booststartscore = score;
}
if (boosts.length > 0) {
boosts[0].display(boosts.length - 1);
if (int((millis() - lastboosttime) / 1000) < boosttime) {
boosts[0].update(boosttime - int((millis() - lastboosttime) / 1000));
}
}
//Net Powerup
if (nets.length <= maxnets && score - netstartscore >= netcost) {
var net = new Net(
netfactor,
nettime,
neticonx,
neticony,
neticonw,
neticon
);
nets.push(net);
netstartscore = score;
}
if (nets.length > 0) {
nets[0].display(nets.length - 1);
if (int((millis() - lastnettime) / 1000) < nettime) {
nets[0].update(nettime - int((millis() - lastnettime) / 1000));
} else {
speedfactor = 1;
}
}
//Bomb Powerup
if (bombs.length <= maxbombs && score - bombstartscore >= bombcost) {
var bomb = new Bomb(bombtime, bombiconx, bombicony, bombiconw, bombicon);
bombs.push(bomb);
bombstartscore = score;
}
if (bombs.length > 0) {
bombs[0].display(bombs.length - 1);
if (int((millis() - lastbombtime) / 1000) < bombtime) {
bombs[0].update(bombtime - int((millis() - lastbombtime) / 1000));
}
}
//Music
if (!gametheme.isPlaying()){
gametheme.playMode("restart");
gametheme.setVolume(0.3);
gametheme.play();
gametheme.setLoop(true);
}
}
//Game Over Screen
function drawGameOver() {
gametheme.stop()
if (!ecg.isPlaying() && !ecgPlayed){
ecg.playMode("restart");
ecg.play();
ecg.setLoop(false);
ecgPlayed = true;
}
textFont(font);
fill("khaki");
background(0);
textSize(48);
textAlign(CENTER, CENTER);
rectMode(CENTER);
text("GAME OVER", width / 2, (9 * height) / 20);
textSize(24);
text("\nYou survived " + gameTimerEnd + " seconds", width / 2, height / 2);
text("\n\n\nYou earned " + score + " antigens", width / 2, height / 2);
//Restart Button
restartbutton = new Button(
"Restart",
width / 4,
(7 * height) / 10,
width / 5,
height / 20,
width / 100,
restartbuttoncolor,
buttonhovercolor
);
restartbutton.hover();
restartbutton.display();
restartbutton.click(3);
//Title Screen Button
titlebutton = new Button(
"Title Screen",
(3 * width) / 4,
(7 * height) / 10,
width / 5,
height / 20,
width / 100,
titlebuttoncolor,
buttonhovercolor
);
titlebutton.hover();
titlebutton.display();
titlebutton.click(0);
}