Search code examples
javascriptprocessingp5.js

Tickle Example: p5.js - use image rather than text


I tried to look at the 7.8: Objects and Images - p5.js Tutorial to recreate This example

I would like to start with an image moving randomly on mouse over. Can someone please guide me to how I go about achieving this?

Something I tried but it's not the same kind of interaction at all. The example interaction is simple and super nice and the amplitude of oscillation is kind of smooth.

function preload() {
  stone = loadImage("stone.png");
  imageMode = center;
}
function setup() {
  createCanvas(1200, 800);

}

function draw() {
  background(42,44,45);


 if((200<mouseX)&&(900>mouseX)&&(250<mouseY)&&(650>mouseY)){
 this.x = random(width*0.5, height*0.5);
    this.y = random(height*0.5, width*0.5);

    this.speed = 0.0001 * (mouseX/ mouseY);

    this.x += random(-this.speed, this.speed);
    this.y += random(-this.speed, this.speed)
   x += random(-3, 3);
    y += random(-3, 3);

  image(stone,this.x + (mouseX / (height)) ,this.y + (mouseY / width), 400, 300);
 }
  else{
  image(stone,width*0.5,height*0.5, 400, 300); }
}

Solution

  • Your code in the editor link is slightly different from the code in your question. I'm going to answer based on the code in the editor. Here is what your code is doing:

    1. preload image
    2. set the canvas size
    3. (render frame)
    4. set the background to (42, 44, 45)
    5. use the CENTER image mode
    6. test if the mouse is within a certain rectangle
    7. If it is outside the rectangle, just draw the image at the center
    8. If it is inside the rectangle, do the following:
    9. Set the values of this.y and this.x randomly, somewhere between height/2 and width/2
    10. Set the value for this.speed to 0.0001 * mouseX / mouseY (note that the maximum value for this is 0.0001 * 899 / 251, which is around 0.00036)
    11. Increment this.x and this.y by (independent) random values between -this.speed and this.speed
    12. Increment x and y (I don't know why you're doing this, x and y are never used in the program)
    13. Draw the image at the coordinates (this.x + (mouseX / height), this.y + (mouseY / width))
    14. (repeat steps 3-13 forever)

    There are a couple of issues here, but the main reason why your code isn't working is because when the mouse is in the rectangle, you just reset the position to a random location. I recommend using a global variable for the position, and incrementing it when the mouse is in the right place. Another thing about incrementing: when you increment this.x and this.y, increment them by more than 1. This will ensure that they actually move, because currently it will take them at least 2500 frames to move a single pixel (and that's only if they move the maximum amount in the same direction every time, which has incredibly low probability).

    I suggest looking up a tutorial on variable scope. The Coding Train has one in Processing, but none in p5.js as far as I'm aware. I'd still suggest watching his Processing variable scope tutorial, although things will be slightly different.

    Here is what I would do:

    let x, y, speed;
    
    //your preload...
    
    function setup() {
      createCanvas(windowWidth, windowHeight);
    
      imageMode(CENTER);
      x = random(width / 2, height / 2);
      y = random(height / 2, width / 2);
      speed = 5
    }
    
    function draw() {
      background(42, 44, 45);
      if (200 < mouseX && 900 > mouseX && 250 < mouseY && 650 > mouseY) {
        x += random(-speed, speed);
        y += random(-speed, speed);
      }
      image(stone, x, y);
    }
    

    You might notice that I used let at the beginning. This is called a variable declaration. There are three steps to using variables: declaration, initialization, and use (see The Coding Train's video, which is slightly outdated but the ideas are all still there). In some languages (like Python), you don't need to use a keyword to declare the variable. In other languages (like Java), not using a keyword will send an error. In JavaScript (and therefore p5.js), not using a keyword will not give you an error, but it will make the behavior less predictable, and it will be much more difficult to know what's going wrong.

    In this state, the image will move smoothly, but it doesn't have the trail, and it doesn't follow the cursor. The trail is actually quite easy: just give background() a fourth input (for alpha, or transparency). The command background(42, 44, 45, 255) has the same result as background(42, 44, 45): a completely opaque background with no trail. The command background(42, 44, 45, 0) has no effect: a completely transparent background. If you give the fourth input a value around 30, it will give a trail akin to that in the example.

    In order to follow the cursor, you need to adjust your if statement. Currently, it tests the mouse's location relative to a static (unchanging) rectangle. So while the stone moves, the rectangle stays where it is. What the example does is define a rectangle around the text, and test the mouse's location against it. Here is the conditional that you might use for that:

    if (abs(mouseX - x) < stone.width / 2 && abs(mouseY - y) < stone.height / 2) {
      //...
    }