중력은 G*M/r^2
이지만 중력상수 G
는 매우 작기도 하고, 어차피 게임 프로그래밍 등에서는 이러한 값이 큰 영향을 주는게 아니라면 무시해도 되니까 보통은 M/r^2
으로 생각하면 된다.
태양과 지구를 생각했을 때, 지구의 속도벡터에 태양과의 중력벡터를 더하면 새로운 지구의 속도벡터가 생기는데, 이를 단순하게 코딩하면 된다.
import Vector from './Vector.js'
// 속도를 가진 입자 클래스
export default class Particle {
public mass: number = 1
readonly pos: Vector
readonly velocity: Vector
constructor(x: number, y: number, speed: number, angle: number) {
const pos = new Vector(x, y)
const velocity = new Vector(0, 0)
velocity.length = speed
velocity.angle = angle
this.pos = pos
this.velocity = velocity
}
get x(): number {
return this.pos.x
}
get y(): number {
return this.pos.y
}
update() {
this.pos.addTo(this.velocity)
}
distanceTo(p: Particle): number {
const x = p.x - this.x
const y = p.y - this.y
return Math.sqrt(y*y + x*x)
}
angleTo(p: Particle): number {
return Math.atan2(p.y - this.y, p.x - this.x)
}
gravitateTo(p: Particle) {
// 중력벡터
const gravity = new Vector(0, 0)
const dist = this.distanceTo(p)
const angle = this.angleTo(p)
// 중력의 크기
// M/r^2
gravity.length = p.mass / (dist*dist)
gravity.angle = angle
this.velocity.addTo(gravity)
}
}
import Particle from './Particle.js'
const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')
const w = window.innerWidth
const h = window.innerHeight
canvas.width = w
canvas.height = h
const sun = new Particle(w/2, h/2, 0, 0)
// 여기서 행성의 최초 각도가 -Math.PI/2인데, 이는
// 최초에 원심력의 방향이어야 하기 때문이다.
// 즉, 태양과 90도를 이루는 각도여야 한다.
const planet = new Particle(w/2 + 200, h/2, 10, -Math.PI/2)
sun.mass = 40000
function update() {
ctx.clearRect(0, 0, w, h)
planet.update()
planet.graviateTo(sun)
ctx.beginPath()
ctx.fillStyle = '#ff0000'
ctx.arc(sun.x, sun.y, 30, 0, Math.PI*2, false)
ctx.fill()
ctx.beginPath()
ctx.fillStyle = '#0000ff'
ctx.arc(planet.x, planet.y, 10, 0, Math.PI*2, false)
ctx.fill()
requestAnimationFrame(update)
}
update()