오늘도 참 추운데요…어제 오후에도 공기가 엄청 차서 많이 놀랐어요….
하지만! 찬 공기 속에서도 흰 눈의 흔적 속에서도 오늘의 공부를 시작해 보겠습니다! YEAH~~^^* 우리는 Coding 꿈나무이니까요~~^^* YEAH~~^^*
발레 꿈나무들의 멋진 춤사위를 귀로 들으시며~^^* 아침을 부드럽게 풀고 계시기 바래요~^^*
공부 정리해서 돌아올게요~^^* 쓩우웅~^^*
먼저, 아주아주 옛날부터 지금까지 vehicle의 조상님들의 약초와 독초에 대한 경험의 기억을 유전자에 담아보겠습니다~^^* 네~^^* 이제 슬슬 DNA를 준비해 볼까요~~^^*
네^^*
food에 대한 유전적 기억을 dna[0]에 담고요~^^*
poison에 대한 유전적 기억을 dna[1]에 담아 볼게요~^^*
왠지 모르게 약초에게 끌리고 왠지 모르게 독초에서 멀어지고픈 마음이 자연스럽게 생기는 안전한 미래가, 이 프로그램을 최종적으로 완성하면, 펼쳐질 것 같아요.
그 미래를 준비하는 첫 날인 오늘!!!
일단 오늘은~^^* 끌림과 멀어지고픔의 강도의 최소/최대 값을 food와 poison에 대해 동일하게 갖도록 해볼게요. 그리고 그 구체적인 값은 최소/최대 범위 안에서 무작위로 설정해 볼게요.
네~^^* 우리의 귀엽고 총명한 vehicle의 태초의 조상이 맞이했던 상황이라고 여겨질 수도 있겠네요.
class Vehicle {
constructor(x, y) {
this.acceleration = createVector(0, 0);
this.velocity = createVector(0, -2);
this.position = createVector(x, y);
this.health = 1;
this.r = 6;
this.maxspeed = 8;
this.maxforce = 0.2;
this.dna = [];
this.dna[0] = random(-5, 5);
//food에 대한 멀어지고픔 최대치 -5 끌림 최대치 +5 사이 무작위 값
this.dna[1] = random(-5, 5);
//poison에 대한 멀어지고픔 최대치 -5 끌림 최대치 +5 사이 무작위 값
}
.
.
.
}
이번에는 vehicle의 DNA에 심어진 이 기억에 따라 vehicle이 자신도 모르게 본능적으로 food와 poison에 반응하는 행동을 표현해야 할 것 같네요~~^^*
네~^^* 내장함수 behaviors()를 준비해 보겠습니다~^^*
먹거리를 몸에 좋은 것 그리고 나쁜 것으로 구분해 볼게요~^^* 그리고 몸에 좋은 것을 먹을 때의 행동 그리고 몸에 나쁜 것을 먹을 때의 행동을 표현해 보겠습니다.
class Vehicle {
.
.
.
behaviors(good, bad) {
const steerG = this.eat(good);
//몸에 좋은 음식에 대한 반응행동 벡터 steerG입니다.
const steerB = this.eat(bad);
//몸에 나쁜 음식에 대한 반응행동 벡터 steerB입니다.
steerG.mult(this.dna[0]);
//몸에 좋은 것에 대한 기억인 dna[0]에 저장된 값을 좋은 음식에 대한 반응행동 벡터 steerG의 크기에 곱하겠습니다.
steerB.mult(this.dna[1]);
//몸에 나쁜 것에 대한 기억인 dna[1]에 저장된 값을 나쁜 음식에 대한 반응행동 벡터 steerB의 크기에 곱하겠습니다.
this.applyForce(steerG);
this.applyForce(steerB);
//vehicle의 행동에 이 반응벡터 steerG와 steerB가 영향을 끼칩니다.
}
.
.
.
}
음…그런데요…
행동을 묘사하는 함수 behaviors()를 마련하고 보니, 함수 eat()를 또 개선할 필요가 있을 것 같네요.
steerG와 steerB가 함수 eat()가 return 반환하는 값을 저장하니까요~^^*
어제 우리가 만들어 보았던 eat()함수를 다시 살펴 볼까요~^^*
<<어제의 함수 eat() 버전>>
eat(list) {
var record = Infinity;
var closest = -1;
for (var i = 0; i < list.length; i++) {
var d = this.position.dist(list[i]);
if(d < record) {
record = d;
closest = i;
}
}
if(record < 5) {
list.splice(closest, 1);
} else if(closest > -1) {
this.seek(list[closest]);
}
}
아직 가장 가까운 먹거리가 5 pixel보다는 떨어져 있지만, 먹거리의 배열에 아직 구성요소가 남아있을 경우( closest > -1 ), 먹지는 않고( 먹거리 배열에서 삭제하지는 않고) 그 먹거리를 향해서 몸을 틀게 되는데요.
이 seek 함수 호출 부분을 return하도록 개선해 보겠습니다~^^*
<<오늘의 함수 eat() 버전>>
eat(list) {
var record = Infinity;
var closest = -1;
for (var i = 0; i < list.length; i++) {
var d = this.position.dist(list[i]);
if(d < record) {
record = d;
closest = i;
}
}
if(record < 5) {
list.splice(closest, 1);
} else if(closest > -1) {
return this.seek(list[closest]);
}
return createVector(0,0);
}
//먹거리가 5 pixel 거리 안에 없지만, 먹거리 배열에 구성요소가 남아있을 경우, 가장 가까운 구성요소를 향해서 몸을 트는 행동 벡터 this.seek(list[closest]);를 반환합니다.
//먹거리가 5 pixel 거리 안에 있으면, 먹거리 배열에서 그 먹거리를 삭제한 후 아무 움직임도 없는(0,0) 행동벡터를 반환합니다.
//먹거리 배열에 아무 구성요소가 없는 경우에도 아무 행동이 없는 (0,0) 행동벡터를 반환합니다.
음…그러면….이제는 또….
네…내장함수 seek()를 수정해서 벡터값을 반환하도록 개선해야 할 것 같아요…!!
이전 버전 먼저 함께 살펴 볼까요~~^^*
seek(target) {
const desired = p5.Vector.sub(target, this.position);
desired.setMag(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
this.applyForce(steer);
}
target으로 몸을 트는 벡터 steer를 생성하여 maxforce 값 안으로 힘이 크기를 조정하여 vehicle에게 이 벡터를 적용시켰는데요.
이제는 vehicle의 행동에 벡터의 적용을 하지 않고, 벡터 steer를 반환하는 것으로 수정해 보겠습니다.
seek(target) {
const desired = p5.Vector.sub(target, this.position);
desired.setMag(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
return steer;
}
네~^^* 그럼 이제~~^^*
새로운 내장 변수 배열 dna[], 새로운 내장 함수 behavior()와 이에 맞게 개선된 내장 함수 eat()와 steer()를 함께 모아 한 눈에 같이 살펴 볼까요~~^^*
class Vehicle {
constructor(x, y) {
.
.
.
this.dna = [];
this.dna[0] = random(-5, 5);
//food에 대한 멀어지고픔 최대치 -5 끌림 최대치 +5 사이 무작위 값
this.dna[1] = random(-5, 5);
//poison에 대한 멀어지고픔 최대치 -5 끌림 최대치 +5 사이 무작위 값
}
.
.
.
behaviors(good, bad) {
const steerG = this.eat(good);
//몸에 좋은 음식에 대한 반응행동 벡터 steerG입니다.
const steerB = this.eat(bad);
//몸에 나쁜 음식에 대한 반응행동 벡터 steerB입니다.
steerG.mult(this.dna[0]);
//몸에 좋은 것에 대한 기억인 dna[0]에 저장된 값을 좋은 음식에 대한 반응행동 벡터 steerG의 크기에 곱하겠습니다.
steerB.mult(this.dna[1]);
//몸에 나쁜 것에 대한 기억인 dna[1]에 저장된 값을 나쁜 음식에 대한 반응행동 벡터 steerB의 크기에 곱하겠습니다.
this.applyForce(steerG);
this.applyForce(steerB);
//vehicle의 행동에 이 반응벡터 steerG와 steerB가 영향을 끼칩니다.
}
eat(list) {
var record = Infinity;
var closest = -1;
for (var i = 0; i < list.length; i++) {
var d = this.position.dist(list[i]);
if(d < record) {
record = d;
closest = i;
}
}
if(record < 5) {
list.splice(closest, 1);
} else if(closest > -1) {
return this.seek(list[closest]);
}
return createVector(0,0);
}
//먹거리가 5 pixel 거리 안에 없지만, 먹거리 배열에 구성요소가 남아있을 경우, 가장 가까운 구성요소를 향해서 몸을 트는 행동 벡터 this.seek(list[closest]);를 반환합니다.
//먹거리가 5 pixel 거리 안에 있으면, 먹거리 배열에서 그 먹거리를 삭제한 후 아무 움직임도 없는(0,0) 행동벡터를 반환합니다.
//먹거리 배열에 아무 구성요소가 없는 경우에도 아무 행동이 없는 (0,0) 행동벡터를 반환합니다.
seek(target) {
const desired = p5.Vector.sub(target, this.position);
desired.setMag(this.maxspeed);
let steer = p5.Vector.sub(desired, this.velocity);
steer.limit(this.maxforce);
return steer;
}
//target으로 몸을 트는 벡터를 생성하여 변수 steer에 저장한 후 maxforce 값 안으로 힘의 크기를 조정하여 steer를 반환합니다.
.
.
.
}
이제 메인 함수이며 무한 반복 함수인 draw()에서는 vehicle의 내장함수 beaviors()를 호출하면서 food를 좋은 음식 poison을 나쁜 음식 argument로 넘겨주면 될 것 같아요~~^^*
function draw() {
.
.
.
vehicle.behavior(food, poison);
vehicle.update();
vehicle.display();
}
시조새님들 존경합니다!!!
네~^^* 처음의 길을 닦는 존재에 대한 감사함을 느끼며, 오늘 vehicle에 몸에 좋은 음식과 위험한 음식에 대한 유전적 기억을 저와 함께 준비해 주셔서 감사합니다~^^*
내일은 이 dna와 이에 대한 반응행동에 대해 우리 함께 좀 더 공부해 나가 볼까요~^^*
네~^^* 좋아요~^^* 고마워요~^^*
새로운 세상으로의 첫 진입은 신기함과 놀라움과 무지함에서 오는 무작위적인 반응행동과 그에 대한 결과에 영향을 받아가며 조금씩 지식도 지헤도 몸 안에 쌓아나가는 것 같아요…
그리고 어느새 그 새로운 세상을 편안하게 누리며 즐겁게 탐험하게 되는 것 같아요~^^*
우리의 vehicle도 이제 점점 새로운 세상에 대한 자신만의 경험 축적으로 지혜를 쌓아나가며 점점 귀엽고 총명해 질 것 같은데요~^^*!!
인내심을 가지고 프로그램 개선에 저와 함께 해 주셔서 감사합니다~^^*
오늘도!
멋진 하루 보내시며~^^*
반가운 만남 기쁨 나누는 보람 만끽하시고요~^^*
뿌듯한 가슴 통통 두드리며 따뜻하게 코~^^* 하셔요~^^*
네~^^* 꿈은 이루어 집니다~^^*
댓글 남기기