어제 비눗방울 만들기 놀이 재미있었지요~~^^* 샴푸의 요정님~~^^*
샴푸의 요정인 우리들이 만들어 내는 비눗방울들이 지붕에서 흘러 내려 땅 아래로 내려가면~, 어머나!
하수관이 비눗방울로 점점 채워지게 되겠네요…
하수관 속에서 비눗방울들의 공기가 빠져서 흐르는 물에 잘 녹아들어야 할텐데요…
그렇지 않으면, 하수관이 비눗방울로 빡빡하게 채워져 제 역할을 못하게 될 수도 있을 것 같아요!
어머 그러면 안돼요!!
그래서~~!!
오늘은 컴퓨터의 업무량을 줄여주는 작업을 해 보면 어떨까요~^^*
뭔가 익숙한 이 느낌????
그렇죠!!
화면 아래로 흘러나간 비눗방울을 비눗방울 배열에서 제거하는 거예요~~^^*
비눗방울이 화면 아래로, 음…넉넉히 100 pixel 정도 아래로, 흘러 내려가면~^^*
화면 밖으로 나갔다는 시그널을 보내기로 할까요?
isOffScreen() {
let pos = this.body.position;
return (pos.y > height + 100)
}
//비눗방울의 y 좌표가 캔버스 바닥보다 100 pixel 아래에 있으면, true 값을 return하도록 할게요~^^*
//그래픽 화면에서, y축 값의 증가는 아래로 내려간다는 의미였지요?^^*
(1) 화면 밖으로 나갔다는 시그널을 확인하면~
if (circles[i].isOffScreen())
(2) matter.js의 world에서 제거를 하고~
removeFromWorld() {
Composite.remove(world, this.body);
}
circles[i].removeFromWorld();
(3) p5.js의 비눗방울 배열에서도 제거를 하고~
circles.splice(i, 1);
(4) 비눗방울 배열의 인덱스를 한 칸 앞으로 되돌릴게요~
i--;
그런데 Why?
Because~ 배열에서 한 요소를 제거한다는 것은… 음… 아날로그 영화 필름의 한 컷을 잘라내고, 그 뒷부분 필름조각을 그 앞부분 끝에 붙이는 것과 비슷할 것 같아요…^^*
배열에서 제거되는 요소의 뒤에 있던 요소가 제거된 요소의 자리로 옮겨지게 되어요. 그 뒤의 요소들도 다 한 칸씩 앞으로 이동하게 되는 효과가 생기겠네요.
그래서~~^^*, 배열에서 요소 하나를 제거하면, 배열의 인덱스를 한 칸 앞으로 줄여야, 제거된 요소 뒤에 있다가 앞으로 한 칸 옮겨진 요소를 빠뜨리지 않고 체크할 수 있어요~~^^*
근데요…같은 자리를 한 번 더 체크하는데 왜 인덱스를 하나 줄여야 되나요?
아!! 그건요!! for loop 때문인 것 같아요~~!!!
for (let i = 0; i < circles.length; i++) {
.
.
.
i--;
}
for loop를 한 번 돌 때마다 index가 하나 증가하기 때문에, 미리 하나 줄여 놓으면, 결국 같은 index자리를 한 번 더 점검하는 효과가 있겠네요~^^*
네~~^^* 그래서~~^^* 배열에서 요소 하나를 제거하면, 다음 요소들이 한 칸씩 앞으로 당겨지기 때문에, 제거된 요소 자리로 옮겨진 요소를 놓치지 않기 위해, index를 하나 줄인 후 for loop를 돌려야 할 것 같네요.
이 네 단계를 정리해 보면~~^^*
isOffScreen() {
let pos = this.body.position;
return (pos.y > height + 100)
}
removeFromWorld() {
Composite.remove(world, this.body);
}
for (let i = 0; i < circles.length; i++) {
circles[i].show();
if (circles[i].isOffScreen()) {
circles[i].removeFromWorld();
circles.splice(i, 1);
i--;
}
}
아하!
하나. 우리가 matter.js로 동그라미를 만들고 p5.js로 이 동그라미를 시각화하기 때문에, matter.js의 World와 p5.js의 배열 모두에서, 제거해야 하는군요!
둘. 배열에서 제거하면, 다음 요소들이 한 칸씩 앞으로 이동하기 때문에, index를 1 줄인 후~ for loop를 돌려 index가 1 증가하면~ 원래의 index 값이 되도록 하여~ 제거된 요소 자리로 한 칸 옮겨진 요소를 놓치지 않고 체크해야 하는군요! i – 1 + 1 = i ~~^^*
이제 그럼 지붕을 흘러 내려 땅 아래 하수구로 들어간 비눗방울을 쏙쏙 녹여서, 하수구의 업무 부담을 줄여주는 프로그램의 전체 코드를 저와 함께 살펴 보시죠!!!
동그라미 갯수 확인용이니, 동그라미는 자동 생성하도록 할게요~^^*
<!DOCTYPE html>
<html lang="en">
<head>
https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/p5.js
https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.6.0/addons/p5.sound.min.js
https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<main>
</main>
http://sketch.js
http://circle.js
http://boundary.js
</body>
</html>
class Boundary {
constructor(x, y, w, h, a) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
let options = {
friction: 0,
restitution: 0.6,
angle: a,
isStatic: true
}
this.body = Bodies.rectangle(this.x, this.y, this.w, this.h, options);
Composite.add(world, this.body);
}
show() {
let pos = this.body.position;
let angle = this.body.angle;
push();
translate(pos.x, pos.y);
rotate(angle);
rectMode(CENTER);
fill(0);
rect(0, 0, this.w, this.h);
pop();
}
}
class Circle {
constructor(x, y, r) {
this.x = x;
this.y = y;
this.r = r;
let options = {
friction: 0,
restitution: 0.6
}
this.body = Bodies.circle(this.x, this.y, this.r, options);
Composite.add(world, this.body);
}
isOffScreen() {
let pos = this.body.position;
return (pos.y > height + 100)
}
removeFromWorld() {
Composite.remove(world, this.body)
}
show() {
let pos = this.body.position;
let angle = this.body.angle;
push();
translate(pos.x, pos.y);
rotate(angle);
rectMode(CENTER);
strokeWeight(1);
stroke(255)
fill(127);
ellipse(0, 0, this.r * 2);
pop();
}
}
const { Engine, World, Bodies, Composite } = Matter;
let engine;
let world;
let circles = [];
let boundaries = [];
function setup() {
createCanvas(400, 400);
engine = Engine.create();
world = engine.world;
boundaries.push(new Boundary(150, 200, width* 0.6, 20, 0.3));
boundaries.push(new Boundary(250, 300, width* 0.6, 20, -0.3));
}
function draw() {
background(51);
Engine.update(engine);
circles.push(new Circle(200, 50, random(5, 10)));
//동그라미를 자동 생성해 보도록 하겠습니다~!
for (let i = 0; i < circles.length; i++) {
circles[i].show();
if (circles[i].isOffScreen()) {
circles[i].removeFromWorld();
circles.splice(i, 1);
i--;
}
}
for (let i = 0; i < boundaries.length; i++) {
boundaries[i].show();
}
console.log(circles.length, world.bodies.length);
//p5.js의 동그라미 배열 속 요소의 갯수와
//matter.js의 world 안의 동그라미 body의 갯수를
//console 창에서 확인해 볼까요?
//화면 아래로 내려가면 제거되어서,
//전체 갯수가 적절하게 유지되고 있을까요?
}
동그라미 갯수를 확인해 봅시다~ 돋보기를 들고 우리 컴퓨터 화면 곳곳을 꼼꼼하게 점검해 볼까요~^^* 콘솔창의 두 수치의 변화도 관찰해 보시면 재미있겠지요~~^^*
오늘도 저와 함께 동그라미 갯수를 조절하여 컴퓨터의 업무를 덜어주는 프로그램을 완성해 주셔서 감사합니다~^^*
음…그런데…오늘 영화 필름 편집 이야기로 배열 요소 제거 설명을 하다보니, 세상의 변화가 좀 실감이 났어요…
만져지지 않는 가상의 정보를 실상의 물체로 느끼는 것에 어느덧 익숙해진 우리는~~^^*
그녀의 진지한 질문이 왠지 유머러스하다고 느끼게 되었습니다~^^*
손으로 필름을 만지던 옛날~~^^*
시간의 먼지를 닦아내고 아날로그 필름 편집의 기억을 들여다 보는 것도 재미있을 것 같아요~~^^*
옛날 영화들을 보면서 새로운 감회를 느끼는 토요일의 망중한을 선물드려요~^^*
오늘도 좋은 아침! 멋진 하루 보내셔요~^^*
내일 우리 또 만나서 코딩 공부 계속 해 나갈까요~~^^*
네~~^^* 꿈은 이루어 집니다~~^^*
댓글 남기기