Why doesn't this ball move?

Ball bl;

void setup () {
  size (600, 300);
}

void draw () {
  background(0);
  bl = new Ball(300, 150);
  bl.display();
}

class Ball {

  float x;
  float y;
  float diameter = 100;
  float xspeed = 1;
  float yspeed = 1;

  Ball (float tempx, float tempy) {
    x = tempx;
    y = tempy;
  }

  void display() {
    x=x+xspeed;
    y=y+yspeed;
    if ( y > height-diameter/2  || y < diameter/2) {
      yspeed = -yspeed;
    } else if ( x > width-diameter/2 || x < diameter/2 ) {
      xspeed = -xspeed;
    }
    ellipse (x, y, diameter, diameter);
  }
}

Thanks for help from now. ^^

«1

Answers

  • Answer ✓

    You are creating a new ball every frame. Move line 9 to setup.

  • Oh, you are right thank you. And do you maybe have any idea how can i create a second ball without adding a new class?

  • I did this btw, what do you think? Is it good way to do this?

    Ball bl, bl2;
    
    void setup () {
      size (600, 400);
      bl = new Ball(300, 150);
      bl2 = new Ball(115, 255);
    }
    
    void draw () {
      background(0);
      bl.display();
      bl2.display();
    }
    
    class Ball {
    
      float x;
      float y;
      float xspeed = 3;
      float yspeed = 4;
      float diameter = 100;
    
      Ball (float tempx, float tempy) {
        x = tempx;
        y = tempy;
      }
    
      void display() {
        x=x+xspeed;
        y=y+yspeed;
        if ( y > height-diameter/2  || y < diameter/2) {
          yspeed = -yspeed;
        } else if ( x > width-diameter/2 || x < diameter/2 ) {
          xspeed = -xspeed;
        }
        ellipse (x, y, diameter, diameter);
      }
    }
    
  • edited April 2017 Answer ✓

    yeah, that's the purpose of a class: to have many objects derived from the same class:without you need to rewrite the class. In the class you can write as if there's only one ball. Outside the class you handle many balls.

    The class is the cookie maker and the objects are the cookies. ONE cookie maker, many objects.

    There is also a tutorial on that named objects

    https://www.processing.org/tutorials/objects/

    Now you have

        Ball bl;
    

    and then

        Ball b1;
        Ball b2;
    

    later use arrays / ArrayList to hold the balls together with a for loop please

  • Answer ✓

    ah our posts overlapped.

    we were writing at the same time

    looks good

    as said: later use arrays / ArrayList to hold the balls together with a for loop please

  • edited April 2017 Answer ✓

    line 19 and 20

    float xspeed = 3;
    float yspeed = 4;
    

    could be

    float xspeed = random(-4,4);
    float yspeed = random(-4,4);
    

    you could give the ball class a color to fill (also random in the constructor of the class or before it)

  • Answer ✓

    line 33 it's not necessary to use else if here, it's even wrong, because we could have an x and y bounce at the same time, in a corner

    just use if

    technically

    technically the method display does also move the ball. Thus is should be named moveAndDisplay or so. Since it also does the bouncing, we could also use run or script as a name for it. But all names should reflect what they are doing and the methods should not hold surprises (do other things beside their purposes suggested by their name)

  • It looks now much better. :\">

    I will learn the ArrayList and study the codes GoToLoop has sent. Then let's see what could i do. :\">

  • Answer ✓

    ;-)

  • edited April 2017

    Chrisir, i think i could make sense of this ArrayList.

    ArrayList<ClassName> ListName;
    
    void setup () {
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
      ListName = new ArrayList<ClassName>();
      for (int i = 0; i < 10; i++) {
        ListName.add(new ClassName());
      }
    }
    
    void draw () {
      background(#70C1B3);
      for (ClassName c : ListName) {
        c.moveAndDisplayEnemyBalls();
        c.moveAndDisplayOurBall();
      }
    }
    
    class ClassName {
    
      float diameter = 30; 
      float x=random(diameter, width-diameter); 
      float y=random(diameter, height-diameter); 
      float xspeed = random(-4, 4); 
      float yspeed = random(-4, 4); 
    
    
      void moveAndDisplayEnemyBalls() {
        x=x+xspeed; 
        y=y+yspeed; 
        if ( y > height-diameter/2  || y < diameter/2) {
          yspeed = -yspeed;
        } 
        if ( x > width-diameter/2 || x < diameter/2 ) {
          xspeed = -xspeed;
        }
        fill(#247BA0);
        stroke(255);
        strokeWeight(2);
        ellipse (x, y, diameter, diameter);
      }
    
      void moveAndDisplayOurBall() {
        fill(#FF1654);
        stroke(255);
        strokeWeight(2);
        ellipse (mouseX, mouseY, diameter, diameter);
      }
    }
    
    void mousePressed() {
      if (mouseButton==LEFT) {
        ListName.add(new ClassName());
      }
    }
    
    void keyPressed() {
      if (keyPressed) {
        if (key==DELETE) {
          ListName.clear();
          for (int i = 0; i < 10; i++) {
            ListName.add(new ClassName());
          }
        }
      }
    }
    

    What do you think about this one? My goal is this: If enemy balls hit our ball then loop clears the array. How can i do this? Or have can i add ball every 30 frame for example?

  • Answer ✓

    Classname and listname should be Ball and balls

    Note that class names are always beginning with a capital and are singular and the List small first letter and plural form.

    Display our ball does not belong inside the ball , it does not use any of the variables in that class. More over you are drawing the same ball again and again how many times as you have enemy balls. Complete waste of processor time.

    Move it outside the class

    Line 18 must be outside the for loop for this

  • edited April 2017 Answer ✓

    Look at dist() and use

    if(dist(.... to check whether hit takes place. if so say list.clear();

    To spawn a new one look at millis() and say in draw

    if (millis() - startTime > interval){

    list.add.....

    startTime= millis();

    }

    startTime and interval must be variables before setup()

    set interval to 1200 or so

  • edited April 2017

    I got the creating new ball every x sec, thanks.

    I learned dist(), logic must something like this i guess: if (dist(mouseX, Balls'X) < diameterOfBall && dist(mouseY, Balls'Y) < diameterOfBall ){ }

    But how can i find the position of these random balls?

    Here are the last version of codes:

    //Time
    int lastTimeCheck;
    
    //Bucket for enemy balls
    ArrayList<Ball> balls;
    
    void setup () {
      //Standart Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
      //Create enemy balls and ArrayList
      balls = new ArrayList<Ball>();
      for (int i = 0; i < 5; i++) {
        balls.add(new Ball());
      }
    }
    
    float diameter = 30;
    
    void draw () {
      background(#70C1B3);
    
      //Show the level on top left. Level is based on interval
      int interval = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/interval, height/40, height/19);
    
      //Create enemy ball every 3 sec
      if ( millis() > lastTimeCheck + interval) {
        lastTimeCheck = millis();
        balls.add(new Ball());
      }
      //Get the created enemy balls
      for (Ball c : balls) {
        c.moveAndDisplayEnemyBalls();
      }
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, diameter, diameter);
    }
    
    //Enemyball
    class Ball {
    
      float x=random(diameter, width-diameter); 
      float y=random(diameter, height-diameter); 
      float xspeed = random(-4, 4); 
      float yspeed = random(-4, 4); 
    
      void moveAndDisplayEnemyBalls() {
        x=x+xspeed; 
        y=y+yspeed; 
        if ( y > height-diameter/2  || y < diameter/2) {
          yspeed = -yspeed;
        } 
        if ( x > width-diameter/2 || x < diameter/2 ) {
          xspeed = -xspeed;
        }
        fill(#247BA0);
        stroke(255);
        strokeWeight(2);
        ellipse (x, y, diameter, diameter);
      }
    }
    
    
    //Add new enemy ball by manuel
    void mousePressed() {
      if (mouseButton==LEFT) {
        balls.add(new Ball());
      }
    }
    
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        balls.clear();
        for (int i = 0; i < 10; i++) {
          balls.add(new Ball());
        }
      }
    }
    
  • edited April 2017 Answer ✓

    If diameter is used exclusively inside class Ball, you should move it to there instead. *-:)

    And if its value never changes, you should consider declare it static final and use an ALL_CAPS name for it. :>

    And while we're at it, how about defining an accompany RADIUS too, so you don't need to type in DIAMETER/2 all the time. ;)

    class Ball {
      static final int DIAMETER = 30, RADIUS = DIAMETER >> 1;
      static final float MIN_SPEED = .8, MAX_SPEED = 4;
    
      float x = random(RADIUS, width  - RADIUS);
      float y = random(RADIUS, height - RADIUS);
    
      float vx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float vy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((x += vx) < RADIUS | x > width  - RADIUS)  vx *= -1;
        if ((y += vy) < RADIUS | y > height - RADIUS)  vy *= -1;
      }
    
      void display() {
        ellipse(x, y, DIAMETER, DIAMETER);
      }
    }
    
  • It looks now more intresting but can you explain two thing:

    Why did you use DIAMETER >> 1 instead of DIAMETER/2? Why do we use ALL_CAPS names for the values never change?

  • Answer ✓
    • >> 1 is equivalent to / 2. :P
    • ALL_CAPS for constants is a convention followed by many programming languages.
    • For example: Java, JS, C, Python, etc.
  • ALL_CAPS convention for constants is even adhered by Processing itself.
    Check out interface PConstants at the link below: ~O)

    https://GitHub.com/processing/processing/blob/master/core/src/processing/core/PConstants.java#L40

  • edited April 2017

    But you've also used bitwise or operator instead of my logical || operator. It seems you have a good reason for that and i feel you don't tell me this. [-X

  • edited April 2017 Answer ✓

    In Java, the operator | is overloaded to accept boolean type in addition to integer values. :ar!

    Therefore the only diff. between || & | is that the former set ups a short-circuit for lazy evaluation:
    https://en.Wikipedia.org/wiki/Short-circuit_evaluation

    While for the latter, its evaluation strategy is eager. :-B
    https://en.Wikipedia.org/wiki/Eager_evaluation

  • edited April 2017

    Thanks, i've learned a lot again. Do you know how can i get the x and y positions of the random balls that i can calculate the dist() to my mouseX and Y and give ''game over'' message?

    //Time
    int lastTimeCheck;
    
    //Bucket for enemy balls
    ArrayList<Ball> balls;
    
    void setup () {
      //Standart Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
      //Create enemy balls and ArrayList
      balls = new ArrayList<Ball>();
      for (int i = 0; i < 5; i++) {
        balls.add(new Ball());
      }
    }
    
    float diameter = 30;
    
    void draw () {
      background(#70C1B3);
    
      //Show the level on top left. Level is based on interval
      int interval = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/interval, height/40, height/19);
    
      //Create enemy ball every 3 sec
      if ( millis() > lastTimeCheck + interval) {
        lastTimeCheck = millis();
        balls.add(new Ball());
      }
      //Get the created enemy balls
      for (Ball c : balls) {
        c.move();
        c.display();
      }
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, diameter, diameter);
    }
    
    //Enemyball
    class Ball {
      static final int DIAMETER = 30, RADIUS = DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 4;
    
      float x = random(RADIUS, width  - RADIUS);
      float y = random(RADIUS, height - RADIUS);
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((x += speedx) < RADIUS || x > width  - RADIUS)  speedx *= -1;
        if ((y += speedy) < RADIUS || y > height - RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(x, y, DIAMETER, DIAMETER);
      }
    }
    
    
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        balls.clear();
        for (int i = 0; i < 10; i++) {
          balls.add(new Ball());
        }
      }
    }
    
  • edited April 2017

    your dist is wrong

    It must be in your ball's for loop in draw (because you want to check every enemy ball against our own mouse ball)

    if(dist(mouseX,mouseY,  c.x, c.y) < diameter/ 2 + c.RADIUS) { 
    
        // game over
    
        .......
    
    } 
    
  • edited April 2017

    What you're asking is about point/circle collision check:
    http://www.JeffreyThompson.org/collision-detection/point-circle.php

    Let's add a new method to your class Ball to check whether mouse's cursor is inside it:

    boolean checkMouseInside() {
      return sq(mouseX - x) + sq(mouseY - y) < RADIUS*RADIUS;
    }
    

    Now within draw(), in your loop there, invoke this new method along w/ the others:

    for (final Ball b : balls) {
      b.move();
      b.display();
      if (b.checkMouseInside())  println("Game Over!   O_o");
    }
    
  • Not bad but it's not taking into account the mouse ball radius

  • edited April 2017

    Oops! I didn't realize those mouse coords. were bound to an ellipse()! b-(

    So it's not point/circle anymore but circle/circle intersect check: 3:-O
    http://www.JeffreyThompson.org/collision-detection/circle-circle.php

    Then let's declare constants for that solely ellipse()'s diameter & radius at the top of the sketch:

    static final int MOUSE_DIAMETER = 30, MOUSE_RADIUS = MOUSE_DIAMETER >> 1;
    

    Inside draw(), we'll display that single ball w/:

    ellipse(mouseX, mouseY, MOUSE_DIAMETER, MOUSE_DIAMETER);
    

    For Ball::checkMouseBallInside(), we're gonna take that extra radius in consideration too: L-)

    boolean checkMouseBallInside() {
      return sq(mouseX - x) + sq(mouseY - y) < RADIUS*RADIUS + MOUSE_RADIUS*MOUSE_RADIUS;
    }
    
  • edited April 2017

    Expression RADIUS*RADIUS + MOUSE_RADIUS*MOUSE_RADIUS seems too big for my taste. /:)
    How about we cache its result as a constant too: :P

    static final int MOUSE_DIAMETER = 30, MOUSE_RADIUS = MOUSE_DIAMETER >> 1;
    
    class Ball {
      static final int DIAMETER = 30, RADIUS = DIAMETER >> 1;
      static final int RADII_SQUARED_SUM = RADIUS*RADIUS + MOUSE_RADIUS*MOUSE_RADIUS;
      static final float MIN_SPEED = .8, MAX_SPEED = 4;
    
      boolean checkMouseBallInside() {
        return sq(mouseX - x) + sq(mouseY - y) < RADII_SQUARED_SUM;
      }
    }
    
  • edited April 2017

    WOW! It works, very smart. :x

    I just changed your codes little bit that i can picture it to myself better :

    boolean checkMouseInside() {
      return sqrt(sq(mouseX - x) + sq(mouseY - y)) < MOUSE_DIAMETER;
    }
    

    Is it o.k. so?

    And can you please explain what does this do:

    (random(1) < .5? -1 : 1);

  • (random(1) < .5? -1 : 1); is a terniary operator, a compressed if-else statement:

    int input=10;  
    boolean is_bigger_than_50 = input >50? true:false;
    

    although this example is redundant as it can be shorten to: boolean is_bigger_than_50 = input >50

    Kf

  • Gottfried, be careful copying these syntactic quirks, they are often not best practice.

    using >> 1 instead of the shorter and clearer / 2 for instance, or anything that's unexpected and needs further clarification, wouldn't pass any decent code review.

  • GottfriedBoehm

    I don't think your last entry is correct- just compare to gotoloops version

  • return sqrt(sq(mouseX - x) + sq(mouseY - y)) < MOUSE_DIAMETER;

    As already pointed out, it should be the sum of radii: #-o

    return sqrt(sq(mouseX - x) + sq(mouseY - y)) < RADIUS + MOUSE_DIAMETER;

    Alternatively you can also use dist(): https://Processing.org/reference/dist_.html :)

    return dist(mouseX, x, mouseY, y) < RADIUS + MOUSE_DIAMETER;

    To simplify even more, cache the sum as 1 constant: B-)

    static final int RADII_SUM = RADIUS + MOUSE_DIAMETER;
    
    boolean checkMouseBallInside() {
      return dist(mouseX, x, mouseY, y) < RADII_SUM;
    }
    
  •          return dist(mouseX, mouseY, x,y) < RADII_SUM;
    
  • edited April 2017

    random(1) < .5? -1 : 1;

    ? : is called the conditional operator. A.K.A ternary b/c it demands 3 operands:
    https://Processing.org/reference/conditional.html

    That particular expression w/ ? : got 50% of evaluating as -1 and 50% of 1.

    Multiplying that to the 1st expression random(MIN_SPEED, MAX_SPEED), make field vx 50% chance to have an initial negative value. :P

  • edited April 2017

    Here is the last version, i am almost happy. :D <:-P

    My next goal is if collisions happen, it display ''GAME OVER'' text with background colour and if player clicks space game starts again. Can you guys help me also for this one?

    //Time
    int lastTimeCheck;
    
    //Diameter and radius of our ball
    static final int FRIEND_DIAMETER = 30, FRIEND_RADIUS = FRIEND_DIAMETER >> 1 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    void setup () {
      //Standart Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    }
    
    void draw () {
      background(#70C1B3);
    
      //Show the level on top left. Level is based on INTERVAL
      int INTERVAL = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/INTERVAL, height/40, height/19);
    
      //Get the created stupid enemy balls at start
      for (EnemyBall c : balls) {
        c.move();
        c.display();
        if (c.checkMouseInside()) {
          println("Game Over!");
        }
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        balls.add(new EnemyBall());
      }
    
      //Get the created intelligent follower enemy balls
      for (FollowerEnemyBall f : followingBalls) {
        f.move();
        f.display();
        if (f.checkMouseInside()) {
          println("Intelligent Ball Got You!");
        }
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        followingBalls.add(new FollowerEnemyBall());
      }
    
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
    }
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float ENEMY_DIAMETER = random(10, 30), ENEMY_RADIUS = ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(ENEMY_RADIUS, width  - ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(ENEMY_RADIUS, height - ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((enemyX += speedx) < ENEMY_RADIUS || enemyX > width  - ENEMY_RADIUS)  speedx *= -1;
        if ((enemyY += speedy) < ENEMY_RADIUS || enemyY > height - ENEMY_RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(enemyX, enemyY, ENEMY_DIAMETER, ENEMY_DIAMETER);
      }
    
      //Enemy ball's distance to mouse
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) < FRIEND_DIAMETER;
      }
    }
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
      float ENEMY_DIAMETER = random(40, 60), ENEMY_RADIUS = ENEMY_DIAMETER / 2;
      float febX = width/2;
      float febY= height/2;
      void move () {
        febX = lerp(febX, mouseX, 0.01);
        febY = lerp(febY, mouseY, 0.01);
      }
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        ellipse (febX, febY, ENEMY_DIAMETER, ENEMY_DIAMETER);
      }
    
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - febX) + sq(mouseY - febY)) < ENEMY_DIAMETER;
      }
    }
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        balls.clear();
        followingBalls.clear();
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        followingBalls.add(new FollowerEnemyBall());
      }
    }
    
  • Show your attempt for this one.

    Where are you stuck?

    Make a boolean gameOver which is initially false; set it to true then.

    In draw() make a BIG if(gameOver)....

  • My attempt is like this:

    above the setup: //Classes for stupid enemy balls and intelligent follower enemy balls EnemyBall e; FollowerEnemyBall f;

    in setup: //Load the classes e = new EnemyBall(); f = new FollowerEnemyBall();

    And here is the whole codes (i get somehow all the time game over):

    //Time
    int lastTimeCheck;
    
    //Classes for stupid enemy balls and intelligent follower enemy balls
    EnemyBall e;
    FollowerEnemyBall f;
    
    //Diameter and radius of our ball
    static final int FRIEND_DIAMETER = 30, FRIEND_RADIUS = FRIEND_DIAMETER >> 1 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    void setup () {
      //Standart Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
    
      //Load the classes
      e = new EnemyBall();
      f = new FollowerEnemyBall();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    }
    
    void draw () {
    
      background(#70C1B3);
    
      //Show the level on top left. Level is based on INTERVAL
      int INTERVAL = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/INTERVAL, height/40, height/19);
    
      if (e.checkMouseInside()) {
        //Get the created stupid enemy balls at start
        for (EnemyBall e : balls) {
          e.move();
          e.display();
        }
    
        //Create stupid enemy ball every 3 secs
        if ( millis() > lastTimeCheck + INTERVAL) {
          lastTimeCheck = millis();
          balls.add(new EnemyBall());
        }
    
        //Get the created intelligent follower enemy balls
        for (FollowerEnemyBall f : followingBalls) {
          f.move();
          f.display();
        }
    
        //Create stupid enemy ball every 3 secs
        if ( millis() > lastTimeCheck + INTERVAL) {
          lastTimeCheck = millis();
          followingBalls.add(new FollowerEnemyBall());
        }
    
        //Create our ball
        fill(#FF1654);
        stroke(255);
        strokeWeight(2);
        ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
      } else {
        //For Game Over Message
        background(0);
      }
    }
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float ENEMY_DIAMETER = random(10, 30), ENEMY_RADIUS = ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(ENEMY_RADIUS, width  - ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(ENEMY_RADIUS, height - ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((enemyX += speedx) < ENEMY_RADIUS || enemyX > width  - ENEMY_RADIUS)  speedx *= -1;
        if ((enemyY += speedy) < ENEMY_RADIUS || enemyY > height - ENEMY_RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(enemyX, enemyY, ENEMY_DIAMETER, ENEMY_DIAMETER);
      }
    
      //Enemy ball's distance to mouse
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) < FRIEND_DIAMETER;
      }
    }
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
      float ENEMY_DIAMETER = random(40, 60), ENEMY_RADIUS = ENEMY_DIAMETER / 2;
      float febX = width/2;
      float febY= height/2;
      void move () {
        febX = lerp(febX, mouseX, 0.01);
        febY = lerp(febY, mouseY, 0.01);
      }
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        ellipse (febX, febY, ENEMY_DIAMETER, ENEMY_DIAMETER);
      }
    
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - febX) + sq(mouseY - febY)) < ENEMY_DIAMETER;
      }
    }
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        balls.clear();
        followingBalls.clear();
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        followingBalls.add(new FollowerEnemyBall());
      }
    }
    
  • First

    Well, some remarks.

      return sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) < FRIEND_DIAMETER;
    

    don't we want < RADIUS + MOUSE_DIAMETER

    (gotoloop said that)

    Second

    not needed:

        //Classes for stupid enemy balls and intelligent follower enemy balls
        EnemyBall e;
        FollowerEnemyBall f;
    

    we handle the enemies via the ArrayList not with simple objects

    Third

    this must be in a for-loop

          if (e.checkMouseInside()) {
    

    because we want to check every enemy against the player

    Fourth

    Make a boolean gameOver which is initially false; set it to true on collision.

    In draw() make a BIG if(gameOver)....

  • sqrt(sq(mouseX - febX) + sq(mouseY - febY))

    You use something like this twice in your code. Look up dist () in the reference.

  • edited May 2017

    For first remark:

    I have just tought < FRIEND_DIAMETER (meant the mouse diameter) works but if i check, i doesn't work pinpoint. Then i had this one:

    return sqrt(sq(mouseX - febX) + sq(mouseY - febY)) <= FRIEND_DIAMETER/2 + ENEMY_DIAMETER/2;

    But after this i've noticed, it doesn't check the collision exactly. then i added FRIEND_DIAMETER/2 + ENEMY_DIAMETER/2 + 5; and this works somehow, i don't know why.

    Remark fourth:

    I've now this one in classes (should it be actually there?) but i get error message (found one too many { characters without a } to match it.

      //Game over tur or false?
      boolean gameOver = false; 
      if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= (FRIEND_DIAMETER/2 + STUPID_INT_ENEMY_DIAMETER/2 + 5)) {
        gameOver = true;
      } else {
        gameOver = false;
      }
    

    And here is the last version:

    //Time
    int lastTimeCheck;
    
    //Diameter and radius of our ball
    static final int FRIEND_DIAMETER = 30, FRIEND_RADIUS = FRIEND_DIAMETER >> 1 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    void setup () {
      //Standard Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    }
    
    void draw () {
    
      background(#70C1B3);
    
      //Show the level on top left. Level is based on INTERVAL
      int INTERVAL = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/INTERVAL, height/40, height/19);
    
      //for (e.checkMouseInside()) {
      //Get the created stupid enemy balls at start
      for (EnemyBall e : balls) {
        e.move();
        e.display();
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        balls.add(new EnemyBall());
      }
    
      //Get the created intelligent follower enemy balls
      for (FollowerEnemyBall f : followingBalls) {
        f.move();
        f.display();
      }
    
      //Create intelligent follower enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        followingBalls.add(new FollowerEnemyBall());
      }
    
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
    }
    //}
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float STUPID_INT_ENEMY_DIAMETER = random(10, 30), STUPID_ENEMY_RADIUS = STUPID_INT_ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(STUPID_ENEMY_RADIUS, width  - STUPID_ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(STUPID_ENEMY_RADIUS, height - STUPID_ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((enemyX += speedx) < STUPID_ENEMY_RADIUS || enemyX > width  - STUPID_ENEMY_RADIUS)  speedx *= -1;
        if ((enemyY += speedy) < STUPID_ENEMY_RADIUS || enemyY > height - STUPID_ENEMY_RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(enemyX, enemyY, STUPID_INT_ENEMY_DIAMETER, STUPID_INT_ENEMY_DIAMETER);
      }
    
      //Game over tur or false?
      boolean gameOver = false; 
      if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= (FRIEND_DIAMETER/2 + STUPID_INT_ENEMY_DIAMETER/2 + 5)) {
        gameOver = true;
      } else {
        gameOver = false;
      }
    }
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
      float INT_ENEMY_DIAMETER = random(40, 60), INT_ENEMY_RADIUS = INT_ENEMY_DIAMETER / 2;
      float febX = width/2;
      float febY= height/2;
      void move () {
        febX = lerp(febX, mouseX, 0.01);
        febY = lerp(febY, mouseY, 0.01);
      }
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        ellipse (febX, febY, INT_ENEMY_DIAMETER, INT_ENEMY_DIAMETER);
      }
    
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - febX) + sq(mouseY - febY)) <= FRIEND_DIAMETER/2 + INT_ENEMY_DIAMETER + 5;
      }
    }
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        balls.clear();
        followingBalls.clear();
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        followingBalls.add(new FollowerEnemyBall());
      }
    }
    
  • This:

        //Game over tur or false?
          boolean gameOver = false; 
          if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= (FRIEND_DIAMETER/2 + STUPID_INT_ENEMY_DIAMETER/2 + 5)) {
            gameOver = true;
          } else {
            gameOver = false;
          }
    

    ??

    you can't just throw lines into the class; they must be inside a function

  • you failed to use radius, you can always use radius where you say diameter / 2

    //Time
    int lastTimeCheck;
    
    //Diameter and radius of our ball // PLAYER with the mouse 
    static final int FRIEND_DIAMETER = 30, 
      FRIEND_RADIUS = FRIEND_DIAMETER / 2 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    
    boolean gameOver = false; 
    
    void setup () {
      //Standard Setup
      size (600, 400);
    
      surface.setResizable(true);
      frameRate(60);
      noCursor();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    }
    
    void draw () {
      if (gameOver) {
        showGameOver();
      } else {
        showGame();
      }
    }//func
    
    // --------------------------------------------------------------------
    
    void showGameOver() {
      background(0);
      fill(255, 0, 0); 
      text("GAME OVER ", 222, 222);
    }
    
    void showGame() {
      background(#70C1B3);
    
      //Show the level on top left. Level is based on INTERVAL
      int INTERVAL = 3000;
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/INTERVAL, height/40, height/19);
    
      //Get the created stupid enemy balls at start
      for (EnemyBall e : balls) {
        e.move();
        e.display();
        e.gameOverManager();
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        balls.add(new EnemyBall());
      }
    
      //Get the created intelligent follower enemy balls
      for (FollowerEnemyBall f : followingBalls) {
        f.move();
        f.display();
      }
    
      //Create intelligent follower enemy ball every 3 secs
      if ( millis() > lastTimeCheck + INTERVAL) {
        lastTimeCheck = millis();
        followingBalls.add(new FollowerEnemyBall());
      }
    
      // display our ball
      fill(#FF1654);  // RED
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
    }
    
    // --------------------------------------------------------------------
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        gameOver=false; 
        balls.clear();
        followingBalls.clear();
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        followingBalls.add(new FollowerEnemyBall());
      }
    }
    
    // from here onwards only classes in the code 
    // =======================================================================
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float STUPID_INT_ENEMY_DIAMETER = random(10, 30), 
        STUPID_ENEMY_RADIUS = STUPID_INT_ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(STUPID_ENEMY_RADIUS, width  - STUPID_ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(STUPID_ENEMY_RADIUS, height - STUPID_ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void move() {
        if ((enemyX += speedx) < STUPID_ENEMY_RADIUS || enemyX > width  - STUPID_ENEMY_RADIUS) 
          speedx *= -1;
        if ((enemyY += speedy) < STUPID_ENEMY_RADIUS || enemyY > height - STUPID_ENEMY_RADIUS)  
          speedy *= -1;
      }
    
      void display() {
        fill(199); // gray
        ellipse(enemyX, enemyY, STUPID_INT_ENEMY_DIAMETER, STUPID_INT_ENEMY_DIAMETER);
      }
    
      //Game over true or false?
      void gameOverManager() { 
        gameOver = false; 
        if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= (FRIEND_RADIUS + STUPID_ENEMY_RADIUS)) {
          gameOver = true;
        } else {
          gameOver = false;
        }
      }
    }//class
    
    // =======================================================================
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
    
      float INT_ENEMY_DIAMETER = random(40, 60), 
        INT_ENEMY_RADIUS = INT_ENEMY_DIAMETER / 2;
    
      float febX = width/2;
      float febY = height/2;
    
      void move () {
        febX = lerp(febX, mouseX, 0.01);
        febY = lerp(febY, mouseY, 0.01);
      }
    
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        fill(255); // white
        ellipse (febX, febY, INT_ENEMY_DIAMETER, INT_ENEMY_DIAMETER);
      }
    
      boolean checkMouseInside() {
        return sqrt(sq(mouseX - febX) + sq(mouseY - febY)) <= FRIEND_RADIUS + INT_ENEMY_RADIUS;
      }
    }//class
    // =======================================================================
    
  • edited May 2017

    WOW! I dig it! Very smart, thanks!

    My next goal is showing the last level on game over screen and if player clicks the space button then level starts from 1 again. I tried too much thing but could not do this, my brain has stopped. :D

    Do you have any idea how can i do this?

    I did this. <:-P

    Here is the last version:

    //Time
    int lastTimeCheck;
    int startingTime;
    
    //Level interval 
    int INTERVAL = 3000; //every x secs gives +1 level
    
    //Variables to create enemy balls (stupid and intelligent balls) every x sec
    int lastTimeCheckStupidBall;
    int INTERVAL_STUPID_BALL = 2000; //Every x secs spawns stupid ball
    int lastTimeCheckIntelligenBall;
    int INTERVAL_FOLLOWER_BALL = 20000; //Every x secs spawns stupid ball
    
    //Diameter and radius of our ball
    static final int FRIEND_DIAMETER = 30, FRIEND_RADIUS = FRIEND_DIAMETER >> 1 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    //Game starts at false
    boolean gameOver = false;
    
    void setup () {
      //Standard Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    
      //test
      startingTime = millis();
    }
    
    
    void draw () {
      if (gameOver) {
        showGameOver();
      } else {
        showGame();
      }
    }
    
    void showGame() {
      background(#70C1B3);
    
      //Show the level on top left. Level is based on INTERVAL
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + ((millis() - startingTime) / INTERVAL), height/40, height/19);
    
      //Get the created stupid enemy balls at start
      for (EnemyBall e : balls) {
        e.run();
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheckStupidBall + INTERVAL_STUPID_BALL) {
        lastTimeCheckStupidBall = millis();
        balls.add(new EnemyBall());
      }
    
      //Get the created intelligent follower enemy balls
      for (FollowerEnemyBall f : followingBalls) {
        f.run();
      }
    
      //Create intelligent follower enemy ball every 5 secs
      if ( millis() > lastTimeCheckIntelligenBall + INTERVAL_FOLLOWER_BALL) {
        lastTimeCheckIntelligenBall = millis();
        followingBalls.add(new FollowerEnemyBall());
      }
    
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
    }
    
    void showGameOver() {
      background(#FF5733);
      textSize(height/10);
      textAlign(CENTER);
      fill(255);
      text("GAME OVER", width/2, height/2);
      textSize(height/20);
      text("\nPress SPACE to try again", width/2, height/2);
    
      //Show the last level on game over screen but how?
    }
    
    //We start the game again
    void keyPressed() {
      if (key==' ') {
        //Clears stupid and intelligent balls
        balls.clear();
        followingBalls.clear();
        //Makes game over true to false that game starts again
        gameOver = false;
        //Adds x quantity stupid balls at game start
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        //Adds 1 intelligent ball at game start
        followingBalls.add(new FollowerEnemyBall());
        //Reset the level
        startingTime = millis();
      }
    }
    
    //=====================CLASSES======================//
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float STUPID_INT_ENEMY_DIAMETER = random(10, 30), STUPID_ENEMY_RADIUS = STUPID_INT_ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(STUPID_ENEMY_RADIUS, width  - STUPID_ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(STUPID_ENEMY_RADIUS, height - STUPID_ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void run() {
        move();
        display();
        gameManager();
      }
    
      void move() {
        if ((enemyX += speedx) < STUPID_ENEMY_RADIUS || enemyX > width  - STUPID_ENEMY_RADIUS)  speedx *= -1;
        if ((enemyY += speedy) < STUPID_ENEMY_RADIUS || enemyY > height - STUPID_ENEMY_RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(enemyX, enemyY, STUPID_INT_ENEMY_DIAMETER, STUPID_INT_ENEMY_DIAMETER);
      }
    
      void gameManager() {
        if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= FRIEND_RADIUS + STUPID_ENEMY_RADIUS + 5) {
          gameOver = true;
        }
      }
    }//Class ends
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
      float INT_ENEMY_DIAMETER = random(40, 60), INT_ENEMY_RADIUS = INT_ENEMY_DIAMETER/2;
      float febX = width/2;
      float febY= height/2;
      float followSpeedX = random(0.0001, 0.01);
      float followSpeedY = random(0.0001, 0.01);
    
      void run() {
        move();
        display();
        gameManager();
      }
    
      void move() {
        febX = lerp(febX, mouseX, followSpeedX);
        febY = lerp(febY, mouseY, followSpeedY);
      }
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        ellipse (febX, febY, INT_ENEMY_DIAMETER, INT_ENEMY_DIAMETER);
      }
    
      void gameManager() {
        if (sqrt(sq(mouseX - febX) + sq(mouseY - febY)) <= FRIEND_RADIUS + INT_ENEMY_RADIUS + 5) {
          gameOver = true;
        }
      }
    }//Class ends
    
  • Answer ✓

    You know that this:

      //Show the level on top left. Level is based on INTERVAL
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + millis()/INTERVAL, height/40, height/19);
    

    will appear in both game and gameOver?

    If we use such a BIG if in draw() nothing should be outside of it.

    So it belongs in a function showLevel which we then call from showGameOver(); and / or showGame();

  • I want to display level in game (i could do this btw, our posts overlapped) and show the last level on gameOver screen, do you have any idea for this? :ar!

  • Answer ✓
    //Time
    int lastTimeCheck;
    
    //Level interval 
    int INTERVAL = 1000; //every x secs gives +1 level
    
    //Variables to create enemy balls (stupid and intelligent balls) every x sec
    int lastTimeCheckStupidBall;
    int INTERVAL_STUPID_BALL = 2000; //Every x secs spawns stupid ball
    int lastTimeCheckIntelligenBall;
    int INTERVAL_FOLLOWER_BALL = 20000; //Every x secs spawns stupid ball
    
    //Diameter and radius of our ball
    static final int FRIEND_DIAMETER = 30, FRIEND_RADIUS = FRIEND_DIAMETER >> 1 ;
    
    //Bucket for stupid enemy balls
    ArrayList<EnemyBall> balls;
    
    //Bucket for intelligent follower enemy balls
    ArrayList<FollowerEnemyBall> followingBalls;
    
    //How many stupid enemy balls at start?
    int enemyBallQuantity = 10;
    
    //Game starts at false
    boolean gameOver = false;
    
    int lastLevel=0; 
    
    void setup () {
      //Standard Setup
      size (600, 400);
      surface.setResizable(true);
      frameRate(60);
      smooth();
      noCursor();
    
      //
      float startingTime = millis();
      lastTimeCheck= millis();
    
      //Create stupid enemy balls and ArrayList for those
      balls = new ArrayList<EnemyBall>();
      for (int i = 0; i < enemyBallQuantity; i++) {
        balls.add(new EnemyBall());
      }
    
      //Create intelligent follower enemy balls and ArrayList for those
      followingBalls = new ArrayList<FollowerEnemyBall>();
      followingBalls.add(new FollowerEnemyBall());
    }
    
    void draw () {
      if (gameOver) {
        showGameOver();
      } else {
        showGame();
      }
    }
    
    // ---------------------------------------------
    
    void showGame() {
      background(#70C1B3);
    
      //Get the created stupid enemy balls at start
      for (EnemyBall e : balls) {
        e.run();
      }
    
      //Create stupid enemy ball every 3 secs
      if ( millis() > lastTimeCheckStupidBall + INTERVAL_STUPID_BALL) {
        lastTimeCheckStupidBall = millis();
        balls.add(new EnemyBall());
      }
    
      //Get the created intelligent follower enemy balls
      for (FollowerEnemyBall f : followingBalls) {
        f.run();
      }
    
      //Create intelligent follower enemy ball every 5 secs
      if ( millis() > lastTimeCheckIntelligenBall + INTERVAL_FOLLOWER_BALL) {
        lastTimeCheckIntelligenBall = millis();
        followingBalls.add(new FollowerEnemyBall());
      }
    
      //Create our ball
      fill(#FF1654);
      stroke(255);
      strokeWeight(2);
      ellipse (mouseX, mouseY, FRIEND_DIAMETER, FRIEND_DIAMETER);
    
      //Show the level on top left. Level is based on INTERVAL
      fill(255);
      textSize(height/25);
      textAlign(TOP);
      text("Level:" + (millis()-lastTimeCheck)/INTERVAL, height/40, height/19);
    }
    
    void showGameOver() {
      background(#FF5733);
      textSize(height/10);
      textAlign(CENTER);
      fill(255);
      text("GAME OVER", width/2, height/2);
    
      textSize(height/20);
      text("Press SPACE to try again ", width/2, height/2 + 33);
    
      //Show the last level on game over screen
      //and stop loop that level stays constant
      text("Level: " 
        +lastLevel, 
        width/2, height/2+66);
    }
    
    //We start the game again
    void keyPressed() {
    
      if (key==' '&&gameOver) {
    
        //Clears stupid and intelligent balls
        balls.clear();
        followingBalls.clear();
    
        //Makes game over from true to false that game starts again
        gameOver = false;
    
        //Adds x quantity stupid balls at game start
        for (int i = 0; i < enemyBallQuantity; i++) {
          balls.add(new EnemyBall());
        }
        //Adds 1 intelligent ball at game start
        followingBalls.add(new FollowerEnemyBall());
    
        //Reset the level
        INTERVAL = 1000;
        lastTimeCheck=millis();
      }
    }
    
    //=====================CLASSES======================//
    
    //Enemyball
    class EnemyBall {
    
      //Diameter and radius of enemy ball
      float STUPID_INT_ENEMY_DIAMETER = random(10, 30), STUPID_ENEMY_RADIUS = STUPID_INT_ENEMY_DIAMETER / 2;
      static final float MIN_SPEED = .8, MAX_SPEED = 1;
    
      float enemyX = abs(random(STUPID_ENEMY_RADIUS, width  - STUPID_ENEMY_RADIUS) - (mouseX));
      float enemyY = abs(random(STUPID_ENEMY_RADIUS, height - STUPID_ENEMY_RADIUS) - (mouseY));
    
      float speedx = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
      float speedy = random(MIN_SPEED, MAX_SPEED) * (random(1) < .5? -1 : 1);
    
      void run() {
        move();
        display();
        gameManager();
      }
    
      void move() {
        if ((enemyX += speedx) < STUPID_ENEMY_RADIUS || enemyX > width  - STUPID_ENEMY_RADIUS)  speedx *= -1;
        if ((enemyY += speedy) < STUPID_ENEMY_RADIUS || enemyY > height - STUPID_ENEMY_RADIUS)  speedy *= -1;
      }
    
      void display() {
        ellipse(enemyX, enemyY, STUPID_INT_ENEMY_DIAMETER, STUPID_INT_ENEMY_DIAMETER);
      }
    
      void gameManager() {
        if (sqrt(sq(mouseX - enemyX) + sq(mouseY - enemyY)) <= FRIEND_RADIUS + STUPID_ENEMY_RADIUS + 5) {
          gameOver = true;
          lastLevel=int(millis()/INTERVAL);
        }
      }
    }//Class ends
    
    //Follower Intelligent Enemy Ball
    class FollowerEnemyBall {
      float INT_ENEMY_DIAMETER = random(40, 60), INT_ENEMY_RADIUS = INT_ENEMY_DIAMETER/2;
      float febX = width/2;
      float febY= height/2;
      float followSpeedX = random(0.0001, 0.01);
      float followSpeedY = random(0.0001, 0.01);
    
      void run() {
        move();
        display();
        gameManager();
      }
    
      void move() {
        febX = lerp(febX, mouseX, followSpeedX);
        febY = lerp(febY, mouseY, followSpeedY);
      }
      void display() {
        stroke(#5DD39E);
        strokeWeight(5);
        ellipse (febX, febY, INT_ENEMY_DIAMETER, INT_ENEMY_DIAMETER);
      }
    
      void gameManager() {
        if (sqrt(sq(mouseX - febX) + sq(mouseY - febY)) <= FRIEND_RADIUS + INT_ENEMY_RADIUS + 5) {
          gameOver = true;
        }
      }
    }//Class ends
    //
    
  • Answer ✓

    our posts overlapped

    You know that this:

    //Show the level on top left. Level is based on INTERVAL
    fill(255);
    textSize(height/25);
    textAlign(TOP);
    text("Level:" + millis()/INTERVAL, height/40, height/19);
    

    will appear in both game and gameOver?

    That's why I removed it from draw() and moved it into the function showGame().

    Lesson learned: When we have a BIG if in draw, nothing in draw() is allowed outside the if.

  • Yeah, got it. :)>-

    But this millis()/INTERVAL shows only the time beginning from the game starts. It doesn't display the last level really. Am i right? :-/

  • edited May 2017

    True.

    But did you test my version?

    I put

          textAlign(TOP);
          text("Level:" + (millis()-lastTimeCheck)/INTERVAL, height/40, height/19);
    

    you set lastTimeCheck when level starts again

  • Yeah, i tested. On game over screen it shows the added up levels. For example first game over on level 2 and the second 3 then i see something like 5 or even more.

  • Answer ✓

    That's another question than your previous

    Adjust line 176

Sign In or Register to comment.