Random color selection from array of colors

Hello - I’m trying to create an array of colors and then have shapes randomly be one of those colors but I cannot find the right syntax. I found two older posts about an array of colors but I can’t get one to work and the other seems to randomly choose R, G, and B from each color?

Any help appreciated.

I’m used to Processing - something like
colors[i] = Color[int(random(Color.length))];

for this so far in oF

I have tried:

in the header: ofColor *colors;

void ofApp::setup(){
colors = new ofColor[5];
//pink
colors[0].r = 234;
colors[0].g = 84;
colors[0].b = 223;
//purple
colors[1].r = 188;
colors[1].g = 75;
colors[1].b = 180;
//light acqua
colors[2].r = 36;
colors[2].g = 211;
colors[2].b = 211;
//deep acqua
colors[2].r = 26;
colors[2].g = 253;
colors[2].b = 146;
//navy
colors[2].r = 55;
colors[2].g = 87;
colors[2].b = 165;
}

void ofApp::draw(){
for(int i = 0; i < 10; i++)
{
ofSetColor(colors[i].r, colors[i].g, colors[i].b);
ofDrawRectangle(100 * i, 100, 100, 100);
}
}

included screenshot shows colors not in the array.

THANKS,
Rachel

hey! a few bugs that might be tripping you up

a) you set colors[2] several times int the above code but you don’t set colors[3] or colors[4], etc.
b) you allocate an array of 5 elements

colors = new ofColor[5];

but in your for loop you draw ten elements

for(int i = 0; i < 10; i++)

hope that helps!

PS: it may be simpler to use a vector (which is similar to a growable array – in java arrayList). also ofColor has a set function so you can do:

colors[3].set(100,200,0);

finally ofColor has named colors, you may find it easier to write:

colors[3] = ofColor::aqua;

the named colors are based on w3c names colors

https://www.spycolor.com/w3c-colors

Thanks Zach! I can’t believe I forgot to change the color numbers. Have done that and things are better.

If I had 5 colors defined but wanted 15 shapes - how would you suggest I approach having!the shapes be randomly chosen from that array of 5 colors?

As it is now, anything above 5 (because I’ve defined 5 colors) is randomly generated from I’m not sure where.

Thanks much!
Rachel

if you do this:

for(int i = 0; i < 10; i++){
ofSetColor(colors[ ofRandom(0,5)]);
ofDrawRectangle(100 * i, 100, 100, 100);
}

it will flicker. there’s a few solutions – you can seed the random number generator:

ofSeedRandom(0);
for(int i = 0; i < 10; i++){
ofSetColor(colors[ (int)ofRandom(0,5)]);
ofDrawRectangle(100 * i, 100, 100, 100);
}

so you always choose the same random numbers… other options involve putting the colors in a vector and shuffling them or making an array of random ints that you set once in setup which refer to which color to draw.

ps: if you call elements in the array beyond what you’ve allocated (ie, if you’ve allocated 5 but ask for element 10), you can get undefined results and your app can even crash :slight_smile: you are basically asking for memory beyond what you’ve asked for.

THANKS ZACH! Very helpful.

I am trying the Vector approach. Brain melt :slight_smile:

Hi guys,
I’ve been spending a few hours on a related topic, so thought it might be good to continue this thread. I created an array for four different colours and would like to pick random two for the background and a word every second.

I’m stuck on the first step, I can’t make the colour change per second. I’m new to vectors so would appreciate if you could help me spot what’s going wrong in this slightly epilectic mess :sweat_smile:

This is what I got now:

h-file:

// vectorcolors; commented this out as I’m not sure which one to use array or vector
ofColor colors[4];
string words;
ofTrueTypeFont font;

ofApp.cpp

void ofApp::setup(){
ofSetFrameRate(30);
ofSetBackgroundAuto(true);
time = ofGetElapsedTimef();

colors[3] = ofColor::black;
colors[2] = ofColor::white;
colors[1] = ofColor::yellow;
colors[0] = ofColor::red;

}

