βμ°¨μ₯λκ»μ μλ €μ£Όμ μ¬μ΄νΈμμ λ²‘ν° μμ보기
벑ν°λ?
벑ν°λ μ¬λ¬Όμ μμ§μμ νλ‘κ·Έλλ°νκΈ° μν κ°μ₯ κΈ°λ³Έμ μΈ κ΅¬μ±μμλ€.
μΌλ°μ μΌλ‘ 벑ν°λ νμ΄νλ‘ νννλ€. νμ΄νκ° κ°λ¦¬ν€λ μͺ½μ λ°©ν₯μ λνλ΄λ©° νμ΄νμ κΈΈμ΄λ ν¬κΈ°λ₯Ό λνλΈλ€.
μ 벑ν°λ₯Ό μ¬μ©ν κΉ?
μ½λλ₯Ό λ¨μννκ³ μ’ λ μ μ μμ λ³μλ₯Ό μ¬μ©ν μ μλ€.
λν, μμ§μμ νλ‘κ·Έλλ°νλ λμ λ°λ³΅μ μΈ μν μ°μ°μ ν λ νΈλ¦¬ν ν¨μ μ§ν©μ μν μ νλ€.
pVectorλ₯Ό μ΄μ©ν νλ‘κ·Έλλ° μμ
μΊλ²μ€λ₯Ό μ΄μ©ν΄μ Bouncing Ball μ λλ©μ΄μ μ λ§λ€μλ€.
λνμ΄ κ° νλ μλ§λ€ νΉμ ν½μ λ§νΌ κ°λ‘ λ° μΈλ‘λ‘ μμ§μ΄λλ‘ νλ‘κ·Έλλ° λμ΄μλ€.
<canvas id="myCanvas" width="300" height="250" style="border: 1px solid #000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// μ λλ©μ΄μ
μ μν λ³μ
const circle = {
x : 100,
y : 100,
xspeed : 1,
yspeed : 3.3,
};
const draw = () => {
context.beginPath();
context.arc(circle.x, circle.y, 10, 0, 2 * Math.PI);
context.fillStyle = '#555555';
context.fill();
};
const update = () => {
context.clearRect(0, 0, canvas.width, canvas.height);
draw();
circle.x = circle.x + circle.xspeed;
circle.y = circle.y + circle.yspeed;
if ((circle.x > canvas.width) || (circle.x < 0)) {
circle.xspeed = circle.xspeed * -1;
}
if ((circle.y > canvas.height) || (circle.y < 0)) {
circle.yspeed = circle.yspeed * -1;
}
requestAnimationFrame(update);
};
update();
</script>
νμ¬ λ³μλ μλμ κ°λ€. (x μ’ν, y μ’ν, x μλ, y μλ)
const circle = {
x : 100,
y : 100,
xspeed : 1,
yspeed : 3.3,
};
λ³μλ₯Ό 2μ°¨μ μ 보λ₯Ό κ°λ, 벑ν°μ μ μ¬ν κ°μ²΄λ‘ λ§λ€λ©΄ μλμ κ°λ€. (μμΉμ μλ)
const PVector = function(x, y) {
this.x = x;
this.y = y;
};
const position = new PVector(100, 100);
const velocity = new PVector(1, 3.3);
λ κ°μ λ²‘ν° κ°μ²΄(μμΉμ μλ)κ° μλ€λ©΄, μμ§μμ λν μκ³ λ¦¬μ¦μ ꡬνν μ μλ€.
* μλ‘μ΄ μμΉ = ν μμΉμ μλλ₯Ό μ μ©ν κ°
position = position + velocity;
μμ μμμ λ°νμΌλ‘ λ 벑ν°λ₯Ό λν΄μ£Όλ λ©μλλ₯Ό μμ±νλ©΄ μλμ κ°λ€
PVector.prototype.add = function(v) {
this.y = this.y + v.y;
this.x = this.x + v.x;
};
λ²‘ν° κ°μ²΄μ λ°±ν° λ§μ λ©μλλ₯Ό νμ©νλ©΄ Bouncing Ball μ λλ©μ΄μ μ€ν¬λ¦½νΈλ₯Ό μλμ κ°μ΄ μμ±ν μ μλ€.
<canvas id="myCanvas" width="300" height="250" style="border: 1px solid #000;"></canvas>
<script>
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
// 2μ°¨μ λ²‘ν° κ°μ²΄λ₯Ό λ§λλ λ©μλ
const PVector = function(x, y) {
this.x = x;
this.y = y;
};
// λ²‘ν° λ§μ
λ©μλ (μμ§μμ λν μκ³ λ¦¬μ¦ : location = location + velocity)
PVector.prototype.add = function(v) {
this.y = this.y + v.y;
this.x = this.x + v.x;
};
// μ λλ©μ΄μ
μ μν λ³μ
// μμΉ, μλ λ²‘ν° κ°μ²΄ μμ±
const position = new PVector(100, 100);
const velocity = new PVector(1, 3.3);
const draw = () => {
context.beginPath();
context.arc(position.x, position.y, 10, 0, 2 * Math.PI);
context.fillStyle = '#555555';
context.fill();
};
const update = () => {
context.clearRect(0, 0, canvas.width, canvas.height);
draw();
// position + velocity λ²‘ν° λ§μ
position.add(velocity);
if ((position.x > canvas.width) || (position.x < 0)) {
velocity.x = velocity.x * -1;
}
if ((position.y > canvas.height) || (position.y < 0)) {
velocity.y = velocity.y * -1;
}
requestAnimationFrame(update);
};
update();
</script>
λ²‘ν° μν (2μ°¨μ)
- add() — λ²‘ν° λ§μ
PVector.prototype.add = function(v) { this.y = this.y + v.y; this.x = this.x + v.x; };β
- sub() — λ²‘ν° λΊμ
PVector.prototype.sub = function(v) { this.x = this.x - v.x; this.y = this.y - v.y; };β
- mult() — 벑ν°μ μ€μκ³±μ
PVector.prototype.mult = function(n) { this.x = this.x * n; this.y = this.y * n; };
- div() — 벑ν°μ μ€μλλμ
PVector.prototype.div = function(n) { this.x = this.x / n; this.y = this.y / n; };
- mag() — λ²‘ν° ν¬κΈ°λ₯Ό κ³μ°ν¨
PVector.prototype.mag = function() { return sqrt(this.x * this.x + this.y * this.y); };
- normalize() — 벑ν°λ₯Ό μ κ·ννμ¬ λ¨μ κΈΈμ΄λ₯Ό 1λ‘ λ§λ€μ΄μ€
PVector.prototype.normalize = function() { const m = this.mag(); if (m > 0) { this.div(m); } };β
- magSq() — 벑ν°μ ν¬κΈ° μ κ³± (μ°Έκ³ )
PVector.prototype.magSq = function() { return this.x * this.x + this.y * this.y; };β
- limit() — 벑ν°μ ν¬κΈ°λ₯Ό μ ν (μ°Έκ³ )
PVector.prototype.limit = function(max) { const mSq = this.magSq(); if (mSq > max * max) { this.div(Math.sqrt(mSq)); //normalize it this.mult(max); } return this; };β
- heading2D() — 2μ°¨μμμ 벑ν°μ λ°©ν₯μ κ°λλ‘ λνλ (μ°Έκ³ )
PVector.prototype.heading = function() { const r = Math.atan2(this.y, this.x); const h = (r * 180.0) / Math.PI; return h; };
- dist() — λ 벑ν°(μ μΌλ‘ κ°μ£Ό)κ° μ ν΄λ¦¬λμ 거리λ₯Ό κ³μ°ν¨ (μ°Έκ³ )
PVector.prototype.dist = function(v) { const d = v.copy().sub(this); return d.mag(); };β
- angleBetween() — λ 벑ν°κ° κ°λλ₯Ό κ³μ°ν¨ (μ°Έκ³ )
PVector.prototype.angleBetween = function(x, y) { const r = this.angleBetweenRads(x,y); const d = (r * 180) / Math.PI; return d; };β
- random2D() — 2μ°¨μ λ²‘ν° λλ€ κ° λ°ν (μ°Έκ³ 1 / μ°Έκ³ 2)
/* PVector.fromAngle = function(angle, length) { if (typeof length === 'undefined') { length = 1; } return new PVector( length * Math.cos(angle), length * Math.sin(angle) ); }; PVector.random2D = function() { return this.fromAngle(Math.random() * Math.PI * 2); }; */ PVector.random2D = function() { return new PVector( 1 * Math.cos(Math.random() * Math.PI * 2), 1 * Math.sin(Math.random() * Math.PI * 2) ); };
- dot() — λ 벑ν°μ λ΄μ μ κ³μ°ν¨
- cross() — λ 벑ν°μ μΈμ μ κ³μ°ν¨ (3μ°¨μμμλ§ κ°λ₯)
- copy() — 벑ν°μ κ΅¬μ± μμλ₯Ό 볡μ¬ν΄μ μ PVector λ‘ λ°ν. ꡬ get λ©μλ (μ°Έκ³ )
PVector.prototype.copy = function() { return new PVector(this.x, this.y); };
μ°Έμ‘° μ¬μ΄νΈ
벑ν°λ?
Canvas κΈ°λ³Έ μ λλ©μ΄μ
https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Basic_animations
https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Basic_animations
Canvasλ‘ μ λλ©μ΄μ ꡬννκΈ°
νμ΄ν ν¨μμμ this
https://velog.io/@yhe228/%ED%99%94%EC%82%B4%ED%91%9C-%ED%95%A8%EC%88%98%EC%97%90%EC%84%9C-this
λ²‘ν° μν λ νΌλ°μ€
https://processing.org/reference/PVector_limit_.html