Comparing version 0.5.0 to 0.6.0
170
doc/api.md
**Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)* | ||
- [button](#button) | ||
- [resources](#resources) | ||
- [properties](#properties) | ||
- [animations](#animations) | ||
- [spritesheet](#spritesheet) | ||
- [images](#images) | ||
- [text](#text) | ||
- [methods](#methods) | ||
- [getImage(name, frameIndex)](#getimagename-frameindex) | ||
- [events](#events) | ||
- ['ready'](#'ready') | ||
- ['progress' (event)](#'progress'-event) | ||
- [vec2d](#vec2d) | ||
@@ -12,3 +23,3 @@ - [Batch](#batch) | ||
- [Engine](#engine) | ||
- [methods](#methods-1) | ||
- [methods](#methods) | ||
- [new Engine(canvas)](#new-enginecanvas) | ||
@@ -36,11 +47,11 @@ - [setSize(size)](#setsizesize) | ||
- [Label](#label) | ||
- [methods](#methods-2) | ||
- [methods](#methods) | ||
- [new Label(text, params)](#new-labeltext-params) | ||
- [draw(context)](#drawcontext-1) | ||
- [draw(context)](#drawcontext) | ||
- [setVisible(visible)](#setvisiblevisible) | ||
- [setZOrder(zOrder)](#setzorderzorder) | ||
- [delete()](#delete) | ||
- [properties](#properties-1) | ||
- [properties](#properties) | ||
- [pos](#pos) | ||
- [size](#size-1) | ||
- [size](#size) | ||
- [scale](#scale) | ||
@@ -61,13 +72,26 @@ - [zOrder](#zorder) | ||
- [Sound](#sound) | ||
- [methods](#methods-3) | ||
- [methods](#methods) | ||
- [new Sound(url)](#new-soundurl) | ||
- [play()](#play) | ||
- [stop()](#stop) | ||
- [setVolume(value)](#setvolumevalue) | ||
- [setPreload(value)](#setpreloadvalue) | ||
- [setPlaybackRate(value)](#setplaybackratevalue) | ||
- [properties](#properties) | ||
- [currentSrc](#currentsrc) | ||
- [volume](#volume) | ||
- [preload](#preload) | ||
- [playbackRate](#playbackrate) | ||
- [maxPoolSize](#maxpoolsize) | ||
- [duration](#duration) | ||
- [buffered](#buffered) | ||
- [events](#events) | ||
- ["progress"](#progress) | ||
- ["ready"](#ready) | ||
- [Sprite](#sprite) | ||
- [methods](#methods-4) | ||
- [methods](#methods) | ||
- [new Sprite(animationName, params)](#new-spriteanimationname-params) | ||
- [setAnimationName(animationName)](#setanimationnameanimationname) | ||
- [setAnimation(animation)](#setanimationanimation) | ||
- [draw(context)](#drawcontext-2) | ||
- [draw(context)](#drawcontext) | ||
- [getSize()](#getsize) | ||
@@ -87,4 +111,4 @@ - [getAnchor()](#getanchor) | ||
- [hitTest(vec2d)](#hittestvec2d) | ||
- [setVisible(visible)](#setvisiblevisible-1) | ||
- [setZOrder(zOrder)](#setzorderzorder-1) | ||
- [setVisible(visible)](#setvisiblevisible) | ||
- [setZOrder(zOrder)](#setzorderzorder) | ||
- [setFrameIndex(frameIndex)](#setframeindexframeindex) | ||
@@ -94,16 +118,16 @@ - [setLoop(loop)](#setlooploop) | ||
- [getFrameIndex()](#getframeindex) | ||
- [delete()](#delete-1) | ||
- [properties](#properties-2) | ||
- [pos](#pos-1) | ||
- [size](#size-2) | ||
- [scale](#scale-1) | ||
- [zOrder](#zorder-1) | ||
- [batch](#batch-1) | ||
- [rotation](#rotation-1) | ||
- [delete()](#delete) | ||
- [properties](#properties) | ||
- [pos](#pos) | ||
- [size](#size) | ||
- [scale](#scale) | ||
- [zOrder](#zorder) | ||
- [batch](#batch) | ||
- [rotation](#rotation) | ||
- [loop](#loop) | ||
- [alpha](#alpha-1) | ||
- [id](#id-1) | ||
- [alpha](#alpha) | ||
- [id](#id) | ||
- [animation](#animation) | ||
- [animationName](#animationname) | ||
- [events](#events-1) | ||
- [events](#events) | ||
- ['animationend'](#'animationend') | ||
@@ -132,2 +156,56 @@ | ||
## resources | ||
var resources = require('chem').resources; | ||
### properties | ||
#### animations | ||
Object containing all the animation metadata, indexed by name. | ||
#### spritesheet | ||
Spritesheet Image. | ||
#### images | ||
Contains a map of your static image resources. These are in public/img. | ||
#### text | ||
Contains a map of your text resources. These are in public/text. | ||
### methods | ||
#### getImage(name, frameIndex) | ||
Obtain a new Image object by extracting it from the spritesheet. | ||
* `name` - the animation name to get the frame of | ||
* `frameIndex` - defaults to `0` | ||
### events | ||
These are events that you can subscribe to: | ||
```js | ||
resources.on('eventName', function() { | ||
// your code here | ||
}); | ||
``` | ||
For more information see [EventEmitter](http://nodejs.org/docs/latest/api/events.html#events_class_events_eventemitter) | ||
#### 'ready' | ||
Emitted when all resources are loaded and you may begin utilizing them. | ||
#### 'progress' (event) | ||
event is an object that contains: | ||
* `total` - total number of resources to fetch | ||
* `complete` - how many resources have been fetched | ||
## vec2d | ||
@@ -529,2 +607,6 @@ | ||
#### stop() | ||
Stops all the Audio instances in the pool. | ||
#### setVolume(value) | ||
@@ -538,2 +620,46 @@ | ||
#### setPlaybackRate(value) | ||
Sets the `playbackRate` property. Same as HTML5 Audio object. | ||
### properties | ||
#### currentSrc | ||
Read-only. URL of the playing sound. | ||
#### volume | ||
Read-only. | ||
#### preload | ||
Read-only. | ||
#### playbackRate | ||
Read-only. | ||
#### maxPoolSize | ||
Read/write. Defaults to 1000; | ||
#### duration | ||
Read only. Only valid after the 'ready' event has fired. | ||
#### buffered | ||
Read only. How much audio has been loaded in seconds. | ||
### events | ||
#### "progress" | ||
Fired when some more audio has been buffered. | ||
#### "ready" | ||
Fired when the sound is done loading. | ||
## Sprite | ||
@@ -773,2 +899,4 @@ | ||
* `frames` - `[{size, pos}]` - both `size` and `pos` here are `Vec2d`s. | ||
* `duration` - length in seconds of the animation | ||
* `name` - string | ||
@@ -775,0 +903,0 @@ #### animationName |
# History | ||
## 0.6.0 | ||
* ability to get/set playbackRate on Sound | ||
* ability to stop() a Sound | ||
* Sound emits "progress" and "ready" event | ||
* remove chem.onReady in favor of chem.resources.on('ready') | ||
* resoures is a normal EventEmitter just like everything else | ||
* resources has a "progress" event | ||
* resources.bootstrap() called by auto generated code instead of chem library | ||
* add automatic text and image resource loading via public/text/ and public/img/ | ||
available on resources.images and resources.text | ||
* add engine.showLoadProgressBar() | ||
## 0.5.0 | ||
@@ -4,0 +17,0 @@ |
@@ -5,4 +5,6 @@ var resources = require('./lib/resources'); | ||
vec2d: require('vec2d'), | ||
button: require('./lib/button'), | ||
resources: resources, | ||
Engine: require('./lib/engine'), | ||
button: require('./lib/button'), | ||
Sound: require('./lib/sound'), | ||
@@ -12,6 +14,2 @@ Sprite: require('./lib/sprite'), | ||
Batch: require('./lib/batch'), | ||
resources: resources, | ||
onReady: resources.onReady, | ||
}; | ||
resources.bootstrap(); |
@@ -50,9 +50,9 @@ var Vec2d = require('vec2d').Vec2d; | ||
Engine.prototype.start = function(){ | ||
this.attachListeners(); | ||
this.startMainLoop(); | ||
attachListeners(this); | ||
startMainLoop(this); | ||
}; | ||
Engine.prototype.stop = function(){ | ||
this.stopMainLoop(); | ||
this.removeListeners(); | ||
stopMainLoop(this); | ||
removeListeners(this); | ||
}; | ||
@@ -72,2 +72,6 @@ | ||
Engine.prototype.showLoadProgressBar = function() { | ||
showLoadProgressBar(this); | ||
}; | ||
Engine.prototype.createFpsLabel = function() { | ||
@@ -85,8 +89,7 @@ var label = new Label(this.fps, { | ||
}; | ||
// private | ||
Engine.prototype.startMainLoop = function(){ | ||
var self = this; | ||
function startMainLoop(self) { | ||
var previousUpdate = new Date(); | ||
this.mainLoopOn = true; | ||
requestAnimationFrame(mainLoop, this.canvas); | ||
self.mainLoopOn = true; | ||
requestAnimationFrame(mainLoop, self.canvas); | ||
@@ -114,10 +117,10 @@ function mainLoop(){ | ||
} | ||
}; | ||
Engine.prototype.attachListeners = function(){ | ||
var self = this; | ||
this.buttonStates = {}; | ||
this.btnJustPressed = {}; | ||
this.btnJustReleased = {}; | ||
} | ||
function attachListeners(self) { | ||
self.buttonStates = {}; | ||
self.btnJustPressed = {}; | ||
self.btnJustReleased = {}; | ||
// disable right click context menu | ||
addListener(this.canvas, 'contextmenu', function(event){ | ||
addListener(self.canvas, 'contextmenu', function(event){ | ||
if (self.buttonCaptureExceptions[button.MouseRight]) return true; | ||
@@ -127,4 +130,4 @@ event.preventDefault(); | ||
// mouse input | ||
this.mousePos = new Vec2d(0, 0); | ||
addListener(this.canvas, 'mousemove', function(event){ | ||
self.mousePos = new Vec2d(0, 0); | ||
addListener(self.canvas, 'mousemove', function(event){ | ||
self.mousePos = new Vec2d( | ||
@@ -135,3 +138,3 @@ (event.offsetX) != null ? event.offsetX : event.pageX - event.target.offsetLeft, | ||
}); | ||
addListener(this.canvas, 'mousedown', function(event){ | ||
addListener(self.canvas, 'mousedown', function(event){ | ||
var buttonId = MOUSE_OFFSET + event.which; | ||
@@ -142,5 +145,5 @@ self.buttonStates[buttonId] = true; | ||
self.canvas.focus(); | ||
return self.bubbleEvent(event); | ||
return bubbleEvent(self, event); | ||
}); | ||
addListener(this.canvas, 'mouseup', function(event){ | ||
addListener(self.canvas, 'mouseup', function(event){ | ||
var buttonId; | ||
@@ -151,6 +154,6 @@ buttonId = MOUSE_OFFSET + event.which; | ||
self.emit('buttonup', buttonId); | ||
return self.bubbleEvent(event); | ||
return bubbleEvent(self, event); | ||
}); | ||
// keyboard input | ||
addListener(this.canvas, 'keydown', function(event){ | ||
addListener(self.canvas, 'keydown', function(event){ | ||
var buttonId = KEY_OFFSET + event.which; | ||
@@ -160,5 +163,5 @@ self.btnJustPressed[buttonId] = !self.buttonStates[buttonId]; | ||
self.emit('buttondown', buttonId); | ||
return self.bubbleEvent(event); | ||
return bubbleEvent(self, event); | ||
}); | ||
addListener(this.canvas, 'keyup', function(event){ | ||
addListener(self.canvas, 'keyup', function(event){ | ||
var buttonId = KEY_OFFSET + event.which; | ||
@@ -168,3 +171,3 @@ self.btnJustReleased[buttonId] = self.buttonStates[buttonId]; | ||
self.emit('buttonup', buttonId); | ||
return self.bubbleEvent(event); | ||
return bubbleEvent(self, event); | ||
}); | ||
@@ -175,5 +178,5 @@ function addListener(element, eventName, listener){ | ||
} | ||
}; | ||
} | ||
Engine.prototype.bubbleEvent = function(event) { | ||
function bubbleEvent(self, event) { | ||
// we need to figure out whether to bubble this key event up. | ||
@@ -184,6 +187,6 @@ // if the button is an exception, bubble it up. | ||
var buttonId = KEY_OFFSET + event.which; | ||
if (this.buttonCaptureExceptions[buttonId] || | ||
(event.ctrlKey && this.buttonCaptureExceptions[button.KeyCtrl]) || | ||
(event.altKey && this.buttonCaptureExceptions[button.KeyAlt]) || | ||
(event.shiftKey && this.buttonCaptureExceptions[button.KeyShift])) | ||
if (self.buttonCaptureExceptions[buttonId] || | ||
(event.ctrlKey && self.buttonCaptureExceptions[button.KeyCtrl]) || | ||
(event.altKey && self.buttonCaptureExceptions[button.KeyAlt]) || | ||
(event.shiftKey && self.buttonCaptureExceptions[button.KeyShift])) | ||
{ | ||
@@ -197,4 +200,4 @@ return true; | ||
Engine.prototype.removeListeners = function(){ | ||
this.listeners.forEach(function(listener) { | ||
function removeListeners(self) { | ||
self.listeners.forEach(function(listener) { | ||
var element = listener[0]; | ||
@@ -205,8 +208,9 @@ var eventName = listener[1]; | ||
}); | ||
this.listeners = []; | ||
}; | ||
Engine.prototype.stopMainLoop = function(){ | ||
this.mainLoopOn = false; | ||
}; | ||
self.listeners = []; | ||
} | ||
function stopMainLoop(self) { | ||
self.mainLoopOn = false; | ||
} | ||
function fallbackRequestAnimationFrame(cb){ | ||
@@ -216,1 +220,47 @@ window.setTimeout(cb, targetSpf * 1000); | ||
function showLoadProgressBar(self) { | ||
resources.on('progress', onProgress); | ||
resources.on('ready', onReady); | ||
self.on('draw', onDraw); | ||
var percent = 0; | ||
function onProgress(e) { | ||
percent = e.total === 0 ? 1 : e.complete / e.total; | ||
} | ||
function onReady() { | ||
resources.removeListener('progress', onProgress); | ||
resources.removeListener('ready', onReady); | ||
self.removeListener('draw', onDraw); | ||
} | ||
function onDraw(context) { | ||
context.save(); | ||
context.setTransform(1, 0, 0, 1, 0, 0); // identity | ||
// clear to black | ||
context.fillStyle = "#000000"; | ||
context.fillRect(0, 0, self.size.x, self.size.y); | ||
// draw a progress bar | ||
var barRadius = Math.floor(self.size.y / 20); | ||
var centerY = Math.floor(self.size.y / 2); | ||
var margin = 5; | ||
// outline | ||
context.strokeStyle = "#ffffff"; | ||
context.lineWidth = 2; | ||
context.strokeRect(margin, centerY - barRadius, | ||
self.size.x - margin * 2, barRadius * 2); | ||
// inside | ||
context.fillStyle = "#ffffff"; | ||
var width = percent * (self.size.x - margin * 4); | ||
context.fillRect(margin * 2, centerY - barRadius + margin, | ||
width, barRadius * 2 - margin * 2); | ||
// text | ||
context.font = "18px sans-serif"; | ||
context.fillStyle = "#000000"; | ||
context.textAlign = "center"; | ||
context.textBaseline = "middle"; | ||
context.fillText("Loading... " + Math.floor(percent * 100) + "%", | ||
margin * 2 + Math.floor(width / 2), centerY); | ||
context.restore(); | ||
} | ||
} |
var vec2d = require('vec2d'); | ||
var Batch = require('batch2'); | ||
var util = require('util'); | ||
var EventEmitter = require('events').EventEmitter; | ||
var onReadyQueue = []; | ||
// exports at bottom because we need to set up this class before | ||
// creating an instance | ||
// set assetsLoaded after all assets are done loading | ||
var assetsLoaded = false; | ||
var spritesheetDone = false; | ||
var animationsJsonDone = false; | ||
var alreadyStarted = false; | ||
util.inherits(ResourceLoader, EventEmitter); | ||
function ResourceLoader() { | ||
EventEmitter.call(this); | ||
exports.bootstrap = bootstrap; | ||
exports.onReady = onReady; | ||
exports.animations = null; | ||
exports.spritesheet = null; | ||
exports.useSpritesheet = true; | ||
exports.getImage = getImage; | ||
function onReady(cb) { | ||
if (assetsLoaded) { | ||
cb(); | ||
} else { | ||
onReadyQueue.push(cb); | ||
} | ||
this.ready = false; | ||
this.text = {}; | ||
this.images = {}; | ||
this.animations = null; | ||
this.spritesheet = null; | ||
this.useSpritesheet = true; | ||
} | ||
function bootstrap(){ | ||
// don't bootstrap twice | ||
if (alreadyStarted) return; | ||
alreadyStarted = true; | ||
ResourceLoader.prototype.bootstrap = function() { | ||
bootstrap(this); | ||
}; | ||
// give the app a chance to skip spritesheet loading | ||
setTimeout(loadSpritesheet); | ||
// fetch a resource from the server | ||
ResourceLoader.prototype.fetchTextFile = fetchTextFile; | ||
ResourceLoader.prototype.fetchImage = fetchImage; | ||
function checkDoneLoading(){ | ||
if (spritesheetDone && animationsJsonDone) { | ||
assetsLoaded = true; | ||
onReadyQueue.forEach(function(cb) { | ||
cb(); | ||
}); | ||
} | ||
// extract an image from the spritesheet | ||
ResourceLoader.prototype.getImage = function(name, frameIndex) { | ||
if (frameIndex == null) frameIndex = 0; | ||
var anim = this.animations[name]; | ||
var buffer = document.createElement('canvas'); | ||
var frame = anim.frames[frameIndex]; | ||
buffer.width = frame.size.x; | ||
buffer.height = frame.size.y; | ||
var context = buffer.getContext('2d'); | ||
context.drawImage(this.spritesheet, | ||
frame.pos.x, frame.pos.y, | ||
frame.size.x, frame.size.y, | ||
0, 0, | ||
frame.size.x, frame.size.y); | ||
return buffer; | ||
}; | ||
function bootstrap(self) { | ||
var batch = new Batch(); | ||
if (self.useSpritesheet) { | ||
batch.push(loadSpritesheet); | ||
batch.push(loadAnimationsJson); | ||
} | ||
var name; | ||
for (name in self.text) { | ||
batch.push(generateLoadText(name)); | ||
} | ||
for (name in self.images) { | ||
batch.push(generateLoadImage(name)); | ||
} | ||
function loadSpritesheet() { | ||
if (!exports.useSpritesheet) { | ||
spritesheetDone = true; | ||
animationsJsonDone = true; | ||
return checkDoneLoading(); | ||
} | ||
// get the spritesheet | ||
exports.spritesheet = new Image(); | ||
exports.spritesheet.src = "spritesheet.png"; | ||
exports.spritesheet.onload = function(){ | ||
spritesheetDone = true; | ||
checkDoneLoading(); | ||
}; | ||
// get the animations.json file | ||
var request = new XMLHttpRequest(); | ||
request.onreadystatechange = function(){ | ||
if (!(request.readyState === 4 && request.status === 200)) { | ||
batch.on('progress', function(e) { | ||
self.emit('progress', e); | ||
}); | ||
// allow the event loop to process one time | ||
// so that the user can get their on('ready') hook in | ||
setTimeout(executeBatch); | ||
function executeBatch() { | ||
batch.end(function(err) { | ||
if (err) { | ||
self.emit('error', err); | ||
return; | ||
} | ||
exports.animations = JSON.parse(request.responseText); | ||
self.ready = true; | ||
self.emit('ready'); | ||
}); | ||
} | ||
function loadAnimationsJson(cb) { | ||
fetchImage("spritesheet.png", function(err, img) { | ||
if (err) return cb(err); | ||
self.spritesheet = img; | ||
cb(); | ||
}); | ||
} | ||
function loadSpritesheet(cb) { | ||
fetchTextFile("animations.json", function(err, text) { | ||
if (err) return cb(err); | ||
self.animations = JSON.parse(text); | ||
// cache some values so don't have to compute them all the time | ||
for (var name in exports.animations) { | ||
var anim = exports.animations[name]; | ||
for (var name in self.animations) { | ||
var anim = self.animations[name]; | ||
anim.duration = anim.delay * anim.frames.length; | ||
@@ -75,25 +104,56 @@ anim.name = name; | ||
} | ||
animationsJsonDone = true; | ||
checkDoneLoading(); | ||
cb(); | ||
}); | ||
} | ||
function generateLoadText(name) { | ||
var path = self.text[name]; | ||
return function(cb) { | ||
fetchTextFile(path, function(err, contents) { | ||
if (err) return cb(err); | ||
self.text[name] = contents; | ||
cb(); | ||
}); | ||
}; | ||
request.open("GET", "animations.json", true); | ||
request.send(); | ||
} | ||
function generateLoadImage(name) { | ||
var path = self.images[name]; | ||
return function(cb) { | ||
fetchImage(path, function(err, img) { | ||
if (err) return cb(err); | ||
self.images[name] = img; | ||
cb(); | ||
}); | ||
}; | ||
} | ||
} | ||
function getImage(name, frameIndex){ | ||
if (frameIndex == null) frameIndex = 0; | ||
var anim = exports.animations[name]; | ||
var buffer = document.createElement('canvas'); | ||
var frame = anim.frames[frameIndex]; | ||
buffer.width = frame.size.x; | ||
buffer.height = frame.size.y; | ||
var context = buffer.getContext('2d'); | ||
context.drawImage(exports.spritesheet, | ||
frame.pos.x, frame.pos.y, | ||
frame.size.x, frame.size.y, | ||
0, 0, | ||
frame.size.x, frame.size.y); | ||
return buffer; | ||
function fetchImage(path, cb) { | ||
var img = new Image(); | ||
img.src = path; | ||
img.onload = function(){ | ||
cb(null, img); | ||
}; | ||
} | ||
function fetchTextFile(path, cb) { | ||
var request = new XMLHttpRequest(); | ||
request.onreadystatechange = onReadyStateChange; | ||
request.open("GET", path, true); | ||
try { | ||
request.send(); | ||
} catch (err) { | ||
cb(err); | ||
} | ||
function onReadyStateChange() { | ||
if (request.readyState !== 4) return; | ||
if (Math.floor(request.status / 100) === 2) { | ||
cb(null, request.responseText); | ||
return; | ||
} | ||
cb(new Error(request.status + ": " + request.statusText)); | ||
} | ||
} | ||
module.exports = new ResourceLoader(); |
@@ -0,4 +1,9 @@ | ||
var EventEmitter = require('events').EventEmitter; | ||
var util = require('util'); | ||
module.exports = Sound; | ||
function Sound(src) { | ||
EventEmitter.call(this); | ||
this.currentSrc = src; | ||
@@ -9,10 +14,11 @@ this.audioPool = [new Audio(src)]; | ||
this.preload = "auto"; | ||
this.playbackRate = 1; | ||
this.buffered = 0; | ||
this.duration = null; | ||
this.applySettings(); | ||
applySettings(this); | ||
progressHooks(this); | ||
} | ||
util.inherits(Sound, EventEmitter); | ||
function audioReadyToPlay(audio) { | ||
return audio.currentTime === 0 || audio.currentTime === audio.duration; | ||
} | ||
Sound.prototype.play = function() { | ||
@@ -28,3 +34,3 @@ for (var i = 0; i < this.audioPool.length; ++i) { | ||
var newAudio = new Audio(this.currentSrc); | ||
this.applySettingsToAudio(newAudio); | ||
applySettingsToAudio(this, newAudio); | ||
newAudio.play(); | ||
@@ -35,5 +41,13 @@ this.audioPool.push(newAudio); | ||
Sound.prototype.stop = function() { | ||
for (var i = 0; i < this.audioPool.length; ++i) { | ||
var audio = this.audioPool[i]; | ||
audio.pause(); | ||
audio.currentTime = 0; | ||
} | ||
}; | ||
Sound.prototype.setVolume = function(vol) { | ||
this.volume = vol; | ||
this.applySettings(); | ||
applySettings(this); | ||
}; | ||
@@ -43,14 +57,47 @@ | ||
this.preload = preload; | ||
this.applySettings(); | ||
applySettings(this); | ||
}; | ||
Sound.prototype.applySettings = function() { | ||
for (var i = 0; i < this.audioPool.length; ++i) { | ||
this.applySettingsToAudio(this.audioPool[i]); | ||
Sound.prototype.setPlaybackRate = function(rate) { | ||
this.playbackRate = rate; | ||
applySettings(this); | ||
}; | ||
function applySettings(self) { | ||
for (var i = 0; i < self.audioPool.length; ++i) { | ||
applySettingsToAudio(self, self.audioPool[i]); | ||
} | ||
} | ||
Sound.prototype.applySettingsToAudio = function(audio) { | ||
audio.volume = this.volume; | ||
audio.preload = this.preload; | ||
function applySettingsToAudio(self, audio) { | ||
audio.volume = self.volume; | ||
audio.preload = self.preload; | ||
audio.playbackRate = self.playbackRate; | ||
audio.defaultPlaybackRate = self.playbackRate; | ||
} | ||
function progressHooks(self) { | ||
var audio = self.audioPool[0]; | ||
audio.addEventListener("progress", onProgress, false); | ||
audio.load(); | ||
var complete = false; | ||
function onProgress() { | ||
try { | ||
// sometimes I get Index Size Error: DOM Exception 1 | ||
self.buffered = audio.buffered.end(audio.buffered.length - 1); | ||
} catch (err) { | ||
return; | ||
} | ||
self.duration = audio.duration; | ||
self.emit('progress'); | ||
if (! complete && self.buffered >= self.duration) { | ||
complete = true; | ||
self.emit('ready'); | ||
} | ||
} | ||
} | ||
function audioReadyToPlay(audio) { | ||
return audio.currentTime === 0 || audio.currentTime === audio.duration; | ||
} |
@@ -73,32 +73,43 @@ var Vec2d = require('vec2d').Vec2d; | ||
}; | ||
Sprite.prototype.getTopLeft = function(){ | ||
return this.pos.minus(this.getAnchor()); | ||
}; | ||
Sprite.prototype.getBottomRight = function(){ | ||
return this.getTopLeft().plus(this.getSize()); | ||
}; | ||
Sprite.prototype.getTop = function(){ | ||
return this.getTopLeft().y; | ||
}; | ||
Sprite.prototype.getLeft = function(){ | ||
return this.getTopLeft().x; | ||
}; | ||
Sprite.prototype.getBottom = function(){ | ||
return this.getBottomRight().y; | ||
}; | ||
Sprite.prototype.getRight = function(){ | ||
return this.getBottomRight().x; | ||
}; | ||
Sprite.prototype.setLeft = function(x){ | ||
this.pos.x = x + this.animation.anchor.x; | ||
}; | ||
Sprite.prototype.setRight = function(x){ | ||
this.pos.x = x - this.animation.anchor.x; | ||
}; | ||
Sprite.prototype.setTop = function(y){ | ||
this.pos.y = y + this.animation.anchor.y; | ||
}; | ||
Sprite.prototype.setBottom = function(y){ | ||
this.pos.y = y - this.animation.anchor.y; | ||
}; | ||
Sprite.prototype.isTouching = function(sprite){ | ||
@@ -112,2 +123,3 @@ var a_tl = this.getTopLeft(); | ||
}; | ||
Sprite.prototype.hitTest = function(pt) { | ||
@@ -118,2 +130,3 @@ var tl = this.getTopLeft(); | ||
}; | ||
Sprite.prototype.setVisible = function(visible){ | ||
@@ -130,2 +143,3 @@ this.visible = visible; | ||
}; | ||
Sprite.prototype.setZOrder = function(zOrder){ | ||
@@ -140,2 +154,3 @@ if (this.batch != null) { | ||
}; | ||
Sprite.prototype.setFrameIndex = function(frameIndex){ | ||
@@ -147,2 +162,3 @@ var secondsPassed = frameIndex * this.animation.delay; | ||
}; | ||
Sprite.prototype.setLoop = function(loop){ | ||
@@ -152,10 +168,11 @@ this.loop = loop; | ||
this._loop = this.loop == null ? this.animation.loop : this.loop; | ||
this.setUpInterval(); | ||
setUpInterval(this); | ||
}; | ||
Sprite.prototype.setAnimationStartDate = function(animationStartDate){ | ||
this.animationStartDate = animationStartDate; | ||
this.setUpInterval(); | ||
setUpInterval(this); | ||
}; | ||
Sprite.prototype.getFrameIndex = function(){ | ||
var ref$, ref1$; | ||
var now = new Date(); | ||
@@ -166,5 +183,8 @@ var totalTime = (now - this.animationStartDate) / 1000; | ||
} else { | ||
return (ref$ = Math.floor(totalTime / this.animation.delay)) < (ref1$ = this.animation.frames.length - 1) ? ref$ : ref1$; | ||
var timeElapsedFrame = Math.floor(totalTime / this.animation.delay); | ||
var lastFrame = this.animation.frames.length - 1; | ||
return Math.min(timeElapsedFrame, lastFrame); | ||
} | ||
}; | ||
Sprite.prototype['delete'] = function(){ | ||
@@ -174,14 +194,13 @@ if (this.batch) this.batch.remove(this); | ||
}; | ||
// private | ||
Sprite.prototype.setUpInterval = function(){ | ||
var self = this; | ||
if (this.interval) this.interval.cancel(); | ||
var _schedule = this._loop ? schedule : wait; | ||
function setUpInterval(self) { | ||
if (self.interval) self.interval.cancel(); | ||
var _schedule = self._loop ? schedule : wait; | ||
var now = new Date(); | ||
var timeSinceStart = (now - this.animationStartDate) / 1000; | ||
var duration = this.animation.duration - timeSinceStart; | ||
this.interval = _schedule(duration, function(){ | ||
var timeSinceStart = (now - self.animationStartDate) / 1000; | ||
var duration = self.animation.duration - timeSinceStart; | ||
self.interval = _schedule(duration, function(){ | ||
return self.emit('animationend'); | ||
}); | ||
}; | ||
} | ||
@@ -188,0 +207,0 @@ function wait(sec, cb) { |
@@ -5,3 +5,3 @@ { | ||
"author": "Andrew Kelley <superjoe30@gmail.com>", | ||
"version": "0.5.0", | ||
"version": "0.6.0", | ||
"main": "index.js", | ||
@@ -14,4 +14,5 @@ "license": "MIT", | ||
"dependencies": { | ||
"vec2d": "~0.1.1" | ||
"vec2d": "~0.1.1", | ||
"batch2": "~0.5.0" | ||
} | ||
} |
@@ -5,2 +5,4 @@ # chem | ||
Inspired by [pyglet](http://www.pyglet.org/). | ||
## Features | ||
@@ -22,2 +24,4 @@ | ||
* Convenient API for keyboard and mouse input. | ||
* Bootstraps the resource loading process and optionally provides a basic | ||
loading progress bar. | ||
@@ -73,6 +77,9 @@ ## Usage | ||
var v = chem.vec2d; | ||
var canvas = document.getElementById("game"); | ||
var engine = new chem.Engine(canvas); | ||
engine.showLoadProgressBar(); | ||
engine.start(); | ||
canvas.focus(); | ||
chem.onReady(function () { | ||
var canvas = document.getElementById("game"); | ||
var engine = new chem.Engine(canvas); | ||
chem.resources.on('ready', function () { | ||
var batch = new chem.Batch(); | ||
@@ -130,4 +137,2 @@ var boom = new chem.Sound('sfx/boom.ogg'); | ||
}); | ||
engine.start(); | ||
canvas.focus(); | ||
}); | ||
@@ -216,2 +221,8 @@ ``` | ||
* `autoBootstrap` - set this to `false` if you do not want public/bootstrap.js | ||
to be auto generated. | ||
If you leave the `spritesheet` export undefined, no spritesheet will be | ||
generated or used at runtime. | ||
### Use any "compile to JS" language | ||
@@ -233,3 +244,20 @@ | ||
chem.onReady(function() { | ||
// Next, locate your canvas: | ||
var canvas = document.getElementById("the-canvas-id"); | ||
// Create the main game engine: | ||
var engine = new Engine(canvas); | ||
// Display a nice loading progress bar while we serve assets: | ||
// (it automatically goes away once loading is complete) | ||
engine.showLoadProgressBar() | ||
// Start the main loop: | ||
engine.start() | ||
// Focus the canvas so that keyboard input works: | ||
canvas.focus() | ||
// Finally, wait until resources are done loading: | ||
chem.resources.on('ready', function() { | ||
// Now you can go for it. All asssets are loaded. | ||
@@ -245,7 +273,10 @@ }); | ||
### Not Using a Spritesheet | ||
### Resource Locations | ||
If you omit the spritesheet object in your chemfile, no spritesheet files | ||
will be generated. Be sure to set `chem.useSpritesheet = false` in your app code to avoiding attempting to load the missing resources. | ||
Text files placed in public/text/ will be available in the `chem.resources.text` | ||
object once the 'ready' event has fired. | ||
Image files placed in public/img/ will be available in the | ||
`chem.resources.images` object once the 'ready' event has fired. | ||
### Reference API Documentation | ||
@@ -252,0 +283,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
57415
862
293
2
+ Addedbatch2@~0.5.0