I need help with my Space Invaders clone (second round loading improperly)

I need some help writing a gameplay loop for my Space Invaders clone. I have it partially working, but for whatever reason the second level only spawns 1 ship instead of the 20 I have coded. I cannot figure out why the level progresses but it doesn’t load the way it should. Should I be recalling the setup function for each level perhaps? Here’s my code

Main Loop:

boolean left, right, up;
boolean space;
Player p;
Spaceships [] s;
Projectile [] proj;
int nextProjectile;
Timer firingTimer;
float spacing = 75;
float x = 100;
float y = 100;
int score = 0;
int finalScore;
int highScore;
int level;
int noOfShips = 10;
int shipCount = noOfShips;

void setup(){
  size(680, 680);
  
  p = new Player();
  
  s = new Spaceships[noOfShips];
  for(int k = 0; k < s.length; k++){
    s[k] = new Spaceships(x);
    x += spacing;
    if(x >= width && y >= 100){
      y += spacing;
      x = 50;
    }
  }
  
  left = false;
  right = false;
  space = false;
  
  proj = new Projectile[5];
  for(int l = 0; l < proj.length; l++){
    proj[l] = new Projectile(150 + l * 50, 550);
  }
  
  nextProjectile = 0;
  level = 0;
  
  firingTimer = new Timer(200);
  firingTimer.start();
}

void draw(){
  background(0, 0, 0);
  
  
  
  switch(level){
    case 0:
    startScreen();
    break;
    
    case 1:
    invadersGame(1);
    break;
    case 2:
    invadersGame(2);
    break;
  }
  

  

}

void startScreen(){
  background(0);
  textAlign(CENTER);
  textSize(120);
  text("INVADERS", width/2, height/2);
  textSize(70);
  text("PRESS SPACE \nTO BEGIN", width/2, 450);
}

void invadersGame(int lv){
  
  switch(lv){
    case 1:
    noOfShips = 10;
    break;
    case 2:
    noOfShips = 20;
    break;
  }
  
  noStroke();
  fill(255);
  textSize(12);
  text("SCORE: " + score, 50, 50);
  text("LEVEL: " + level, 150, 50);
  text("AMMO: ", 90, 550);
  text("SHIP COUNT :" + shipCount, 250, 50);
    if(space){
    if(firingTimer.complete()){
      proj[nextProjectile].fire(p.x + p.w/9, p.y + p.h/2, p.facing);
        nextProjectile = (nextProjectile + 1)%proj.length;
        firingTimer.start();
      
    }
  }
  
  for(int i = 0; i < proj.length; i++){
    proj[i].update();
    for(int j = 0; j < s.length; j++){
      if(intersect(proj[i], s[j]) && !s[j].dead){
        //fill(0, 0, 255);
        //rect(0, 0, width, height);
        proj[i].reset();
        s[j].destroy();
        shipCount -= 1;
        if(shipCount == 0){
          //j = 0;
          level++;
          println("Level Up");
          levelUp();
          s[j].reset();
        }
      }
    }
    proj[i].display();
  }
  p.update();
  p.display();
  
  for(int k = 0; k < s.length; k++){
    if(!s[k].dead){
      s[k].move();
    }
    s[k].update();
    s[k].display();
    if(intersect(p, s[k]) && !s[k].dead){
      //fill(255, 0, 0, 50);
     // rect(0, 0, width, height);
    }
  } 
}

void levelUp(){
  
  for(int m = 0; m < s.length; m++){
    if(s[m].dead){
      s[m].dead = false;
      s[m].move();
    }
    s[m].update();
    s[m].display();
  }
  
}

boolean intersect(Player b1, Spaceships b2){
  //Distance on x axis
  float distX = abs((b1.x + b1.w/2) - (b2.x + b2.w/2));
  //distance on y axis
  float distY = abs((b1.y + b1.h/2) - (b2.y + b2.w/2));
  //what is the combined half widths
  float combinedHW = b1.w/2 + b2.w/2;
  //what is the combined half heights
  float combinedHH = b1.h/2 + b2.h/2;
  
  //Check for x axis collision
  if(distX < combinedHW){
    //check on y axis
    if(distY < combinedHH){
      //we collided
      println("YIPPIE");
      return true;
    }
  }
  return false;
}

boolean intersect(Projectile b1, Spaceships b2){
  //Distance on x axis
  float distX = abs((b1.x + b1.w/2) - (b2.x + b2.w/2));
  //distance on y axis
  float distY = abs((b1.y + b1.h/2) - (b2.y + b2.w/2));
  //what is the combined half widths
  float combinedHW = b1.w/2 + b2.w/2;
  //what is the combined half heights
  float combinedHH = b1.h/2 + b2.h/2;
  
  //Check for x axis collision
  if(distX < combinedHW){
    //check on y axis
    if(distY < combinedHH){
      //we collided
      println("YIPPIE");
      return true;
    }
  }
  return false;
}

void keyPressed(){
  switch(keyCode){
    case 37:
    left = true;
    break;
    
    case 38:
    up = true;
    break;

    case 39:
    right = true;
    break;

    case 32:
    space = true;
    if(level == 0){
      level++;
    }
    break;
  }
}


void keyReleased(){
  switch(keyCode){
    case 37:
    left = false;
    break;
    
    case 38:
    up = false;
    break;
   
    case 39:
    right = false;
    break;

    case 32:
    space = false;
    break;
  } 
}

Player Class:

class Player{
  float x, y, w, h;
  float speedX, maxSpeed;
  String facing;
  
  Player(){
    x = width/2;
    y = 600;
    w = 22;
    h = 44;
    maxSpeed = 5;
    speedX = 0;
    facing = "up";
  }
  
