Object walk with trail (footprints)

Can I combine object with trail and object with no trail?

1 Like

Yes. The easiest way to leave a trail is to use a black rect with weak opaqueness (instead of background (0):wink:

To leave no trail you can delete the item (the one you want to leave no trail) with a small rectangle just deleting the item before moving it

2 Likes
void setup() {
size (700,700); //set the size of the window
smooth();
}
void draw() {
background(255); // Draw a white background
//Set ellipses and rect to CENTER mode
ellipseMode(CENTER);
rectMode(CENTER);
//Draw Body
stroke(0);
fill(175);
rect(mouseX, mouseY, 20, 100);
//Draw Head
stroke(0);
fill(255);
ellipse(mouseX, mouseY-30, 60,60);
//Draw Zoog's eyes
fill(0);
ellipse(mouseX-18, mouseY-30,16,32);
ellipse(mouseX+18, mouseY-30,16,32);
// Draw legs
stroke(0);
line(mouseX+10, mouseY+50,mouseX+20, mouseY+60);
line(mouseX-10, mouseY+50,mouseX-20, mouseY+60);
}

I just want to make the legs leave trails and the others no trails. Can you teach me? sorry I’m a troublesome because I don’t really understand

1 Like

Ah, do you mean trail like in footsteps?

1 Like

yes, like in footsteps. sorry for the misunderstanding

1 Like

Before you start with footprints I would create a separate function to draw Zoog like this

void setup() {
  size (700, 700); //set the size of the window
  smooth();
}
void draw() {
  background(255); // Draw a white background
  //Draw Zoog
  drawZoog(mouseX, mouseY);

}

void drawZoog(float x, float y){
  push();
  //Set ellipses and rect to CENTER mode
  ellipseMode(CENTER);
  rectMode(CENTER);
  //Draw Body
  stroke(0);
  fill(175);
  rect(x, y, 20, 100);
  //Draw Head
  stroke(0);
  fill(255);
  ellipse(x, y-30, 60, 60);
  //Draw Zoog's eyes
  fill(0);
  ellipse(x-18, y-30, 16, 32);
  ellipse(x+18, y-30, 16, 32);
  // Draw legs
  stroke(0);
  line(x+10, y+50, x+20, y+60);
  line(x-10, y+50, x-20, y+60);
  pop();
}
3 Likes

You can store the footprints positions

ArrayList<PVector> listFP = new ArrayList(); 

listFP.add(new PVector(mouseX+.., mouseY+..));

Example

ArrayList<PVector> listFootprints = new ArrayList();

void setup() {
  size (700, 700); //set the size of the window
  smooth();
  noCursor();
}
void draw() {
  background(255); // Draw a white background

  // draw FootPrints
  for (PVector pv : listFootprints) {
    noFill();
    ellipse(pv.x, pv.y, 7, 3);
  }

  //Draw Zoog
  drawZoog(mouseX, mouseY);
}

void drawZoog(float x, float y) {
  push();
  //Set ellipses and rect to CENTER mode
  ellipseMode(CENTER);
  rectMode(CENTER);
  //Draw Body
  stroke(0);
  fill(175);
  rect(x, y, 20, 100);
  //Draw Head
  stroke(0);
  fill(255);
  ellipse(x, y-30, 60, 60);
  //Draw Zoog's eyes
  fill(0);
  ellipse(x-18, y-30, 16, 32);
  ellipse(x+18, y-30, 16, 32);
  // Draw legs
  stroke(0);
  line(x+10, y+50, x+20, y+60);
  line(x-10, y+50, x-20, y+60);

  // store footprints
  listFootprints.add(new PVector(x+20, y+60));
  listFootprints.add(new PVector(x-20, y+60));

  pop();
}

Hey, and welcome to the forum!

Great to have you here!

Chrisir

3 Likes

thank you so much for helping me do this!

1 Like

thank you so much for helping me do this and thanks for the welcome!

1 Like

here is an improved version where we check
whether the current footprint has already been stored (for example
when Zoog stands, we don’t want to record the same
footprint position over and over again…)

this can be improved of course



ArrayList<PVector> listFootprints = new ArrayList();

void setup() {
  size (700, 700); //set the size of the window
  smooth();
  noCursor();   // hides mouse cursor
}

void draw() {
  background(255); // Draw a white background

  // draw FootPrints
  drawFootPrints();

  // show size of the list (for testing)
  text(listFootprints.size(), 17, 17);

  //Draw Zoog
  drawZoog(mouseX, mouseY);
}

// ---------------------------------------------------------------------------------

void drawZoog(float x, float y) {
  // draw Zoog

  // store formatting
  push();

  //Set ellipses and rect to CENTER mode
  ellipseMode(CENTER);
  rectMode(CENTER);
  //Draw Body
  stroke(0);
  fill(175);
  rect(x, y, 20, 100);
  //Draw Head
  stroke(0);
  fill(255);
  ellipse(x, y-30, 60, 60);
  //Draw Zoog's eyes
  fill(0);
  ellipse(x-18, y-30, 16, 32);
  ellipse(x+18, y-30, 16, 32);
  // Draw legs
  stroke(0);
  line(x+10, y+50, x+20, y+60);
  line(x-10, y+50, x-20, y+60);

  // store footprints (from legs position)
  storeFootprints(x, y);

  // restore formatting
  pop();
}

void storeFootprints( float x, float y ) {
  // first time we store the foot print
  if (listFootprints.size()==0) {
    listFootprints.add(new PVector(x+20, y+60));
    listFootprints.add(new PVector(x-20, y+60));
    return; // leave
  }

  // After the first time we check if the last position was the same,
  // we store the foot print only when it's new:
  // Second last position in list:
  if (listFootprints.get(listFootprints.size()-2).x != x+20 || listFootprints.get(listFootprints.size()-2).y != y+60)
    listFootprints.add(new PVector(x+20, y+60));
  // last position
  if (listFootprints.get(listFootprints.size()-1).x != x-20 || listFootprints.get(listFootprints.size()-1).y != y+60)
    listFootprints.add(new PVector(x-20, y+60));
}

void drawFootPrints() {
  for (PVector pv : listFootprints) {
    noFill();
    ellipse(pv.x, pv.y, 7, 3);
  }
}
//

2 Likes

thank you so much! have a nice day :slightly_smiling_face:

2 Likes

in this version

  • we suppress the initial footprint (because it’s not connected to the trail)
  • and we make a more catlike paw trail (with 3 dots)


ArrayList<PVector> listFootprints = new ArrayList();

void setup() {
  size (700, 700); //set the size of the window
  smooth();
  noCursor();   // hides mouse cursor

  //mouseX = width/2;
  //mouseY = height/2;
}

void draw() {
  background(255); // Draw a white background

  // draw FootPrints
  drawFootPrints();

  // show size of the list (for testing)
  text(listFootprints.size() +" " + mouseX, 17, 17);

  //Draw Zoog
  drawZoog(mouseX, mouseY);
}

// ---------------------------------------------------------------------------------

void drawZoog(float x, float y) {
  // draw Zoog

  // store formatting
  push();

  //Set ellipses and rect to CENTER mode
  ellipseMode(CENTER);
  rectMode(CENTER);
  //Draw Body
  stroke(0);
  fill(175);
  rect(x, y, 20, 100);
  //Draw Head
  stroke(0);
  fill(255);
  ellipse(x, y-30, 60, 60);
  //Draw Zoog's eyes
  fill(0);
  ellipse(x-18, y-30, 16, 32);
  ellipse(x+18, y-30, 16, 32);
  // Draw legs
  stroke(0);
  line(x+10, y+50, x+20, y+60);
  line(x-10, y+50, x-20, y+60);

  // store footprints (from legs position)
  if (mouseX>0 && mouseY>0) {   // if mouse is there
    storeFootprints(x, y);
  }

  // restore formatting
  pop();
}

void storeFootprints( float x, float y ) {
  // first time we store the foot print
  if (listFootprints.size()==0) {
    listFootprints.add(new PVector(x+20, y+60));
    listFootprints.add(new PVector(x-20, y+60));
    return; // leave
  }

  // After the first time we check if the last position was the same,
  // we store the foot print only when it's new:
  // Second last position in list:
  if (listFootprints.get(listFootprints.size()-2).x != x+20 || listFootprints.get(listFootprints.size()-2).y != y+60)
    listFootprints.add(new PVector(x+20, y+60));
  // last position
  if (listFootprints.get(listFootprints.size()-1).x != x-20 || listFootprints.get(listFootprints.size()-1).y != y+60)
    listFootprints.add(new PVector(x-20, y+60));
}

void drawFootPrints() {
  for (PVector pv : listFootprints) {
    noFill();
    ellipse(pv.x, pv.y, 2, 2);
    ellipse(pv.x+3, pv.y+3, 2, 2);
    ellipse(pv.x+3, pv.y-3, 2, 2);
  }
}
//

2 Likes

Thank you so much! Sorry, may I ask again? What if the tracks were replaced with legs? like this
image

1 Like

like here

(The small check if it’s new doesn’t work)

Explanation

Instead of PVector (the in-built type to store a point with x,y) that we used previously we define a new type “Line” that stores 2 PVectors (line from point 1 to point 2). To define a type, we made a class “Line”.

To store a line in our list we just say

    listFootprints.add(new Line(new PVector(x1, y1), new PVector(x2, y2)));

As you can see we make a new line by passing 2 PVectors in it (that we make on the fly) and add the line to the list. (you have to read this from inside to outside: from x1,y1 to PVector, 2 PVectors needed to make a line, add the line to list)

  • The nice thing of using a class is that we can place a function “display()” inside a class to work with one line.

Sketch

ArrayList<Line> listFootprints = new ArrayList();

void setup() {
  size (700, 700);    // set the size of the window
  smooth();
  noCursor();   // hides mouse cursor
}

void draw() {
  background(255); // Draw a white background

  // draw FootPrints
  drawFootPrints();

  // show size of the list (for testing)
  text(listFootprints.size(), 17, 17);

  //Draw Zoog
  drawZoog(mouseX, mouseY);
}

// ---------------------------------------------------------------------------------

void drawZoog(float x, float y) {
  // draw Zoog

  // store formatting
  push();

  //Set ellipses and rect to CENTER mode
  ellipseMode(CENTER);
  rectMode(CENTER);
  //Draw Body
  stroke(0);
  fill(175);
  rect(x, y, 20, 100);
  //Draw Head
  stroke(0);
  fill(255);
  ellipse(x, y-30, 60, 60);
  //Draw Zoog's eyes
  fill(0);
  ellipse(x-18, y-30, 16, 32);
  ellipse(x+18, y-30, 16, 32);
  // Draw legs
  stroke(0);
  line(x+10, y+50, x+20, y+60);
  line(x-10, y+50, x-20, y+60);

  // store footprints (from legs position)
  if (mouseX>0 && mouseY>0) {   // if mouse is there
    storeFootprints(x+10, y+50, x+20, y+60);
    storeFootprints(x-10, y+50, x-20, y+60);
  }

  // restore formatting
  pop();
}

void storeFootprints( float x1, float y1,
  float x2, float y2) {
  // store the foot print

  // The first 3 times we store the foot print
  if (listFootprints.size()==0 || listFootprints.size()==1 || listFootprints.size()==2) {
    listFootprints.add(new Line(new PVector(x1, y1), new PVector(x2, y2)));
    return; // leave
  }//if

  // After the first time we check if the last position was the same,
  // we store the foot print only when it's new:
  // last position:
  if (  listFootprints.get(listFootprints.size()-2).pv1.x != x1 || listFootprints.get(listFootprints.size()-2).pv1.y != y1   )
    listFootprints.add(new Line(new PVector(x1, y1),
      new PVector(x2, y2)));
} //func

void drawFootPrints() {
  for (Line l1 : listFootprints) {
    noFill();
    l1.display();
  }//for
}//func

// ============================================================================

class Line {
  PVector pv1;
  PVector pv2;

  // constr
  Line(PVector pv1_, PVector pv2_) {
    pv1=pv1_.copy();
    pv2=pv2_.copy();
  }// constr

  void display() {
    line(pv1.x, pv1.y,
      pv2.x, pv2.y);
  }//method
  //
}//class
//

2 Likes

Sorry for the late reply, thanks for the help! I’ll understand the code first. If I need further assistance, may I send you a message? if not, that’s fine

1 Like

An alternative solution might be to use layers, drawing the trail in a transparent image that is drawn at each frame with the rest of the objects. This way you don’t have to store the steps in an ArrayList, and doing many steps doesn’t increase the computational cost.

3 Likes

push() saves the current state of formatting (for the rectMode() etc.).

when you use rectMode(CENTER); etc. the formatting changes.

at the end, pop() restores the formatting (push() and pop() always come together).

  • So, by restoring the formatting, we are polite to the rest of the program, we don’t change the formatting for it.