diff --git a/client/index.html b/client/index.html index 10672d3..7a7bf8f 100644 --- a/client/index.html +++ b/client/index.html @@ -23,6 +23,7 @@ + diff --git a/client/lib/core/page_base.js b/client/lib/core/page_base.js index d1953d2..db414c6 100644 --- a/client/lib/core/page_base.js +++ b/client/lib/core/page_base.js @@ -31,6 +31,16 @@ NPGClient.AppPage.prototype = { return self.uiElems; }, + // + hasUIElem: function(name) { + var self = this; + if (self.uiElems.length > 0) { + for (var i = 0; i < self.uiElems.length; i++) + if (self.uiElems[i].name == name) return true; + } + return false; + }, + // getUIElemByName: function(name) { diff --git a/client/lib/core/page_handler.js b/client/lib/core/page_handler.js index ecafe2e..0cb35df 100644 --- a/client/lib/core/page_handler.js +++ b/client/lib/core/page_handler.js @@ -57,6 +57,21 @@ NPGClient.PageHandler = { return undefined; }, + // + getUIElem: function(name) { + var self = this; + var elem = []; + if (self.pages.length > 0) { + for (var i = 0; i < self.pages.length; i++) { + elem = self.pages[i].getUIElems(); + for (e in elem) { + if (elem[e].name == name) return elem[e]; + } + } + } + return undefined; + }, + // @need rework getUIElemFromPage: function(elem, page) { var self = this; @@ -82,6 +97,18 @@ NPGClient.PageHandler = { return undefined; }, + // + updateServerInfos: function() { + var self = this; + // server infos + self.getUIElem('servinfo_users').update(NPGClient.SERVER.nPlayers); + self.getUIElem('servinfo_games_running').update(NPGClient.SERVER.nGamesRunning); + self.getUIElem('servinfo_games_avail').update(NPGClient.SERVER.nGamesAvail); + + }, + + + // create login page createLoginPage: function() { // @@ -89,7 +116,8 @@ NPGClient.PageHandler = { var self = this; var p = new NPGClient.AppPage(NPGClient.LOGIN.NAME); // Title label - p.addUIObject(new NPGClient.UILabel('login_title', NPGClient.LOGIN.TITLE)); + //p.addUIObject(new NPGClient.UILabel('login_title', NPGClient.LOGIN.TITLE)); + p.addUIObject(new NPGClient.UILabel(NPGClient.LOGIN.TITLE)); // name input p.addUIObject(new NPGClient.UIInputText('login_input', NPGClient.LOGIN.INPUT)); // Server status @@ -108,11 +136,14 @@ NPGClient.PageHandler = { var self = this; var p = new NPGClient.AppPage(NPGClient.STARTMENU.NAME); // Title label - p.addUIObject(new NPGClient.UILabel('login_title', NPGClient.STARTMENU.TITLE)); + //p.addUIObject(new NPGClient.UILabel('startmenu_title', NPGClient.STARTMENU.TITLE)); + p.addUIObject(new NPGClient.UILabel(NPGClient.STARTMENU.TITLE)); // Start Menu p.addUIObject(new NPGClient.UIMenu(NPGClient.STARTMENU.MENU)); - // Server Players and Games status - + // Server Players and Games info + p.addUIObject(new NPGClient.UIStatusValue(NPGClient.STARTMENU.SERVINFO_USERS)); + p.addUIObject(new NPGClient.UIStatusValue(NPGClient.STARTMENU.SERVINFO_GAMES_RUNNING)); + p.addUIObject(new NPGClient.UIStatusValue(NPGClient.STARTMENU.SERVINFO_GAMES_AVAIL)); // self.pages.push(p); }, diff --git a/client/lib/keyboard/event_handler.js b/client/lib/keyboard/event_handler.js index 54daf6b..85ef7e4 100644 --- a/client/lib/keyboard/event_handler.js +++ b/client/lib/keyboard/event_handler.js @@ -78,6 +78,7 @@ NPGClient.evtHandler = { if (!NPGClient.Utils.nameEmpty()) { NPGClient.Utils.removeChar(); NPGClient.PageHandler.getCurrPageUIElemByName('login_cursor').translateX(-15); + NPGClient.PageHandler.getCurrPageUIElemByName('login_cursor').resetBlink(); } break; default: @@ -86,6 +87,7 @@ NPGClient.evtHandler = { NPGClient.Utils.addChar(evt.keyCode); newNameW = NPGClient.ui.ctx.measureText(NPGClient.userName).width; NPGClient.PageHandler.getCurrPageUIElemByName('login_cursor').translateX(15); + NPGClient.PageHandler.getCurrPageUIElemByName('login_cursor').resetBlink(); } break; } diff --git a/client/lib/npg_client.js b/client/lib/npg_client.js index 3641e2b..9ed26a8 100644 --- a/client/lib/npg_client.js +++ b/client/lib/npg_client.js @@ -5,11 +5,31 @@ var NPGClient = { 'version': '' }; + +// LOGIN NAME NPGClient.NAMEMAXSIZE = 8; NPGClient.userName = ''; -// ui +// SERVER INFOS +NPGClient.SERVER = { + isUp: false, + nPlayers : 0, + nGamesRunning : 0, + nGamesAvail : 0, + gamesList : [], + updateInfos: function(data) { + var self = this; + self.nPlayers = data.infos.nUsers; + self.nGamesRunning = data.infos.nGamesRunning; + self.nGamesAvail = data.infos.nGamesAvail; + self.gamesList = []; + for (g in data.games) self.gamesList(data.games[g]); + }, +}; + + +// UI NPGClient.CAN_W = 800; NPGClient.CAN_H = 500; NPGClient.CAN_COL = '#000000'; @@ -51,6 +71,7 @@ NPGClient.LOGIN = { }, }, TITLE: { + 'name': 'login_title', 'text': 'nodePong', 'x': 400, 'y': 150, @@ -93,6 +114,7 @@ NPGClient.LOGIN = { NPGClient.STARTMENU = { NAME: 'start_menu', TITLE: { + 'name': 'start_menu_title', 'text': 'nodePong', 'x': 400, 'y': 150, @@ -132,19 +154,39 @@ NPGClient.STARTMENU = { } } }, - SERVSTATUS: { - 'text': { - 'online' : 'server: online', - 'offline' : 'server: offline', - }, - 'x': 380, - 'y': 250, + SERVINFO_USERS: { + 'name': 'servinfo_users', + 'label': 'Users online:', + 'x': 70, + 'y': 470, 'style': { - 'font': '15px Arial', + 'font': '15px Monospace', + 'col': '#FFFFFF', + 'align': 'left' + }, + }, + SERVINFO_GAMES_RUNNING: { + 'name': 'servinfo_games_running', + 'label': 'Games running:', + 'x': 400, + 'y': 470, + 'style': { + 'font': '15px Monospace', 'col': '#FFFFFF', 'align': 'center' }, }, + SERVINFO_GAMES_AVAIL: { + 'name': 'servinfo_games_avail', + 'label': 'Games available:', + 'x': 730, + 'y': 470, + 'style': { + 'font': '15px Monospace', + 'col': '#FFFFFF', + 'align': 'right' + }, + }, }; diff --git a/client/lib/socket/socketio_handler.js b/client/lib/socket/socketio_handler.js index 74a08a9..d4d4af2 100644 --- a/client/lib/socket/socketio_handler.js +++ b/client/lib/socket/socketio_handler.js @@ -81,11 +81,17 @@ NPGClient.SocketIO = { self.isConnected = false; }); + // 'serverInfosUpdate' + self.socket.on('serverInfosUpdate', function(data) { + NPGClient.Utils.log(' > Server infos update. ' + data); + NPGClient.SERVER.updateInfos(data); + NPGClient.PageHandler.updateServerInfos(); + }); + // 'regDone' self.socket.on('regDone', function() { NPGClient.Utils.log(' > Server: User registration done'); - //NPGClient.PageHandler.moveToPage(NPGClient.STARTMENU.NAME); - NPGClient.PageHandler.setCurrPage(NPGClient.STARTMENU.NAME); + NPGClient.PageHandler.setCurrPage(NPGClient.STARTMENU.NAME); }); // 'regNameTaken' diff --git a/client/lib/ui/objects/ui_cursor.js b/client/lib/ui/objects/ui_cursor.js index 035c15e..775669e 100644 --- a/client/lib/ui/objects/ui_cursor.js +++ b/client/lib/ui/objects/ui_cursor.js @@ -34,8 +34,18 @@ NPGClient.UICursor.prototype.constructor = NPGClient.UICursor; NPGClient.UICursor.prototype.reset = function() { var self = this; self.moveTo(self.x0, self.y0); + self.bState = true; + self.bCount = 0; } +// resetBlink +NPGClient.UICursor.prototype.resetBlink = function() { + var self = this; + self.bState = true; + self.bCount = 0; +} + + // draw NPGClient.UICursor.prototype.draw = function(ctx) { var self = this; diff --git a/client/lib/ui/objects/ui_label.js b/client/lib/ui/objects/ui_label.js index cdc2af9..a88f2e1 100644 --- a/client/lib/ui/objects/ui_label.js +++ b/client/lib/ui/objects/ui_label.js @@ -3,35 +3,39 @@ * @author frtk@tetalab */ -NPGClient.UILabel = function(n, o) { - +NPGClient.UILabel = function(o) { + // + NPGClient.UIObject.call(this, o); // obj name - this.name = n !== undefined ? n : ''; - // bkg rect - //this.bkg = r !== undefined ? r : new NPGClient.UIRect(); + this.name = o.name !== undefined ? o.name : ''; // pos this.x = o.x !== undefined ? o.x : 0; this.y = o.y !== undefined ? o.y : 0; - // text this.text = o.text !== undefined ? o.text : ''; // text style - this.s = o.style !== undefined ? o.style : new NPGClient.UITextStyle(); + this.s = o.style !== undefined ? o.style : ''; }; -NPGClient.UILabel.prototype = { +/** + * Inheritance + */ +NPGClient.UILabel.prototype = Object.create(NPGClient.UIObject.prototype); - // Constructor - constructor: NPGClient.UILabel, - - // - draw: function(ctx) { - var self = this; - NPGClient.Utils.setTxtStyle(ctx, self.s); - ctx.fillText(self.text, self.x, self.y); - } + +/** + * Functions + */ +// +NPGClient.UILabel.prototype.constructor = NPGClient.UILabel; + +// +NPGClient.UILabel.prototype.draw = function(ctx) { + var self = this; + NPGClient.Utils.setTxtStyle(ctx, self.s); + ctx.fillText(self.text, self.x, self.y); }; diff --git a/client/lib/ui/objects/ui_menu.js b/client/lib/ui/objects/ui_menu.js index 454c577..5ba382c 100644 --- a/client/lib/ui/objects/ui_menu.js +++ b/client/lib/ui/objects/ui_menu.js @@ -56,6 +56,7 @@ NPGClient.UIMenu.prototype.selectPrevItem = function(t) { } if (self.hasCursor) { self.cursor.translateY(cShift); + self.cursor.resetBlink(); } } }; @@ -76,6 +77,7 @@ NPGClient.UIMenu.prototype.selectNextItem = function(t) { } if (self.hasCursor) { self.cursor.translateY(cShift); + self.cursor.resetBlink(); } } }; diff --git a/client/lib/ui/objects/ui_status_value.js b/client/lib/ui/objects/ui_status_value.js new file mode 100644 index 0000000..2345406 --- /dev/null +++ b/client/lib/ui/objects/ui_status_value.js @@ -0,0 +1,52 @@ +/** + * @file ui_status_value.js + * @author frtk@tetalab + */ + +NPGClient.UIStatusValue = function(o) { + // + NPGClient.UIObject.call(this, o); + // obj name + this.name = o.name !== undefined ? o.name : ''; + // pos + this.x = o.x !== undefined ? o.x : 0; + this.y = o.y !== undefined ? o.y : 0; + // + this.s = o.style !== undefined ? o.style : ''; + // label + this.label = o.label !== undefined ? o.label : ''; + // widget var value + this.value = 0; + +}; + + +/** + * Inheritance + */ +NPGClient.UIStatusValue.prototype = Object.create(NPGClient.UIObject.prototype); + + +/** + * Functions + */ +// +NPGClient.UIStatusValue.prototype.constructor = NPGClient.UIStatusValue; + +// +NPGClient.UIStatusValue.prototype.update = function(v) { + var self = this; + self.value = v; +}; + +// +NPGClient.UIStatusValue.prototype.draw = function(ctx) { + var self = this; + NPGClient.Utils.setTxtStyle(ctx, self.s); + // + var txt = self.label + ' ' + self.value; + // + ctx.fillText(txt, self.x, self.y); + +}; + diff --git a/package.json b/package.json index 6a2516e..c846fbf 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "npg_app.js", - "version": "0.2.1", + "version": "0.2.2", "description": "Multiplayer online Pong Game using nodejs and socket.io", "directories": { "server": "server", diff --git a/server/npg_server.js b/server/npg_server.js index ffb4614..908ef22 100644 --- a/server/npg_server.js +++ b/server/npg_server.js @@ -123,13 +123,10 @@ var NPGServer = { self.log('Server: User name already taken - reseting client UI'); } else { self.createUser(data, socket); + self.updateAllClientsServerInfos(); + // + self.sendMsgToSocket(socket, 'regDone'); } -/* - self.updateClientsServerInfo(); // update all clients info - io.sockets.sockets[socketId].emit('playerCreated'); // send socket msg - }, -*/ - }, // @@ -139,6 +136,8 @@ var NPGServer = { if (self.isUser(id)) { self.log('[Client:' + id + '] User ' + u.name + ' disconnected'); self.deleteUser(u.name); + // + self.updateAllClientsServerInfos(); } }, @@ -207,13 +206,6 @@ var NPGServer = { self.users.push(new User(name, socket)); self.log('Server: number of players: n= ' + self.users.length); self.log('Server: player registered, send user ' + name + ' to menu page.'); - // send user auth - self.sendMsgToSocket(socket, 'regDone'); - }, - - removeDuplicateUser: function(name) { - var self = this; - self.log('Server: player already registered, removing duplicate.'); }, // @@ -229,6 +221,76 @@ var NPGServer = { } }, + + + /** + * + * Server Infos (players and games) + * + */ + //--- + updateAllClientsServerInfos: function(socket) { + var self = this; + for (u in self.users) { + self.users[u].sendMsg('serverInfosUpdate', { infos: self.getServerInfos(), games: self.getGamesList() }); + } + self.log('Server: updated server infos for all clients'); + }, + + //--- + updateClientServerInfos: function(socket) { + var self = this; + socket.emit('serverInfosUpdate', { infos: self.getServerInfos(), games: self.getGamesList() }); + self.log('Server: update client server info'); + }, + + //--- + getServerInfos: function() { + var self = this; + return { + nUsers: self.nPlayers(), + nGamesRunning: self.nGamesRunning(), + nGamesAvail: self.nGamesAvail() + } + }, + + //--- + getGamesList: function() { + var self = this; + var res = []; + for (g in self.games) { + res.push(self.games[g].getHostName()); + } + return res; + }, + + //--- + nPlayers: function() { + var self = this; + return self.users.length; + }, + + //--- + nGamesRunning: function() { + var self = this; + var n = 0; + for (g in self.games) { + if (self.games[g].status == 'running') n++; + } + return n; + }, + + //--- + nGamesAvail: function() { + var self = this; + var n = 0; + for (g in self.games) { + if (self.games[g].status == 'available') n++; + } + return n; + }, + + }; @@ -240,13 +302,11 @@ var NPGServer = { * */ var User = function(name, socket) { - // this.name = (name !== undefined) ? name : ''; this.socket = (socket !== undefined) ? socket : ''; // this.status = ''; - }; // User.prototype.constructor = User; diff --git a/version.md b/version.md index e73159a..7d3eeef 100644 --- a/version.md +++ b/version.md @@ -1,4 +1,26 @@ + +# **v0.2.2:** +## focus: Start Menu Page +-------------------------- +### client objects update +- UICursor: added resetBlink() function to reset blink on menu item change (to avoid "shadow" cursor) +- UIMenu: added cursor resetBlink() in select next/previous item function +- UILabel: added UIObject inheritance and changed param initialization + +### client objects creation +- UIStatusValue: ui element to display server infos (number of users, games running and games available) + +### client start menu page +- added 3 UIStatusValue elements +- all 3 elements are updated within the page_handler + +### server +- added server infos update for all clients when a user register or disconnect + + + + # **v0.2.1:** ## focus: Start Menu Page --------------------------