Help needed, bounce, clickable area

Alright i have two issues at hand with the code below.

  1. Bounces
    Bouncing the bullseye works with the code below in the horizontal X. When i change that to Y it also works.
    How can i make X and Y work by making it bounce to the edges of the window? Cause when i do certain maths on them it sometimes works but always ends up flying out of the screen.

  2. Clickable area
    The bullseye requires the circles within to give different scores. For the center being the highest score and the score decreasing the further you miss the center. I can’t figure this out, i’ve tried to give the X,Y, Width and Height dimensions of those circles different scores. Which kind of works but it overrides the others or counts them up (so if i click the middle i get +10 instead of +4 cuz the others give +1, +2 + 3.

int 
  circleSize, 
  rectX, rectY, rectSize, 
  scoreX, scoreY, score, mis, bonus, 
  red, white, green;

int[] bonusArray = new int[4];

float circleX, circleY, snelheid;

boolean 
  start;

void setup() {
  size(500, 500); 
  smooth(8);
  background(5);
  circleX = width/2;
  circleY = height/2;
  circleSize = 40;
  rectX = width/2;
  rectY = height;
  rectSize = 80;
  red = color(255, 0, 0);
  white = color(255);
  green = color(0, 255, 0);
  start = false;
  scoreX = width/50;
  scoreY = height/20;
  score = 0;
  mis = 0;
  bonus = 0;
  snelheid = random(5, 8);
  bonusArray[0] = 0;
  bonusArray[1] = 1;
  bonusArray[2] = 2;
  bonusArray[3] = 3;
}

void draw() {
  clear();
  noStroke();
  scoreText();
  buttonText();
  bullseye();
  println(snelheid);
}

void scoreText() {
  textSize(18);
  text("Score: " + score, scoreX, scoreY);
  text("Aantal mis: " + mis, scoreX*11, scoreY);
  text("Bonus: " + bonusArray[bonus], scoreX*26, scoreY);
}

void bullseye() {
  for (int circles = circleSize; circles > 0; circles -= 20) {
    fill(red);
    ellipse(circleX, circleY, circles, circles);
    fill(white);
    ellipse(circleX, circleY, circles-10, circles-10);
  }
  if (start) {
    circleX = circleX + snelheid;
  } else if (!start) {
    circleX = width/2;
  }
  if (circleX > width || circleX < 0) {
    snelheid = snelheid * -1.010;
  }
}

void buttonText() {
  noStroke();
  fill(green);
  rect(rectX-rectSize/2, rectY-rectSize/2, rectSize, rectSize/2);
  fill(red);
  textSize(24);
  if (!start) {    
    text("Start", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  } else if (start) {
    text("Stop", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  } else if (!start) {
    text("Start", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  }
}

void mousePressed() {
  if (mouseX > rectX-rectSize/2 && mouseX < rectX-rectSize/2 + rectSize &&
    mouseY > rectY-rectSize/2 && mouseY < rectY-rectSize/2 + rectSize/2) {
    start = ! start;
  } 
  if (mouseX > circleX-circleSize/2 && mouseX < circleX + circleSize/2 &&
    mouseY > circleY-circleSize/2 && mouseY < circleY + circleSize/2) {
    score += 1;
    bonus += 1;
    if (bonus > 3) {
      bonus = 3;
    }
    if (bonus == 1) score = score+=0;
    if (bonus == 2) score = score+=1;
    if (bonus >= 3) score = score+=2;
  } else if (mouseX > rectX-rectSize/2 && mouseX < rectX-rectSize/2 + rectSize &&
    mouseY > rectY-rectSize/2 && mouseY < rectY-rectSize/2 + rectSize/2) {
    score = 0;
    bonus = 0;
    mis = 0;
  } else {
    mis += 1;
    bonus = 0;
  }
}

The code below is where i tried step 1 and 2 and failed.

int 
  circleSize, 
  rectX, rectY, rectSize, 
  scoreX, scoreY, score, mis, bonus, 
  red, white, green;

int[] bonusArray = new int[4];

float circleX, circleY, snelheid;

boolean 
  start;

void setup() {
  size(500, 500); 
  smooth(8);
  background(5);
  circleX = width/2;
  circleY = height/2;
  circleSize = 40;
  rectX = width/2;
  rectY = height;
  rectSize = 80;
  red = color(255, 0, 0);
  white = color(255);
  green = color(0, 255, 0);
  start = false;
  scoreX = width/50;
  scoreY = height/20;
  score = 0;
  mis = 0;
  bonus = 0;
  snelheid = random(5, 10);
  bonusArray[0] = 0;
  bonusArray[1] = 1;
  bonusArray[2] = 2;
  bonusArray[3] = 3;
}

void draw() {
  clear();
  noStroke();
  scoreText();
  buttonText();
  bullseye();
  //println(snelheid);
}

void scoreText() {
  textSize(18);
  text("Score: " + score, scoreX, scoreY);
  text("Aantal mis: " + mis, scoreX*11, scoreY);
  text("Bonus: " + bonusArray[bonus], scoreX*26, scoreY);
}

void bullseye() {
  for (int circles = circleSize; circles > 0; circles -= 20) {
    fill(red);
    ellipse(circleX, circleY, circles, circles);
    fill(white);
    ellipse(circleX, circleY, circles-10, circles-10);
  }
  if (start) {
    circleX = circleX + snelheid;
    circleY = circleY + snelheid;
  } else if (!start) {
    circleX = width/2;
  }
  if (circleX > width || circleX < 0 ) {
    snelheid = snelheid * -1.010;
  }
  if (circleY > height || circleY < 0 ) {
    snelheid = snelheid * -1.010;
  }
}

void buttonText() {
  noStroke();
  fill(green);
  rect(rectX-rectSize/2, rectY-rectSize/2, rectSize, rectSize/2);
  fill(red);
  textSize(24);
  if (!start) {    
    text("Start", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  } else if (start) {
    text("Stop", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  } else if (!start) {
    text("Start", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  }
}

void mousePressed() {
  if (mouseX > rectX-rectSize/2 && mouseX < rectX-rectSize/2 + rectSize &&
    mouseY > rectY-rectSize/2 && mouseY < rectY-rectSize/2 + rectSize/2) {
    start = ! start;
  } 
  if (mouseX > circleX-circleSize/2 && mouseX < circleX + circleSize/2 &&
    mouseY > circleY-circleSize/2 && mouseY < circleY + circleSize/2 ) {
    score += 1;
    bonus += 1;
    println(score, bonus);
  } 
  if (mouseX > circleX-circleSize/2 && mouseX < circleX + circleSize/3 &&
    mouseY > circleY-circleSize/2 && mouseY < circleY + circleSize/3 ) {
    score += 2;
    bonus += 1;
  } 
  if (mouseX > circleX-circleSize/2 && mouseX < circleX + circleSize/4 &&
    mouseY > circleY-circleSize/2 && mouseY < circleY + circleSize/4 ) {
    score += 3;
    bonus += 1;
  } 
  if (mouseX > circleX-circleSize/2 && mouseX < circleX + circleSize/6 &&
    mouseY > circleY-circleSize/2 && mouseY < circleY + circleSize/6 ) {
    score += 4;
    bonus += 1;
  } 
  if (mouseX > rectX-rectSize/2 && mouseX < rectX-rectSize/2 + rectSize &&
    mouseY > rectY-rectSize/2 && mouseY < rectY-rectSize/2 + rectSize/2) {
    score = 0;
    bonus = 0;
    mis = 0;
  } else {
    mis += 1;
    bonus = 0;
  }
  if (bonus > 3) {
    bonus = 3;
  }
  if (bonus == 1) score = score+=0;
  if (bonus == 2) score = score+=1;
  if (bonus >= 3) score = score+=2;
}
1 Like

All right, let’s start with your first question:
You should assign a speed variable for each axis, in order to control the horizontal and vertical movements independently:
float speedX, speedY;
and assign them random values as well… (inside setup):

  speedX = random(5, 10);
  speedY = random(5, 10);

Then, in order to force the target to always remain within the boundaries of the canvas, you have to update the position of the circle, in the exact frame in which it touches the side of the canvas, before reversing the direction of its movement. So you prevent your program from incurring into some glitch.

  if (start) {
    circleX = circleX + speedX;
    circleY = circleY + speedY;
  } else {
    circleX = width/2;
    circleY = height/2;
  }
  if (circleX - circleSize/2 <= 0) {
    circleX = circleSize/2;
    speedX = speedX * -1.010;
  }
  if (circleX + circleSize/2 >= width) {
    circleX = width - circleSize/2;
    speedX = speedX * -1.010;
  }
  if (circleY - circleSize/2 <= 0) {
    circleY = circleSize/2;
    speedY = speedY * -1.010;
  }
  if (circleY + circleSize/2 >= height) {
    circleY = height - circleSize/2;
    speedY = speedY * -1.010;
  }

There’s an outstanding explanation written by @quark that you can find here.

Now, for your second question, we have to make some major changes.
You should always store the distance between the mouse and the center of the circle in a variable. For this you can use the dist() method. See dist().

float d = dist(mouseX, mouseY, circleX, circleY);

Then, in order to assign a score to each ring of the target, you can make use of the map() function, and thus avoid annoying calculations. With this method you can re-map any number from one range to another. See map().
You want to do this only if the mouse is inside the target:

  if (d <= circleSize/2) score += (int)map(d, circleSize/2, 0, minScore, maxScore+1);

Put everything together, your code would look like this: (with some minor corrections here and there)

int 
  circleSize, 
  rectX, rectY, rectSize, 
  scoreX, scoreY, score, mis, bonus, 
  red, white, green;

int[] bonusArray = new int[4];

float circleX, circleY;
float speedX, speedY;

boolean start;

void setup() {
  size(500, 500); 
  smooth(8);
  background(5);
  circleX = width/2;
  circleY = height/2;
  circleSize = 40;
  rectX = width/2;
  rectY = height;
  rectSize = 80;
  red = color(255, 0, 0);
  white = color(255);
  green = color(0, 255, 0);
  start = false;
  scoreX = width/50;
  scoreY = height/20;
  score = 0;
  mis = 0;
  bonus = 0;

  speedX = random(5, 10);
  speedY = random(5, 10);
  
  bonusArray[0] = 0;
  bonusArray[1] = 1;
  bonusArray[2] = 2;
  bonusArray[3] = 3;
}

void draw() {
  clear();
  noStroke();
  scoreText();
  buttonText();
  bullseye();
}

void scoreText() {
  textSize(18);
  text("Score: " + score, scoreX, scoreY);
  text("Aantal mis: " + mis, scoreX*11, scoreY);
  text("Bonus: " + bonusArray[bonus], scoreX*26, scoreY);
}

void bullseye() {
  for (int circles = circleSize; circles > 0; circles -= 20) {
    fill(red);
    ellipse(circleX, circleY, circles, circles);
    fill(white);
    ellipse(circleX, circleY, circles-10, circles-10);
  }
  if (start) {
    circleX = circleX + speedX;
    circleY = circleY + speedY;
  } else {
    circleX = width/2;
    circleY = height/2;
  }
  if (circleX - circleSize/2 <= 0) {
    circleX = circleSize/2;
    speedX = speedX * -1.010;
  }
  if (circleX + circleSize/2 >= width) {
    circleX = width - circleSize/2;
    speedX = speedX * -1.010;
  }
  if (circleY - circleSize/2 <= 0) {
    circleY = circleSize/2;
    speedY = speedY * -1.010;
  }
  if (circleY + circleSize/2 >= height) {
    circleY = height - circleSize/2;
    speedY = speedY * -1.010;
  }
}

void buttonText() {
  noStroke();
  fill(green);
  rect(rectX-rectSize/2, rectY-rectSize/2, rectSize, rectSize/2);
  fill(red);
  textSize(24);

  if (start) {
    text("Stop", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  } else {
    text("Start", rectX-rectSize/3, rectY-rectSize+rectSize/6*5);
  }
}

void mousePressed() {
  int minScore = 1;
  int maxScore = 4;
  float d = dist(mouseX, mouseY, circleX, circleY);

  if (d <= circleSize/2) { 
    score += (int)map(d, circleSize/2, 0, minScore, maxScore+1);
    bonus++;
  } else {
    mis += 1;
    bonus = 0;
  }
  if (bonus > 3) bonus = 3;
  //score = score + bonusArray[bonus];

  if (mouseX > rectX-rectSize/2 && mouseX < rectX-rectSize/2 + rectSize &&
    mouseY > rectY-rectSize/2 && mouseY < rectY-rectSize/2 + rectSize/2) {
    score = 0;
    bonus = 0;
    mis = 0;
    start = !start;
  }
}

I commented the line //score = score + bonusArray[bonus]; because I do not know if this is what you intend to do with the bonusArray.

3 Likes

Oh my god this is amazing! The way you explained it is great. I’m having trouble understanding map() at the moment but i’m probably going to get how it works eventually when i experiment with it. The best part is that i compared your code with the one i had and saw what you corrected. This allowed me to understand the if statement better. Great learning material! Thanks again for your time and effort @Ov3rM1nD .

1 Like

In addition to the reference, check out the examples to better understand map():

2 Likes

You’re welcome buddy. I love to help. As @jeremydouglass said, check out some examples and do some trials with the map() function. This function is one of the best features in Processing.

1 Like