Silverback9

#야생으로

Creative Coding 독학 제118일 2024년07월23일(화)

오늘은 pursue를 표현하는 프로그램을 본격적으로 만들어 보겠습니다~^^*

target의 미래 위치를 예상한다는 것은, target이 현재 움직이고 있다는 것을 바탕으로 하는 것 같아요~^^*

그래서, 이번 프로그램에서는, pursue하는 존재도, target이 되는 존재도, 운동성을 가진 존재로 가정하여, Class Vehicle의 속성을 가지도록 하겠습니다~^^*

그런데요~^^* 모습이 서로 달라야, 우리가 pursuer와 target을 구별할 수가 있을 것 같아요~^^* 토끼의 모습과 족제비의 모습이 달라서, 우리가 쉽게 경찰 토끼 Cop Bunny가 도둑 족제비 Thief Weasel을 pursue 하는 과정을 지켜볼 수 있는 것처럼요~^^*

그리고요~^^* target은 처음부터 이미 먼저 움직이고 있고 pursuer가 그 target을 따라가는 모습이 target-pursuer 관계를 표현하는 것 같아요~^^*

그래서!!!

Class Vehicle의 특성을 상속받되, 처음 운동속도가 NONZERO 값, 즉 0이 아닌 값을 가지고 있어서 이미 움직이고 있도록 하고, 모습도 다르게 표현해보는 것이 어떨까요~~^^*

어제는 오후의 홍차와 함께 음악을 들으며 좀 쉬었으니~^^* pursue의 개념이해부터 복습을 한 후 코드를 만들어 볼까요~^^*

아래 동영상 강의를 클릭하시면 오늘 공부내용을 바로 시작(3:15)하실 수 있어요~^^* 6:35까지 보시면 오늘 공부 끝~^^*

먼저 오늘의 핵심 코드를 살펴 볼까요~^^*

하나. Class Vehicle을 상속받은 Class Target을 정의해 보겠습니다.

(1) Class Target의 velocity에 nonzero값을 넣어 놓겠습니다. target이 처음부터 스스로 움직이고 있는데, pursuer가 따라가는 모양새가 자연스럽게 표현될 것 같아요~^^*!!

(2) 모습 표현의 내용을 새롭게 바꾸도록 해 볼게요~^^* 빨간 동그라미로 표현해 보겠습니다~^^* target과 pursuer의 모습이 달라서 우리가 이 둘을 쉽게 구별할 수 있게 되겠네요~^^*

class Target extends Vehicle{
   constructor(x, y) {
     super(x, y);
     this.vel = p5.Vector.random2D();
     this.vel.mult(5);
   }
   show(){
     stroke(255);
     strokeWeight(2);
     fill(255, 0, 0);
     push();
     translate(this.x, this.y);
     circle(0,0, this.r*2);
     pop();
   }
}

둘. pursuer를 Class Vehicle로, target을 Class Target으로 정의해서 생성하겠습니다~^^*

let pursuer;
let target;
pursuer = new Vehicle(100, 100);
target = new Target(200, 100);

셋. pursuer가 target의 위치를 향해 몸을 틀도록 할게요~^^* 그러면~^^* 움직이는 pursuer가 움직이는 target을 pursue하는 관계성이 생길 것 같아요~~^^*!!

let steering = pursuer.seek(target.pos);
pursuer.applyForce(steering);

넷. target이 화면 밖으로 사라지면 다시 화면에 나타나도록 하여, “게임은 계속 되어야 한다!”를 실현해 보겠습니다~^^*

target.edges();

이제 전체 코드를 우리 함께 살펴 봐요~~^^*

<!DOCTYPE html>
<html>
  <head>
    https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.2.0/p5.min.js
    <link rel="stylesheet" type="text/css" href="style.css">
    <meta charset="utf-8" />

  </head>
  <body>
    http://vehicle.js
    http://sketch.js
  </body>
</html>
//부모 Class Vehicle을 먼저 정의합니다. 
//자녀 Class Target을 그 아래에 정의합니다. 
//부모 -> 자녀  순서대로 정의해야 p5.js가 이해할 수 있습니다~^^*

class Vehicle {
  constructor(x, y) {
    this.pos = createVector(x, y);
    this.vel = createVector(0, 0);
    this.acc = createVector(0, 0);
    this.maxSpeed = 4;
    this.maxForce = 0.25;
    this.r = 16;
  }

  seek(target) {
    let force = p5.Vector.sub(target, this.pos);
    force.setMag(this.maxSpeed);
    force.sub(this.vel);
    force.limit(this.maxForce);
    this.applyForce(force);
  }

  applyForce(force) {
    this.acc.add(force);
  }

  update() {
    this.vel.add(this.acc);
    this.vel.limit(this.maxSpeed);
    this.pos.add(this.vel);
    this.acc.set(0, 0);
  }

  show() {
    stroke(255);
    strokeWeight(2);
    fill(255);
    push();
    translate(this.pos.x, this.pos.y);
    rotate(this.vel.heading());
    triangle(-this.r, -this.r / 2, -this.r, this.r / 2, this.r, 0);
    pop();
  }

