Websocket error when following multiplayer node tutorial "Client State"

View previous topic View next topic Go down

Websocket error when following multiplayer node tutorial "Client State"

Post by Anniee1990 on Fri Dec 30, 2016 5:38 pm

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);





Anniee1990

Posts : 1
Reputation : 0
Join date : 2016-12-30

View user profile

Back to top Go down

View previous topic View next topic Back to top

- Similar topics

 
Permissions in this forum:
You cannot reply to topics in this forum