Having some issues with Void Draw in Processing

56 views Asked by At
void setup() {
    size(500,500);
    background(#87ceeb);
    fill(#567d46);
    rect(0,height/2,500,height/2);
    fill(#FFA500);
    circle(50,50,75);
    // Cloud 1
    noStroke();
    fill(#FFFFFF);
    circle(335,50,50);
    circle(300,50,35);
    circle(370,50,35);
    noStroke();
    fill(#FFFFFF);
    circle(335,75,50);
    circle(300,75,35);
    circle(370,75,35);
    // Cloud 2
    noStroke();
    fill(#FFFFFF);
    circle(200,50,50);
    circle(165,50,35);
    circle(235,50,35);
    // Bush 1
    fill(#112A12);
    circle(100,425,50);
    circle(65,425,35);
    circle(135,425,35);
    noStroke();
    fill(#112A12);
    circle(100,450,50);
    circle(65,450,35);
    circle(135,450,35);
    // Bush 2
    fill(#112A12);
    circle(400,250,50);
    circle(365,250,35);
    circle(435,250,35);
    noStroke();
    // Path
    fill(#d9b99b);
    rect(0,300,width,75);
    // Post
    fill(#563d2d);
    rect(20,225,35,15);
    fill(#5C4033);
    rect(50,200,15,100);
    fill(#563d2d);
    rect(65,210,35,15);
  }
 
 
  void draw() {
    if (key == 'n'){
      background(#040348);
      fill(#006400);
      rect(0,height/2,500,height/2);
      // Moon
      fill(#d3d3d3);
      circle(450,50,75);
      fill(#808080);
      circle(435,35,15);
      fill(#808080);
      circle(450,65,25);
      // Rock
      rect(365,190,100,100);
      rect(350,280,130,20);
      fill(#563d2d);
      rect(365,300,100,85);
      textSize(35);
      fill(#d3d3d3);
      text("RIP",390,235);
      // Tree
      fill(#563d2d);
      rect(60,140,75,200);
      fill(#154734);
      rect(25,150,145,75);
      rect(35,125,125,75);
      // Stars
      fill(#ffff00);
      circle(75,50,10);
      circle(135,80,10);
      circle(225,65,10);
      circle(275,200,10);
      circle(300,150,10);
      circle(330,20,10);
 
 
      // Path
      fill(#AC9362);
      rect(0,400,width,75);
     
    } else if (key == 'd') {
    background(#87ceeb);
    fill(#567d46);
    rect(0,height/2,500,height/2);
    fill(#FFA500);
    circle(50,50,75);
    // Cloud 1
    noStroke();
    fill(#FFFFFF);
    circle(335,50,50);
    circle(300,50,35);
    circle(370,50,35);
    noStroke();
    fill(#FFFFFF);
    circle(335,75,50);
    circle(300,75,35);
    circle(370,75,35);
    // Cloud 2
    noStroke();
    fill(#FFFFFF);
    circle(200,50,50);
    circle(165,50,35);
    circle(235,50,35);
    // Bush 1
    fill(#112A12);
    circle(100,425,50);
    circle(65,425,35);
    circle(135,425,35);
    noStroke();
    fill(#112A12);
    circle(100,450,50);
    circle(65,450,35);
    circle(135,450,35);
    // Bush 2
    fill(#112A12);
    circle(400,250,50);
    circle(365,250,35);
    circle(435,250,35);
    noStroke();
    // Path
    fill(#d9b99b);
    rect(0,300,width,75);
    // Post
    fill(#563d2d);
    rect(20,225,35,15);
    fill(#5C4033);
    rect(50,200,15,100);
    fill(#563d2d);
    rect(65,210,35,15);
   
    }
  }
 
    void mousePressed() {
        fill(#FF0000);
        circle(mouseX,mouseY,50);
    }

I want to make it so that whenever I click it places an object into the canvas, but whenever I switch between day and night and return, the circles dispear. On top of that, I can only place circles before I switch between day and night. Swithcing causes the next circles being placed to dispear immidetaly. How can I fix these issues.

I tried to placing the void mousepressed function inside the loop, however that did nto work either.

2

There are 2 answers

0
Kduck On

remember that each time the draw function is called (60 times per secon i think), everything disapears since you call background() that's why you need to draw your circles again.

To overcome that problem you could store the coordinates of your circles in an array and then draw from those coordinates. For example you can create an IntList for the x voordinates and add mouseX to it each time the mouse is pressed and do the same for the y coodrinates, then go over your lists and call circle(x,y,50) for each coordinate.

//start of your sketch
IntList xcoord = new IntList();
IntList ycoord = new IntList();

//in the draw
for(int i = 0;i<xcoord.size();i++) {
  circle(xcoord.get(i),ycoord.get(i),50);
}

//the mousePressed()
void mousePressed() {
  xcoord.append(mouseX);
  ycoord.append(mouseY);
}
0
George Profenza On

One other technique you can use caching the drawings using PGraphics. You can think of this as if using layers in Photoshop or a similar application and the drawing API is almost identical to what you already use:

  1. create a PGraphics instance (via PGraphics yourLayer = createGraphics(width, height))
  2. use drawing commands in between yourLayer.beginDraw() and yourLayer.endDraw() (E.g. yourLayer.background(#FFFFFF))
  3. to render the layer use image(yourLayer, 0, 0) (as it it were a PImage).

Here's an example of your code using 3 layers: day, night and a draw layer for the dynamic (mouse event driven circles):

PGraphics dayLayer;
PGraphics nightLayer;
PGraphics drawLayer;

void setup() {
  size(500, 500);
  
  // create layers
  dayLayer   = createGraphics(width, height);
  nightLayer = createGraphics(width, height);
  drawLayer  = createGraphics(width, height);
  
  // draw into layers
  // draw day layer
  dayLayer.beginDraw();
  
    dayLayer.background(#87ceeb);
    dayLayer.fill(#567d46);
    dayLayer.rect(0, height/2, 500, height/2);
    dayLayer.fill(#FFA500);
    dayLayer.circle(50, 50, 75);
    // Cloud 1
    dayLayer.noStroke();
    dayLayer.fill(#FFFFFF);
    dayLayer.circle(335, 50, 50);
    dayLayer.circle(300, 50, 35);
    dayLayer.circle(370, 50, 35);
    dayLayer.noStroke();
    dayLayer.fill(#FFFFFF);
    dayLayer.circle(335, 75, 50);
    dayLayer.circle(300, 75, 35);
    dayLayer.circle(370, 75, 35);
    // Cloud 2
    dayLayer.noStroke();
    dayLayer.fill(#FFFFFF);
    dayLayer.circle(200, 50, 50);
    dayLayer.circle(165, 50, 35);
    dayLayer.circle(235, 50, 35);
    // Bush 1
    dayLayer.fill(#112A12);
    dayLayer.circle(100, 425, 50);
    dayLayer.circle(65, 425, 35);
    dayLayer.circle(135, 425, 35);
    dayLayer.noStroke();
    dayLayer.fill(#112A12);
    dayLayer.circle(100, 450, 50);
    dayLayer.circle(65, 450, 35);
    dayLayer.circle(135, 450, 35);
    // Bush 2
    dayLayer.fill(#112A12);
    dayLayer.circle(400, 250, 50);
    dayLayer.circle(365, 250, 35);
    dayLayer.circle(435, 250, 35);
    dayLayer.noStroke();
    // Path
    dayLayer.fill(#d9b99b);
    dayLayer.rect(0, 300, width, 75);
    // Post
    dayLayer.fill(#563d2d);
    dayLayer.rect(20, 225, 35, 15);
    dayLayer.fill(#5C4033);
    dayLayer.rect(50, 200, 15, 100);
    dayLayer.fill(#563d2d);
    dayLayer.rect(65, 210, 35, 15);
    
  dayLayer.endDraw();
  
  // draw night layer
  nightLayer.beginDraw();
    nightLayer.background(#040348);
    nightLayer.fill(#006400);
    nightLayer.rect(0, height/2, 500, height/2);
    // Moon
    nightLayer.fill(#d3d3d3);
    nightLayer.circle(450, 50, 75);
    nightLayer.fill(#808080);
    nightLayer.circle(435, 35, 15);
    nightLayer.fill(#808080);
    nightLayer.circle(450, 65, 25);
    // Rock
    nightLayer.rect(365, 190, 100, 100);
    nightLayer.rect(350, 280, 130, 20);
    nightLayer.fill(#563d2d);
    nightLayer.rect(365, 300, 100, 85);
    nightLayer.textSize(35);
    nightLayer.fill(#d3d3d3);
    nightLayer.text("RIP", 390, 235);
    // Tree
    nightLayer.fill(#563d2d);
    nightLayer.rect(60, 140, 75, 200);
    nightLayer.fill(#154734);
    nightLayer.rect(25, 150, 145, 75);
    nightLayer.rect(35, 125, 125, 75);
    // Stars
    nightLayer.fill(#ffff00);
    nightLayer.circle(75, 50, 10);
    nightLayer.circle(135, 80, 10);
    nightLayer.circle(225, 65, 10);
    nightLayer.circle(275, 200, 10);
    nightLayer.circle(300, 150, 10);
    nightLayer.circle(330, 20, 10);


    // Path
    nightLayer.fill(#AC9362);
    nightLayer.rect(0, 400, width, 75);
  nightLayer.endDraw();
  
  // render day layer once
  image(dayLayer, 0, 0);
}


void draw() {
  // re-render a background layer (day / night) on keypress
  if (key == 'n') {
    image(nightLayer, 0, 0);
  } else if (key == 'd') {
    image(dayLayer, 0, 0);
  }
  // dynamic drawing layer on top of everything (last drawing instruction)
  image(drawLayer, 0, 0);
}

void mousePressed() {
  drawLayer.beginDraw();
  drawLayer.fill(#FF0000);
  drawLayer.circle(mouseX, mouseY, 50);
  drawLayer.endDraw();
}

Notes:

  • identation in setup() is not obligatory, just visualising how drawing instructions are grouped
  • in an ideal world you'd encapsulate these drawing calls into re-usable functions.

Speaking of images, a slightly different approach could be use assets for the day/night layers. examples:

  • using a raster drawing app to save .png to load via loadImage()
  • using a vector drawing app to save .svg to load via loadShape()
  • using one sketch to make these drawings then save the to disk (via save("day.png"))

This if course would cache the background graphics as static. If you need them dynamic (E.g. animate them layer, change parts of the content you would indeed need to use a technique similar to Kduck's answer where you would store the shape type and parameters (x, y, size, etc.))

Update:

Here's a version using PShape:

PShape dayLayer;
PShape nightLayer;
PShape drawLayer;

void setup() {
  size(500, 500);
  
  // create layers
  dayLayer   = createShape(GROUP);
  nightLayer = createShape(GROUP);
  drawLayer  = createShape(GROUP);
  
  // draw into layers
  // draw day layer
    
  rect(dayLayer, 0, 0, width, height, #87ceeb);
  rect(dayLayer, 0, height/2, 500, height/2, #567d46);
  circle(dayLayer, 50, 50, 75, #FFA500);
  // Cloud 1
  circle(dayLayer, 335, 50, 50, #FFFFFF);
  circle(dayLayer, 300, 50, 35, #FFFFFF);
  circle(dayLayer, 370, 50, 35, #FFFFFF);
  
  circle(dayLayer, 335, 75, 50, #FFFFFF);
  circle(dayLayer, 300, 75, 35, #FFFFFF);
  circle(dayLayer, 370, 75, 35, #FFFFFF);
  // Cloud 2

  circle(dayLayer, 200, 50, 50, #FFFFFF);
  circle(dayLayer, 165, 50, 35, #FFFFFF);
  circle(dayLayer, 235, 50, 35, #FFFFFF);
  // Bush 1
  circle(dayLayer, 100, 425, 50, #112A12);
  circle(dayLayer,  65, 425, 35, #112A12);
  circle(dayLayer, 135, 425, 35, #112A12);
  circle(dayLayer, 100, 450, 50, #112A12);
  circle(dayLayer,  65, 450, 35, #112A12);
  circle(dayLayer, 135, 450, 35, #112A12);
  // Bush 2
  circle(dayLayer, 400, 250, 50, #112A12);
  circle(dayLayer, 365, 250, 35, #112A12);
  circle(dayLayer, 435, 250, 35, #112A12);
  // Path
  rect(dayLayer, 0, 300, width, 75, #d9b99b);
  // Post
  rect(dayLayer, 20, 225, 35, 15, #563d2d);
  rect(dayLayer, 50, 200, 15, 100, #5C4033);
  rect(dayLayer, 65, 210, 35, 15, #563d2d);
  
  // draw night layer
  rect(nightLayer, 0, 0, width, height, #040348);
  rect(nightLayer, 0, height/2, 500, height/2, #006400);
    // Moon
  circle(dayLayer, 450, 50, 75, #d3d3d3);
  circle(dayLayer, 435, 35, 15, #d3d3d3);
  circle(dayLayer, 450, 65, 25, #d3d3d3);
    // Rock
  rect(nightLayer, 365, 190, 100, 100, #d3d3d3);
  rect(nightLayer, 350, 280, 130, 20, #d3d3d3);
  rect(nightLayer, 365, 300, 100, 85, #563d2d);
    // Tree
  rect(nightLayer, 60, 140, 75, 200, #563d2d);
  rect(nightLayer, 25, 150, 145, 75, #154734);
  rect(nightLayer, 25, 150, 145, 75, #154734);
  rect(nightLayer, 35, 120, 125, 75, #154734);
    // Stars
  circle(nightLayer, 75, 50, 10, #ffff00);
  circle(nightLayer,135, 80, 10, #ffff00);
  circle(nightLayer,225, 65, 10, #ffff00);
  circle(nightLayer,275,200, 10, #ffff00);
  circle(nightLayer,300,150, 10, #ffff00);
  circle(nightLayer,330, 20, 10, #ffff00);
  
    // Path
  rect(nightLayer, 0, 400, width, 75, #AC9362);
  
  // render day layer once
  shape(dayLayer, 0, 0);
}


void draw() {
  moveShapes(nightLayer);
  // re-render a background layer (day / night) on keypress
  if (key == 'n') {
    shape(nightLayer, 0, 0);
  } else if (key == 'd') {
    shape(dayLayer, 0, 0);
  }
  
  // dynamic drawing layer on top of everything (last drawing instruction)
  shape(drawLayer, 0, 0);
}

void mousePressed() {
  circle(drawLayer, mouseX, mouseY, 50, #FF0000);
}

void rect(PShape target, float x, float y, float width, float height, int fill){
  PShape rect = createShape(RECT, x, y, width, height);
  rect.setFill(fill);
  rect.setStroke(false);
  target.addChild(rect);
} 

void ellipse(PShape target, float x, float y, float width, float height, int fill){
  PShape rect = createShape(ELLIPSE, x, y, width, height);
  rect.setFill(fill);
  rect.setStroke(false);
  target.addChild(rect);
} 

void circle(PShape target, float x, float y, float size, int fill){
  ellipse(target, x, y, size, size, fill);
} 

void moveShapes(PShape layer){
  // early exit if there aren't at least 2 shapes
  if(layer.getChildCount() < 2) return;
  float movementAmount = 3;
  
  PShape[] shapes = layer.getChildren();
  // skip 1st shape (could be background)
  for(int i = 1 ; i < shapes.length; i++){
    PShape shape = shapes[i];
    shape.resetMatrix();
    shape.translate(sin(frameCount * 0.01 * i) *  movementAmount, cos(frameCount * 0.01 * i) *  movementAmount);
  }
}

Notes:

  • wrapping re-usable blocks of code into functions can help clean-up code / remove duplication
  • using PShape allows you to later access the shapes as a hierarchy and change them (notice night mode)

Have fun!