Websocket error when following multiplayer node tutorial "Client State"
Page 1 of 1
Websocket error when following multiplayer node tutorial "Client State"
Hi all, I have just joined the forum - I didn't realise there was one! I am having some difficulty in the 'client state' tutorial - I have followed it through but seem to be getting the error "cannot read property 'port number' of undefined. The error occurs with this line of code: var p = Player.Li[pack.id]; and also this line delete Attack.Li[data.attack[i]];
If anybody could help me that would be great. Sorry for all the code.
index.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8"> <!--character encoding for HTML-->
<!-- link to the stylesheet for the background stars and clouds-->
<link rel="stylesheet" type="text/css" href="css/stars.css" />
<!--request socket.io files-->
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
</head>
<body>
<div class="stars"></div>
<div class="twinkling"></div>
<div class="clouds"></div>
<!--end the parallax starts effect -->
<!--LOG IN FUNCTIONALITY-->
<!--only div visible before logging in-->
<div id="logDiv">
Username: <input id="logDiv-username" type="text"></input>
Password: <input id="logDiv-password" type="text"></input>
<button id="logDiv-signIn">Sign In</button>
<button id="logDiv-register">Register</button>
</div>
<!--GAME DIV-->
<!--display is none by default-->
<!--only visible once logged in-->
<div id="gameDiv" style="display:none;">
<canvas id="ctx" width="600" height="600" style="border:1px solid #000000;"></canvas>
<div id="chat-text" style="width:600px;height:100px;background-color:#dee2e8;overflow-y:scroll">
<div> Game Chat</div>
</div>
<!--form allows user to press enter to send message-->
<form id="chat-form">
<input id="chat-input" type="text" style="width:600px;height:20px;background-color:#edeff2"></input>
</form>
</div>
<script>
var socket = io();
//SIGN IN FUNCTIONALITY
var logDiv = document.getElementById('logDiv');
var logDivUsername = document.getElementById('logDiv-username');
var logDivPassword = document.getElementById('logDiv-password');
var logDivSignIn = document.getElementById('logDiv-signIn');
var logDivRegister = document.getElementById('logDiv-register');
//when user hits sign in btn package emitted to server with 'signIn' values
logDivSignIn.onclick = function(){
socket.emit('signIn',{username:logDivUsername.value, password:logDivPassword.value});
}
logDivRegister.onclick = function(){
socket.emit('register',{username:logDivUsername.value, password:logDivPassword.value});
}
//server emits 'signInResponse'
//if successful sign in div hidded, game div visible
socket.on('signInResponse', function(data){
if(data.success){
logDiv.style.display = 'none';
gameDiv.style.display = 'inline-block';
} else
alert("Sign in unsuccessful, please check credentials.");
});
//server emits 'registerResponse'
//if registration successful div hidded, game div visible
socket.on('registerResponse', function(data){
if(data.success){
alert("Registration successful.");
} else
alert("Registration unsuccessful, username currently is use.");
});
//CHAT FUNCTIONALITY
var chatText = document.getElementById('chat-text');
var chatInput = document.getElementById('chat-input');
var chatForm = document.getElementById('chat-form');
var ctx = document.getElementById("ctx").getContext("2d");
ctx.font = '30px Ariel';
//CHAT FUNCTIONALITY
//when 'addToChat' message received from server function is called and
//apended to 'addChatText' innerHTML
socket.on('addToChat', function(data){
chatText.innerHTML += '<div>' + data + '</div>';
});
//when package with evalAnswer is recieved on client, print
socket.on('evalAns', function(data){
console.log(data);
});
//preventDefault prevents the page from refreshing
//called upon user submitting/enter
//DEBUG -- if 0 value == / then eval to server for debugging
//upon server receiving 'sendMsgServer package it adds to chat div
chatForm.onsubmit = function(e){
e.preventDefault();
if (chatInput.value[0] === '/')
socket.emit('evalToServer', chatInput.value.slice(1));
else
socket.emit('sendMsgServer', chatInput.value);
//reset value to 'nothing'
chatInput.value = '';
}
//GAME LOGIC
var ctx = document.getElementById("ctx").getContext("2d");
ctx.font = '30px Ariel';
ctx.fillStyle = 'purple'
//container - class contains data about players
//sets characteristics depending upon the init package on the server
//initialization package - contains creation of all new data
//container - class contains data about players
//sets characteristics depending upon the init package on the server
var Player = function(initPack){
var companion = {};
companion.id = initPack.id;
companion.number = initPack.number;
companion.x = initPack.x;
companion.y = initPack.y;
Player_Li[companion.id] = companion;
return companion;
}
Player_Li = {};
//container - class contains data about attacks
//sets characteristics depending upon the init package on the server
var Attack = function(initPack){
var companion = {};
companion.id = initPack.id;
companion.number = initPack.number;
companion.x = initPack.x;
companion.y = initPack.y;
Attack_Li[companion.id] = companion;
return companion;
}
Attack_Li = {};
//create init package - loop through all players & attack, for each call
//'new player/attack' & add to list
socket.on('init', function(data){
for (var i = 0 ; i < data.player.length; i++){
new Player(data.player[i]);
}
for (var i = 0 ; i < data.attack.length; i++){
new Attack (data.attack[i]);
}
});
//update package - contains difference between new and updated data
//loops through all players
socket.on('update', function(data){
//{ player : [{id:123,x:0,y:0},{id:1,x:0,y:0}], bullet: []}
for(var i = 0 ; i < data.player.length; i++){
var pack = data.player[i];
var p = Player.Li[pack.id];
//check memory for player with said id, if new info on 'x' & 'y' update package
if(p){
if(pack.x !== undefined)
p.x = pack.x;
if(pack.y !== undefined)
p.y = pack.y;
}
}
for(var i = 0 ; i < data.attack.length; i++){
var pack = data.attack[i];
var b = Attack.Li[data.attack[i].id];
if(b){
if(pack.x !== undefined)
b.x = pack.x;
if(pack.y !== undefined)
b.y = pack.y;
}
}
});
//removal package - sends package with list of pokeballs/players id's to remove
//loops through all and delete from list
socket.on('remove',function(data){
//{player:[12323],bullet:[12323,123123]}
for(var i = 0 ; i < data.player.length; i++){
delete Player.Li[data.player[i]];
}
for(var i = 0 ; i < data.attack.length; i++){
delete Attack.Li[data.attack[i]];
}
});
//every 40 m/s (25 p/s)
//removes conent from x & y pos & W-bottom right & H
//loop through every player in the array
//fill canvas with player number, & pos
//loop through all attacks, draw them to the canvas (rectangle w:5, h:5)
//top R corner of bullet @ x-5 & y-5
setInterval(function(){
ctx.clearRect(0,0,600,600);
for(var i in Player.Li)
ctx.fillText(Player.Li[i].number,Player.Li[i].x,Player.Li[i].y);
for (var i in Attack.Li)
ctx.fillRect(Attack.Li[i].x-5,Attack.Li[i].y-5,5,5);
},40);
//KEYPRESS FUNCTIONALITY
//function called upon keypress, will emit keypress package,
//contains input id and displays the state
//sends true states to server upon keyPress
document.onkeydown = function(event){
if(event.keyCode === 87) // w
socket.emit('keyPress',{inputId:'up',state:true});
else if(event.keyCode === 83) //s
socket.emit('keyPress',{inputId:'down',state:true});
else if(event.keyCode === 65) //a
socket.emit('keyPress',{inputId:'L',state:true});
else if(event.keyCode === 68) //d
socket.emit('keyPress',{inputId:'R',state:true});
}
//function called upon keypress, will emit keypress package,
//contains input id and displays the state
//sends false states to server upon keypress
document.onkeyup = function(event){
if(event.keyCode === 87) // w
socket.emit('keyPress',{inputId:'up',state:false});
else if(event.keyCode === 83) //s
socket.emit('keyPress',{inputId:'down',state:false});
else if(event.keyCode === 65) //a
socket.emit('keyPress',{inputId:'L',state:false});
else if(event.keyCode === 68) //d
socket.emit('keyPress',{inputId:'R',state:false});
}
//MOUSEMOVE FUNCTIONALITY
//on mouse down inputID 'attack', with state == true is sent to the server
document.onmousedown = function(event){
socket.emit('keyPress',{inputId:'attack',state:true});
}
//on mouse down inputID 'attack', with state == false is sent to the server
document.onmouseup = function(event){
socket.emit('keyPress',{inputId:'attack',state:false});
}
//mouse angle
//extract x & y relative to screen centre (-250 vals)
document.onmousemove = function(event){
var x = -250 + event.clientX - 8;
var y = -250 + event.clientY - 8;
//calculate angle
var angle = Math.atan2(y,x) / Math.PI * 180;
socket.emit('keyPress',{inputId:'mouseAngle',state:angle});
}
</script>
</body>
</html>
app.js:
//create server, listening on port 3000
//when there is a request to port 3000 the server is notified
//depending on the request a specific action will be carried out
var express = require('express');
var app = express();
var serv = require('http').Server(app);
var colors = require('colors/safe');
//var MongoClient = require('mongodb').MongoClient;
//connection url
//var url = ('localhost:27017/Game', 'account', 'progress');
//use connect method to connect to server
http://MongoClient.connect(url, function(err, db){
// if (err) return console.log('Error: ' + err);
// console.log('mongodb is connected to the server');
//});
//insert into collection
http://db.account.insert({username:"wendy3", password:"lilac3"});
http://console.log('hello'.green); // outputs green text
//function carried out if request == nothing
//client sent to index.html
app.get('/',function(req, res) {
res.sendFile(__dirname + '/client/index5.html');
});
//function == query == 'client', client directed to client directory
app.use('/project4',express.static(__dirname + '/project4'));
serv.listen(8080);
console.log(colors.bold.yellow("Server is running on port 8080"));
//create socket & player lists
//global variables
var Socket_Li = {};
//create socket object socket:unique ID
//class contains attributes relevent to player & bullets
//used as a model for new player creation, each new player is constructed via below parameters
var Entity = function(){
var companion = {
x:200,
y:200,
speedX:0,
speedY:0,
id:"",
}
//call update function
companion.update = function(){
companion.updatePos();
}
companion.updatePos = function(){
companion.x += companion.speedX;
companion.y += companion.speedY;
}
//returns the distance between the two players
companion.getDistance = function(pt){
//(companion.x-pt.x,2 & companion.y-pt.y,2 compares the difference in distance
//between the two entities
//sqrt returns the square root of specified values within the parameter.
return Math.sqrt(Math.pow(companion.x-pt.x,2) + Math.pow(companion.y-pt.y,2));
}
return companion;
}
//player class - additional attributes added to Entity
var Player = function(id){
//assigns the entity attributes to the companion object
var companion = Entity();
companion.id = id;
//assign each player with a different random number
//player numbers are added to sockets
http://math.floor returns that largerst int <= to previous assigned number
companion.number = "" + Math.floor(8 * Math.random());
//following properties will track the keypress states
companion.pressUp = false;
companion.pressDown = false;
companion.pressL = false;
companion.pressR = false;
companion.pressAttack = false;
companion.mouseAngle = 0;
companion.maxSpeed = 8;
companion.hp = 10;
companion.hpMax = 10;
//when player function is called...
//calls companion.update & companion.updateSpeed functions
//overrides update so that speed is updated, followed by x,y axis etc
var big_update = companion.update;
companion.update = function(){
companion.updateSpeed();
big_update();
//attack is created for each player
if(companion.pressAttack){
companion.Attacknow(companion.mouseAngle);
}
}
//attack now function
companion.Attacknow = function(angle){
var b = Attack(companion.id, angle);
//attack is spawned on top of the player x & y are same
b.x = companion.x;
b.y = companion.y;
}
//calls every frame and updates the x and y azis depending on keypress
companion.updateSpeed = function(){
if (companion.pressUp)
companion.speedY = -companion.maxSpeed; //opposite
else if (companion.pressDown)
companion.speedY = companion.maxSpeed;
else
companion.speedY = 0;
if(companion.pressR)
companion.SpeedX = companion.maxSpeed;
else if(companion.pressL)
companion.SpeedX = -companion.maxSpeed; //opposite
else
companion.speedX = 0;
}
//create player object player:unique ID
//add player to initPackage
Player_Li[id] = companion;
initPack.player.push({
id:companion.id,
x:companion.x,
y:companion.y,
//number:companion.number,
});
return companion;
}
Player_Li = {};
//static function - associated with the class, not object itself
//all player related code to go within Player class
Player.onConnect = function(socket){
//create player with socket id
var player = Player(socket.id);
//listens for keypress on the client, sets the
//keypress values to the true/false states on the client
socket.on('keyPress',function(data){
if(data.inputId === 'up')
player.pressUp = data.state;
else if(data.inputId === 'down')
player.pressDown = data.state;
else if(data.inputId === 'L')
player.pressL = data.state;
else if(data.inputId === 'R')
player.pressR = data.state;
else if(data.inputId === 'attack')
player.pressAttack = data.state;
else if(data.inputId === 'mouseAngle')
player.mouseAngle = data.state;
});
}
Player.onDisconnect = function(socket){
delete Player_Li[socket.id];
removePack.player.push(socket.id);
}
//loops through all players in playerLi & calls update function
Player.update = function(){
var pack = [];
//i = key in list - loops through all playes
for(var i in Player_Li){
var player = Player_Li[i];
//increment x & y
player.update();
//data package, including R,L,up,down movements is pushed for each socket &
//sent back to the client where it is then displayed
pack.push({
id:player.id,
x:player.x,
y:player.y,
});
}
return pack;
}
//PlayerHit = function(){
// companion.hp = companion.hp - 1;
// socket.emit('hp');
//}
//to create bullet an entity is created,
var Attack = function(parent, angle){
var companion = Entity();
//create radom id
companion.id = Math.random();
//angles are used to determine x & y pos
companion.speedX = Math.cos(angle/180*Math.PI) * 8;
//collision detection - pokeball/attack cannot touch parent
companion.speedY = Math.sin(angle/180*Math.PI) * 8;
companion.parent = parent;
//entities are never removed, so big_update is called
//timer increments through loop, once reached 110 fps attack is removed
companion.timer = 0;
companion.toRemove = false;
var big_update = companion.update;
companion.update = function(){
if(companion.timer++ > 110)
companion.toRemove = true;
big_update();
//loop through all players in the game
//in order for collision to take place distance must be < 28
//parent of pokeball must not = id of player trying to touch
//i = key in list - loops through all players in playerLi object
for (var i in Player_Li){
var p = Player_Li[i];
//if parent of attack != id of player who attacked
if(companion.getDistance(p) < 28 && companion.parent !== p.id){
companion.toRemove = true;
}
}
}
//attack is added to the list
//add to initPackage, id,x,y params
Attack_Li[companion.id] = companion;
initPack.attack.push({
id:companion.id,
x:companion.x,
y:companion.y,
});
return companion;
}
Attack_Li = {};
//update function - loop through every attack and call update
//create attack with random angle if math.random < 0.07
http://math.random = value 0-1
Attack.update = function(){
//create package to be sent to the client
var pack = [];
for(var i in Attack_Li){
var attack = Attack_Li[i];
attack.update();
//remove from attack list if attack needs to be removed & add to removePackage
if(attack.toRemove){
delete Attack_Li[i];
removePack.attack.push(attack.id);
} else
pack.push({
id:attack.id,
x:attack.x,
y:attack.y,
});
}
return pack;
}
//constant variable -- set to false if server live
var DEBUG = true;
//users object contains credentials of all users
var USERS = {
"wendy":"lilac",
"wendy1":"lilac1",
"wendy2":"lilac2",
}
//callback (cb) parameter (function) called with result required
//if will happen in the future at some point a call back is used
//evaluates an expression after specified number of m/s.
var validCredentials = function (data,cb){
setTimeout(function(){
//user needs to exist - check username & password match USERS object
cb (USERS[data.username] === data.password);
},10);
}
//function checks whether username is available, data returns true if name taken
var usernameAvailable = function(data,cb){
setTimeout(function(){
//returns true if name taken
cb (USERS[data.username]);
},10);
}
var addUser = function(data,cb){
setTimeout(function(){
//username must be = to password in users object
cb (USERS[data.username] = data.password);
cb();
},10);
}
//load and initialize websocket file, returns .io object containing library functions
var io = require('socket.io')(serv,{});
io.sockets.on('connection', function(socket){
socket.id = Math.random();
//add player to sockets
Socket_Li[socket.id] = socket;
//create new listener 'signIn;
socket.on('signIn', function(data){
//data validation
//emit true/false 'signInResponse' package to client
//2nd parameter (result) is a function - added because we do not know when it will be called
//is called when action (button) takes place
validCredentials(data, function(result){
//if result = successful, player is connected & package emitted
if (result){
Player.onConnect(socket);
socket.emit('signInResponse',{success:true});
} else {
socket.emit('signInResponse',{success:false});
}
});
});
//create new listener 'register;
//username taken = not successful emitted to client
//username available = successfull emitted to client - data credentials added to addUser function
socket.on('register', function(data){
//data validation
usernameAvailable(data, function(result){
//if usernmae != available
if (result){
socket.emit('registerResponse', {success:false});
}else {
//if username = available
addUser(data, function(){
socket.emit('registerResponse', {success:true});
});
}
});
});
socket.on('disconnect', function(){
delete Socket_Li[socket.id];
Player.onDisconnect(socket);
});
//server receives package from chat input
socket.on('sendMsgServer', function(data){
var playerName = ("" + socket.id).slice(2,7);
//i = key in list - loops through all sockets in socket_Li object
for (var i in Socket_Li){
//emit 'addToChat' package
Socket_Li[i].emit('addToChat',playerName + ': ' + data);
}
});
//THIS SHOULD NOT BE ACCESSIBLE
//evaluates string within data
//sends result to client
//if debug = !debug nothing happens
socket.on('evalToServer', function(data){
if (!DEBUG)
return;
var res = eval(data);
socket.emit('evalAns', res);
});
});
//contains all initialisation data
//new players are added to init pack
var initPack = {player:[],attack:[]};
//contains all removal data
//removed players are added to remove pack
var removePack = {player:[],attack:[]};
//loop, called every 40/ms through all connected players and send new position to canvas in client file
setInterval(function(){
//package contains player info & sent to all connected players
var pack = {
player:Player.update(),
attack:Attack.update(),
}//i = key in list - loops through all sockets in socketLi object
for(var i in Socket_Li){
var socket = Socket_Li[i];
//packages sent to client every 40 m/s
socket.emit('init',initPack);
socket.emit('update',pack);
socket.emit('remove',removePack);
}
//empty packs every 40 m/s to prevent duplication of entities
initPack.player = [];
initPack.bullet = [];
removePack.player = [];
removePack.bullet = [];
},1000/25);
If anybody could help me that would be great. Sorry for all the code.
index.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8"> <!--character encoding for HTML-->
<!-- link to the stylesheet for the background stars and clouds-->
<link rel="stylesheet" type="text/css" href="css/stars.css" />
<!--request socket.io files-->
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
</head>
<body>
<div class="stars"></div>
<div class="twinkling"></div>
<div class="clouds"></div>
<!--end the parallax starts effect -->
<!--LOG IN FUNCTIONALITY-->
<!--only div visible before logging in-->
<div id="logDiv">
Username: <input id="logDiv-username" type="text"></input>
Password: <input id="logDiv-password" type="text"></input>
<button id="logDiv-signIn">Sign In</button>
<button id="logDiv-register">Register</button>
</div>
<!--GAME DIV-->
<!--display is none by default-->
<!--only visible once logged in-->
<div id="gameDiv" style="display:none;">
<canvas id="ctx" width="600" height="600" style="border:1px solid #000000;"></canvas>
<div id="chat-text" style="width:600px;height:100px;background-color:#dee2e8;overflow-y:scroll">
<div> Game Chat</div>
</div>
<!--form allows user to press enter to send message-->
<form id="chat-form">
<input id="chat-input" type="text" style="width:600px;height:20px;background-color:#edeff2"></input>
</form>
</div>
<script>
var socket = io();
//SIGN IN FUNCTIONALITY
var logDiv = document.getElementById('logDiv');
var logDivUsername = document.getElementById('logDiv-username');
var logDivPassword = document.getElementById('logDiv-password');
var logDivSignIn = document.getElementById('logDiv-signIn');
var logDivRegister = document.getElementById('logDiv-register');
//when user hits sign in btn package emitted to server with 'signIn' values
logDivSignIn.onclick = function(){
socket.emit('signIn',{username:logDivUsername.value, password:logDivPassword.value});
}
logDivRegister.onclick = function(){
socket.emit('register',{username:logDivUsername.value, password:logDivPassword.value});
}
//server emits 'signInResponse'
//if successful sign in div hidded, game div visible
socket.on('signInResponse', function(data){
if(data.success){
logDiv.style.display = 'none';
gameDiv.style.display = 'inline-block';
} else
alert("Sign in unsuccessful, please check credentials.");
});
//server emits 'registerResponse'
//if registration successful div hidded, game div visible
socket.on('registerResponse', function(data){
if(data.success){
alert("Registration successful.");
} else
alert("Registration unsuccessful, username currently is use.");
});
//CHAT FUNCTIONALITY
var chatText = document.getElementById('chat-text');
var chatInput = document.getElementById('chat-input');
var chatForm = document.getElementById('chat-form');
var ctx = document.getElementById("ctx").getContext("2d");
ctx.font = '30px Ariel';
//CHAT FUNCTIONALITY
//when 'addToChat' message received from server function is called and
//apended to 'addChatText' innerHTML
socket.on('addToChat', function(data){
chatText.innerHTML += '<div>' + data + '</div>';
});
//when package with evalAnswer is recieved on client, print
socket.on('evalAns', function(data){
console.log(data);
});
//preventDefault prevents the page from refreshing
//called upon user submitting/enter
//DEBUG -- if 0 value == / then eval to server for debugging
//upon server receiving 'sendMsgServer package it adds to chat div
chatForm.onsubmit = function(e){
e.preventDefault();
if (chatInput.value[0] === '/')
socket.emit('evalToServer', chatInput.value.slice(1));
else
socket.emit('sendMsgServer', chatInput.value);
//reset value to 'nothing'
chatInput.value = '';
}
//GAME LOGIC
var ctx = document.getElementById("ctx").getContext("2d");
ctx.font = '30px Ariel';
ctx.fillStyle = 'purple'
//container - class contains data about players
//sets characteristics depending upon the init package on the server
//initialization package - contains creation of all new data
//container - class contains data about players
//sets characteristics depending upon the init package on the server
var Player = function(initPack){
var companion = {};
companion.id = initPack.id;
companion.number = initPack.number;
companion.x = initPack.x;
companion.y = initPack.y;
Player_Li[companion.id] = companion;
return companion;
}
Player_Li = {};
//container - class contains data about attacks
//sets characteristics depending upon the init package on the server
var Attack = function(initPack){
var companion = {};
companion.id = initPack.id;
companion.number = initPack.number;
companion.x = initPack.x;
companion.y = initPack.y;
Attack_Li[companion.id] = companion;
return companion;
}
Attack_Li = {};
//create init package - loop through all players & attack, for each call
//'new player/attack' & add to list
socket.on('init', function(data){
for (var i = 0 ; i < data.player.length; i++){
new Player(data.player[i]);
}
for (var i = 0 ; i < data.attack.length; i++){
new Attack (data.attack[i]);
}
});
//update package - contains difference between new and updated data
//loops through all players
socket.on('update', function(data){
//{ player : [{id:123,x:0,y:0},{id:1,x:0,y:0}], bullet: []}
for(var i = 0 ; i < data.player.length; i++){
var pack = data.player[i];
var p = Player.Li[pack.id];
//check memory for player with said id, if new info on 'x' & 'y' update package
if(p){
if(pack.x !== undefined)
p.x = pack.x;
if(pack.y !== undefined)
p.y = pack.y;
}
}
for(var i = 0 ; i < data.attack.length; i++){
var pack = data.attack[i];
var b = Attack.Li[data.attack[i].id];
if(b){
if(pack.x !== undefined)
b.x = pack.x;
if(pack.y !== undefined)
b.y = pack.y;
}
}
});
//removal package - sends package with list of pokeballs/players id's to remove
//loops through all and delete from list
socket.on('remove',function(data){
//{player:[12323],bullet:[12323,123123]}
for(var i = 0 ; i < data.player.length; i++){
delete Player.Li[data.player[i]];
}
for(var i = 0 ; i < data.attack.length; i++){
delete Attack.Li[data.attack[i]];
}
});
//every 40 m/s (25 p/s)
//removes conent from x & y pos & W-bottom right & H
//loop through every player in the array
//fill canvas with player number, & pos
//loop through all attacks, draw them to the canvas (rectangle w:5, h:5)
//top R corner of bullet @ x-5 & y-5
setInterval(function(){
ctx.clearRect(0,0,600,600);
for(var i in Player.Li)
ctx.fillText(Player.Li[i].number,Player.Li[i].x,Player.Li[i].y);
for (var i in Attack.Li)
ctx.fillRect(Attack.Li[i].x-5,Attack.Li[i].y-5,5,5);
},40);
//KEYPRESS FUNCTIONALITY
//function called upon keypress, will emit keypress package,
//contains input id and displays the state
//sends true states to server upon keyPress
document.onkeydown = function(event){
if(event.keyCode === 87) // w
socket.emit('keyPress',{inputId:'up',state:true});
else if(event.keyCode === 83) //s
socket.emit('keyPress',{inputId:'down',state:true});
else if(event.keyCode === 65) //a
socket.emit('keyPress',{inputId:'L',state:true});
else if(event.keyCode === 68) //d
socket.emit('keyPress',{inputId:'R',state:true});
}
//function called upon keypress, will emit keypress package,
//contains input id and displays the state
//sends false states to server upon keypress
document.onkeyup = function(event){
if(event.keyCode === 87) // w
socket.emit('keyPress',{inputId:'up',state:false});
else if(event.keyCode === 83) //s
socket.emit('keyPress',{inputId:'down',state:false});
else if(event.keyCode === 65) //a
socket.emit('keyPress',{inputId:'L',state:false});
else if(event.keyCode === 68) //d
socket.emit('keyPress',{inputId:'R',state:false});
}
//MOUSEMOVE FUNCTIONALITY
//on mouse down inputID 'attack', with state == true is sent to the server
document.onmousedown = function(event){
socket.emit('keyPress',{inputId:'attack',state:true});
}
//on mouse down inputID 'attack', with state == false is sent to the server
document.onmouseup = function(event){
socket.emit('keyPress',{inputId:'attack',state:false});
}
//mouse angle
//extract x & y relative to screen centre (-250 vals)
document.onmousemove = function(event){
var x = -250 + event.clientX - 8;
var y = -250 + event.clientY - 8;
//calculate angle
var angle = Math.atan2(y,x) / Math.PI * 180;
socket.emit('keyPress',{inputId:'mouseAngle',state:angle});
}
</script>
</body>
</html>
app.js:
//create server, listening on port 3000
//when there is a request to port 3000 the server is notified
//depending on the request a specific action will be carried out
var express = require('express');
var app = express();
var serv = require('http').Server(app);
var colors = require('colors/safe');
//var MongoClient = require('mongodb').MongoClient;
//connection url
//var url = ('localhost:27017/Game', 'account', 'progress');
//use connect method to connect to server
http://MongoClient.connect(url, function(err, db){
// if (err) return console.log('Error: ' + err);
// console.log('mongodb is connected to the server');
//});
//insert into collection
http://db.account.insert({username:"wendy3", password:"lilac3"});
http://console.log('hello'.green); // outputs green text
//function carried out if request == nothing
//client sent to index.html
app.get('/',function(req, res) {
res.sendFile(__dirname + '/client/index5.html');
});
//function == query == 'client', client directed to client directory
app.use('/project4',express.static(__dirname + '/project4'));
serv.listen(8080);
console.log(colors.bold.yellow("Server is running on port 8080"));
//create socket & player lists
//global variables
var Socket_Li = {};
//create socket object socket:unique ID
//class contains attributes relevent to player & bullets
//used as a model for new player creation, each new player is constructed via below parameters
var Entity = function(){
var companion = {
x:200,
y:200,
speedX:0,
speedY:0,
id:"",
}
//call update function
companion.update = function(){
companion.updatePos();
}
companion.updatePos = function(){
companion.x += companion.speedX;
companion.y += companion.speedY;
}
//returns the distance between the two players
companion.getDistance = function(pt){
//(companion.x-pt.x,2 & companion.y-pt.y,2 compares the difference in distance
//between the two entities
//sqrt returns the square root of specified values within the parameter.
return Math.sqrt(Math.pow(companion.x-pt.x,2) + Math.pow(companion.y-pt.y,2));
}
return companion;
}
//player class - additional attributes added to Entity
var Player = function(id){
//assigns the entity attributes to the companion object
var companion = Entity();
companion.id = id;
//assign each player with a different random number
//player numbers are added to sockets
http://math.floor returns that largerst int <= to previous assigned number
companion.number = "" + Math.floor(8 * Math.random());
//following properties will track the keypress states
companion.pressUp = false;
companion.pressDown = false;
companion.pressL = false;
companion.pressR = false;
companion.pressAttack = false;
companion.mouseAngle = 0;
companion.maxSpeed = 8;
companion.hp = 10;
companion.hpMax = 10;
//when player function is called...
//calls companion.update & companion.updateSpeed functions
//overrides update so that speed is updated, followed by x,y axis etc
var big_update = companion.update;
companion.update = function(){
companion.updateSpeed();
big_update();
//attack is created for each player
if(companion.pressAttack){
companion.Attacknow(companion.mouseAngle);
}
}
//attack now function
companion.Attacknow = function(angle){
var b = Attack(companion.id, angle);
//attack is spawned on top of the player x & y are same
b.x = companion.x;
b.y = companion.y;
}
//calls every frame and updates the x and y azis depending on keypress
companion.updateSpeed = function(){
if (companion.pressUp)
companion.speedY = -companion.maxSpeed; //opposite
else if (companion.pressDown)
companion.speedY = companion.maxSpeed;
else
companion.speedY = 0;
if(companion.pressR)
companion.SpeedX = companion.maxSpeed;
else if(companion.pressL)
companion.SpeedX = -companion.maxSpeed; //opposite
else
companion.speedX = 0;
}
//create player object player:unique ID
//add player to initPackage
Player_Li[id] = companion;
initPack.player.push({
id:companion.id,
x:companion.x,
y:companion.y,
//number:companion.number,
});
return companion;
}
Player_Li = {};
//static function - associated with the class, not object itself
//all player related code to go within Player class
Player.onConnect = function(socket){
//create player with socket id
var player = Player(socket.id);
//listens for keypress on the client, sets the
//keypress values to the true/false states on the client
socket.on('keyPress',function(data){
if(data.inputId === 'up')
player.pressUp = data.state;
else if(data.inputId === 'down')
player.pressDown = data.state;
else if(data.inputId === 'L')
player.pressL = data.state;
else if(data.inputId === 'R')
player.pressR = data.state;
else if(data.inputId === 'attack')
player.pressAttack = data.state;
else if(data.inputId === 'mouseAngle')
player.mouseAngle = data.state;
});
}
Player.onDisconnect = function(socket){
delete Player_Li[socket.id];
removePack.player.push(socket.id);
}
//loops through all players in playerLi & calls update function
Player.update = function(){
var pack = [];
//i = key in list - loops through all playes
for(var i in Player_Li){
var player = Player_Li[i];
//increment x & y
player.update();
//data package, including R,L,up,down movements is pushed for each socket &
//sent back to the client where it is then displayed
pack.push({
id:player.id,
x:player.x,
y:player.y,
});
}
return pack;
}
//PlayerHit = function(){
// companion.hp = companion.hp - 1;
// socket.emit('hp');
//}
//to create bullet an entity is created,
var Attack = function(parent, angle){
var companion = Entity();
//create radom id
companion.id = Math.random();
//angles are used to determine x & y pos
companion.speedX = Math.cos(angle/180*Math.PI) * 8;
//collision detection - pokeball/attack cannot touch parent
companion.speedY = Math.sin(angle/180*Math.PI) * 8;
companion.parent = parent;
//entities are never removed, so big_update is called
//timer increments through loop, once reached 110 fps attack is removed
companion.timer = 0;
companion.toRemove = false;
var big_update = companion.update;
companion.update = function(){
if(companion.timer++ > 110)
companion.toRemove = true;
big_update();
//loop through all players in the game
//in order for collision to take place distance must be < 28
//parent of pokeball must not = id of player trying to touch
//i = key in list - loops through all players in playerLi object
for (var i in Player_Li){
var p = Player_Li[i];
//if parent of attack != id of player who attacked
if(companion.getDistance(p) < 28 && companion.parent !== p.id){
companion.toRemove = true;
}
}
}
//attack is added to the list
//add to initPackage, id,x,y params
Attack_Li[companion.id] = companion;
initPack.attack.push({
id:companion.id,
x:companion.x,
y:companion.y,
});
return companion;
}
Attack_Li = {};
//update function - loop through every attack and call update
//create attack with random angle if math.random < 0.07
http://math.random = value 0-1
Attack.update = function(){
//create package to be sent to the client
var pack = [];
for(var i in Attack_Li){
var attack = Attack_Li[i];
attack.update();
//remove from attack list if attack needs to be removed & add to removePackage
if(attack.toRemove){
delete Attack_Li[i];
removePack.attack.push(attack.id);
} else
pack.push({
id:attack.id,
x:attack.x,
y:attack.y,
});
}
return pack;
}
//constant variable -- set to false if server live
var DEBUG = true;
//users object contains credentials of all users
var USERS = {
"wendy":"lilac",
"wendy1":"lilac1",
"wendy2":"lilac2",
}
//callback (cb) parameter (function) called with result required
//if will happen in the future at some point a call back is used
//evaluates an expression after specified number of m/s.
var validCredentials = function (data,cb){
setTimeout(function(){
//user needs to exist - check username & password match USERS object
cb (USERS[data.username] === data.password);
},10);
}
//function checks whether username is available, data returns true if name taken
var usernameAvailable = function(data,cb){
setTimeout(function(){
//returns true if name taken
cb (USERS[data.username]);
},10);
}
var addUser = function(data,cb){
setTimeout(function(){
//username must be = to password in users object
cb (USERS[data.username] = data.password);
cb();
},10);
}
//load and initialize websocket file, returns .io object containing library functions
var io = require('socket.io')(serv,{});
io.sockets.on('connection', function(socket){
socket.id = Math.random();
//add player to sockets
Socket_Li[socket.id] = socket;
//create new listener 'signIn;
socket.on('signIn', function(data){
//data validation
//emit true/false 'signInResponse' package to client
//2nd parameter (result) is a function - added because we do not know when it will be called
//is called when action (button) takes place
validCredentials(data, function(result){
//if result = successful, player is connected & package emitted
if (result){
Player.onConnect(socket);
socket.emit('signInResponse',{success:true});
} else {
socket.emit('signInResponse',{success:false});
}
});
});
//create new listener 'register;
//username taken = not successful emitted to client
//username available = successfull emitted to client - data credentials added to addUser function
socket.on('register', function(data){
//data validation
usernameAvailable(data, function(result){
//if usernmae != available
if (result){
socket.emit('registerResponse', {success:false});
}else {
//if username = available
addUser(data, function(){
socket.emit('registerResponse', {success:true});
});
}
});
});
socket.on('disconnect', function(){
delete Socket_Li[socket.id];
Player.onDisconnect(socket);
});
//server receives package from chat input
socket.on('sendMsgServer', function(data){
var playerName = ("" + socket.id).slice(2,7);
//i = key in list - loops through all sockets in socket_Li object
for (var i in Socket_Li){
//emit 'addToChat' package
Socket_Li[i].emit('addToChat',playerName + ': ' + data);
}
});
//THIS SHOULD NOT BE ACCESSIBLE
//evaluates string within data
//sends result to client
//if debug = !debug nothing happens
socket.on('evalToServer', function(data){
if (!DEBUG)
return;
var res = eval(data);
socket.emit('evalAns', res);
});
});
//contains all initialisation data
//new players are added to init pack
var initPack = {player:[],attack:[]};
//contains all removal data
//removed players are added to remove pack
var removePack = {player:[],attack:[]};
//loop, called every 40/ms through all connected players and send new position to canvas in client file
setInterval(function(){
//package contains player info & sent to all connected players
var pack = {
player:Player.update(),
attack:Attack.update(),
}//i = key in list - loops through all sockets in socketLi object
for(var i in Socket_Li){
var socket = Socket_Li[i];
//packages sent to client every 40 m/s
socket.emit('init',initPack);
socket.emit('update',pack);
socket.emit('remove',removePack);
}
//empty packs every 40 m/s to prevent duplication of entities
initPack.player = [];
initPack.bullet = [];
removePack.player = [];
removePack.bullet = [];
},1000/25);
Anniee1990- Posts : 1
Reputation : 0
Join date : 2016-12-30
Similar topics
» Create a game first / Follow the NODE.JS multiplayer videos first?
» Cant figure out collision error
» Questions with RC's multiplayer series
» Map Creation Tutorial
» Cant figure out collision error
» Questions with RC's multiplayer series
» Map Creation Tutorial
Page 1 of 1
Permissions in this forum:
You cannot reply to topics in this forum
|
|