Permalink
Browse files

Adds player position and orientation networking code.

  • Loading branch information...
Overv committed Dec 29, 2011
1 parent 520f2c9 commit 15574d5a6f15b3b6a0b8e4bda4daac86eac73f3d
Showing with 228 additions and 12 deletions.
  1. +115 −3 js/network.js
  2. +1 −0 js/player.js
  3. +107 −9 js/render.js
  4. +2 −0 js/world.js
  5. BIN media/player.png
  6. +3 −0 multiplayer.html
View
@@ -36,6 +36,9 @@ Client.prototype.connect = function( uri, nickname )
socket.on( "setblock", function( data ) { s.onBlockUpdate( data ); } );
socket.on( "msg", function( data ) { s.onMessage( data ); } );
socket.on( "kick", function( data ) { s.onKick( data ); } );
+ socket.on( "join", function( data ) { s.onPlayerJoin( data ); } );
+ socket.on( "leave", function( data ) { s.onPlayerLeave( data ); } );
+ socket.on( "player", function( data ) { s.onPlayerUpdate( data ); } );
}
// setBlock( x, y, z, mat )
@@ -63,6 +66,23 @@ Client.prototype.sendMessage = function( msg )
} );
}
+// updatePlayer()
+//
+// Sends the current player position and orientation to the server.
+
+Client.prototype.updatePlayer = function()
+{
+ var player = this.world.localPlayer;
+
+ this.socket.emit( "player", {
+ x: player.pos.x,
+ y: player.pos.y,
+ z: player.pos.z,
+ pitch: player.angles[0],
+ yaw: player.angles[1]
+ } );
+}
+
// on( event, callback )
//
// Hooks an event.
@@ -143,6 +163,38 @@ Client.prototype.onKick = function( data )
if ( this.eventHandlers["kick"] ) this.eventHandlers.kick( data.msg );
}
+// onPlayerJoin( data )
+//
+// Called when a new player joins the game.
+
+Client.prototype.onPlayerJoin = function( data )
+{
+ this.world.players[data.nick] = data;
+}
+
+// onPlayerLeave( data )
+//
+// Called when a player has left the game.
+
+Client.prototype.onPlayerLeave = function( data )
+{
+ delete this.world.players[data.nick];
+}
+
+// onPlayerUpdate( data )
+//
+// Called when the server has sent updated player info.
+
+Client.prototype.onPlayerUpdate = function( data )
+{
+ var pl = this.world.players[data.nick];
+ pl.x = data.x;
+ pl.y = data.y;
+ pl.z = data.z;
+ pl.pitch = data.pitch;
+ pl.yaw = data.yaw;
+}
+
// ==========================================
// Server
// ==========================================
@@ -256,6 +308,7 @@ Server.prototype.onConnection = function( socket )
socket.on( "nickname", function( data ) { s.onNickname( socket, data ); } );
socket.on( "setblock", function( data ) { s.onBlockUpdate( socket, data ); } );
socket.on( "chat", function( data ) { s.onChatMessage( socket, data ); } );
+ socket.on( "player", function( data ) { s.onPlayerUpdate( socket, data ); } );
socket.on( "disconnect", function() { s.onDisconnect( socket ); } );
}
@@ -300,8 +353,26 @@ Server.prototype.onNickname = function( socket, data )
socket.emit( "spawn", {
x: world.spawnPoint.x,
y: world.spawnPoint.y,
- z: world.spawnPoint.z
+ z: world.spawnPoint.z,
} );
+
+ // Inform other players
+ socket.broadcast.emit( "join", {
+ nick: data.nickname,
+ x: world.spawnPoint.x,
+ y: world.spawnPoint.y,
+ z: world.spawnPoint.z,
+ pitch: 0,
+ yaw: 0
+ } );
+
+ world.players[data.nickname] = {
+ x: world.spawnPoint.x,
+ y: world.spawnPoint.y,
+ z: world.spawnPoint.z,
+ pitch: 0,
+ yaw: 0
+ };
}
} );
}
@@ -364,6 +435,41 @@ Server.prototype.onChatMessage = function( socket, data )
} );
}
+// onPlayerUpdate( socket, data )
+//
+// Called when a client sends a position/orientation update.
+
+Server.prototype.onPlayerUpdate = function( socket, data )
+{
+ if ( typeof( data.x ) != "number" || typeof( data.y ) != "number" || typeof( data.z ) != "number" ) return false;
+ if ( typeof( data.pitch ) != "number" || typeof( data.yaw ) != "number" ) return false;
+
+ // Check if the user has authenticated themselves before allowing them to send updates
+ var s = this;
+ socket.get( "nickname", function( err, name )
+ {
+ if ( name != null )
+ {
+ var pl = s.world.players[name];
+ pl.x = data.x;
+ pl.y = data.y;
+ pl.z = data.z;
+ pl.pitch = data.pitch;
+ pl.yaw = data.yaw;
+
+ // Forward update to other players
+ socket.volatile.broadcast.emit( "player", {
+ nick: name,
+ x: pl.x,
+ y: pl.y,
+ z: pl.z,
+ pitch: pl.pitch,
+ yaw: pl.yaw
+ } );
+ }
+ } );
+}
+
// onDisconnect( socket, data )
//
// Called when a client has disconnected.
@@ -372,12 +478,18 @@ Server.prototype.onDisconnect = function( socket )
{
if ( this.log ) this.log( "Client " + socket.handshake.address.address + " disconnected." );
- this.activeAddresses[socket.handshake.address.address] = false;
+ delete this.activeAddresses[socket.handshake.address.address];
var s = this;
socket.get( "nickname", function( err, name )
{
- s.activeNicknames[name] = false;
+ delete s.activeNicknames[name];
+ delete s.world.players[name];
+
+ // Inform other players
+ socket.broadcast.emit( "leave", {
+ nick: name
+ } );
if ( s.eventHandlers["leave"] )
s.eventHandlers.leave( name );
View
@@ -25,6 +25,7 @@ function Player()
Player.prototype.setWorld = function( world )
{
this.world = world;
+ this.world.localPlayer = this;
this.pos = world.spawnPoint;
this.velocity = new Vector( 0, 0, 0 );
this.angles = [ 0, Math.PI, 0 ];
View
@@ -9,13 +9,14 @@
var vertexSource =
"uniform mat4 uProjMatrix;"+
"uniform mat4 uViewMatrix;"+
+ "uniform mat4 uModelMatrix;"+
"attribute vec3 aPos;"+
"attribute vec4 aColor;"+
"attribute vec2 aTexCoord;"+
"varying vec4 vColor;"+
"varying vec2 vTexCoord;"+
"void main() {"+
- " gl_Position = uProjMatrix * uViewMatrix * vec4( aPos, 1.0 );"+
+ " gl_Position = uProjMatrix * uViewMatrix * ( uModelMatrix * vec4( aPos, 1.0 ) );"+
" vColor = aColor;"+
" vTexCoord = aTexCoord;"+
"}";
@@ -66,27 +67,44 @@ function Renderer( id )
var projMatrix = this.projMatrix = mat4.create();
var viewMatrix = this.viewMatrix = mat4.create();
+ // Create dummy model matrix
+ var modelMatrix = this.modelMatrix = mat4.create();
+ mat4.identity( modelMatrix );
+ gl.uniformMatrix4fv( this.uModelMat, false, modelMatrix );
+
// Create 1px white texture for pure vertex color operations (e.g. picking)
- var texture = this.texWhite = gl.createTexture();
+ var whiteTexture = this.texWhite = gl.createTexture();
gl.activeTexture( gl.TEXTURE0 );
- gl.bindTexture( gl.TEXTURE_2D, texture );
+ gl.bindTexture( gl.TEXTURE_2D, whiteTexture );
var white = new Uint8Array( [ 255, 255, 255, 255 ] );
gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, white );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
gl.uniform1i( this.uSampler, 0 );
+ // Load player texture
+ var playerTexture = this.texPlayer = gl.createTexture();
+ playerTexture.image = new Image();
+ playerTexture.image.onload = function()
+ {
+ gl.bindTexture( gl.TEXTURE_2D, playerTexture );
+ gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, playerTexture.image );
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
+ gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
+ };
+ playerTexture.image.src = "media/player.png";
+
// Load terrain texture
- var texture = this.texTerrain = gl.createTexture();
- texture.image = new Image();
- texture.image.onload = function()
+ var terrainTexture = this.texTerrain = gl.createTexture();
+ terrainTexture.image = new Image();
+ terrainTexture.image.onload = function()
{
- gl.bindTexture( gl.TEXTURE_2D, texture );
- gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture.image );
+ gl.bindTexture( gl.TEXTURE_2D, terrainTexture );
+ gl.texImage2D( gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, terrainTexture.image );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST );
gl.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST );
};
- texture.image.src = "media/terrain.png";
+ terrainTexture.image.src = "media/terrain.png";
}
// draw()
@@ -114,6 +132,85 @@ Renderer.prototype.draw = function()
}
}
+// drawPlayer( pos )
+//
+// Test function for development of player rendering.
+
+Renderer.prototype.drawPlayer = function( pos )
+{
+ var gl = this.gl;
+
+ // Player head
+ var vertices = [
+ // Top
+ 0, 0, 0.5, 8/64, 0, 1, 1, 1, 1,
+ 0.5, 0, 0.5, 16/64, 0, 1, 1, 1, 1,
+ 0.5, 0.5, 0.5, 16/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0.5, 16/64, 8/32, 1, 1, 1, 1,
+ 0, 0.5, 0.5, 8/64, 8/32, 1, 1, 1, 1,
+ 0, 0, 0.5, 8/64, 0, 1, 1, 1, 1,
+
+ // Bottom
+ 0, 0, 0, 16/64, 0, 1, 1, 1, 1,
+ 0, 0.5, 0, 16/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 24/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 24/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0, 0, 24/64, 0, 1, 1, 1, 1,
+ 0, 0, 0, 16/64, 0, 1, 1, 1, 1,
+
+ // Front
+ 0, 0, 0.5, 8/64, 8/32, 1, 1, 1, 1,
+ 0, 0, 0, 8/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0, 0, 16/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0, 0, 16/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0, 0.5, 16/64, 8/32, 1, 1, 1, 1,
+ 0, 0, 0.5, 8/64, 8/32, 1, 1, 1, 1,
+
+ // Rear
+ 0, 0.5, 0.5, 24/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0.5, 32/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 32/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 32/64, 16/32, 1, 1, 1, 1,
+ 0, 0.5, 0, 24/64, 16/32, 1, 1, 1, 1,
+ 0, 0.5, 0.5, 24/64, 8/32, 1, 1, 1, 1,
+
+ // Left
+ 0, 0, 0.5, 16/64, 8/32, 1, 1, 1, 1,
+ 0, 0.5, 0.5, 24/64, 8/32, 1, 1, 1, 1,
+ 0, 0.5, 0, 24/64, 16/32, 1, 1, 1, 1,
+ 0, 0.5, 0, 24/64, 16/32, 1, 1, 1, 1,
+ 0, 0, 0, 16/64, 16/32, 1, 1, 1, 1,
+ 0, 0, 0.5, 16/64, 8/32, 1, 1, 1, 1,
+
+ // Right
+ 0.5, 0, 0.5, 0, 8/32, 1, 1, 1, 1,
+ 0.5, 0, 0, 0, 16/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 8/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0, 8/64, 16/32, 1, 1, 1, 1,
+ 0.5, 0.5, 0.5, 8/64, 8/32, 1, 1, 1, 1,
+ 0.5, 0, 0.5, 0, 8/32, 1, 1, 1, 1
+ ];
+
+ var buffer = gl.createBuffer();
+ buffer.vertices = vertices.length / 9;
+ gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
+ gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.DYNAMIC_DRAW );
+
+ gl.bindTexture( gl.TEXTURE_2D, this.texPlayer );
+
+ mat4.translate( this.modelMatrix, [ pos.x, pos.y, pos.z ] );
+ gl.uniformMatrix4fv( this.uModelMat, false, this.modelMatrix );
+
+ this.drawBuffer( buffer );
+
+ mat4.identity( this.modelMatrix );
+ gl.uniformMatrix4fv( this.uModelMat, false, this.modelMatrix );
+
+ gl.bindTexture( gl.TEXTURE_2D, this.texTerrain );
+
+ gl.deleteBuffer( buffer );
+}
+
// pickAt( min, max, mx, myy )
//
// Returns the block at mouse position mx and my.
@@ -275,6 +372,7 @@ Renderer.prototype.loadShaders = function()
// Store variable locations
this.uProjMat = gl.getUniformLocation( program, "uProjMatrix" );
this.uViewMat= gl.getUniformLocation( program, "uViewMatrix" );
+ this.uModelMat= gl.getUniformLocation( program, "uModelMatrix" );
this.uSampler = gl.getUniformLocation( program, "uSampler" );
this.aPos = gl.getAttribLocation( program, "aPos" );
this.aColor = gl.getAttribLocation( program, "aColor" );
View
@@ -30,6 +30,8 @@ function World( sx, sy, sz )
this.sx = sx;
this.sy = sy;
this.sz = sz;
+
+ this.players = {};
}
// createFlatWorld()
View
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
@@ -174,6 +174,9 @@
// Update local player
player.update();
+ // Update networked player
+ client.updatePlayer();
+
// Build chunks
render.buildChunks( 5 );

0 comments on commit 15574d5

Please sign in to comment.