  void update(){
    if(left){
      speedX = -maxSpeed;
    }
    if(right){
      speedX = maxSpeed;
    }
    if((!left && !right) || (left && right)){
      speedX = 0;
    }
    
    checkBounds();
    
    PVector v = new PVector();
    v.x = speedX;
    x += v.x;
  }
  
  void display(){
    fill(0, 0, 255);
    rect(x, y - 10, w / 1.5, h + 5);
    rect(x, y, w * 2, h);
  }
  
  void checkBounds(){
     if(x > width){
      x = -w;
    }
    if(x < -w){
      x = width;
    }

  }
  
}

Projectile Class:

class Projectile{
  float x, y, w, h, vx, vy, startingX, startingY;
  float speed;
  boolean inMotion;
  
  Projectile(float sx, float sy){
    startingX = sx;
    startingY = sy;
    x = sx;
    y = sy;
    w = 10;
    h = 15;
    vx = 0;
    vy = 0;
    speed = 10;
    inMotion = false;
  }
  
  void update(){
    x += vx;
    y += vy;
    checkBounds();
  }
  
  void display(){
    fill(255);
    rect(x, y, w, h);
  }
  
  void fire(float newX, float newY, String facing){
    x = newX;
    y = newY;
    if(!inMotion){
      switch(facing){
        case "up":
        vx = 0;
        vy = -speed;
        w = 10;
        h = 20;
        break;
      }
      inMotion = true;
    }
  }
  
  void reset(){
    x = startingX;
    y = startingY;
    vx = 0;
    vy = 0;
    inMotion = false;
  }
  
  void checkBounds(){
    if(x < -w || x > width || y < -h || y > height){
      reset();
    }
  }
    
}

Spaceships Class:

class Spaceships{
  float x;
  float y;
  float w;
  float h;
  float vx;
  float vy;
  float speed;
  float shipSize;
  color c;
  boolean dead;
  int storedTime = 0;
  boolean levelComplete;
  
  Spaceships(float tempX){
  x = tempX;
  y = 100;
  w = 50;
  h = 25;
  vx = 0;
  vy = 0;
  speed = random(1, 2);
  dead = false;
  }
  
  void move(){
    x = x + speed;
    if(x > width){
      //x = x - -speed;
      //x -= -speed;
      speed = -speed;
      y += 100;
    }else if(x < 0){
      speed = -speed;
      y += 100;
    }else if(y > height - 100){
      y = height - 100;
    }
  }
  
  void update(){
    x += vx;
    y += vy;
    //checkBounds();
  }
  
  void display(){
    float offset = shipSize / 4;
    ellipseMode(CENTER);
    rectMode(CENTER);
    strokeWeight(2);
    stroke(0);
    fill(170);
    ellipse(x, y - 10, w / 2, h / 2);
    ellipse(x, y, w, h /2 +3);
    
    stroke(0);
    fill(50, 100, 100);
    ellipse(x, y, w/4, h/4);
    ellipse(x + offset + 15, y, w/5, h/5);
    ellipse(x - offset - 15, y, w/4, h / 4);
    
  }
  
  void destroy(){
    vx = 0;
    vy = 0;
    x = -1000;
    dead = true;
    score += 100;
  }
  
  
  void reset(){
    x = 100;
    y = 100;
    vx = 0;
    vy = 0;
    dead = false;
    speed = random(1, 2);
    //inMotion = false;
  }
  
  void checkBounds(){
    if(x < 0 || x > width){
      //reset();
      x = -speed;
    }
  }
  
  
  
}

Timer Class:

class Timer{
  int startTime;
  int interval;
    
    Timer(int timeInterval){
      interval = timeInterval;
    }
    
    void start(){
      startTime = millis();
    }
    
    boolean complete(){
      int elapsedTime = millis() - startTime;
      if(elapsedTime > interval){
        return true;
      }else{
        return false;
      }
    }
}

If someone could please let me know what I am doing wrong I would greatly appreciate it!

Thanks in advance,
-Mellie

Hello @PaddedMellie ,

Please read:
Guidelines—Asking Questions

It is not necessary to post your entire code.

I suggest that you introduce a state variable to manage state changes:

  • Create a global variable called state:
    boolean state = true; // Initial value
  • Isolate the code that makes the ships and make a function called make()
    You can then call this once in setup or as required later.
  • When there is a state change such as level increasing call the function set state = true; which can then be used to call make().
  • If you are calling make() in draw you only want to do it once and then set
    state = false; after so it is not called multiple times for every draw() cycle..

Code added to draw():

boolean state = true;

void draw(){
  background(0, 0, 0);
   
  if (state)
    {
    println(level, state);  
    
    switch(level)
      {
      case 0:
      break;
      
      case 1:
      shipCount = 1;
      make(shipCount);
      break;
      
      case 2:
      shipCount = 3;
      make(shipCount);
      break;
      
      case 3:
      shipCount = 5;
      make(shipCount);
      break;      
      }          
    state = false;

    println(level, state);   
    }    
    
  switch(level)
    {
    // Your original code here
    }
  }

// makes ships
void make(int _noOfShips)
  {
  s = new Spaceships[_noOfShips];

  // Your code   
 }

The above worked for me and was from experience.

There are other changes to make and you can work these out.
Make liberal use of println() to see what is (or is not) going on at different points in your code.
Use the tools available to you to debug… right click on a variable and Show usage… was useful for me to peruse your code.

At some point consider reworking your code.
The example I provided was patched in… you may be able to integrate this with other code or find a better solution.

See:

Have fun!

:)

1 Like