Code to change the direction of the ball not working

Hi, I’ve got a plan for a silly bouncing ball sketch. I worked out the timer, but now my ball will not rebound of the edge off the screen. It either goes clean off, or at best gets stuck i the corner. I have used the same bounding code in different sketches and it has worked no problem. So imagine my dismay to find that the ball now no longer bounces. Sad face. I have put the code beneath.



Ball _ball = new Ball();

float width = 400;
float height = 400;

void setup(){
size(400,400);
background(0);

}

void draw(){
  _ball.display();
  _ball.timerA();
 
  _ball.move(); 
  
}


class Ball{
  float x; 
  float y;
  float r;
  float speedX;
  float speedY;
 
  
  //timer vars
   int saveTimeA;
  
   int totalTimeA = 3000;
  
   boolean move = false;
   
Ball(){
 x = 200;
 y = 200;
 r = 30;
 }//bll
  
void display(){
  background(0);
  ellipseMode(CENTER);
   noStroke();
   fill(17,75,100);
   ellipse(x,y, r*2,r*2);
  }//disp
  
void timerA(){

 int passedTime = millis()- saveTimeA; // take saveTime from curent time
        
  if (passedTime > totalTimeA){  // if more than 3000 (3 secs)
    move = !move;                // change move to it's opposite 
    saveTimeA = millis();        //reset timer
  } 
}//time



void move(){
  
  // when true the ball moves
  // the bounding code works in other sketches but not in this one 
  //I have tried the code to reverse the directionof the ball in different parts of the sketch to no avial
  //I know that it has something to do with my boolean function but I can't work out the logic

  if (move == false){
    speedX =0;
    speedY =0;
     //bounding
     }else if (move == true){
     speedX = 3;
     speedY = 3;
     
    
     x = x+speedX;
     y = y+speedY;
     }
     //bounding code to reverse the direction of the ball
      if (x <0 || x >width){
           speedX*= -1; 
          }
      
      if(y <0|| y >height){
           speedY *= -1; 
          }
    }//move 
  
}//clss

Any help pointing out my, probably ever easy to fix mistakeis greatly appreciated.

When after the bounce the ball is still in the return zone it can lead to stuttering of the ball

Solution

Check each boundary separately

Say something like

if(x<=7) speedX = abs(speedX); // always positive

if(x>+width-7) speedX = - abs(speedX);// negative

2 Likes

Hi thanks, but I can’t get it working. I’ll just rewrite the code and get the bounding working before I put the timer in. I’ll update on how it goes. No time to do it today though. Thanks life! :slight_smile:

1 Like

Hello,

Move this to your constructor:

I also commented out this:

//_ball.timerA(); //Try with and without this code

This is one of those cool exercises that you should think about each step and write from scratch.

Do not look at any of the examples below unless you want some insight.

And then write from scratch. :)

Some examples:
https://natureofcode.com/book/chapter-1-vectors/

My example
int posX = 200;  //intial position
int posY = 50;
int dirX = 1;    //need an initial  direction
int velX = 5;    //need an initial  velocity

void setup() 
	{
  size(400, 100);
	}

void draw() 
	{
  background(0);
  
  //velX = posX/time time is each frame (1)
  //posX = velX*time time is each frame (1)
  
  posX += dirX*velX;
  
  //sets explicitly
  //if (posX > width) dirX = -1;
  //if (posX < 0) dirX = 1;
  
  //toggles
  //if (posX > width) dirX = -1*dirX;
  //if (posX < 0) dirX = -1*dirX;
  
  //toggles
  if ( posX < 0 || posX > width) dirX = -1*dirX;
  
  circle(posX, posY, 10);
	}

:)

3 Likes

Well spotted…!

Chrisir

Hi glv,

Cheers for your help. I took a stab it myself and realised that I needed a variable sperate from the speed, to control the direction. I just couldn’t figure out how to implement it. However looking at the examples you provided, let me work it out. I’ll look at using vectors more as I think the answer to my problem lies with in implementing them. I have provided my code up to a working framework below.

In this code the ball changes colour based on the timer. I have not used vectors in this, but will implement them next.

//physical ball look
float x  = 200;
float y = 200;
float r = 50;
int G = 175;

//speed 
float speedX = 3;
float speedY = 2.5;
//direction
int dirX = 1;
int dirY = 1;

//timer
int  passedTime;
int savedTime; 
int totalTime = 3000;

//boolean switch
boolean move = true;

void setup(){
noStroke();
size(400,400);
savedTime = millis();
}

void draw(){
 background(100);
 
 fill(75, G,0);
 ellipse(x,y,r*2,r*2);
 
 //bounding - chage ball direction  when it hits the edge
  if (x < 0 || x > width){
    dirX *= -1;
  }
  if (y < 0 || y > height){
     dirY *= -1; 
  }
    
// move the ball
x = x + (speedX * dirX);
y = y + (speedY * dirY);
//timer will be used to stop/ start the ball. Like a switch
// I have left it as a colour change to show that it works and to see when the ball should stop/start
passedTime = millis() - savedTime;
  
  if (passedTime > totalTime){
    move = !move;
       savedTime = millis();
  }
 
//boolean switch     
if (move == true){
    G = 175;
}else if( move == false){
    G = 0;
 }      
}

The problem I have is when I try to use the timer to act as a switch to move the ball.
This is where I am with the code. I don’t have any more time to work on it today.


//physical ball look
float x = 200;
float y = 200;
float r = 50;
int G;

//speed 
float speedX = 3;
float speedY = 2.5;
//direction
int dirX = 1;
int dirY = 1;

