2023. 6. 7. 20:46ㆍ개인노트-인강
인터랙티브 웹 개발 Canvas 불꽃놀이 인강 정리
# 불꽃놀이 원 모양으로 랜덤 파티클 만들어보기
이번에는 폭죽의 모양을 제대로 구성하는 방법에 대해서 알아보겠습니다.
## 파티클이 원이 아닌 사각형으로 퍼져나간 이유
vx와 vy의 랜덤값 범위를 좌표에 표시해 보면 사각형 모양이 나옵니다. (예 : vx의 랜덤값 범위 -5~5, vy의 랜덤값 범위 -5~5)
랜덤값의 범위를 원 모양이 나오게 만들어주어야 합니다.
랜덤 r (반지름) 과 랜덤 세타 값을 구하면 사방으로 퍼지는 원의 모양을 만들 수 있게 됩니다.
### 원모양으로 퍼져나갈 vx와 vy 구하기
// ...
createParticles() {
const PARTICLE_NUM = 400;
const x = randomNumBetween(0, this.canvasWidth);
const y = randomNumBetween(0, this.canvasHeight);
for (let i = 0; i < PARTICLE_NUM; i++) {
const r = randomNumBetween(0, 3);
const angle = (Math.PI / 180) * randomNumBetween(0, 360);
// const vx = randomNumBetween(-5, 5);
// const vy = randomNumBetween(-5, 5);
const vx = r * Math.cos(angle);
const vy = r * Math.sin(angle);
this.particles.push(new Particle(x, y, vx, vy));
}
}
// ...
# 중력과 마찰효과 넣기
중력효과를 넣으면 파티클이 아래로 떨어지는 효과가 추가되어 좀 더 자연스러워 보이고, 마찰을 넣게 되면 속도가 점점 0에 수렴하게 되면서 좀 더 불꽃놀이같은 모양을 만들 수 있습니다.
## 중력 적용
export default class Particle extends CanvasOption {
constructor(x, y, vx, vy) {
super();
// ...
this.gravity = 0.12;
}
update() {
this.vy += this.gravity;
// ...
}
draw() {
// ...
}
}
## 마찰 적용
매 프레임 마다 속도 x와 속도 y 값에 모두 같은 마찰값을 곱해주어서 점점 느려지게 만들어 0으로 수렴하게 합니다.
export default class Particle extends CanvasOption {
constructor(x, y, vx, vy) {
super();
// ...
this.friction = 0.93;
}
update() {
this.vx *= this.friction;
this.vy *= this.friction;
// ...
}
draw() {
// ...
}
}
# 파티클마다 opacity 값도 랜덤으로 적용하기
opacity 값도 랜덤으로 생성하여 생성자 함수로 넘겨줍니다.
createParticles() {
// ...
const opacity = randomNumBetween(0.6, 0.9);
this.particles.push(new Particle(x, y, vx, vy, opacity));
}
}
// ...
constructor(x, y, vx, vy, opacity) {
super();
// ...
this.opacity = opacity;
// ...
}
// ...
# 꼬리효과 만들기
현재 캔버스 전체에 매 프레임마다 이전 프레임을 지우는 대신에 검정 배경색을 칠하고 있습니다. 여기에 alpha 값을 적용하면 꼬리 모양을 만들 수 있습니다.
예를 들어 alpha 값을 10을 적용하면 alpha 값이 10 밖에 되지않아서 여러번 칠해야 화면이 검정색이 되기 때문에 잔상이 남는 것처럼 보이게 됩니다.
// ...
render() {
const frame = () => {
requestAnimationFrame(frame);
// ...
this.ctx.fillStyle = this.bgColor + "40"; // #00000010
// ...
};
}
# 화면 크기에 따라 폭죽이 퍼지는 크기 조절하기(반지름 r 크기 조절하기)
innerWidth를 사용하여 랜덤 r를 구하게 된다면 화면 가로가 작아지거나 화면 가로가 클 때는 비슷한 사이즈 비율로 원을 만들 수 있어서 문제를 해결할 수 있는 것처럼 보이지만, 세로의 화면이 작아질 때는 그 문제를 해결하지 못하고,
반대로 innerWidth 대신에 innerHeight 값을 토대로 랜덤 r을 구하게 되면 그 문제가 반대로 생깁니다.
그래서 innerWidth 와 innerHeight 의 빗변의 길이를 피타고라스의 정의를 이용하여 길이를 구한다음, 빗변의 길이를 토대로 랜덤 반지름 r를 구해보겠습니다.
util.js
빗변구하기 함수
// ...
export const hypotenuse = (x, y) => {
return Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
}
index.js
// ...
createParticles() {
// ...
for (let i = 0; i < PARTICLE_NUM; i++) {
const r =
randomNumBetween(2, 100) * hypotenuse(innerWidth, innerHeight) * 0.0001;
// ...
}
}
// ...
'개인노트-인강' 카테고리의 다른 글
개인 노트 정리) 시각디자인1 - 시각디자인 기초 (0) | 2023.06.16 |
---|---|
개인 노트 정리) Canvas - 2-04. 꼬리(Tail class) 만들기 (0) | 2023.06.11 |
개인 노트 정리) Canvas - 2-02. 파티클과 폭죽의 기본 원리 (0) | 2023.06.06 |
개인 노트 정리) Canvas - 2-01. 보일러 플레이트 두가지 방법 (0) | 2023.06.04 |
개인 노트 정리) Canvas - 1-08. 캔버스 resize 다루기 (0) | 2023.06.01 |