//--------------------------------------------------------------
void ofApp::update(){

if (ofGetElapsedTimef() - time > 1.0) {
ofSetBackgroundColor(colors[(int)ofRandom(0,3)]);
    counter++;
}

Love, Annina

You can just do this in the update function, it should work fine.

void ofApp::update(){
    
    if (ofGetFrameNum() % 30 == 0) { //30 here is the frame rate you've set ofApp to.
    ofSetBackgroundColor(colors[(int)ofRandom(0,3)]);
    }
}

if you want to go the elapsedTimef() - time route, you need to do it this way:

float time; //in ofApp.h

void ofApp::setup(){
 ofSetFrameRate(30);
    ofSetBackgroundAuto(true);
    
    time = ofGetElapsedTimef();

    colors[3] = ofColor::black;
    colors[2] = ofColor::white;
    colors[1] = ofColor::yellow;
    colors[0] = ofColor::red;
    
}

void ofApp::update(){
    if(ofGetElapsedTimef() - time > 1.0){
         ofSetBackgroundColor(colors[(int)ofRandom(0,3)]);
        time = ofGetElapsedTimef(); //reset time to the current time.
    }
}

Hope it helps, cheers!

1 Like

Also note, ofRandom(0, 3) is 0 inclusive and 3 exclusive, so it’ll never return 3, if you want a random number between 0 and 3, you need to do ofRandom(0, 4). :slight_smile:

1 Like

Yass, works! Thank you so much Ayruos! Sometimes the simplest things are the hardest :heart_eyes:

Hey hey,

I know this topic was here for a while but I am running into some difficulties while trying to choose a random color from a vector, getting a “Thread 1: EXC_BAD_ACCESS (code=1, address=0x0)”

I am wondering if I made any mistakes that I can not locate. The app compiles fine but the app window doesn’t appear.

.h

vector <ofColor> colors;

.cpp setup()

int numOfColors = 6;

colors[0].set(192, 216, 96);
colors[1].set(120, 144, 72);
colors[2].set(96, 120, 72);
colors[3].set(240, 240, 216);
colors[4].set(96, 72, 72);
colors[5].set(85, 68, 61);

for(int i = 0; i < numOfColors; i++) {
    ofColor newColor;
    string colorName = "colors" + ofToString(i);
    colors.push_back(newColor);
}

.cpp draw()

ofSetColor(colors[ofRandom(0,7)]);
ofTranslate(ofGetWidth()/2, 150);

root(len, angle);

Any ideas would be much appreciated :slight_smile: Thank you in advance!

@Frogsie
in your code you make a vector that can contain ofColor objects but don’t put any into the vector - the code is failing on the first line in setup as you are sending a value to a thing that does not yet exist…

colors[0].set(192, 216, 96);

as you are trying to set the color of an ofColor object in the vector at position [0] but you have not yet put an ofColor object into the vector…

if you run your loop first and fill the vector with ofColor objects you can then set them to your colours…

void ofApp::setup(){
    numOfColors = 6;
    
    for(int i = 0; i < numOfColors; i++) {
        ofColor newColor;
        colors.push_back(newColor);
    }
    colors[0].set(192, 216, 96);
    colors[1].set(120, 144, 72);
    colors[2].set(96, 120, 72);
    colors[3].set(240, 240, 216);
    colors[4].set(96, 72, 72);
    colors[5].set(85, 68, 61);
}

Hi,
When you declare the vector in ofApp.h, it’s not filled yet.
So colors[0] is looking for the first element in the vector, which is empty.
This is probably the error.

You can try to declare the vector with empty ofColor object like this:
vector<ofColor> colors(6);
Then the indexing with [] will work.

And in draw you call ofRandom(0,7) which may give 6 and colors[6] is exceeding the size of the array, so I would suggest:
ofRandom(color.size());

Good luck
Edit: @danb was faster :wink:

1 Like

Thank you @danb & @Jildert. I have followed your advice and it works like magic. It is so easy to get lost in the structure if its not yet so deeply imprinted but this forum is helping me immensely. Hope you are having a beautiful day!