Skip to content

Instantly share code, notes, and snippets.

@edom18
Created September 8, 2013 11:06
Show Gist options
  • Save edom18/6483891 to your computer and use it in GitHub Desktop.
Save edom18/6483891 to your computer and use it in GitHub Desktop.
ホーミングレーザーっぽい動き
#ホーミングレーザーを作ってみる
Unity本を参考にホーミングレーザーを作ってみました。
実装はレーザーの進行方向を判断したのち、回転させる角度を係数によって制御すること。
例えば、レーザーの進行方向からみて50度の位置に敵がいた場合に、
そのまま50度分の回転をさせるのではなく、係数をかけて徐々に角度になるように制御する。
ただ、係数が一定だと延々と敵の周りを回り続ける場合があるので、
時間が経つにつれて係数の度合いを変化させ、いずれはしっかりと敵に向かうようにするところがポイント。
@import "compass/reset";
canvas {
vertical-align: top;
background: #111;
}
<canvas id="cv"></canvas>
{PI, cos, sin, atan2, abs, random} = Math
class Point
constructor: (@x, @y, @color = 'red', @r = 5) ->
draw: (ctx) ->
ctx.beginPath()
ctx.save()
ctx.arc(@x, @y, @r, PI * 2, false)
ctx.fillStyle = @color
ctx.fill()
ctx.restore()
return
clone: ->
return new Point @x, @y, @color, @r
add: (point) ->
@x += point.x
@y += point.y
return @
sub: (point) ->
@x -= point.x
@y -= point.y
return @
class Line
constructor: (@pt1, @pt2, @color = 'blue') ->
draw: (ctx) ->
ctx.beginPath()
ctx.save()
ctx.translate @pt1.x, @pt1.y
ctx.moveTo 0, 0
ctx.lineTo @pt2.x - @pt1.x, @pt2.y - @pt1.y
ctx.strokeStyle = @color
ctx.stroke()
ctx.restore()
class Laser
constructor: (@pos, @target, @sp = 5, @color = 'blue') ->
@_k = random()
@_prevTarget = @pos.clone()
@disposed = false
dispose: ->
@disposed = true
update: ->
@_k += 0.01;
sub = @target.clone().sub @pos
rad = atan2(-sub.y, sub.x)
rad += PI * 2 if rad < 0
tmp = rad - PI / 2
tmp *= @_k
rad = PI / 2 + tmp
x = cos(rad) * @sp
y = sin(rad) * @sp
@dispose() if abs(sub.x) < 1 and abs(sub.y) < 1
@pos.add(new Point x, -y)
@_line = new Line @_prevTarget, @pos
@_prevTarget = @pos.clone()
draw: (ctx) ->
@_line.draw ctx
do (win = window, doc = document) ->
cv = doc.getElementById 'cv'
ctx = cv.getContext '2d'
w = win.innerWidth
h = win.innerHeight
cv.width = w
cv.height = h
len = 15
player = null
enemy = null
lasers = []
init = ->
player = new Point w / 2 + h / 3, h / 2 + h / 3, 'green'
enemy = new Point 130, 130, 'red'
laser = new Laser(player.clone(), enemy)
lasers.push laser
update = ->
_lasers = lasers.slice()
for l, i in _lasers
l.update()
lasers.splice(i, 1) if l.disposed is true
return
angle = 0
render = (ctx) ->
ctx.save()
ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'
ctx.fillRect 0, 0, w, h
ctx.restore()
angle = (angle + 1) % 360
enemy.x += cos(angle * PI / 180)
enemy.y += sin(angle * PI / 180)
player.draw ctx
enemy.draw ctx
l.draw(ctx) for l in lasers
return
doc.addEventListener 'DOMContentLoaded', ->
init()
do _loop = ->
window.requestAnimationFrame _loop
update()
render ctx
, false
doc.addEventListener 'click', ->
laser = new Laser(player.clone(), enemy)
lasers.push laser
, false
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment