[p5.js] 벡터를 활용한 캐릭터 인터랙션 만들기

2023. 2. 28. 17:27
반응형

벡터

x, y를 묶어서 계산해주는 개념

 

 

 

기본 캐릭터 코드

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background("tomato");
  face(width/2, height/2);
}

function face(x,y) {
  push();
    translate(x, y);
  
    //귀
    ellipse(-150,0,60,60);
    ellipse(150,0,60,60);
  
    //얼굴
    ellipse(0,0,300,300);
  
    //흰자
    ellipse(-60,0,100,100);
    ellipse(60,0,100,100);
  
    //검은자
    fill("black");
    ellipse(-60,0,60,60);
    ellipse(60,0,60,60);
  
    //입
    ellipse(0,80,40,30);
  
    //코
    strokeWeight(5);
    line(0,45,-15,35);
    line(0,45,15,35);
  
    //눈썹
    rectMode(CENTER);
    rect(-60,-70,50,10,5);
    rect(60,-70,50,10,5);
  
    //머리카락
    ellipse(0,-140,120,80);
    ellipse(-60,-130,90,60);
    ellipse(60,-130,90,60);
  pop();
}

 

 

 

마우스 오버 시 표정이 바뀌는 인터랙션

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background("tomato");
  face(width/2, height/2);
}

function face(x,y) {
  push();
    translate(x, y);
  
    let center = createVector(x,y);
    let mouse = createVector(mouseX, mouseY);
    let d = center.dist(mouse);
  
    let s = 1;
    let mouseW = 40;
  
    if(d < 150){
      s = 1.2;
      mouseW = 80;
    }
    scale(s);
  
    //귀
    ellipse(-150,0,60,60);
    ellipse(150,0,60,60);
  
    //얼굴
    ellipse(0,0,300,300);
  
    //흰자
    ellipse(-60,0,100,100);
    ellipse(60,0,100,100);
  
    //검은자
    fill("black");
    ellipse(-60,0,60,60);
    ellipse(60,0,60,60);
  
    //입
    ellipse(0,80,mouseW,30);
  
    //코
    strokeWeight(5);
    line(0,45,-15,35);
    line(0,45,15,35);
  
    //눈썹
    rectMode(CENTER);
    rect(-60,-70,50,10,5);
    rect(60,-70,50,10,5);
  
    //머리카락
    ellipse(0,-140,120,80);
    ellipse(-60,-130,90,60);
    ellipse(60,-130,90,60);
  pop();
}

 

 

 

마우스 커서를 따라다니는 눈동자

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background("skyblue");
  face(width/2, height/2);
}

function face(x,y) {
  push();
    translate(x, y);
  
    let center = createVector(x,y);
    let mouse = createVector(mouseX, mouseY);
  
    //마우스가 얼만큼 움직였는지 구함
    let move = p5.Vector.sub(mouse,center);
  
    //눈동자 위치가 너무 확확 바뀌지 않도록 퀄리티업
    move.mult(0.1);
  
    //검은자가 흰자영역을 벗어나지 않도록 제한
    move.limit(20);
  
  
  
    //귀
    ellipse(-150,0,60,60);
    ellipse(150,0,60,60);
  
    //얼굴
    ellipse(0,0,300,300);
  
    //흰자
    ellipse(-60,0,100,100);
    ellipse(60,0,100,100);
  
  
    fill("black");
  
    //검은자
    push();
      translate(move.x, move.y);
      ellipse(-60,0,60,60);
      ellipse(60,0,60,60);
    pop();
  
    //입
    ellipse(0,80,40,30);
  
    //코
    strokeWeight(5);
    line(0,45,-15,35);
    line(0,45,15,35);
  
    //눈썹
    rectMode(CENTER);
    rect(-60,-70,50,10,5);
    rect(60,-70,50,10,5);
  
    //머리카락
    ellipse(0,-140,120,80);
    ellipse(-60,-130,90,60);
    ellipse(60,-130,90,60);
  pop();
}

 

 

얼굴 각 부위도 함께 따라 움직임 + 마우스클릭 시 눈 깜빡이게 해서 3D 느낌 나도록 수정

function setup() {
  createCanvas(400, 400);
}

function draw() {
  background("skyblue");
  face(width/2, height/2);
}

function face(x,y) {
  push();
    translate(x, y);
  
    let center = createVector(x,y);
    let mouse = createVector(mouseX, mouseY);
  
    //마우스가 얼만큼 움직였는지 구함
    let move = p5.Vector.sub(mouse,center);
  
    //눈동자 위치가 너무 확확 바뀌지 않도록 퀄리티업
    move.mult(0.1);
  
    let pupilMove = move.copy();
  
    //검은자가 흰자영역을 벗어나지 않도록 제한
    pupilMove.limit(20);
  
    let eyeMove = move.copy();
    eyeMove.mult(0.5);
  
    let noseMove = move.copy();
    noseMove.mult(0.7);
  
    let mouthMove = move.copy();
    mouthMove.mult(0.4);
  
    let hairMove = move.copy();
    hairMove.mult(0.3);
  
    let browMove = move.copy();
    browMove.mult(0.6);
  
    let earMove = move.copy();
    earMove.mult(-0.5);
  
  
    //귀
    push();
      translate(earMove.x, earMove.y);
      ellipse(-150,0,60,60);
      ellipse(150,0,60,60);
    pop();
  
    //얼굴
    ellipse(0,0,300,300);
  
    //눈 부분
    push();
    translate(eyeMove.x, eyeMove.y);
  
    if(mouseIsPressed){
      rectMode(CENTER);
      fill("black");
      rect(-60,0,80,10,5);
      rect(60,0,80,10,5);   
     }
    else {
      //흰자
      translate(eyeMove.x, eyeMove.y);
      ellipse(-60,0,100,100);
      ellipse(60,0,100,100);

      //검은자
      push();
        fill("black");
        translate(pupilMove.x, pupilMove.y);
        ellipse(-60,0,60,60);
        ellipse(60,0,60,60);
      pop(); 
    }
    pop();
  
    //입
    push();
      translate(mouthMove.x, mouthMove.y);
      fill("black");
      ellipse(0,80,40,30);
    pop();
  
    //코
    push();
      translate(noseMove.x, noseMove.y);
      strokeWeight(5);
      line(0,45,-15,35);
      line(0,45,15,35);
    pop();
  
    //눈썹
    push();
      translate(browMove.x, browMove.y);
      fill("black");
      rectMode(CENTER);
      rect(-60,-70,50,10,5);
      rect(60,-70,50,10,5);
    pop();
  
    //머리카락
    push();
      translate(hairMove.x, hairMove.y);
      fill("black");
      ellipse(0,-140,120,80);
      ellipse(-60,-130,90,60);
      ellipse(60,-130,90,60);
    pop();
  pop();
}

 

 

결과물

 

반응형

BELATED ARTICLES

more