Game Client Source code overview
The client in this game is developed using cocos2d-x framework using its JavaScript API,
This means by using this framework we are enabling our game to be cross platform .
With the same code base ! including the WebSocket part
The game client game logic will be explained using the web version of Cocos2d-x.
And in the end i will show you how to compile the source code in iOS and Windows Desktop
To develop in JavaScript and HTML5 you can choose several tools.
To develop in JavaScript and HTML5 you can choose several tools.
You can use simple text editor like Vi , Notepad++ , and debug the code With
build-in Chrome Debugger . Or you can take the full IDE Approach as i shown in this Tutorial :Debug Cocos2d-x HTML5 Project using NetBeans IDE and Chrome browser in 10 easy steps.
build-in Chrome Debugger . Or you can take the full IDE Approach as i shown in this Tutorial :Debug Cocos2d-x HTML5 Project using NetBeans IDE and Chrome browser in 10 easy steps.
The game flow is very simple:
- Player enter its User name.
- Client Send the user name to the server
- Server confirms the user name and send back to the client
- Server Updates other client about new user
- Client receives the confirmation from the server
- Client enter to the Game room.
- Client plays , send the play move to server for confirmation
- Server get the play move Confirms the move
- Server send back confirmation to client and updates other clients about the player move
and on and one until the game end
Go to the source code you previously cloned from :
https://github.com/meiry/multiplayer_cocos2dx-js_using_netty_websockets
Go to the /Client/WarCardJS directory this is where all the client side source code are in.
To run it im using simple Apache server installed locally .
then start it by going to where the index.html is. like normal static web site .
Before we start we need to configure few things in our Cocos2d-x framework
In the project.json file we adding the additional files and modules that is part of this Game
in our case we added the JS files which we are going to be using in our game
and additional Cocos2d-x module.
project.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | { "project_type": "javascript", "debugMode" : 1, "showFPS" : true, "frameRate" : 60, "noCache" : false, "id" : "gameCanvas", "renderMode" : 0, "engineDir":"frameworks/cocos2d-html5", "modules" : ["cocos2d","extensions"], "jsList" : [ "src/GameConfig.js", "src/GameScene.js", "src/resource.js", "src/app.js", "src/Player.js" ] } |
- Line 12 : New module is added called "extensions" for advance GUI
- Line 15 - 19 : The new js source files the game is using .
main.js
This file is the game bootstrap , that mean here the game starts , the first game scene Initialize
here .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | cc.game.onStart = function(){ if(!cc.sys.isNative && document.getElementById("cocosLoading")) //If referenced loading.js, please remove it document.body.removeChild(document.getElementById("cocosLoading")); // Pass true to enable retina display, on Android disabled by default to improve performance cc.view.enableRetina(cc.sys.os === cc.sys.OS_IOS ? true : false); // Adjust viewport meta cc.view.adjustViewPort(true); // Setup the resolution policy and design resolution size cc.view.setDesignResolutionSize(450, 800, cc.ResolutionPolicy.SHOW_ALL); // Instead of set design resolution, you can also set the real pixel resolution size // Uncomment the following line and delete the previous line. // cc.view.setRealPixelResolution(960, 640, cc.ResolutionPolicy.SHOW_ALL); // The game will be resized when browser size change cc.view.resizeWithBrowserSize(true); //load resources cc.LoaderScene.preload(g_resources, function () { cc.director.runScene(new LoginScene()); }, this); }; |
- Line 10 : set the window resolution
- Line 18 : The name of our first game scene called LoginScene ,
the screen of the LoginScene will be shown first
app.js
This file is holding the main Scene called LoginScene that Initialize LOGIN Screen that lives inside the LoginLayer Object
This is the first file that starting the game .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | var TEXT_INPUT_FONT_NAME = "Thonburi"; var TEXT_INPUT_FONT_SIZE = 36; var sceneIdx = -1; var TEXT_FIELD_ERR = 1; var LoginLayer = cc.Layer.extend({ sprite:null, size:null, textFieldUserName:null, textErorrConnectedField:null, enterWorldScene:null, textField:null, ctor:function () { ////////////////////////////// // 1. super init first this._super(); this.size = cc.winSize; return true; }, onEnter:function () { //----start2----onEnter this._super(); var winSize = cc.director.getWinSize(); // Create the textfield this.textField = new ccui.TextField(); this.textField.setMaxLengthEnabled(true); this.textField.setMaxLength(30); this.textField.setTouchEnabled(true); this.textField.fontName = TEXT_INPUT_FONT_NAME; this.textField.fontSize = 30; this.textField.placeHolder = "[click here for user name]"; this.textField.x = winSize.width / 2.0; this.textField.y = winSize.height / 2.0; this.textField.addEventListener(this.textFieldEvent, this); this.addChild(this.textField); cc.MenuItemFont.setFontSize(35); var menu = new cc.Menu( new cc.MenuItemFont("Login Game", this.loginGame, this) ); menu.alignItemsVerticallyWithPadding(4); menu.x = this.size.width / 2; menu.y = this.size.height / 2 - 50; this.addChild(menu,5); }, onExit:function () { this._super(); }, createErrorMsg:function () { this.textErorrConnectedField = new cc.TextFieldTTF("Error Connecting Server try again", TEXT_INPUT_FONT_NAME, TEXT_INPUT_FONT_SIZE+20); this.textErorrConnectedField.setTag(TEXT_FIELD_ERR); this.textErorrConnectedField.x = cc.winSize.width / 2; this.textErorrConnectedField.y = cc.winSize.height / 2 +50; this.addChild(this.textErorrConnectedField,2); }, loginGame:function (sender) { //remove error msg if any if(this.getChildByTag(TEXT_FIELD_ERR)!==null) { this.removeChildByTag(TEXT_FIELD_ERR); } //check login in the server var txtUserName = this.textField.getString(); var config = { event:Events.LOGIN, username:txtUserName }; var message = Encode(config); try { ws = new WebSocket("ws://localhost:8888/ws"); ws.onopen = function() { ws.send(message); }; ws.onmessage = function (e) { console.log("app->srv.ws.onmessage():"+e.data); if(e.data!==null || e.data !== 'undefined') { var jsonFromClient = Decode(e.data); if(jsonFromClient.event === Events.LOGIN_DONE) { enterWorldScene = new EnterWorldScene(jsonFromClient); cc.director.runScene(enterWorldScene); } } }; ws.onclose = function (e) { }; ws.onerror = function (e) { }; } catch (e) { console.error('Sorry, the web socket at "%s" is un-available', url); } }, onClickTrackNode:function (clicked) { var textField = this._trackNode; if (clicked) { textField.attachWithIME(); } else { textField.detachWithIME(); } }, }); var LoginScene = cc.Scene.extend({ onEnter:function () { this._super(); var layer = new LoginLayer(); this.addChild(layer); } }); |
- Lines 19 - 42 : Setup the Textbox and the login button
- Line 37 : add listener to when the player is clicking the login button the loginGame function will be triggered.
- Lines 57 - 97 : The loginGame function ,
- Line 72 This function will open the WebSocket connection With the server .
and wait for handshake confirmation from the server - Lines 76 -87 : the ws.onmessage callback is part of the browser WebSocket API
and it is triggered when there is massage from the server. - Lines 80 - 85 : when the massage is coming from the server first thing is the client do
Is decode the JSON massage , check if the event we receive are the right one in our case
LOGIN_DONE ( as part of our protocol ) .
If we got LOGIN_DONE it means the players was confirmed and we are ready to start the game and invoke the game scene called :"EnterWorldScene" which holds the game logic.
Multiplayer Card Game using WebSockets,Java Netty Server ,Cocos2d-x-HTML5 - Part 7
This comment has been removed by the author.
ReplyDeleteThank you for your article!
ReplyDeleteBut link to seventh part of does not open and please add a link to github.
Sure !
ReplyDeletehttps://github.com/meiry/multiplayer_cocos2dx-js_using_netty_websockets
fixed the links and added the github link in the header
ReplyDeleteI'm doing a server for the game on the Unreal Engine, learning Netty by examples. I think you will be interested in this book ;)
ReplyDeleteMultiplayer Game Programming: Architecting Networked Games (2015)
https://kat.cr/multiplayer-game-programming-architecting-networked-games-2015-by-josh-glazer-sanjay-madhav-dr-soc-t12040097.html
Vadim it looks great !
ReplyDeleteI will take alook
Thanks allot , im thinking about doing full game server tutorial soon
ReplyDeleteusing cluster servers , sticky session , and proxy server .
Using Java as server and C++/HTML5 as client
Hi. I am new to java and i have an idea of a card game that is played in my country. I am learning java to code that particular game. Your tutorial has given me a headway. Thank you so so much.
ReplyDelete