Coffee2D is a HTML5 game engine that abstracts a lot of the things one would need to make a game with HTML5 canvas. It leverages some of the CoffeeScript features like the class
keyword to integrate better with games written in CoffeeScript.
Coffee2D currently provides:
- Simple scene graphs
- Sprite rendering
- Event handling
- Tweening
- Isometric maps
To get started, check out the code in the examples folder.
To build, run make clean && make build
. This creates the file build/engine-all.js
, which can be dropped into any project that wants to use Coffee2D
Component is the base class for every game object. Every game object should extend Component. Game objects can override update
and draw
functions. Every component can add child components. Once added, the components will be automatically added to the game loop to be updated and drawn every frame:
class Card extends Component
constructor: (@suit, @value) ->
super()
@setSize(50, 80)
# the rectangle will be drawn automatically
@addChild new Rect 0, 0, @size.w, @size.h, 'white'
update: (dt) ->
# dt is delta time passed since last update
# (update stuff...)
super()
draw: (ctx) ->
# ctx is the canvas context associated with this scene
# (draw additional stuff other than the rectangle...)
super()
Scene is a Component. It is the top level component and contains everything else, you can create a scene by passing in the canvas object:
$(document).ready ->
canvas = $('#canvas')[0]
scene = new Scene canvas
Coordinates are relative to the parent. In this case the rectangle would be draw at x = 20, y = 40 relative to the canvas, but its position is x = 10, y = 20 in its parent component:
class Parent extends Component
constructor: ->
super()
# add a rectangle
rect = new Rect 0, 0, 50, 80, 'white'
@addChild rect
# set the position of the rectangle
rect.setPosition 10, 20
$(document).ready ->
canvas = $('#canvas')[0]
scene = new Scene canvas
parent = new Parent
scene.addChild parent
# set the position of the parent
parent.setPosition 10, 20
DOM events on the canvas are handled by the Scene. You can simply add listeners for them:
unit.addListener 'click', -> unit.select()
# keys are a little different
unit.onKeyDown 39, -> unit.move()
Any component can fire events. Non-components can also fire events from the Event class:
# event origin is automatically set to unit
unit.dispatchEvent {type: 'kill', target: enemy}
enemy.addListener 'kill', (evt) -> if evt.target == enemy then enemy.die()
# can also fire events from Event class, origin will not be set
Event.dispatchEvent {type: 'init'}
Rectangles and polygons are supported:
class Card extends Component
constructor: (@suit, @value) ->
super()
# add a rectangle
@addChild new Rect 0, 0, 50, 80, 'white'
# add a diamond shape
@addChild new Polygon [[25, 0], [50, 40], [25, 80], [0, 40]], 'red'
Sprite can be created be created from a sprite sheet. You can assign different sets of animations to the sprite. Please refer to the hibiki example for details.
You can create isometric maps from a tileset. The tileset is a sprite sheet where each cell is a tile. Please refer to the isometric map example for details
Create simple animations with tweening. You can tween any numeric property of a Component. You can provide a callback when creating the tween that will be invoked when the tween finishes. On completion, the tween will also create a 'tweenFinished' event:
# create a tween that animates the unit 200 pixels to the right in 3 seconds
tween = unit.animateTo {position: {x: unit.position.x + 200}}, 3000
# set a onComplete callback
tween.onComplete ( -> unit.attack(enemy))
# you can also listen on the tweenComplete event
commander.addListener 'tweenFinished', (evt) ->
# tween.obj is the object that the tween was animating, in this case it would
# be unit
if evt.origin.obj == tween.obj
console.log "unit #{tween.obj.name} is in position"
Todo:
- Audio
- More geometric shapes
- Collision detection
- Physics