//timer
int  passedTime;
int savedTime; 
int totalTime = 3000;

//boolean switch
boolean move = true;

void setup(){
noStroke();
size(400,400);

savedTime = millis();

}

void draw(){
 background(100);
 
 fill(75, G,0);
 ellipse(x,y,r*2,r*2);
 
//timer
passedTime = millis() - savedTime;
  
  if (passedTime > totalTime){
    move = !move;
       savedTime = millis();
  }
      
// current code bounces ball and stops it
  //the ball moves re dirX + dirY but stops       

if (move == true){ 
     //if uncommented the ball stutters
      //dirX =1;
     // dirY =1;
     
  //bounding - chage ball direction  when it hits the edge
    if (x < 0 || x > width){
         dirX *= -1;
      }// if
      if (y < 0 || y > height){
         dirY *= -1; 
      }
           
  // move the ball
    x = x + (speedX * dirX);
    y = y + (speedY * dirY);     
  
    G = 175;
}else if( move == false){
    dirX = 0;
    dirY = 0;
  
    G = 0; 
    //uncommented the ball just reverses direction in a loop
       //dirX =1;
       // dirY =1;      
}
      //if this is uncommenteed the ball stutters
     //dirX =1;
     //dirY =1; 

}

when the ball pauses, just don’t add the speed to the position

Besides, for reflection at the walls, add r, so the outer part of the ball reflects, not its center. Looks better.

By the way, separation of speed and dirX is not necessary

not sure what the timer is supposed to do. Pause ball and change color?

my version below

Chrisir

//physical ball look
float x = 200;
float y = 200;
float r = 50;
int G;

//speed 
float speedX = 3;
float speedY = random(0.3, 2.5);

//direction
int dirX = 1;
int dirY = 1;

//timer
int  passedTime;
int savedTime; 
int totalTime = 3000;

//boolean switch
boolean move = true;

void setup() {
  noStroke();
  size(400, 400);

  savedTime = millis();
}

void draw() {
  background(100);

  fill(75, G, 0);
  ellipse(x, y, r*2, r*2);

  //timer
  passedTime = millis() - savedTime;

  if (passedTime > totalTime) {
    move = !move;
    savedTime = millis();
  }

  // current code bounces ball and stops it
  //the ball moves re dirX + dirY but stops       

  if (move) {  // short for move == true  
    //if uncommented the ball stutters
    //dirX =1;
    // dirY =1;

    //bounding - chage ball direction  when it hits the edge
    if (x < r || x > width-r) {
      dirX *= -1;
    }// if
    if (y < r || y > height-r) {
      dirY *= -1;
    }

    // move the ball
    x = x + (speedX * dirX);
    y = y + (speedY * dirY);     

    G = 175;
  } else { // short for if ( move == false) 

    // change color only
    G = 0; 


    //dirX = 0;
    //dirY = 0;

    //uncommented the ball just reverses direction in a loop
    //dirX =1;
    // dirY =1;
  }
  //if this is uncommenteed the ball stutters
  //dirX =1;
  //dirY =1;
}
1 Like

I am pleased with that.

Once you have worked through all of this you will reflect on it and say “That was easy!”.
Not much time these days to assist…

Stay well!

It is not necessary but can help with understanding; the examples did it several different ways.
You choose what is best for you at this stage of your code development.

Glean insight from examples and then work through it yourself.

:)

1 Like

You might find this post useful.

1 Like

Sorry I’ve been naff at keeping upto date here and replying to your comments. I’ve had a few health issues and then been away. Anyway. I have sloved my issue. I needed to make the timer a seperate class. When I did that it all fell into place.
See my code below.

Ball ball;       //ball class
Timer timer; //timer class

void setup(){
size(400,400);
noStroke();
ball = new Ball();
timer = new Timer(3000);
timer.start();
}

void draw(){
  background(0);
 //displayball
 ball.display();
 ball.move();    
}

class Ball {
  
//physical ball look
float x;
float y;
float r;
int G;


//speed
float speedX;
float speedY;
//direction
int dirX;
int dirY;
 //boolean
 boolean go_or_stop;
Ball (){
x = 200;
y = 200;
r = 50;
go_or_stop = true;

dirX = 1;
dirY = 1;
  }//bll
  
void display(){
  
 fill(75, 100,0);
 ellipse(x,y,r*2,r*2);
}

//move ball
 void move(){

   if (timer.isFinished()) {
   go_or_stop= !go_or_stop;
    timer.start();
  }
if (go_or_stop ==  true){
  speedX = 3;
  speedY = 2.5;
}else {
  speedX = 0;
  speedY = 0;
}
   x = x + (speedX * dirX);
   y = y + (speedY * dirY);
   
   //bounding code
   if (x < 0 || x > width){
    dirX *= -1;
  }// if
  if (y < 0 || y > height){
     dirY *= -1; 
     }  
   }
 }

class Timer {

  int savedTime; // When Timer started
  int totalTime; // How long Timer should last

  Timer(int tempTotalTime) {
    totalTime = tempTotalTime;
  }

  // Starting the timer
  void start() {
    // When the timer starts it stores the current time in milliseconds.
    savedTime = millis();
  }

  // The function isFinished() returns true if 5,000 ms have passed. 
  // The work of the timer is farmed out to this method.
  boolean isFinished() { 
    // Check how much time has passed
    int passedTime = millis()- savedTime;
    if (passedTime > totalTime) {
      return true;
    } else {
      return false;
    }
  }
}

The timer came from Daniel Shiffman - Learning Processing
Thanks for all the help

2 Likes