  edges() {
    if (this.pos.x > width + this.r) {
      this.pos.x = -this.r;
    } else if (this.pos.x < -this.r) {
      this.pos.x = width + this.r;
    }
    if (this.pos.y > height + this.r) {
      this.pos.y = -this.r;
    } else if (this.pos.y < -this.r) {
      this.pos.y = height + this.r;
    }
  }
}

class Target extends Vehicle {
  //Class Vehicle을 상속받습니다. 
  
  constructor(x, y) {
    super(x, y);
    
    this.vel = p5.Vector.random2D();
    this.vel.mult(5);
    //초기 속도 벡터를 무작위 방향의 단위 벡터로 생성하겠습니다.
    //벡터 크기를 5배 증가시키겠습니다. 
    //프로그램을 실행할 때마다 서로 다른 방향을 가진 Target이 생성될 것입니다. 
  }

  show() {
    stroke(255);
    strokeWeight(2);
    fill(255,0,0);
    push();
    translate(this.pos.x, this.pos.y);
    circle(0, 0, this.r * 2);
    pop();
    //빨간 동그라미 모습을 합니다. 
  }
}

let pursuer;
let target;

function setup() {
  createCanvas(400, 400);
  pursuer = new Vehicle(100, 100);
  target = new Target(200, 100);

  //pursuer는 Class Vehicle의 운동성과 모습을 가집니다.
  //target은 Class Vehicle을 상속받은 Class Target의 운동성과 모습을 가집니다. 
  //pursuer와 target은 서로 거의 비슷하면서 살짝 다른 운동성과 서로 완전히 다른 모습을 한 존재로 생성됩니다. 
}

function draw() {
  background(0);
 
  let steering = pursuer.seek(target.pos);
  pursuer.applyForce(steering);

  //pursuer가 taget 방향으로 몸을 틉니다. 
 
  pursuer.update();
  pursuer.show();
  
  target.edges();

  //화면 밖으로 나가면 다시 화면 안에 나타납니다. 

  target.update();
  target.show();
}

신출귀몰하는 target을 인내심을 가지고 끝까지 pursue하는 pursuer를 만나러 가볼까요~?^^* 멈춤 버튼을 누르기 전까지 우리의 믿음직한 pursuer는 멈추지 않아요~! 실행버튼을 누를 때마다 다른 곳에서 나타나는 target도 대단한걸요~~^^*

오늘 우리는 Class Vehicle의 속성을 상속 받으면서, 자신만의 속성을 더한 Class Target을 만나 보았어요.

하나의 작은 씨앗이 싹을 틔우고 자라고 열매를 맺고 시들어 삶을 마감하는 풀잎의 짧은 생애는 그만의 생애로만 하릴없이 끝나지는 않는 것 같아요.

생애 동안 정성을 들여 맺었던 열매들 속의 씨앗들이 또 싹을 틔우고 자라고 열매를 맺고 또 다른 씨앗들을 세상에 선물하니까요~^^*

그렇게…

어떤 큰 꿈은,

하나의 존재가 다 실현하기에는 벅찬 꿈은,

그래서 매일매일을 좀 서럽게 느끼게 만들던 그 큰 꿈은,

그래도 결국 다시 힘내서 씨익 웃으며 하루를 시작하게 만들던 벅찬 꿈은,

그 존재의 다음 세대가

그 꿈의 핵심을 이해하고

자신만의 고유한 색깔과 방식을 덧입혀 자신 나름으로 실현해 나가는 것 같아요.

그래서…

처음 그 꿈을 꾼 피와 살을 가진 존재는

더이상 만져지지 않는 추상적인 존재로 바뀌지만,

그의 꿈은

시간과 함께 다음 세대들을 통해서

점점 더 그 모습을 선명하게 갖추어 실현되어 가는 것 같아요.

흩어져 꽃 피우는 민들레처럼,

흩어져 자라나는 단풍나무처럼,

꿈이 실현되는 공간을 넓혀 나가면서요.

어떤 벅찬 꿈을 꾸면서, 그 꿈을 함께 꾸도록 우리를 초대하고는, 문자와 영상과 소리로만 그 자취를 느낄 수 있는, 그리고 어쩌면 그 어떤 자취도 느낄 수 없는, 존재가 되어 가늠할 수 없는 역사의 시간 속에 계신 분들을….공기처럼 막연하고도 감사하게 느껴보게 되네요.

벅찬 꿈을 오늘도 어김없이 꾸고 일어나

오늘 하루를 열심히 묵묵히 살아가면서,

그 바쁜 와중에도

저와 함께 코딩 공부를 해주셔서 감사합니다~^^*

근데요….우리 내일도 코딩 공부 함께 해요~^^*

새로운 도전이 또! 우리 앞에 뙇! 기다리고 있거든요…

코딩 공부를 통해 다져진 도전정신이,

우리 서로의 벅찬 꿈을 pursue할 힘을 보태주면 참 좋겠어요~^^*

네!!! 꿈은 이루어 집니다~!!!

댓글 남기기