Skip to content

Instantly share code, notes, and snippets.

@basicxman
Created April 12, 2012 21:09
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 basicxman/2371006 to your computer and use it in GitHub Desktop.
Save basicxman/2371006 to your computer and use it in GitHub Desktop.
class Game
constructor: ->
@ctx = document.getElementById("game").getContext("2d")
@ctx.canvas.style.background = "#000"
@startAngle = (5 * Math.PI) / 6
@endAngle = Math.PI / 6
@curSA = @startAngle
@curEA = @endAngle
@notifier = document.createElement("canvas")
@notifier.width = 64;
@notifier.height = 64;
@notifierCtx = @notifier.getContext("2d")
@notifierAngle = -Math.PI / 4
@notifierX = 0
@notifierY = 0
@isDragging = false
@gW = 5000
@gH = 3750
@vW = @ctx.canvas.width
@vH = @ctx.canvas.height
@dX = -((@gW - @vW) / 2)
@dY = -((@gH - @vH) / 2)
@objs = []
for x in [0...@gW] by 100
for y in [0...@gH] by 50
@objs.push [x, y]
for event in ["mouseup", "mouseout"]
@ctx.canvas.addEventListener event, ((e) => this.resetDrag())
@ctx.canvas.addEventListener "mousedown", (e) =>
if e.button != 0
return
@velX = undefined
@velY = undefined
@timeout = setTimeout((=> this.startDrag(e)), 100)
document.addEventListener "mousemove", (e) =>
x = e.pageX
y = e.pageY
cx1 = @ctx.canvas.offsetLeft
cy1 = @ctx.canvas.offsetTop
cx2 = cx1 + @vW
cy2 = cy1 + @vH
if x <= cx2 and x >= cx1 and y <= cy2 and y >= cy1
return
if y > cy2
@notifierY = -@dY + @vH - 64
@notifierX = -@dX + x - cx1 - 32
@notifierAngle = 0
else if y < cy1
@notifierY = -@dY
@notifierX = -@dX + x - cx1 - 32
@notifierAngle = Math.PI
else if x > cx2
@notifierY = -@dY + y - cy1 - 32
@notifierX = -@dX + @vW - 64
@notifierAngle = -Math.PI / 2
else if x < cx1
@notifierY = -@dY + y - cy1 - 32
@notifierX = -@dX
@notifierAngle = Math.PI / 2
if y > cy2 and x > cx2
@notifierAngle = -Math.PI / 4
@notifierY += 10
@notifierX = -@dX + @vW - 54
if y > cy2 and x < cx1
@notifierAngle = Math.PI / 4
@notifierY += 10
@notifierX = -@dX - 10
if y < cy1 and x < cx1
@notifierAngle = Math.PI / 2 + Math.PI / 4
@notifierY -= 10
@notifierX = -@dX - 10
if y < cy1 and x > cx2
@notifierAngle = -Math.PI / 2 - Math.PI / 4
@notifierY -= 10
@notifierX = -@dX + @vW - 54
@ctx.canvas.addEventListener "mousemove", (e) =>
if @isDragging
this.bufferAdvance(@bufDragTime, e.timeStamp)
this.bufferAdvance(@bufDragX, e.offsetX)
this.bufferAdvance(@bufDragY, e.offsetY)
if @bufDragX[2]? and @bufDragX[1]?
this.pan(@bufDragX[1] - @bufDragX[2], @bufDragY[1] - @bufDragY[2])
anim = =>
this.gameLoop()
requestAnimFrame(anim)
anim()
bufferReset: ->
@bufDragTime = [undefined, undefined, undefined]
@bufDragX = [undefined, undefined, undefined]
@bufDragY = [undefined, undefined, undefined]
bufferAdvance: (buffer, value) ->
buffer[0] = buffer[1]
buffer[1] = buffer[2]
buffer[2] = value
startDrag: (e) ->
@isDragging = true
this.bufferReset()
resetDrag: ->
if @bufDragTime[0]? and @bufDragTime[2]?
t = @bufDragTime[2] - @bufDragTime[0]
rise = @bufDragY[2] - @bufDragY[0]
run = @bufDragX[2] - @bufDragX[0]
@velX = run / t
@velY = rise / t
clearTimeout(@timeout)
@isDragging = false
this.bufferReset()
pan: (x, y) ->
@dX = Math.min(Math.max(@dX - x, -(@gW - @vW)), 0)
@dY = Math.min(Math.max(@dY - y, -(@gH - @vH)), 0)
update: ->
decay = 1.05
panMultiplier = -8
deadband = 0.005
if @velX != undefined and @velY != undefined
this.pan(panMultiplier * @velX, panMultiplier * @velY)
@velX /= decay
@velY /= decay
if (Math.abs(@velX) < deadband)
@velX = undefined
if (Math.abs(@velY) < deadband)
@velY = undefined
@curSA += 0.005
@curEA -= 0.005
if @curSA >= (3 * Math.PI) / 2
@curSA = @startAngle
@curEA = @endAngle
draw: ->
@ctx.clearRect(0, 0, @vW, @vH)
@ctx.save()
@ctx.translate(@dX, @dY)
@ctx.font = "8pt Helvetica"
@ctx.fillText("#{@dX} #{@dY}", @dX, @dY)
@x1 = -@dX - 100
@y1 = -@dY - 100
@x2 = @x1 + @vW + 100
@y2 = @y1 + @vH + 100
for obj in @objs
if obj[0] > @x2 or obj[0] < @x1 or obj[1] > @y2 or obj[1] < @y1
continue
@ctx.fillStyle = "#39f"
@ctx.beginPath()
@ctx.arc(obj[0], obj[1], 2, 0, Math.PI * 2, true)
@ctx.closePath()
@ctx.fill()
@ctx.fillStyle = "rgba(255, 255, 255, 1)"
@ctx.fillText("#{obj[0]}, #{obj[1]}", obj[0], obj[1])
@notifierCtx.save()
@notifierCtx.translate(32, 32)
@notifierCtx.rotate(@notifierAngle)
@notifierCtx.clearRect(-32, -32, 64, 64)
@notifierCtx.fillStyle = "rgba(255, 127, 0, 0.9)"
@notifierCtx.beginPath()
@notifierCtx.arc(0, -12, 20, @startAngle, @endAngle, false)
@notifierCtx.lineTo(0, 32)
@notifierCtx.closePath()
@notifierCtx.fill()
@notifierCtx.strokeStyle = "rgba(255, 255, 255, 0.3)"
@notifierCtx.beginPath()
@notifierCtx.arc(0, -12, 17, @curSA, @curEA, false)
@notifierCtx.lineWidth = 6
@notifierCtx.stroke()
@notifierCtx.restore()
@ctx.drawImage(@notifier, @notifierX, @notifierY)
@ctx.restore()
gameLoop: ->
this.update()
this.draw()
window.game = new Game
window.game.gameLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment