Search code examples
arraysprocessing

Object to continue moving after one go


I was wondering if anyone could help me with this program.

I need to make the ball that is going horizontally start moving again and then shoot another ball that is going vertically. How can I make this happen over and over again, rather than it stopping after one go?

Also, how can I make the ball launching done by any key on the keyboard rather than the touchpad?

This is my program:

    int xPos =200;
    int yPos =700;
    int xDir=3;   // SPEED
    
    float ball2X;
    float ball2Y;
    float ball2Speed=5;
    boolean ball2Exist = false;
    
    void setup () {  
    size (1280, 960);
    }
    
    void draw() {
    background(255);
    fill (255, 200, 200);
    rect (0, 550, width, height);
    fill (225);
    
    //Player(ball)
    ellipse(xPos, yPos, 140, 140);
    fill (255, 200, 200);
      xPos=xPos+xDir;
      if (xPos>width-20 || xPos<20)
      {
        xDir=-xDir;
      }
      
      if(ball2Exist)
      {
        fill (255, 0, 0);
        ellipse(ball2X, ball2Y, 70, 70);
        ball2Y -= ball2Speed;
      }
    }
    
    void mouseClicked() {
      if(xDir!=0) // first click
      xDir = 0;
      else // second click
      {
        ball2X = xPos;
        ball2Y = yPos;
        ball2Exist = true;
      }
    }

Solution

  • In order to make the ball launching done by pressing a key, you can use the keyPressed() function in the same way that you used the mouseClicked() function. In order to make the horizontal ball continue moving after launching a ball, you can just set the ball's speed xDir to its old value. To ensure that it continues going in the same direction you should use a variable to store its current value before you set it to 0, then you can set xDir to this value after launching the ball. In order to have multiple red balls you want to store a list of ball information so that you can draw multiple balls at the same time and in order to this effectively, you probably want to create a Ball class.

    In the following program, I made a ball class to encapsulate all of the ball drawing, and I used PVectors to deal with the x and y corrdinates for position and speed.

    // Horizontal ball
    Ball mainBall;
    // List of red balls
    ArrayList<Ball> balls;
    
    void setup () {  
      size (1280, 960);
      
      //Create main ball
      mainBall = new Ball(200, 700, 3, 0, 140, color(255, 200, 200));
      
      // Create list of balls
      balls = new ArrayList<Ball>();
    }
    
    void draw() {
      background(255);
    
      fill (255, 200, 200);
      rect (0, 550, width, height);
      
      ellipseMode(CENTER);
    
      //If the main ball collides with edge of window, reverse speed
      mainBall.collisionUpdate();
      //Draw the main ball
      mainBall.drawBall();
      
      //Create arraylist to store balls to get removed from the list
      ArrayList<Ball> toRemove = new ArrayList<Ball>();
      
      // For every ball
      for(Ball ball : balls){
        ball.drawBall();
        
        //If the ball is off the screen need to remove it
        if(ball.isNotVisible()){
          toRemove.add(ball);
        }
      }
      
      // Remove all the non-visible balls
      balls.removeAll(toRemove);
    }
    
    void launch(){
      // Add a new ball to the list
      balls.add(new Ball(mainBall.position.x, mainBall.position.y, 0, -5, 70, color(255, 0, 0)));
    }
    
    void mouseClicked() {
      launch();
    }
    
    void keyPressed(){
      launch();
    }
    
    // Ball class
    class Ball{
      PVector position;
      PVector speed;
      float diameter;
      color c;
      
      Ball(float x, float y, float xSpeed, float ySpeed, float _diameter, color _c){
        position = new PVector(x, y);
        speed = new PVector(xSpeed, ySpeed);
        diameter = _diameter;
        c = _c;
      }
      
      void drawBall(){
        fill(c);
        circle(position.x, position.y, diameter);
        // Update position of ball
        position.add(speed);
      }
    
      void collisionUpdate(){
        if(position.x < diameter/2 || position.x > width-diameter/2 || position.y < diameter/2 || position.y > height-diameter/2 ){
          //Reverse speed
          speed.mult(-1);
        }
      }
      
      // Return true or false if the ball is off the screen
      boolean isNotVisible(){
         return position.x > width+diameter || position.x < -diameter || position.y > height+diameter || position.y < -diameter;
      }
    }
    

    Edit:

    To make the balls decelerate and ricochet off the window boundaries. I also used a random function to randomise the speed and the rate at which the balls decelerate.

    // Horizontal ball
    Ball mainBall;
    // List of red balls
    ArrayList<Ball> balls;
    
    PVector oldSpeed;
    
    void setup () {  
      size (1280, 960);
      
      //Create main ball
      mainBall = new Ball(200, 700, 3, 0, 140, color(255, 200, 200));
      
      // Create list of balls
      balls = new ArrayList<Ball>();
    }
    
    void draw() {
      background(255);
    
      fill (255, 200, 200);
      rect (0, 550, width, height);
      
      ellipseMode(CENTER);
    
      //If the main ball collides with edge of window, reverse speed
      mainBall.collisionUpdate();
      //Draw the main ball
      mainBall.drawBall();
      
      //Create arraylist to store balls to get removed from the list
      ArrayList<Ball> toRemove = new ArrayList<Ball>();
      
      // For every ball
      for(Ball ball : balls){
        // Balls bounce within the screen
        ball.collisionUpdate();
        
        // Slow the speed of the ball
        ball.slowSpeed(random(0.98,0.999));
        
        ball.drawBall();
        
        //If the ball is off the screen need to remove it
        if(ball.isNotVisible()){
          toRemove.add(ball);
        }
      }
      
      // Remove all the non-visible balls
      balls.removeAll(toRemove);
    }
    
    void launch(){
      if(!mainBall.isStationary()){
        oldSpeed = mainBall.speed;
        mainBall.setSpeed(0, 0);
      }else{
        // Add a new ball to the list
        balls.add(new Ball(mainBall.position.x, mainBall.position.y, 0, random(-8, -5), 70, color(255, 0, 0)));
        //Make the main ball move again
        mainBall.setSpeed(oldSpeed);
      }
    }
    
    void mouseClicked(){
      launch();
    }
    
    void keyPressed(){
      launch();
    }
    
    // Ball class
    class Ball{
      PVector position;
      PVector speed;
      float diameter;
      color c;
      
      Ball(float x, float y, float xSpeed, float ySpeed, float _diameter, color _c){
        position = new PVector(x, y);
        speed = new PVector(xSpeed, ySpeed);
        diameter = _diameter;
        c = _c;
      }
      
      void drawBall(){
        fill(c);
        circle(position.x, position.y, diameter);
        // Update position of ball
        position.add(speed);
      }
      
      void setSpeed(float xSpeed, float ySpeed){
        speed = new PVector(xSpeed, ySpeed);
      }
      
      void setSpeed(PVector _speed){
        speed = _speed;
      }
      
      boolean isStationary(){
        return speed.x == 0 && speed.y == 0;
      }
    
      void collisionUpdate(){
        if(position.x < diameter/2 || position.x > width-diameter/2 || position.y < diameter/2 || position.y > height-diameter/2 ){
          //Reverse speed
          speed.mult(-1);
        }
      }
      
      void slowSpeed(float deceleration){
          if(speed.mag() < 0.5){
              speed = new PVector(0, 0);
          }else{
              speed.mult(deceleration);
          }
      }
      
      // Return true or false if the ball is off the screen
      boolean isNotVisible(){
         return position.x > width+diameter || position.x < -diameter || position.y > height+diameter || position.y < -diameter;
      }
    }