Making an eraser

edited December 2016 in How To...

Hello,

I am trying to do something simple. I draw a rectangle in the middle of the window, and I want to erase it by 10*10 white rectangle Which will simply fill the window with background color white, but the main problem is:

  1. I want to erase one line at a time. 2.from left to right and after eraser goes one line below then goes from right to left

first question: I move the eraser from left to right in the first line but I really don't know How the eraser will be shifted one line below so that it can goes ahead from right to left ?

second question: This move, left to right-right to left, goes on till the bigger rectangle disappear. I think that this move will be an if under the for function, right?

Tagged:

Answers

  • Answer ✓

    Here is an example:

    int rectW = 300;
    int eraserW = 10;
    int margin = 50;
    color BG_Color = 255;
    int x, y;
    
    
    void setup() {
      size(400, 400);
      frameRate(25);
      background(BG_Color);
      noStroke();
    
      // draw big rectangle
      fill(0);
      rect(margin, margin, 300, 300);
      fill(BG_Color);
    }
    
    
    void draw() {
    
      rect(margin+x, margin+y, eraserW, eraserW);
    
      // increase x-position
      x = x + eraserW;
    
      // if x is reaches right border
      if (x >= rectW) {
        // reset x to 0
        x =0;
        // increase y
        y = y + eraserW;
      }
    
      // if y reaches bottom
      if (y >= rectW) {
        println("done");
        noLoop();
      }
    }
    

    There are other ways to achieve this, i've chosen this one, because i thinks it's easier to understand.

  • edited December 2016

    Thank you Benja. I got the idea. I guess my only problem is moving eraser from right to left right now. I should figure it out, but you gave me the first step thanks again.

  • Oh i think i did not read that part of your question.

    If you have problems, feel free to ask again, it's not much you would have to change.

  • edited December 2016

    Hi again Benja, I made this: but How can I put 'İf' statements in a 'for' with this way?

    Object a;
    void setup(){
      size(600,600);
      background(255);
      a=new Object();
      fill(0);
      rect(100,100,400,400);
    }
    void draw(){
      a.move();
      a.display();
    }
    class Object{
      float x;
      float y;
      float z=10;
    
      Object(){
        x=90;
        y=100;
      }
      void display(){
        fill(255);
        stroke(255);
        rect(x,y,10,10);
      }
      void move(){
        x=x+z;
         if(x>=500){
          x=x+z*-1;
           if (y>=100){
           y=y+z;
           z=-10;
         }
    
        }
        }
    }     
    
  • Not sure where you want to use a for-loop here.

    But multiplying "z" with -1 seems like a good way to go. You might just want to re-assign it to z then. So the direction of the eraser gets inverted after every line.

    z = z * -1;

    But you don't only want to do this when x get larger than your right border, you want to do it too, when you hit the left one.

    So you can change your if-statement to somehting like this:

    if (x >= 500 || x<100) {

  • As you can see in the move function, eraser first goes one line to right and then one line to left after going one line down. Thus, I can erase two line with this function. But, I want to put this motion into a loop so that the eraser can do this action till y hit the end? Doesn't it make sense?

  • No it doesn't. With a loop you can erase as many parts as you want. But since the display will only be updated at the end of draw, so you won't see the single steps, the big rectangle will completely be erased. So the actual loop that you want to use id draw().

    You want to change the position for your white rectangle once every frame. You can do this by calling the move()-function, as you did. But you do the direction change only once, as mentioned above, you could do it every time your x get larger than the right border or smaller than the left border.

    void move() {
        // move horizontally
        x= x + size*direction;
    
        // if border is reached
        if (x>=500 || x<100) {
          // one step back
          x = x - direction*size;
          // one step down
          y = y + size;
          // change direction
          direction = direction * -1;
        }
      }
    

    I would try to use variable-names that help to understand what they are representing. "Object", "a" and "z" could mean everything. If you always try to find "speaking" names, it will help you and others a lot to understnad what's going on in your code.

  • Someone else recently had a similar problem -- they wanted to do a 2D looping activity and update one step each time draw was called (so that they could see it happening). Here was that discussion:

    https://forum.processing.org/two/discussion/comment/81713/#Comment_81713

  • Never late to say thanks: Thank you

  • edited December 2016

    And please don't name your custom class as Object. It is the base class for all the classes (atleast those built by a user) in Java.
    It's currently not causing trouble as you're using the Processing IDE. Try with basic Java, and problems should pop up unless you're careful of the way you create instances of your class.

  • Thanks Lord_of_Galaxy, right now I don't understand fully What do you mean because I don't know Java. I have recently got in processing and kept learning with videos, but I will keep that in mind.

  • Ok. Basically, Processing is just Java under the hood. That's why I told you not to name your class as Object.

  • But in the Daniel Shiffman videos, he always name the classes with object. I am getting confused. Why this codding world is so messy? Someone says that this is A and after that other one claims this is B. ( maybe it is because there are many ways to solve a problem) Anyway, many thanks for helping me. I think When I get the whole point I may see the difference, but seems that it takes time. Again, thanks so much.

  • Well, the reason he does that is because as long as you stick with the Processing IDE, it won't cause any problems. But it's not a good programming practice.

  • Hi everyone, I made it. Thank you for your patience and help. Here is the code:

    float x=100;  //x location
    float y=100; //y location
    float z=10; //speed
    void setup() {
      size(600, 600);
      background(255);
      fill(0);
      rect(100, 100, 400, 400);
    }
    void draw() {
      fill(255);
      noStroke();
      rect(x, y, 12, 12);
      x=x+z;
      if (x>=500) { // When eraser hit right
        x=x+z*-1;
        y=y+z;
        z=-12;
      } else if (x<=90) {  // When eraser hit left
        y=y+z*-1;
        z=12;
      }
    
      if (y>=500) {   // When eraser hit bottom
        println("done");
        noLoop();
      }
    }
    
  • Hello!

    well done!

    there are things that can be discussed though:

    I wouldn't name your speed as z, because z is usually seen as the depth (together with x,y,z in 3D).

    in line 18 and 21 you increase the speed (you use 12 instead of 10) and have plain numbers in the code (12). It would be better to use z instead. Because when you now want to increase or decrease the speed as a programmer (e.g. float speedX=2; //speed), you need to change it in 3 places in your code, not only in one place. This is always a bad sign for your code.

    Your also add z (the speed) to your y to go to the next line: y=y+z;. This is dangerous since the offset for the next line has nothing to do with your speed. The offset y is rather the size of the rectangle. Speed and size of the rectangle is not the same. When you mix those things up in the future you will get into trouble. Better name values like speed (instead of z) and rectSize (instead of 12) and use them consistently.

    Here is my version.

    Best, Chrisir ;-)

    // a white eraser moves accross a black rect
    
    float x=100;  //x location
    float y=100; //y location
    
    float speedX=10; //speed
    float sizeRect=12; // size
    
    
    void setup() {
      size(600, 600);
    
      // the big black rect 
      background(255);
      fill(0);
      rect(100, 100, 400, 400);
    }
    
    void draw() {
    
      // display rect 
      fill(255);
      noStroke();
      rect(x, y, sizeRect, sizeRect);
    
      // move rect 
      x+=speedX;
    
      // bounce rect
      if (x>=501) {
        // When eraser hit right
        y+=sizeRect; // new line 
        speedX=-abs(speedX); // new speed direction
      } else if (x<=88) {  
        // When eraser hit left
        y+=sizeRect; // new line
        speedX=abs(speedX); // new speed direction
      }
    
      // all done? 
      if (y>=500) {   // When eraser hit bottom
        println("done"); // message 
        noLoop();   // full stop
      }
    }
    
  • your rectangle has now these properties:

    float x=100;  //x location
    float y=100; //y location
    
    float speedX=10; //speed
    float sizeRect=12; // size
    

    can you make it into a class?

    you could also fill a 3D cube with your rect / box

  • Well first here it is in class. I hope I did not make mistake. It works. I have to make x position 90, because the difference between rectSize (you named sizeRect) and speed.

    Eraser eraser;
    void setup() {
      size(600, 600);
      eraser=new Eraser();
      background(255);
      fill(0);
      rect(100, 100, 400, 400);
    }
    void draw() {
      eraser.move();
      eraser.display();
    }
    
    class Eraser {
      float x, y, rectSize, speedx;
      Eraser() {
        x=90;
        y=100;
        speedx=10;
        rectSize=12;
      }
      void display() {
        fill(255);
        noStroke();
        rect(x, y, rectSize, rectSize);
      }
    
      void move() {
        x+=speedx;
        if (x>=500) {
          y+=rectSize;
          speedx=-abs(speedx);
        } else if (x<=90) {
          y+=rectSize;
          speedx=abs(speedx);
        }
    
        if (y>=500) {
          println("done");
          noLoop();
        }
      }
    }
    
  • Secondly, yes I should named variables properly you are right, but I have not get the 3D part yet. I checked out and now I am aware of it.

    Your also add z (the speed) to your y to go to the next line: y=y+z;. This is dangerous since the offset for the next line has nothing to do with your speed. The offset y is rather the size of the rectangle.

    I thought that if eraser go to next line the y position should have +value (like a gravity) so that's why it worked.I am enlightened. I mean my method was wrong but my way of thinking was right.

    Third, yes my next step for this project put it in a 3D. Many thanks.

  • Something that I clearly don't understand is why your class is called "Eraser"? A very strange name for something that just draws rectangles with no stroke and white fill.

  • Yes you are right but that's how you erase something. I mean the background is white so it paints again with white color to erase a black rectangle. It is same effect. How could else make this effect in another way?

  • Ok, if you say so.

  • MoverBackAndForth

    MoverLinewise

    ?

  • edited January 2017

    @Sinsinati --

    How could else make this effect in another way?

    The other way to do this is a bit more complicated:

    1. Create a PGraphics page https://processing.org/reference/PGraphics.html
    2. Draw in it
    3. In the draw loop, call background() to wipe the screen, then apply the page using image(page,0,0).
    4. To erase something, set the pixels in that area of the page to transparent (0,0);

    Note that this approach will work with drawing and erasing on top of anything -- for example, on top of a photograph -- while the colored rectangle method will only work on top of a solid color background.

  • Good idea from jeremydouglass, that's what I meant anyway.

  • edited January 2017

    Well I do not know I did it or not properly bu I got the point that with PGraphics each layer is independent and makes 'eraser' 'MoverBackAndForth' 'MoverLinewise' and now 'sq' free from color background. Thanks jeremydouglass and thanks for contributions Chrisir , Lord_of_the_Galaxy . Here is the code:

    PGraphics square; // the big square
    PGraphics sq; // the mover
    float rectSize=12;
    float speedx=10;
    float x=100;
    float y=100;
    
    void setup() {
      size(600, 600);
      square= createGraphics(height, width);
      sq=createGraphics(height, width);
    }
    
    void draw() {
      background (125);
    
      square.beginDraw(); //start to draw the big square
      square.fill(color(1, 0, 0, 0));
      square.rect(100, 100, 400, 400);
      square.endDraw();
    
      sq.beginDraw();
      sq.noStroke();
      sq.fill(225);
      sq.rect(x, y, rectSize, rectSize);
      x+=speedx;
      if (x>=500) {
        y+=rectSize;
        speedx=-abs(speedx);
      } else if (x<=100) {
        y+=rectSize;
        speedx=abs(speedx);
      }
    
      if (y>=500) {
        println("done");
        noLoop();
      }
      sq.endDraw();
    
      image(square, 0, 0);
      image(sq, 0, 0);
    }
    
  • The big advantage of PGraphics is that it won't be cleared by calling background in the sketch's draw() method.
    That means that you can shift lines 17 to 20 of your code to setup().
    Also remember that your current code will make your "rect" leave a trail.

Sign In or Register to comment.