Skip to content

Instantly share code, notes, and snippets.

@ikeryou
Last active September 8, 2016 06:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ikeryou/6861f0cbd8318b65fdd4870b26a3ea0b to your computer and use it in GitHub Desktop.
Save ikeryou/6861f0cbd8318b65fdd4870b26a3ea0b to your computer and use it in GitHub Desktop.
衝突判定
class Ball
constructor: ->
@radius = 0
@x = 0
@y = 0
@vx = 0
@vy = 0
@mass = 1
@bounce = 0.9
class Main
constructor: ->
@_balls = []
// -------------------------
// エントリーポイント
// -------------------------
start: =>
// ステージサイズ
sw = 1000
sh = 1000
i = 0
num = 100
while i < num
ball = new Ball()
@_balls.push(ball)
// 位置とかランダムに
ball.x = Math.random() * sw
ball.y = Math.random() * sh
ball.vx = Math.random() * 10 - 5
ball.vy = Math.random() * 10 - 5
ball.radius = 5 + Math.random() * 5
ball.mass = ball.radius
i++
// -------------------------
// 更新
// -------------------------
update: =>
for val,i in @_balls
val.x += val.vx
val.y += val.vy
@checkWall(val)
i = 0
num = @_ball.length
while i < num - 1
ballA = @_ball[i]
l = i + 1
while l < num
ballB = @_ball[l]
@checkBall(ballA, ballB)
l++
i++
// -------------------------
// 壁チェック
// -------------------------
checkWall: (ball) =>
// ステージサイズ
sw = 1000
sh = 1000
if ball.x > sw * 0.5
ball.x = sw * 0.5
ball.vx *= ball.bounce
else if ball.x < -sw * 0.5
ball.x = -sw * 0.5
ball.vx *= ball.bounce
if ball.y > sh * 0.5
ball.y = sh * 0.5
ball.vy *= ball.bounce
else if ball.y < -sh * 0.5
ball.y = -sh * 0.5
ball.vy *= ball.bounce
// -------------------------
// Ball同士チェック
// -------------------------
checkBall: (ball0, ball1) =>
dx = ball1.x - ball0.x
dy = ball1.y - ball0.y
dist = Math.sqrt(dx * dx + dy * dy)
if dist < ball0.radius + ball1.radius
angle = Math.atan2(dy, dx)
sin = Math.sin(angle)
cos = Math.cos(angle)
pos0 = {x:0, y:0}
pos1 = @rotate(dx, dy, sin, cos, true)
vel0 = @rotate(ball0.vx, ball0.vy, sin, cos, true)
vel1 = @rotate(ball1.vx, ball1.vy, sin, cos, true)
vxTotal = vel0.x - vel1.x
vel0.x = ((ball0.mass - ball1.mass) * vel0.x + 2 * ball1.mass * vel1.x) / (ball0.mass + ball1.mass)
vel1.x = vxTotal + vel0.x
absV = Math.abs(vel0.x) + Math.abs(vel1.x)
overlap = (ball0.radius + ball1.radius) - Math.abs(pos0.x - pos1.x)
pos0.x += vel0.x / absV * overlap
pos1.x += vel1.x / absV * overlap
pos0F = @rotate(pos0.x, pos0.y, sin, cos, false)
pos1F = @rotate(pos1.x, pos1.y, sin, cos, false)
ball1.x = ball0.x + pos1F.x
ball1.y = ball0.y + pos1F.y
ball0.x = ball0.x + pos0F.x
ball0.y = ball0.y + pos0F.y
vel0F = @rotate(vel0.x, vel0.y, sin, cos, false)
vel1F = @rotate(vel1.x, vel1.y, sin, cos, false)
ball0.vx = vel0F.x
ball0.vy = vel0F.y
ball1.vx = vel1F.x
ball1.vy = vel1F.y
# -----------------------------------
# 座標回転
# -----------------------------------
rotate: (x, y, sin, cos, reverse) =>
result = {x:0, y:0}
if reverse
result.x = x * cos + y * sin
result.y = y * cos - x * sin
else
result.x = x * cos - y * sin
result.y = y * cos + x * sin
return result
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment