# Object walk with trail (footprints)

**URL:** https://discourse.processing.org/t/object-walk-with-trail-footprints/42059
**Category:** Coding Questions
**Created:** [May 23, 2023, 10:22am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059 "2023-05-23T10:22:14Z")
**Posts on this page:** 17
**Page:** 1

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 10:22am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/1 "2023-05-23T10:22:14Z")

</div>

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

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 10:28am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/2 "2023-05-23T10:28:09Z")

</div>

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

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

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 10:37am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/3 "2023-05-23T10:37:55Z")

</div>

```auto
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

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 10:55am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/4 "2023-05-23T10:55:09Z")

</div>

Ah, do you mean trail like in footsteps?

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 11:10am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/5 "2023-05-23T11:10:07Z")

</div>

yes, like in footsteps. sorry for the misunderstanding

---

<div class="post-metadata">

### Author: ![quark](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/quark/32/26_2.png) [@quark](https://discourse.processing.org/u/quark)
#### Post date: [May 23, 2023, 11:21am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/6 "2023-05-23T11:21:48Z")

</div>

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

```auto
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();
}

```

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 11:35am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/7 "2023-05-23T11:35:40Z")

</div>

You can store the footprints positions

```auto
ArrayList<PVector> listFP = new ArrayList(); 

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

```

* * *

**Example**

```auto
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

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 12:36pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/8 "2023-05-23T12:36:45Z")

</div>

thank you so much for helping me do this!

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 12:37pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/9 "2023-05-23T12:37:15Z")

</div>

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

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 12:44pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/10 "2023-05-23T12:44:46Z")

</div>

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

```auto

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);
  }
}
//

```

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 12:53pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/11 "2023-05-23T12:53:27Z")

</div>

thank you so much! have a nice day 🙂

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 1:04pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/12 "2023-05-23T13:04:03Z")

</div>

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)

```auto

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);
  }
}
//

```

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 23, 2023, 1:10pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/13 "2023-05-23T13:10:38Z")

</div>

Thank you so much! Sorry, may I ask again? What if the tracks were replaced with legs? like this  
 ![image](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/3X/f/2/f2d260031394a8dd12e70b15bb481180cbe70d58.png)

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 23, 2023, 3:38pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/14 "2023-05-23T15:38:49Z")

</div>

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

```auto
    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**

```auto
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
//

```

---

<div class="post-metadata">

### Author: ![kenkt](https://avatars.discourse-cdn.com/v4/letter/k/35a633/32.png) [@kenkt](https://discourse.processing.org/u/kenkt)
#### Post date: [May 25, 2023, 1:44am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/15 "2023-05-25T01:44:55Z")

</div>

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

---

<div class="post-metadata">

### Author: ![DavidGR74](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/davidgr74/32/18371_2.png) [@DavidGR74](https://discourse.processing.org/u/DavidGR74)
#### Post date: [May 29, 2023, 9:48am UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/16 "2023-05-29T09:48:25Z")

</div>

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.

---

<div class="post-metadata">

### Author: ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)
#### Post date: [May 30, 2023, 8:51pm UTC](https://discourse.processing.org/t/object-walk-with-trail-footprints/42059/18 "2023-05-30T20:51:00Z")

</div>

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.
