We are about to switch to a new forum software. Until then we have removed the registration on this forum.
I could Google the answer, but then I'll just be working through that instead of this...
What I'm currently trying to do is implement a score counter, that's based on one of the 'raindrops' getting to / exceeding the height of the window.
Score counter starts at 10 -> Each drop that hits / exceeds height is -1 from score -> game over at 0
So what I immediately thought was that I could subtract 1 from the score counter each time a drop went off the screen. But they just keep counting, rather than the behaviour I'm expecting which is for them to be replaced each time.
When a droplet goes off the screen the score continues to decrease. It keeps decreasing indefinitely, so if only one droplet goes off screen the game is automatically lost.
I don't understand why this is, and have included what I believe to be the related code beneath. From line 6 of that code I'm checking the current drop element of the iteration to see whether it's above the value of height.
If it is above the height value, the score is decreased. This is one action on this one array element, on the next iteration the condition of line 6 will be referencing a different drop, so why is it that the previous droplet continues to reduce the score? I'm not really following that.
Here's the part of the code relating to this :
// Move and display all drops
for (int i = 0; i < totalDrops; i++ ) {
drops[i].move();
drops[i].display();
if (drops[i].y > height) {
score -= 1;
println(score);
if (score< 1) {
println("lost lost lost lost");
}
background(0);
}
if (catcher.intersect(drops[i])) {
drops[i].caught();
}
}
Here's the rest of the code, sorry it's a bit long winded :
// Example 10-10: The raindrop catching game
Catcher catcher; // One catcher object
Timer timer; // One timer object
Drop[] drops; // An array of drop objects
int totalDrops = 0; // totalDrops
int score = 10;
void setup() {
size(400, 400);
frameRate(60);
smooth();
catcher = new Catcher(32); // Create the catcher with a radius of 32
drops = new Drop[10]; // Create 1000 spots in the array
timer = new Timer(3000); // Create a timer that goes off every 2 seconds
timer.start(); // Starting the timer
}
void draw() {
background(255);
// Set catcher location
catcher.setLocation(mouseX, mouseY);
// Display the catcher
catcher.display();
// Check the timer
if (timer.isFinished()) {
// Deal with raindrops
// Initialize one drop
drops[totalDrops] = new Drop();
// Increment totalDrops
totalDrops ++ ;
// If we hit the end of the array
if (totalDrops >= drops.length) {
totalDrops = 0; // Start over
}
timer.start();
}
// Move and display all drops
for (int i = 0; i < totalDrops; i++ ) {
drops[i].move();
drops[i].display();
if (drops[i].y > height) {
score -= 1;
println(score);
}
if (score< 1) {
println("lost lost lost lost");
}
if (catcher.intersect(drops[i])) {
drops[i].caught();
}
}
}
// Example 10-10: The raindrop catching game
class Catcher {
float r; // radius
color col; // color
float x,y; // location
Catcher(float tempR) {
r = tempR;
col = color(50,10,10,150);
x = 0;
y = 0;
}
void setLocation(float tempX, float tempY) {
x = tempX;
y = tempY;
}
void display() {
stroke(0);
fill(col);
ellipse(x,y,r*2,r*2);
}
// A function that returns true or false based on
// if the catcher intersects a raindrop
boolean intersect(Drop d) {
// Calculate distance
float distance = dist(x,y,d.x,d.y);
// Compare distance to sum of radii
if (distance < r + d.r) {
return true;
} else {
return false;
}
}
}
// Example 10-10: The raindrop catching game
class Drop {
float x,y; // Variables for location of raindrop
float speed; // Speed of raindrop
color c;
float r; // Radius of raindrop
Drop() {
r = 8; // All raindrops are the same size
x = random(width); // Start with a random x location
y = -r*4; // Start a little above the window
speed = random(1,5); // Pick a random speed
c = color(50,100,150); // Color
}
// Move the raindrop down
void move() {
// Increment by speed
y += speed;
}
// Check if it hits the bottom
boolean reachedBottom() {
// If we go a little beyond the bottom
if (y > height + r*4) {
return true;
} else {
return false;
}
}
// Display the raindrop
void display() {
// Display the drop
fill(c);
noStroke();
for (int i = 2; i < r; i++ ) {
ellipse(x,y + i*4,i*2,i*2);
}
}
// If the drop is caught
void caught() {
// Stop it from moving by setting speed equal to zero
speed = 0;
// Set the location to somewhere way off-screen
y = - 1000;
}
}
// http://www.learningprocessing.com
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 "totalTime" has 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;
}
}
}
Answers
Try this:
...
...
By just using if(drops[i].y > height) you run into trouble: the condition continues to remain true, which is why the counter still keeps counting down, even though the drop has disappeared.
My solution here is slightly buggy in that you may need to play around with the tolerance level (height+-3 or 4 etc). I have had similar issues in the past where objects seem to jump the condition boundaries - not quite sure why this happens - possibly related to frame rate issues. Rather use a range than a definitive statement in this case to ensure that you catch the condition.