Space Invaders V-2

This is a fairly straightforward upgrade on my last iteration of Space Invaders to use an analog thumb joystick instead of keys. I also made a few changes to the code, specifically changing the scoring system, allowing the ship to move in more directions, making it autoshoot, and allowing the ship to collide with the enemies (which kills the enemy and looses a life).

The new code is

import processing.serial.*;
Serial myPort;
Game game;
float divisions= 50;
void setup() {
  printArray(Serial.list());
  String portname=Serial.list()[0];
  println(portname);
  myPort = new Serial(this, portname, 9600);
  myPort.clear();
  myPort.bufferUntil('\n');
  size(500, 500);
  game= new Game();
  frameRate(30);
}
void draw() {
  game.draw();
  if (!game.update()) {
    int score= game.getScore();
    game=null;
    background(0);
    textSize(32);
    text("Game Over", width/7, height/2-50);
    text("Score: "+score, width*3/7, height/2+50);
    noLoop();
  }
}
void keyPressed() {
  game.keyPressed(key);
}
void serialEvent(Serial myPort) {
  game.serialEvent(myPort);
}
import java.util.Iterator;
class Game {
  ArrayList<Enemy> enemies;
  Ship ship;
  ArrayList<Projectile> projectiles;
  float timer;
  float enemyRate= 500;
  float levelTimer;
  float levelRate= 30000;
  int lives;
  int score;
  int scoreStep;
  Game() {
    enemies= new ArrayList<Enemy>();
    ship= new Ship(this);
    projectiles= new ArrayList<Projectile>();
    timer= millis();
    levelTimer= millis();
    lives= 10;
    scoreStep=1;
  }
  void keyPressed(int key) {
    ship.keyPressed(key);
  }
  boolean update() {
    Enemy enemy;
    Iterator<Enemy> enemyIterator= enemies.iterator();
    while (enemyIterator.hasNext()) {
      try {
        enemy=enemyIterator.next();
      }
      catch(Exception e) {
        break;
      }
      enemy.update();
      Projectile projectile;
      Iterator<Projectile> projectileIterator= projectiles.iterator();
      if (enemy.reachedEnd(height-ship.sHeight)) {
        enemies.remove(enemyIterator);
        enemies.remove(enemy);
        score-=100;
        lives--;
      }
      if (enemy.checkImpact(ship)) {
        enemies.remove(enemyIterator);
        enemies.remove(enemy);
        score-=100;
        lives--;
      }
      while (projectileIterator.hasNext()) {
        try {
          projectile=projectileIterator.next();
        }
        catch(Exception e) {
          break;
        }
        if (projectile.checkImpact(enemy)) {
          enemies.remove(enemyIterator);
          enemies.remove(enemy);
          projectiles.remove(projectileIterator);
          projectiles.remove(projectile);
          score+=scoreStep;
        }
      }
      if (levelTimer+levelRate<millis()) {
        enemyRate/=1.3;
        scoreStep*=2;
        levelTimer=millis();
      }
    }
    ship.update();
    for (Projectile projectile : projectiles) {
      projectile.update();
    }
    if (timer+enemyRate<millis()) {
      enemies.add(new Enemy(width/divisions, height/divisions, game));
      timer=millis();
    }
    return lives>0;
  }
  void draw() {
    background(0);
    for (Enemy enemy : enemies) {
      enemy.draw();
    }
    ship.draw();
    for (Projectile projectile : projectiles) {
      projectile.draw();
    }
    fill(255);
    textSize(10);
    text("lives: "+lives, 10, height-10);
    text("score: "+score, width-80, height-10);
  }
  void addProjectile(Projectile projectile) {
    projectiles.add(projectile);
  }
  int getScore() {
    return score;
  }
  void serialEvent(Serial myPort) {
    ship.serialEvent(myPort);
  }
}
class Projectile{
  float x;
  float y;
  float xVelocity;
  float yVelocity;
  Projectile(float x, float y){
    this.x=x;
    this.y=y;
  }
  void update(){
    x+=xVelocity;
    y+=yVelocity;
  }
  void draw(){
    stroke(255);
    point(x,y);
  }
  boolean checkImpact(Enemy enemy){
    return((x-enemy.getX())*(x-enemy.getX())+(y-enemy.getY())*(y-enemy.getY()))<enemy.getR()*enemy.getR();
  }
}
class Enemy {
  float x;
  float y;
  float r;
  float xVelocity;
  int direction;
  Game game;
  Enemy(float x, float y, Game game) {
    this.game=game;
    this.x=x;
    this.y=y;
    r=sqrt(width*height/(divisions*divisions));
    xVelocity=r/2;
    direction=1;
  }
  void update() {
    if (r<x&&x<width-r||direction==0) {
      if (direction==0) {
        if (x<width/2) {
          direction=1;
        } else {
          direction=-1;
        }
      }
      x+=xVelocity*direction;
    } else if (x<=r&&direction!=0) {
      y+=2*r;
      direction=0;
    } else if (x>=width-r&&direction!=0) {
      y+=2*r;
      direction=0;
    }
  }
  void draw() {
    fill(255);
    ellipse(x, y, r, r);
  }
  float getX() {
    return x;
  }
  float getY() {
    return y;
  }
  float getR() {
    return r;
  }
  boolean reachedEnd(float y) {
    return this.y>y;
  }
  boolean checkImpact(Ship ship) {
    return((x-ship.getX())*(x-ship.getX())+(y-ship.getY())*(y-ship.getY()))<ship.getR()*ship.getR();
  }
}
class Ship{
  float x;
  float step;
  float y;
  boolean shooting;
  float sWidth;
  float sHeight;
  float timer;
  float fireRate;
  float step0;
  Game game;
  Ship(Game game){
    this.game= game;
    x= width/2;
    step= width/(divisions*2);
    y= width*(divisions-2)/divisions;
    sWidth= width/divisions;
    sHeight= height/divisions;
    timer= millis();
    fireRate= 250;
    shooting=false;
    step0=step;
  }
  void keyPressed(int key){
    if(key=='x'&&x<width-sWidth){
      x+= step;
    }
    else if(key=='z'&&x>sWidth){
      x-= step;
    }
    else if(key==' '){
      shooting=!shooting;
    }
  }
  void serialEvent(Serial myPort){
    String s=myPort.readStringUntil('\n');
    s=trim(s);
    if (s!=null){
      int values[]=int(split(s,','));
      int X= 0, Y=0;
      if (values.length==3){
        X=(int)map(values[0],0,1023,-step, step);
        Y=(int)map(values[1],0,1023,-step, step);
        if(values[2]>0){
          step=step0/2;
          shooting=true;
        }
        else{
          shooting=false;
          step=step0*2;
        }
      }
      x+=X;
      y-=Y;
      if(x<0){
        x=sWidth;
      }
      if(x>width){
        x=width-sWidth;
      }
      if(y<0){
        y=sHeight;
      }
      if(y>height){
        y=height-sHeight;
      }
    }
  }
  void update(){
    if(timer+fireRate<millis()&&shooting){
      shoot();
      timer= millis();
    }
  }
  void draw(){
    triangle(x-sWidth/2,sHeight+y,x,y,x+sWidth/2,sHeight+y);
  }
  void shoot(){
    game.addProjectile(new ShipProjectile(x,y));
  }
  float getY(){
    return y;
  }
  float getX(){
    return x;
  }
  float getR(){
    return sWidth;
  }
}
class ShipProjectile extends Projectile{
  ShipProjectile(float x, float y){
    super(x,y);
    xVelocity=0;
    yVelocity=-height/divisions*3/4;
  }
}

The arduino code is super simple:

const int X= A0;
const int Y= A1;
const int Z= A2;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
}

void loop() {
 // if(Serial.available()>0){
    int x = analogRead(X);
    delay(1);
    int y = analogRead(Y);
    delay(1);
    int z = analogRead(Z);
    delay(1);
    Serial.print(x);
    Serial.print(',');
    Serial.print(y);
    Serial.print(',');
    Serial.println(z);
  //}
}

 

Leave a Reply

Your email address will not be published. Required fields are marked *