UNPKG

d-zone

Version:

An ambient life simulation driven by the user activity within a Discord server

205 lines (183 loc) 7.2 kB
var EventEmitter = require('events').EventEmitter; var inherits = require('inherits'); var Input = require('./input.js'); var util = require('./../common/util.js'); var now = global.performance && global.performance.now ? function() { return performance.now() } : Date.now || function () { return +new Date() }; module.exports = Game; inherits(Game, EventEmitter); function Game(options) { this.setMaxListeners(0); this.step = options.step || 1000/60; this.lastUpdate = 0; this.dt = 0; this.ticks = 0; this.input = new Input(); this.input.on('keydown',this.keydown.bind(this)); this.input.on('keyup',this.keyup.bind(this)); this.mouseButtons = []; this.centerMouseX = -999; this.centerMouseY = -999; this.entities = []; this.schedule = []; this.mouseOver = false; var self = this; this.interval = setInterval(function() { if(self.crashed) return; var rightNow = now(); self.dt += rightNow - self.lastUpdate; //if((self.ticks & 7) == 0) console.log(delta); if(self.lastUpdate > 0 && self.dt > 60000) { console.log('too many updates missed! game crash...'); self.crashed = true; self.paused = true; } if(self.dt > self.step) { while(self.dt >= self.step) { self.dt -= self.step; if(self.paused) continue; self.ticks++; self.update(); } } self.lastUpdate = now(); }, this.step); } var lastUpdateTime = 0; Game.prototype.update = function() { var timeThis = this.timeUpdates && (this.ticks & 255) == 0; if(timeThis) console.time('update'); //if(timeThis) console.log('entities:',this.entities.length, 'actors:', Object.keys(this.users.actors).length, 'update listeners', this.listenerCount('update'), 'message listeners',this.users.listenerCount('message')); //if(timeThis) var updateStart = now(); //if(timeThis) console.log('entities:', this.entities.length); this.emit('update'); // TODO: Move scheduling to entity? for(var i = 0; i < this.schedule.length; i++) { var task = this.schedule[i]; var endTick; if(task.type == 'repeat') { endTick = task.start + task.count; if(task.start <= this.ticks) { var ticks = this.ticks - task.start; task.cb({ ticks: ticks, percent: ticks / task.count }); } } else if(task.type == 'once') { endTick = task.tick; } if(task.type == 'deleted' || endTick <= this.ticks) { if(task.type == 'once') task.cb(); else if(task.type == 'repeat' && task.afterCB) task.afterCB(); this.schedule.splice(i,1); i--; } } this.emit('render'); if(timeThis) console.timeEnd('update'); //if(timeThis) var thisUpdateTime = now() - updateStart; //if(timeThis) var updateTimeChange = thisUpdateTime-lastUpdateTime; //if(timeThis && updateTimeChange <= 0) console.log('%c'+updateTimeChange, 'color: #00bb00'); //if(timeThis && updateTimeChange > 0) console.log('%c'+updateTimeChange, 'color: #ff0000'); //if(timeThis) lastUpdateTime = thisUpdateTime; }; Game.prototype.bindCanvas = function(canvas) { this.input.bindCanvas(canvas); this.viewWidth = canvas.width; this.viewHeight = canvas.height; this.input.on('mousemove',this.mousemove.bind(this)); this.input.on('mousedown',this.mousedown.bind(this)); this.input.on('mouseup',this.mouseup.bind(this)); this.input.on('mouseout',this.mouseout.bind(this)); this.input.on('mouseover',this.mouseover.bind(this)); this.input.on('mousewheel',this.mousewheel.bind(this)); this.input.on('touchmove', this.touchmove.bind(this)); this.input.on('touchstart', this.touchstart.bind(this)); this.input.on('touchend', this.touchend.bind(this)); this.input.on('touchcancel', this.touchcancel.bind(this)); canvas.on('resize',this.viewResize.bind(this)); }; Game.prototype.viewResize = function(resize) { this.viewWidth = resize.width; this.viewHeight = resize.height; this.input.mouseScale = resize.scale; this.emit('resize', resize); }; Game.prototype.mousemove = function(mouseEvent) { if(this.mouseOut) return; //this.mouseOut = false; this.mouseX = mouseEvent.x; this.mouseY = mouseEvent.y; this.centerMouseX = Math.floor(mouseEvent.x - this.viewWidth / 2); this.centerMouseY = Math.floor(mouseEvent.y - this.viewHeight / 2); mouseEvent.centerMouseX = this.centerMouseX; mouseEvent.centerMouseY = this.centerMouseY; //console.log({mouseX: this.mouseX, mouseY:this.mouseY, centerMouseX:this.centerMouseX, centerMouseY:this.centerMouseY}); this.emit('mousemove',mouseEvent); }; Game.prototype.mousedown = function(mouseEvent) { if(this.mouseOver) { console.log(this.mouseOver); window.actor = this.mouseOver; } this.mouseButtons.push(mouseEvent.button); this.emit('mousedown',mouseEvent); }; Game.prototype.touchend = function(mouseEvent) { util.findAndRemove(mouseEvent.button, this.mouseButtons); this.emit('touchend',mouseEvent); }; Game.prototype.touchmove = function(mouseEvent) { if(this.mouseOut) return; this.mouseOut = false; this.mouseX = mouseEvent.x; this.mouseY = mouseEvent.y; this.centerMouseX = Math.floor(mouseEvent.x - this.viewWidth / 2); this.centerMouseY = Math.floor(mouseEvent.y - this.viewHeight / 2); mouseEvent.centerMouseX = this.centerMouseX; mouseEvent.centerMouseY = this.centerMouseY; this.emit('touchmove',mouseEvent); }; Game.prototype.touchcancel = function(mouseEvent) { this.mouseOut = true; this.mouseOver = false; this.emit('touchcancel',mouseEvent); }; Game.prototype.touchstart = function(mouseEvent) { if(this.mouseOver) { console.log(this.mouseOver); window.actor = this.mouseOver; } this.mouseButtons.push(mouseEvent.button); this.emit('touchstart',mouseEvent); }; Game.prototype.mouseup = function(mouseEvent) { util.findAndRemove(mouseEvent.button, this.mouseButtons); this.emit('mouseup',mouseEvent); }; Game.prototype.mouseout = function(mouseEvent) { this.mouseOut = true; this.mouseOver = false; this.emit('mouseout',mouseEvent); }; Game.prototype.mouseover = function(mouseEvent) { this.mouseOut = false; this.emit('mouseover',mouseEvent); }; Game.prototype.mousewheel = function(mouseEvent) { this.emit('mousewheel',mouseEvent); }; Game.prototype.keydown = function(keyEvent) { this.emit('keydown',keyEvent); }; Game.prototype.keyup = function(keyEvent) { this.emit('keyup',keyEvent); }; Game.prototype.reset = function() { this.emit('destroy'); this.removeAllListeners('update'); this.schedule = []; while(this.entities.length > 0) { this.entities[0].remove(); } };