var Mobile = require('./mobile'); var Item = require('./item'); var NonPlayerCharacter = require('./nonplayercharacter'); var PlayerCharacter = require('./playercharacter'); var OnionNpc = require('./npcs/onionnpc'); var GrugNpc = require('./npcs/grugnpc'); var GlendaNpc = require('./npcs/glendanpc'); function Game() { var lastTime = 0; var socketConnections = []; var mobileIdCount = 1; var itemIdCount = 1; this.mobiles = []; this.nonplayer = []; this.items = []; this.init = function() { lastTime = new Date().getTime(); setInterval(function() { var currentTime = new Date().getTime(); var delta = (currentTime - lastTime) / (1000 / 60); game.tick(delta); lastTime = currentTime; }, 100); this.mobiles = []; mobileIdCount = 1; this.items = []; itemIdCount = 1; this.spawnOnion(); this.spawnGrug(); this.spawnGlenda(); } this.getConnections = function() { return socketConnections; } this.addConnection = function(key, connection) { socketConnections[key] = connection; }; this.removeConnection = function(key) { delete socketConnections[key]; }; this.shutdown = function() { for(var index in this.getConnections()) { socketConnections[index].close(); } socketConnections = []; }; this.tick = function(delta) { for(var index in this.mobiles) { var mobile = this.mobiles[index]; mobile.update(delta, this); } for(var index in this.mobiles) { var mobile = this.mobiles[index].mobile; this.pickUp(this.mobiles[index]); mobile.angleRadians = this.angleTo(mobile.position, mobile.targetPosition); if(mobile.targetPosition.x != mobile.position.x) { if(Math.abs(mobile.position.x - mobile.targetPosition.x) < mobile.maxSpeed * (1000/120)) { mobile.position.x = mobile.targetPosition.x; mobile.targetAngle = mobile.angleRadians; } else { mobile.targetAngle = mobile.angleRadians; mobile.position.x += mobile.maxSpeed * Math.cos(mobile.angleRadians) * delta; } } if(mobile.targetPosition.y != mobile.position.y) { if(Math.abs(mobile.position.y - mobile.targetPosition.y) < mobile.maxSpeed * (1000/120)) { mobile.position.y = mobile.targetPosition.y; mobile.targetAngle = mobile.angleRadians; } else { mobile.targetAngle = mobile.angleRadians; mobile.position.y += (mobile.maxSpeed) * Math.sin(mobile.angleRadians) * delta; } } } for(var index in this.items) { var item = this.items[index]; if(item == null) { this.items.splice(this.items.indexOf(item), 1); index--; } } if(this.items.length < 5) { this.spawnItem("Food " + itemIdCount); } } this.addPlayer = function(playerData, socketKey) { var newPlayer = new PlayerCharacter(this); var mobile = newPlayer.init(mobileIdCount++, socketKey, playerData); this.mobiles.push(newPlayer); console.log("Player " + newPlayer.id + " joined"); return newPlayer; }; this.takeOverNpc = function(playerData, socketKey) { var maxNpc = 3; var mobilecopy = this.mobiles.slice(0, this.mobiles.length-1); for(var index = mobilecopy.length-1; index >= 0; index--) { } var newPlayer = new PlayerCharacter(this); newPlayer.init(mobileIdCount++, socketKey, playerData); this.mobiles.push(newPlayer); console.log("Player " + newPlayer.id + " joined"); return newPlayer; }; this.removePlayer = function(socketKey) { for(var index in this.mobiles) { var player = this.mobiles[index]; if(player.mobile.socketKey == socketKey) { console.log("Player " + player.mobile.id + " disconnected"); this.mobiles.splice(this.mobiles.indexOf(player), 1); return; } } console.log("Player with key " + socketKey + " not found"); } this.takeOverPlayer = function(socketKey) { for(var index in this.mobiles) { var player = this.mobiles[index]; if(player.mobile.socketKey == socketKey) { console.log("Player " + player.mobile.id + " disconnected"); //this.mobiles.splice(this.mobiles.indexOf(player), 1); var replacementNpc = new NonPlayerCharacter(this); replacementNpc.takeOver(player); this.mobiles[index] = replacementNpc; return; } } console.log("Player with key " + socketKey + " not found"); } this.movePlayer = function(playerId, movementData) { for(var index in this.mobiles) { var player = this.mobiles[index].mobile; if(player.id == playerId) { player.targetPosition = movementData.targetPosition; return; } } }; this.updatePlayer = function(playerId, playerInfo) { for(var index in this.mobiles) { var player = this.mobiles[index].mobile; if(player.id == playerId) { for(var key in player) { if(playerInfo.hasOwnProperty(key)) { player[key] = playerInfo[key]; } } return; } } } this.sendToAll = function(data) { for(var socketIndex in this.getConnections()) { socketConnections[socketIndex].send(data); } } this.sendToOthers = function(key, data) { for(var socketIndex in this.getConnections()) { if(socketIndex == key) { continue; } socketConnections[socketIndex].send(data); } } this.getUpdate = function() { var allMobiles = []; for(var index in this.mobiles) { allMobiles.push(this.mobiles[index].mobile); } return {mobiles: allMobiles, items: this.items}; } this.formatFloat = function(val) { if (Number.isNaN(parseFloat(val))) { return 0; } return parseFloat(val.toFixed(6)); }; this.distanceTo = function(source, target) { return this.formatFloat(Math.sqrt(Math.pow(target.x - source.x, 2) + Math.pow(target.y - source.y, 2))); } this.angleTo = function(source, target) { return this.formatFloat(Math.atan2(target.y - source.y , target.x - source.x)); } this.getRandomPosition = function(origin, range) { if(origin == null) { origin = {x: 0, y: 0}; } if(range == null) { range = {min: -250, max: 500}; } var position = {x: 0, y: 0}; position.x = parseInt(range.max * Math.random() + range.min) + origin.x; position.y = parseInt(range.max * Math.random() + range.min) + origin.y; return position; } this.spawnNpc = function(npcData) { var newNpc = new NonPlayerCharacter(this); newNpc.init(mobileIdCount++, npcData); this.mobiles.push(newNpc); }; this.spawnOnion = function(){ var newNpc = new OnionNpc(this); newNpc.init(mobileIdCount++, {}); this.mobiles.push(newNpc); } this.spawnGrug = function(){ var newNpc = new GrugNpc(this); newNpc.init(mobileIdCount++, {}); this.mobiles.push(newNpc); } this.spawnGlenda = function(){ var newNpc = new GlendaNpc(this); newNpc.init(mobileIdCount++, {}); this.mobiles.push(newNpc); } this.spawnItem = function(name) { var newItem = new Item(); newItem.id = itemIdCount++; newItem.color = "green"; newItem.name = name; newItem.position = this.getRandomPosition(); this.items.push(newItem); }; this.pickUp = function(mobile) { if(mobile.inventory.length >= mobile.maxInventory) { return; } for(var itemIndex in this.items) { var item = this.items[itemIndex]; if(item != null && this.inBounds(mobile.mobile, item)) { mobile.inventory.push(item); console.log(mobile.mobile.name + "("+mobile.mobile.id+") picked up " + item.name + "("+item.id+") at ", item.position); this.items[itemIndex] = null; continue; } } } this.inBounds = function(mobile, item) { var halfMobileWidth = mobile.width / 2; var halfMobileHeight = mobile.height / 2; var halfItemWidth = item.width / 2; var halfItemHeight = item.height / 2; if(mobile.position.x + halfMobileWidth > item.position.x - halfItemWidth && mobile.position.x - halfMobileWidth < item.position.x + halfItemWidth && mobile.position.y + halfMobileHeight > item.position.y - halfItemHeight && mobile.position.y - halfMobileHeight < item.position.y + halfItemHeight) { return true; } return false; } this.sendChat = function(mobile, message) { var mobileName = mobile.name; message = mobileName + ": " + message; var chatData = {action: "chat", data:{mobileid:mobile.id, message:message}}; console.log("chat:", message); game.sendToAll(JSON.stringify(chatData)); } this.handleChat = function(chatData) { for(var index in this.mobiles) { var mobile = this.mobiles[index]; if(mobile.id == chatData.data.mobileid) { this.sendChat(mobile.mobile, chatData.data.message); break; } } } }; module.exports = new Game();