Midterm Project: Immune Defenders!

Introduction and Concept

The idea for this project came as a sort of natural follow-up to my projects in this class so far. I have tried to include elements of bioinspiration in almost every assignment I have done for this class so far (barring the Data Visualization of Week 4), so I already knew I wanted to do something within that theme.

My inspiration for this game came almost directly from the retro arcade game Galaga by Namco (see image), and the many space shooters it inspired.

Namco’s Galaga

So, my goal was to now somehow combine a space shooter with the immune system. I also wanted it to be relatively accurate to the human immune system, so there was that added challenge.

So, the end result is a game where you control an effector B-cell (or plasma cell), to shoot antibodies at and neutralize bacteria, just like your own immune system does millions of times each day, even when you’re healthy.

Code and Design

With a whopping 783 lines of code (including class definitions), this is easily the largest project I have ever coded. Here are some chunks that I am particularly proud of:

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);
  }
}

So, the above code is used to shoot the bullets that are a core component of the game. But the code is written mainly to handle the challenge of summoning multiple bullets together during the Vitamin C powerup (more on that later). I could have just called it a day and made three separate “new bullets” with the correct x-positions, but I wanted a way to make it uniform for no matter how many bullets could be added by the powerup. This tool from Wolfram Alpha was essential for this, as it calculated a mathematical formula (the part which has quite a few terms involving multiplication of -1 raised to the bullet number). So, whether I add 3, 5, or 19 bullets, theoretically, I should get a consistent result.

//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);
    }
  }
}

The above part of the code deals with the collision logic for the bacteria, and is another part I’m proud of. Using splice() instead of pop() ensures that the correct bacterium is deleted, even when they move out of order because of their different speeds.

Other Code Features

Other features of the code that are important for the functioning of the game, but are not particularly remarkable are the event handlers for clicking and key presses. While clicking to change stage, I had to ensure that the user wouldn’t accidentally click out of the game into the game over screen, but that was easy enough with some conditionals. Key event listeners involve the shooting using the keyboard, movement visa left/right or A/D keys, and using powerups via the Z, X, C keys. Each had their respective actions coded within the event handler itself.

There is also a timer that tracks the time from each iteration of the game starting anew (even in the same sketch run), as well as a counter to track score. The timer is used to both indicate the length of time survived by the player, as well as to control the powerup cooldowns.

Classes

There are a total of 7 classes: Bacteria (display, movement and collision of bacteria), Immune (immune cell display), Bullet (display, movement and collision of bullet), Boost, Net, Bomb (display and update of the cooldown of the powerups), and Button (hover/click behavior of end-screen buttons). I realize now that I could have probably included the three powerup classes under one, but I had initially planned to have their respective functions as class methods. I could probably still have done that by inheritance, but I wasn’t aware of how to make parent classes in p5 or JS, and I did not have sufficient time to learn.

Gameplay

As described earlier, the game is basically a Galaga clone. All you primarily do is shoot down or dodge waves of bacteria (enemy spaceships). To make the gameplay more interesting however, I included three powerups.

The first powerup (try pressing the Z key), allows you to shoot out 3 antibodies per shot instead of just one. That turns out to be particularly useful when the bacteria tend to be just off the exact center mark of the white blood cell.

The second powerup (X key) allows you to slow down the bacteria, giving you more time to shoot or dodge them, whichever you prefer. This powerup was based on the ability of some neutrophils (one of the types of white blood cells that act as a first-line defender) to produce traps that literally stick the bacteria in place so that they can be neutralized and then consumed by other immune cells.

The third and final powerup (C key) almost feels like cheating as it completely nukes everything on the screen and gives you the rewards for it. Initially, I wanted to balance it by reducing the score you get back, but I realized that would confuse players (after all, the bacteria are being killed). So, instead I balanced it with a high score cost, which does kind of match real life. Such an attack that kills multiple colonies of bacteria in one go often results in the immune cells attacking the body’s own healthy cells as well, engaging in inflammatory reactions with massive collateral damage, often causing even more damage than the disease on its own.

The best part about these powerups according to me is that they’re all based at least loosely in real biological concepts, and are not just make-believe gameplay conveniences.

Graphics

Graphics were mostly obtained from royalty-free clipart on the web, which I then recolored to increase contrast/make them look more interesting. The title card’s image was generated using DALLE-3 on Bing Copilot. Any editing required was easily done in Microsoft Paint 3D.

All of the graphics elements involved in this project.

Sound and Music

Pixabay has always been a lifesaver for me when it comes to obtaining high-quality royalty-free/Creative Commons-licensed music and sound effects without any pesky registration or annoying PLUS subscriptions (this is not an ad). I already had somewhat of a general idea of the feel of music I was going for, so I just searched up a few different categories and stuck to the music that immediately hit it off with me. I trimmed a few of the sound clips using Audacity and also put them through FileConvert’s compression tool to reduce the burden on p5.js, which does tend to struggle with loading heavy images/sounds. My only regret is not leaving enough time to include SFX for the powerups.

Pixabay User Interface

Challenges, Improvements and Future Considerations

Bug-fixing was probably the most challenging aspect. Because I had worked on the project over several days, I found that there were often things I was forgetting that led to weird interactions and things not going as expected. Asking my roommate to play-test the game definitely did help.

There are many things that I wanted to include that had to be left out in the interest of time. I had planned to include other pathogens, including viruses that didn’t damage your health but instead temporarily blocked your ability to shoot, and even a parasite final boss that would not attack you directly but instead open up more wounds for hordes of bacteria and viruses to enter the blood vessel and overwhelm the player.

Additionally, as mentioned earlier, I would have preferred to have more sound effects, for not just the powerup, but also when the player was hit by a bacterium and lost a life. However, overall, I am happy with the final result, and I can say that it closely matched my initial expectations.

Midterm Demo

Fullscreen Link: https://editor.p5js.org/amiteashp/full/Uvgv-fIWb

Link to project on P5 editor: https://editor.p5js.org/amiteashp/sketches/Uvgv-fIWb

 

Leave a Reply