<html>
<body>
<div id="stage"></div>
</body>
</html>
/**
* BASE.JS
*/
window.requestAnimationFrame = (function() {
return window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame ||
window.oRequestAnimationFrame ||
function(callback) {
return window.setTimeout(callback, 16.6667);
};
}());
var add_listener = function(target, event, callback, context) {
var fn = function(e) {
callback.call(context, e);
};
if(target.addEventListener)
target.addEventListener(event, fn, false);
};
var set_interval = function(ms, fn, context) {
return setInterval(function() {
fn.call(context);
}, ms);
};
var set_timeout = function(ms, fn, context) {
return setTimeout(function() {
fn.call(context);
}, ms);
};
var request_animation_frame = function(callback, context) {
return window.requestAnimationFrame(function() {
callback.call(context);
});
};
var make_canvas = function(w, h, id, pid) {
var canvas = document.createElement('canvas');
canvas.width = Number(w) || 1;
canvas.height = Number(h) || 1;
canvas.id = (id !== null && typeof(id) == 'string') ? id : '';
var ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = false;
ctx.mozImageSmoothingEnabled = false;
ctx.webkitImageSmoothingEnabled = false;
if(pid !== null && typeof(pid) == 'string') {
var p = document.getElementById(pid);
if(p)
p.appendChild(canvas);
else
document.getElementsByTagName('body')[0].appendChild(canvas);
}
return canvas;
};
//Closure - goog inheritence
var inherit = function(sub, sup) {
var t = function() {};
t.prototype = sup.prototype;
sub._super = sup.prototype;
sub.prototype = new t();
sub.prototype.constructor = sub;
};
/**
* KEYBOARD.JS
*/
var Keyboard = function() {
if(Keyboard.prototype._singleton)
return Keyboard.prototype._singleton;
Keyboard.prototype._singleton = this;
this.keys = {};
this.lastKeys = {};
add_listener(window, 'keydown', this.onKeyDown, this);
add_listener(window, 'keyup', this.onKeyUp, this);
};
Keyboard.Keys = {
UP: 38,
DOWN: 40,
LEFT: 37,
RIGHT: 39
};
Keyboard.prototype.onKeyDown = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
this.keys[keyCode] = true;
};
Keyboard.prototype.onKeyUp = function(e) {
var keyCode = e.which ? e.which : e.keyCode;
this.keys[keyCode] = false;
};
Keyboard.prototype.keyPressed = function(key) {
return this.keys[key] === true;
};
Keyboard.prototype.keyHit = function(key) {
return (this.keyPressed(key) && !this.lastKeys[key]);
};
Keyboard.prototype.reset = function() {
for(var k in this.keys) {
this.lastKeys[k] = this.keys[k];
}
};
/**
* STATE.JS
*/
var State = function(game) {
this.game = game;
this.width = this.game.getWidth();
this.height = this.game.getHeight();
this.canvas = make_canvas(this.width, this.height);
this.ctx = this.canvas.getContext('2d');
this.ctx.font = '22px bold \'courier new\'';
this.ticks = 0;
this.updateFrameTicks = 0;
this.renderFrameTicks = 0;
this.updateFrames = 0;
this.renderFrames = 0;
this.ups = 0;
this.rps = 0;
};
State.DELTA_TIME = 16.6667;
State.MAX_UPDATES = 3;
State.prototype.update = function(ms) {
this.ticks += ms;
var updates = 0;
while(this.ticks >= State.DELTA_TIME && updates < State.MAX_UPDATES) {
this.updateState();
this.updateFrameTicks += State.DELTA_TIME;
this.updateFrames++;
if(this.updateFrameTicks >= 1000) {
this.ups = this.updateFrames;
this.updateFrames = 0;
this.updateFrameTicks -= 1000;
}
this.ticks -= State.DELTA_TIME;
updates++;
}
if(updates > 0) {
this.renderFrameTicks += updates*State.DELTA_TIME;
this.renderFrames++;
if(this.renderFrameTicks >= 1000) {
this.rps = this.renderFrames;
this.renderFrames = 0;
this.renderFrameTicks -= 1000;
}
this.renderState(updates*State.DELTA_TIME);
}
};
State.prototype.updateState = function() {
};
State.prototype.renderState = function(ms) {
};
State.prototype.renderFPS = function() {
this.ctx.save();
this.ctx.fillStyle = '#ffffff';
this.ctx.strokeStyle = '#000000';
this.ctx.strokeText('UPS: ' + this.ups, 20, 20);
this.ctx.fillText('UPS: ' + this.ups, 20, 20);
this.ctx.strokeText('FPS: ' + this.rps, 20, 40);
this.ctx.fillText('FPS: ' + this.rps, 20, 40);
this.ctx.restore();
};
State.prototype.destroyState = function() {
delete this.ctx;
delete this.canvas;
};
/**
* LEVEL_STATE.JS
*/
var LevelState = function(game) {
State.call(this, game);
var g1 = this.ctx.createRadialGradient(this.width/2, this.height/2, 0, this.width/2, this.height/2, this.width/2);
g1.addColorStop(0.1, '#7d97c2');
g1.addColorStop(0.2, '#6f85a9');
g1.addColorStop(0.3, '#607391');
g1.addColorStop(0.4, '#53627b');
g1.addColorStop(0.5, '#485469');
g1.addColorStop(0.6, '#3d4757');
g1.addColorStop(0.7, '#343c48');
g1.addColorStop(0.8, '#282d36');
g1.addColorStop(0.9, '#22262c');
g1.addColorStop(1.0, '#16181b');
this.g1 = g1;
this.player = {
x: 0, y: 0, w: 50, h: 50, t: 100,
speed: 5,
baseCol: 'rgba(0, 0, 0, 1)',
faceCol: 'rgba(41, 134, 58, 0.4)',
topCol: 'rgba(134, 212, 149, 0.2)'
};
};
inherit(LevelState, State);
LevelState.prototype.updateState = function() {
var kb = Keyboard();
if(kb.keyPressed(Keyboard.Keys.UP)) {
this.player.y -= this.player.speed;
}
if(kb.keyPressed(Keyboard.Keys.DOWN)) {
this.player.y += this.player.speed;
}
if(kb.keyPressed(Keyboard.Keys.LEFT)) {
this.player.x -= this.player.speed;
}
if(kb.keyPressed(Keyboard.Keys.RIGHT)) {
this.player.x += this.player.speed;
}
if(this.player.x - this.player.w/2 < 0) {
this.player.x = this.player.w/2;
}
if(this.player.x + this.player.w/2 >= this.width) {
this.player.x = this.width - this.player.w/2 - 1;
}
if(this.player.y - this.player.h/2 < 0) {
this.player.y = this.player.h/2;
}
if(this.player.y + this.player.h/2 >= this.height) {
this.player.y = this.height - this.player.h/2 - 1;
}
};
LevelState.prototype.renderState = function(ms) {
this.ctx.clearRect(0, 0, this.width, this.height);
this.ctx.fillStyle = this.g1;
this.ctx.fillRect(0, 0, this.width, this.height);
this.ctx.fillStyle = this.player.baseCol;
this.ctx.fillRect(this.player.x - this.player.w/2, this.player.y - this.player.h/2, this.player.w, this.player.h);
this.ctx.fillStyle = this.player.faceCol;
this.ctx.fillRect(this.player.x - this.player.w/2, this.player.y - this.player.t + this.player.h/2, this.player.w, this.player.t);
this.ctx.fillStyle = this.player.topCol;
this.ctx.fillRect(this.player.x - this.player.w/2, this.player.y - this.player.t - this.player.h/2, this.player.w, this.player.h);
this.renderFPS();
this.game.blitCanvas(this.canvas);
};
/**
* GAME.JS
*/
var SCREEN_WIDTH = 640,
SCREEN_HEIGHT = 480;
var Game = function() {
if(Game.prototype._singleton)
return Game.prototype._singleton;
Game.prototype._singleton = this;
this.width = SCREEN_WIDTH;
this.height = SCREEN_HEIGHT;
this.canvas = null;
this.ctx = null;
this.state = null;
this.keyboard = new Keyboard();
this.running = false;
this.lastUpdate = 0;
this.init();
};
Game.prototype.init = function() {
this.canvas = make_canvas(this.width, this.height, 'screen', 'stage');
this.ctx = this.canvas.getContext('2d');
this.state = new LevelState(this);
};
Game.prototype.start = function() {
if(!this.running) {
this.running = true;
this.lastUpdate = +Date.now();
this.animFrame = request_animation_frame(this.update, this);
}
};
Game.prototype.update = function() {
var now = +Date.now();
var ms = now - this.lastUpdate;
this.lastUpdate = now;
this.animFrame = request_animation_frame(this.update, this);
this.state.update(ms);
this.keyboard.reset();
};
Game.prototype.blitCanvas = function(canvas) {
this.ctx.clearRect(0, 0, this.width, this.height);
this.ctx.drawImage(canvas, 0, 0);
};
Game.prototype.getWidth = function() {
return this.width;
};
Game.prototype.getHeight = function() {
return this.height;
};
/**
* RUN_GAME.js
*/
var g = new Game();
g.start();
Output
You can jump to the latest bin by adding /latest
to your URL
Keyboard Shortcuts
Shortcut | Action |
---|---|
ctrl + [num] | Toggle nth panel |
ctrl + 0 | Close focused panel |
ctrl + enter | Re-render output. If console visible: run JS in console |
Ctrl + l | Clear the console |
ctrl + / | Toggle comment on selected lines |
ctrl + ] | Indents selected lines |
ctrl + [ | Unindents selected lines |
tab | Code complete & Emmet expand |
ctrl + shift + L | Beautify code in active panel |
ctrl + s | Save & lock current Bin from further changes |
ctrl + shift + s | Open the share options |
ctrl + y | Archive Bin |
Complete list of JS Bin shortcuts |
JS Bin URLs
URL | Action |
---|---|
/ | Show the full rendered output. This content will update in real time as it's updated from the /edit url. |
/edit | Edit the current bin |
/watch | Follow a Code Casting session |
/embed | Create an embeddable version of the bin |
/latest | Load the very latest bin (/latest goes in place of the revision) |
/[username]/last | View the last edited bin for this user |
/[username]/last/edit | Edit the last edited bin for this user |
/[username]/last/watch | Follow the Code Casting session for the latest bin for this user |
/quiet | Remove analytics and edit button from rendered output |
.js | Load only the JavaScript for a bin |
.css | Load only the CSS for a bin |
Except for username prefixed urls, the url may start with http://jsbin.com/abc and the url fragments can be added to the url to view it differently. |