Skip to content

Instantly share code, notes, and snippets.

@itsbth
Created October 26, 2011 12:03
Show Gist options
  • Save itsbth/1316145 to your computer and use it in GitHub Desktop.
Save itsbth/1316145 to your computer and use it in GitHub Desktop.
WORLD_SIZE = [0..31]
BLOCKS = _([1, 1, 33, 34, 50]).reverse()
Vector = {
add: (a, b) ->
{x: a.x + b.x, y: a.y + b.y}
subtract: (a, b) ->
{x: a.x - b.x, y: a.y - b.y}
multiply: (a, b) ->
{x: a.x * b, y: a.y * b}
}
Texture = {
_textures: {},
_ready: {},
load: (path, id) ->
img = new Image
Texture._ready[id] = false
img.onload = -> Texture._ready[id] = true
img.src = path
Texture._textures[id] = img
get: (id) ->
Texture._textures[id]
ready: (id) ->
if id?
Texture._ready[id]
else
_(Texture._ready).all(_.identity)
}
class Renderer
constructor: (@ctx, @world) ->
@terrain = Texture.get 'terrain'
render: ->
@ctx.clearRect(0, 0, 512, 512)
for x in WORLD_SIZE
for y in WORLD_SIZE
@world.grid[x][y].render @, {x: x, y: y}
for entity in @world.entities
entity.render @
null
drawBlock: (pos, id) ->
[sx, sy] = [(id % 16) * 16, Math.floor(id / 16) * 16]
@ctx.drawImage(@terrain, sx, sy, 16, 16, pos.x * 16, pos.y * 16, 16, 16)
drawSprite: (pos, sheet, id) ->
[sx, sy] = [(id % 9) * 16, Math.floor(id / 9) * 18]
@ctx.drawImage(sheet, sx, sy, 16, 18, pos.x - 8, pos.y - 18, 16, 18)
class World
constructor: ->
@grid = []
@entities = []
tick: ->
for entity in @entities
entity.tick()
generate: ->
noise = new SimplexNoise
for x in WORLD_SIZE
@grid[x] = []
for y in WORLD_SIZE
nv = (noise.noise(x / 10, y / 10) + 1) / 2
console.log nv
if y > 10
@grid[x][y] = new BreakableBlock @, {x: x, y: y}, (if nv > y / 32 then 2 else 1), 10
else if y == 10
@grid[x][y] = new BreakableBlock @, {x: x, y: y}, 3, 10
else
@grid[x][y] = new Air @, {x: x, y: y}
null
create: (type, args...) ->
new type(@, null, args...)
addEntity: (entity) ->
@entities.push entity
replace: (block, new_block) ->
{x, y} = block.pos
@grid[x][y] = new_block
new_block.pos = block.pos
new_block
to_grid: (pos) ->
{x: Math.floor(pos.x / 16), y: Math.floor(pos.y / 16)}
class Entity
constructor: (@world, @pos, @sprite) ->
tick: ->
render: (renderer) ->
class Human extends Entity
constructor: (world, pos) ->
super(world, pos, Texture.get 'human')
@vel = {x: 4, y: 0}
@spc = 0
tick: ->
if @pos.x > 500
@vel.x = -4
else if @pos.x < 12
@vel.x = 4
@vel.y += 5
@pos = Vector.add(@pos, @vel)
@gp = @world.to_grid @pos
if @world.grid[@gp.x][@gp.y].solid
@pos.y = @gp.y * 16
@vel.y = 0
render: (renderer) ->
renderer.drawBlock(@gp, 223)
renderer.drawSprite(@pos, @sprite, (if @vel.x > 0 then 10 else 30) + (@spc++ % 2))
class Block
constructor: (@world, @pos, @id) ->
@solid = true
render: (renderer) ->
renderer.drawBlock(@pos, @id)
click: ->
class Air extends Block
constructor: (world, pos) ->
super(world, pos, -1)
@solid = false
render: (renderer) ->
# do nothing
class BreakableBlock extends Block
constructor: (world, pos, id, @health) ->
super
@max_health = @health
render: (renderer) ->
super
dmg = 10 - Math.floor(@damage() * 10)
renderer.drawBlock(@pos, 239 + dmg) if dmg > 0
click: ->
console.log @id
if @health > 0
@health -= 1
else
@world.replace @, @world.create Air
damage: ->
@health / @max_health
Texture.load 'terrain.png', 'terrain'
Texture.load 'human_base.png', 'human'
world = new World
world.generate()
world.addEntity new Human(world, {x: 30, y: 30})
document.addEventListener 'DOMContentLoaded', ->
canvas = document.getElementById 'cv'
canvas.addEventListener 'click', (evt) ->
x = Math.floor(evt.offsetX / 16)
y = Math.floor(evt.offsetY / 16)
world.grid[x][y].click()
ctx = canvas.getContext '2d'
renderer = new Renderer ctx, world
draw = ->
world.tick()
renderer.render() if Texture.ready()
setTimeout arguments.callee, 100
setTimeout draw, 100
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment