Last active
December 23, 2015 11:29
-
-
Save nornagon/6629179 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
component = (c) -> | |
c::_added = (gobj) -> | |
throw 'added twice' if @me? | |
@me = gobj | |
@world = @me.world | |
@init? @_args... | |
new_c = (args...) -> | |
r = new c | |
r._args = args | |
r | |
eval "#{c.name} = new_c" | |
new_c | |
class GameObject | |
constructor: (@world) -> | |
@_messages = {} | |
@components = {} # can have > 1 component of each type? | |
addComponent: (c) -> | |
@components[c.constructor.component_name] = c | |
for k,_ of c.__proto__ when k isnt 'init' and k isnt 'constructor' | |
@on k, do (k) -> (args...) -> c[k] args... | |
c._added? this | |
on: (e, f) -> | |
# TODO: optimisation: when there's only one listener, hook it up directly. | |
(@[e] = (args...) -> @send e, args...) unless @[e]? | |
(@_messages[e] ?= []).push f | |
send: (e, args...) -> | |
val = f.apply(this, args) for f in (@_messages[e] ? []) | |
val | |
remove: -> | |
@removeMe = yes | |
@send '_removed' | |
class World | |
constructor: -> | |
@entities = [] | |
make: (template) -> | |
if typeof template is 'function' then template = template() | |
e = new GameObject this | |
for c in template | |
e.addComponent c | |
@add e | |
add: (e) -> | |
@entities.push e | |
e | |
update: (dt) -> | |
e.update? dt for e in @entities | |
@entities = (e for e in @entities when not e.removeMe) | |
Template = (fn) -> throw 'need a function' unless typeof fn is 'function'; fn | |
# e.g: | |
component class Countdown | |
init: (@sec, @opts = {}) -> | |
update: (dt) -> | |
if @sec > 0 | |
@sec -= dt * (@opts.speed ? 1) | |
@me.send 'counted' if @sec <= 0 | |
component class ExplodeOnCounted | |
counted: -> | |
console.log 'boom!' | |
@me.remove() | |
# ... | |
Bomb = Template ({seconds}) -> [ | |
Countdown seconds, speed: 2 | |
ExplodeOnCounted() | |
] | |
w = new World | |
w.make Bomb seconds: 3 | |
w.update(2) | |
w.update(2) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment