1

Objective: When the red candles are clicked, they should turn green. At the moment, when a candle is clicked, the next candle in the array is changed, instead of the candle that was clicked. When the last candle is clicked, the first candle changes color, so the problem continues to wrap around the array. What would the issue be and how would I fix it?

I've tried all kinds of array manipulation, i.e. (candles[i-1]... etc). And different ways of assigning the color (having a separate 'colors' array. All of which led to the same issue.

let candles = [];
let numCandles = 15;
let bg, r, g;

function setup(){
    
    createCanvas(windowWidth,windowHeight);
    r = color(239,83,80);
    g = color(38,166,154);
    bg = color(19,23,34);
    background(bg);

    for(let i = 0; i < numCandles; i++){
        let c = new candleStick(i);
        candles.push(c);
        c.show();
    }
}

function draw(){
    
    resizeCanvas(windowWidth, windowHeight);
    background(bg);
    for(let i = 0; i < numCandles; i++){
        candles[i].show();
    }
}

function mousePressed(){

    for(let i = 0; i < numCandles; i++){
        
    if(mouseX <= candles[i].x + candles[i].bodyWidth && mouseX >= candles[i].x &&
        mouseY <= candles[i].y + candles[i].bodyHeight && mouseY >= candles[i].y){

            if(candles[i].col == r){
                candles[i].col = g;
                
            }
            else if(candles[i].col == g){
                candles[i].col = r;
                
            }
            
        }
    }
}

class candleStick{

    constructor(index){
        this.bodyHeight = 200;
        this.bodyWidth = 20;
        this.offset = 25;
        this.index = index;
        this.col = r;
        this.x = (windowWidth/2) - (this.index * this.offset) + (numCandles * (this.offset + this.bodyWidth)/4);
        this.y = (windowHeight/2) - this.bodyHeight;
    }

    drawBody(){
        rect(this.x, this.y, this.bodyWidth , this.bodyHeight,2);
        fill(this.col);
        noStroke();
    }

    drawLine(){
        line((height/2 - this.bodyWidth/2) - (this.index * this.offset), (width/2 - this.bodyHeight/2), (height/2 - this.bodyWidth/2) - (this.index * this.offset) , (width/2 - this.bodyHeight/2) - 300);
    }

    show(){
        this.drawBody();
        this.drawLine();
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>

Expected result: When a candle is clicked, the color of that candle changes (from red to green and from green to red). All other candles should remain the same.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
konar
  • 23
  • 3

1 Answers1

0

Functions like fill(), noStroke(), ... set states, which are used to draw shapes. fill() sets the color used to fill shapes and noStroke() disables drawing the outline.
rect() draws a rectangle, using the current states.

This means fill() and noStroke() have to be called before rect():

class candleStick{

    // [...]

     drawBody(){
        fill(this.col);
        noStroke();
        rect(this.x, this.y, this.bodyWidth , this.bodyHeight,2);
    }

    // [...]
}

Note, the states which you've set didn't affect the currently drawn "candle", the state affected the next candle in the row. This caused the shifting effect.

let candles = [];
let numCandles = 15;
let bg, r, g;

function setup(){

    createCanvas(windowWidth,windowHeight);
    r = color(239,83,80);
    g = color(38,166,154);
    bg = color(19,23,34);
    background(bg);

    for(let i = 0; i < numCandles; i++){
        let c = new candleStick(i);
        candles.push(c);
        c.show();
    }
}

function draw(){

    resizeCanvas(windowWidth, windowHeight);
    background(bg);
    for(let i = 0; i < numCandles; i++){
        candles[i].show();
    }
}

function mousePressed(){

    for(let i = 0; i < numCandles; i++){

    if(mouseX <= candles[i].x + candles[i].bodyWidth && mouseX >= candles[i].x &&
       mouseY <= candles[i].y + candles[i].bodyHeight && mouseY >= candles[i].y){

            if(candles[i].col == r){
                candles[i].col = g;
            }
            else if(candles[i].col == g){
                candles[i].col = r;
            }
        }
    }
}

class candleStick{

    constructor(index){
        this.bodyHeight = 200;
        this.bodyWidth = 20;
        this.offset = 25;
        this.index = index;
        this.col = r;
        this.x = (windowWidth/2) - (this.index * this.offset) + (numCandles * (this.offset + this.bodyWidth)/4);
        this.y = (windowHeight/2) - this.bodyHeight;
    }

    drawBody(){
        fill(this.col);
        noStroke();
        rect(this.x, this.y, this.bodyWidth , this.bodyHeight,2);
    }

    drawLine(){
        line((height/2 - this.bodyWidth/2) - (this.index * this.offset), (width/2 - this.bodyHeight/2), (height/2 - this.bodyWidth/2) - (this.index * this.offset) , (width/2 - this.bodyHeight/2) - 300);
    }

    show(){
        this.drawBody();
        this.drawLine();
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.8.0/p5.js"></script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • 1
    Thank you so much! I knew the answer had to be something simple. It was causing me so much frustration but the fix worked beautifully. I'll keep this idea of 'states' in p5 in mind for future projects. You're amazing :) – konar Jun 11 '19 at 20:18