We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hello all; I am having trouble removing points from my canvas. The points, actually ellipses, are held in an arraylist. I have written the code so that once the mouse is pressed, the points should disappear and start over. The problem is, they do not remove. The problem is on lines 218-221 and the class is at the bottom of the code, around line 400. Thanks. import org.gicentre.utils.stat.*; //import graph library
//import g4p_controls.*;
ArrayList<Ball> balls = new ArrayList(); // arraylist for ball objects
ArrayList<Point> points = new ArrayList();
float gcorX, gcorY; // goal coords
int timeIter = 300; //time step- internal clock
float bscore; //best score
String[] str_a; //one copy of scorelist (use to copies to determine best and worst)
String[] str_b; //one copy of scorelist (use to copies to determine best and worst)
float[] scores; //scorelist
final int pop = 10; //population size- final bc it shouldnt be changed in the program
int cur_sub; //current iteration- OLD METHOD, but still in just in case
public int gen_num = 0; //count generation number
int countDone; // count how many balls in the population finished their run in that generation
float diameter = 30;
float globmin = 1000; //base var
float [] generations; // array of generations
int total = points.size();
//GWindow window;
Ball globalBall = new Ball(-1, "0"); // starter/ global best ball
//public void windowDraw(PApplet app, GWinData data) {
// app.background(0);
// //app.point((gen_num*2), min(scores));
// }
//public void windowMouse(PApplet app, GWinData data, MouseEvent event) {
//}
//public void windowKey(PApplet app, GWinData data, KeyEvent event) {
//}
void setup() {
size(800, 800);
background(0);
generations = new float[gen_num]; // init generations with size
//window = GWindow.getWindow(this, "Graph", 100, 50, 500, 500, JAVA2D);
//window.addDrawHandler(this, "windowDraw");
//window.addMouseHandler(this, "windowMouse");
//window.addKeyHandler(this, "windowKey");
bscore = dist(0, 0, width, height); // calc score
gcorX= random(width);
gcorY= random(height);
ellipseMode(CENTER);
//begin init scorestrings
str_a = new String[pop];
str_b = new String[pop];
scores = new float[pop];
for (int j = 0; j<pop; j++) {
str_a[j] = starterString();
scores[j] = 0;
}
//end init scorestrings
//for every done ball, add a new one/replace it
cur_sub = -1;
countDone = 0;
for ( int i=0; i < pop; i++ ) balls.add( new Ball( i, str_a[i] ) );
}
//begin init of starter string( Initial) so that the mutation has a place to begin
String starterString() {
String mut = "" + char( '0' + int( random(4) ) ); // + "00000000" ;
return( mut );
}
//end init
//begin init instructions and strings of values- cr and hr refer to the textlines explaining each movement. r is a placeholder string so that the strings return a value to it based on the results of the cr loop
String hr( String cr ) {
String r = "";
for ( int t = 0; t < cr.length(); t++) {
if ( cr.charAt(t) == '0' ) r+= 'N';
if ( cr.charAt(t) == '1' ) r+= 'L';
if ( cr.charAt(t) == '2' ) r+= 'R';
if ( cr.charAt(t) == '3' ) r+= 'A';
}
return( r );
}
//end init instructions and cr/hr
void draw() {
background(0); //layer 2
fill(255, 0, 0); //red
//starting pad
pushMatrix();
stroke(255, 200);
fill(0, 255, 0, 200);
ellipse(width/2, height/2, 25, 25);
popMatrix();
//end starting pad
String extra = ""; //message
if ( bscore < 20 ) extra = "That's close enough! Click the mouse to move the goal."; //message
//text inits and placements
pushMatrix();
fill(255, 0, 0);
text("| Best ever: (" + hr(globalBall.genome) + ") = " + int(bscore) + " |", 50, 20 );
popMatrix();
pushMatrix();
fill(255, 200);
text("| key: A = accelerate, R = right, L = left, N = do nothing | ", 500, height-20);
popMatrix();
pushMatrix();
fill(0, 0, 255);
text(extra, 30, height -20);
fill(#3FB73F);
text("| Generation " + gen_num+ " |", 280, 20 );
text("| minimum of gen:" + (min(scores))+ " |", 400, 20); //why does this get a NullPointer Exception? and why does it not plot the points? Frustrated.
text("| best:" + (bscore)+ " |", 600, 20);
popMatrix();
//end text inits and placements
//globmin = min(globmin, min(scores));
//text("globmin: " + globmin, 250, 34);
//text for genome (hr/cr);
for ( int tt=0; tt< pop; tt++) {
fill (balls.get(tt).col);
text( "(" + hr( balls.get(tt).genome ) + ")", 10, 48 + 14 * tt);
}
//text for genome (hr/cr);
// If no ball, last ball is done, simulate next one.
// If all balls done, simulate next generation.
if ( countDone == pop ) { // balls.size() == 0 ) {
while ( balls.size () > 0 ) balls.remove(0);
//cur_sub++;
// If all balls in this generation simulated, create next generation.
//if ( cur_sub == gen_size ) {
countDone = 0; // cur_sub = 0;
//println( "Making next generation..." );
// Always keep the best one, and toss the worse.
arrayCopy( str_a, str_b ); //copy for scrambling later
int bestIndex = 0;
int worstIndex = 0;
for ( int j = 0; j < pop; j++ ) {
if ( scores[bestIndex] > scores[j] ) {
bestIndex = j;
} //getting best score for index
if ( scores[worstIndex] < scores[j] ) {
worstIndex = j;
}
//getting worst score for index
}
str_b[worstIndex] = str_b[bestIndex]; // Replace the worst with a copy of the best for breeding.
// Scramble.
for ( int j = 0; j < pop; j++ ) {
str_a[j] = scramble( j, str_b[int(random(pop))], str_b[int(random(pop))] ); //scrambles initial a(stored in b) and replaces old a with new values
}
str_a[0] = str_b[bestIndex]; // Always keep the best.
//Add all the balls to simulate.
for ( int j = 0; j < pop; j++ ) {
balls.add( new Ball( j, str_a[j] ) );
}
gen_num++; //increment generation counter
//}
}
globalBall.render(); // draw best as red(see coloring above in beginning of draw)
for ( int i=0; i < balls.size(); i++ ) balls.get(i).move(); //init move function for balls
//begin goal init
stroke(255);
fill(255, 140);
ellipse(gcorX, gcorY, diameter, diameter);
//end goal init
Point p = new Point(gen_num, (min(scores)+292.89));
points.add(p);
for(Point pt: points){
pt.displaypt();
}
if(mousePressed ==true){
for(int l = 0; l<total; l++){
points.remove(l);
}
}
} // end draw
String scramble( int which, String a, String b ) { // begin switching random values with substring r as the intermediate
String r;
int pos = int(random(min(a.length(), b.length())));
r = a.substring(0, pos) + b.substring(pos, b.length());
// Mutation! //change or add a random value between position 0 and length of r
if ( random(1) < .5 ) {
pos = int(random(r.length()));
if ( random(1) < .5 ) {
String mut = "" + char( '0' + int( random(4) ) );
//println( "New Ball #" + which + ": Mutation! Adding a char: '" + mut + "' at position " + pos );
r = r.substring(0, pos) + mut + r.substring(pos, r.length());
} else {
if ( r.length() > 0 ) {
pos = int(random(r.length()-1));
//println( "New Ball #" + which + ": Mutation! Losing the char at position " + pos );
r = r.substring(0, pos) + r.substring(pos+1, r.length());
}
}
}
return( r ); //return the value to change the initial strings, reset w/change basically
}
//begin goal changing
void mousePressed() {
if (mouseButton == LEFT) {
gcorX = random(width);
gcorY = random(height);
bscore = dist(0, 0, width, height);
gen_num=0;
}
}
//end goal changing
class Ball {
float x, y, z, v; //position related
color col; //color of balls
int current_inst;//current instruction
int inst_time;//time between instructions
int[] instructions; //array of instructions
boolean dis = false; //disable ball
int num; //uuuhhhh... i forget
String genome; //GENOME
int checknum; //check number for genome val to ensure smooth transition
boolean inst_a, inst_b, inst_c; //instructions
Ball(int cknum, String input) {
//x = width/2;
//y = height-20;
x = width/2;
y = height/2;
if (cknum == -1) {
x = -20;
y = -20;
}
z =0;
v = 0;
col=color(random(40, 255), random(40, 255), random(40, 255), 200);
inst_a = inst_b = inst_c = false;
checknum = cknum; //making sure the numbers are the same to avoid glitches
current_inst = 0;
checkString( input );
inst_time = millis() + timeIter;
dis = false; //not disabled
genome = input; //read input (parse/checkstring) and input it into the genome
}
void checkString(String in) { //parsing function
instructions = new int[in.length()];
for ( int j = 0; j < in.length(); j++ ) {
instructions[j] = int( in.charAt(j) - '0' );
}
//reads each character in the input string and puts it into instructions to be enacted
}
//begin scoreReport- uses an array to store the scores of the generation so that a best and a worst can be calculated
void scoreRep() {
scores[checknum] = dist(x, y, gcorX, gcorY) + genome.length(); //uses the distance between the translated ball(at x, y) and the goal at the gcords. //also, just added a penalty for length of genome, to try and promote a more direct route
if ( scores[checknum] < bscore ) { // if the score is not the best score, change the scores to be recalculated by the next generation
bscore = scores[checknum];
globalBall.x = x;
globalBall.y = y;
globalBall.z = z;
globalBall.col = col;
globalBall.genome = genome; //checks the best aspects and records the genome, moves the values for position
}
countDone++;
//if ( scores[checknum] < 20 ) {
// gcorX = random(width);
// gcorY = random(height);
//}
//balls.remove(0);
}
void move() {
if ( millis() > inst_time && !dis) { // if the millisecond function (internal clock) is greater than the instance time and not disabled,
inst_time = millis() + timeIter; //time between things
if ( current_inst < instructions.length ) { //for every instruction in the instruction array
int i = instructions[current_inst++]; //i is used to represent the value of the instruction at the current instruction value
switch( i ) { //switches between actions for instruction. For example, if the value "i" is 2, it would enact instruction case 2. it reads and enacts on the instructions based on their value and reads them in sequence based on their position in the array
case 0:
// Do nothing.
break;
case 1:
inst_a = !inst_a;
break;
case 2:
inst_b = !inst_b;
break;
case 3:
inst_c = !inst_c;
break;
default:
//println( "Bum instruction: " + i )//instruction does not exist
break;
}
} else { // Terminate run.
inst_a=inst_b=inst_c=false;
v=0;
dis = true; // disable is true, end run, set v to 0, set instructions to false, and statify the scoreReport
scoreRep();
}
}
// movement systems follow.
z+=(inst_a?-.1:0)+(inst_b?.1:0); //conditional operator/ternary operator. I dont want to explain it here, it is a shorthand. Go here for more: http://stackoverflow.com/questions/798545/what-is-the-java-operator-called-and-what-does-it-do
v+=(inst_c?.1:0); //conditional
//x=(x+width+v*cos(z))%width;
//y=(y+height+v*sin(z))%height;
x=x+v*cos(z); //math for x based on angle of movement (v is basically serving as a hypotenuse here)
y=y+v*sin(z); //math for y based on angle of movement (v is basically serving as a hypotenuse here)
v*=.99;
render(); //calls a display function
}
void render() {
pushMatrix(); //layer 4
translate(x, y); //move the thing by the x and y calculated in move
rotate(z); //rotate by z
noStroke();
fill(col); //fill with color
if ( checknum==-1) fill(255, 0, 0); //if it is the best ball, color it red
ellipseMode(CENTER); //put measurements in center
ellipse(0, 0, 25, 25); //ball size
stroke(0);//black edge
noFill(); //triangle no fill
triangle(-6, -5, 8, 0, -6, 5); // triangle(-5, -8.66, 0, 10, 5, -8.66);
popMatrix();
}
}
class Point{
float xpos, ypos;
float size = 2;
Point(float x, float y){
xpos = x;
ypos = y;
}
void displaypt(){
pushMatrix();
noStroke();
fill(255, 0, 0, 100);
ellipse(xpos, ypos, size, size);
popMatrix();
}
}
Answers
Easiest fix is doing the loop backwards. See posts over backwards tag:
https://forum.Processing.org/two/discussions/tagged/backwards
I tried replacing the code with
but it doesn't seem to have worked. Is there any complications with using enhanced loops?
If you wanna remove() all at once, just invoke clear():
http://docs.Oracle.com/javase/8/docs/api/java/util/Collection.html#clear--
What is that variable total? Use method size() instead:
for (int i = points.size(); i-- != 0; points.remove(i));
But as I've mentioned earlier, clear() gets the job done in this case. B-)
total is points.size(), just wanted it as a variable. Dunno why. I tried using clear, but it just clears the screen for a second and the points are still there when it ends. NEVERMIND though- your reverse loop (for (int i = points.size(); i-- != 0; points.remove(i));) worked just fine. Thanks for the help!
In order to clear the canvas, we use background().
I'm puzzled how clear() method failed and the backwards loop + remove() was successful! @-)
The clear cleared the whole screen only while the mouse was pressed- I might have used it incorrectly, as I just called clear(); in an if(mousePressed){ }. However, it works like a charm! and good to know about the background();. Thanks!
Oh, you've called Processing's clear() function instead of Collection's clear() method: ^#(^
In short, you shoulda called
points.clear()
in order to remove() all elements from that Collection.