Bài viết này sẽ hướng dẫn cách làm thế nào để có thể tạo 1 game mulitiplay với Cocos2d-x thông qua Socket.IO.
- Network trong Cocos2d-x 3.x.x: Socket.IO.
- Network trong Cocos2d-x 3.x.x: WebSockets.
- Network trong Cocos2d-x 3.x.x: HTTPClient.
Bài viết sẽ giới thiệu về 1 ví dụ sử dụng Socket.IO trong Cocos2d-x, cung cấp kiến thức giúp có thể tạo game mulitiplay đơn giản, cũng như hỗ trợ bước đầu làm được 1 game online.
Socket.IO là gì?
Socket.IO là 1 thư viện JavaScript và cũng là 1 loại WebSocket API.
Sự khác biệt rõ ràng nhất giữa Socket.IO và WebSockets:
- Socket.IO cho phép
send
/emit
messages bằng cách xác định bằng 1 tên event. - Trong trường hợp của Socket.IO: 1 message từ Server sẽ đến tất cả các Client đang kết nối. Với WebSockets: Nếu muốn điều tương tự như Socket.IO cần phải tạo 1 mảng của tất cả các kết nối và lặp qua nó để gửi message đến tất cả các client.
Cấu hình
Download và cài đặt Node.js.
Khởi tạo project. Ở đây 1 folder có tên là STDIO_SERVER
.
Để cấu hình và chạy server. Có thể sử dụng command line hoặc GitSCM.
- Vào folder
STDIO_SERVER
và sử dụng command line. - Sử dụng GitSCM: Right mouse click và selected Git Bash Here. Có thể download Git tại http://git-scm.com.
Tiếp theo cài đặt Socket.IO. Có 2 cách để cài đặt:
- Sử dụng file manifest.
- Không sử dụng file manifest (command line/GIT).
Sử dụng file manifest
Sử dụng file manifest package.json (file cấu hình) có nội dung như sau:
{ "name":"stdio_server", "version":"0.0.1", "private":"true", "dependencies":
{ "socket.io":"0.9.16", } }
Ở đây trong phần dependencies khai báo version Socket.IO .
Ngoài ra, nếu sử dụng nhiều modules khác của Socket.IO như express,... có thể khai báo vào trong phần dependencies này.
Sau đó, sử dụng command line/GIT và lệnh sau để cấu hình cho server.
npm install
Không sử dụng file manifest
Ngoài cách sử dụng file manifest package.json. Có thể sử dụng command line hoặc GIT để cài đặt SocketIO với lệnh như sau:
npm install socket.io@0.9.16
Với 0.9.16 chính là version của socket IO. Tương tự như với các modules khác như express.
Kết quả
Sau khi cấu hình xong. Trong folder STDIO_SERVER
sẽ có 1 folder node_modules
.
Hiện thực Server
Sau khi cấu hình xong, tạo 1 file JavaScript tên là STDIO_SERVER.js
để có thể chạy Server của mình trong folder STDIO_SERVER
.
var http = require('http'), socketIO = require('socket.io'), port = 8888, ip = '127.0.0.1', server = http.createServer().listen(port, ip, function(){ console.log('Socket.IO server started at %s:%s!', ip, port); }), io = socketIO.listen(server); var run = function(socket){ console.log('connect....'); socket.emit('hello', 'Hello from Socket.IO'); socket.send('Hello from SocketIO'); socket.on('echotest', function (data) { console.log(data); }) socket.on('message', function(msg){ console.log('Received: ' + msg); }); socket.disconnect('disconnect', function() { console.log('Client disconnect'); }); } io.sockets.on('connection', run);
Phân tích:
Trong Node.js, function requires()
được dùng để import 1 module.
- Dòng 1-11: đoạn code này sẽ:
- Khởi động 1 Server HTTP.
- Khai báo 1 biến server sử dụng
module http
có sẵn trong Node.js. - Lắng nghe ở port 8888 (Chờ đợi một yêu cầu kết nối từ Client).
- Chú ý: lúc này Server vẫn chưa làm gì cả kể có khi có 1 yêu cầu kết nối từ Client.
- Dòng 13: khi 1 Client kết nối với Server thì sẽ function này sẽ được gọi. Lúc này Server đã bắt đầu làm việc. Socket.IO cung cấp 3 event chính là
connect
,message
vàdisconnect
ở cả 2 phía server và client. 1 client kết nối tới Server bằngfunction connect(
). - Dòng 16: gửi dữ liệu tới cho tất cả các Client đang kết nối. Với tên event là
hello
và nội dung làHello from Socket.IO
. - Dòng 17: gửi dữ liệu tới cho tất cả các Client đang kết nối. Với tên event mặc định là
message
và nội dung làHello from STDIO
. - Dòng 19-21: nhận dữ liệu từ Client với tên event là
echotest
và nội dung là biếndata
. - Dòng 23-25: nhận dữ liệu từ Client với tên event là
message
và nội dung là biếnmsg
. Cũng tương tự như ở Server, ở phía Client cũng cófunction send()
nhằm gửi dữ liệu với tên event mặc định làmessage
. - Dòng 27-29: khi Server đóng kết nối với Client.
Run Server
Để chạy Server, dùng sử dụng lệnh sau:
node STDIO_SERVER.js
Client
Khởi tạo dự án. Trong bài viết này, ví dụ sẽ thực hiện trên các file có sẵn sau khi khởi tạo project:
- HelloWordScene.h
- HelloWordScene.cpp
HelloWordScene.h
#ifndef __HELLOWORLD_SCENE_H__ #define __HELLOWORLD_SCENE_H__ #include "cocos2d.h" #include "ui/cocosGUI.h" #include <network/SocketIO.h> using namespace cocos2d::network; using namespace cocos2d::ui; class HelloWorld : public cocos2d::Layer, public SocketIO::SIODelegate { public: static cocos2d::Scene* createScene(); virtual bool init(); // a selector callback void menuCloseCallback(cocos2d::Ref* pSender); // implement the "static create()" method manually // socket.io even\vent listener void onReceiveEvent(SIOClient* client, const std::string& data); // SIODelegate virtual void onConnect(SIOClient* client); virtual void onMessage(SIOClient* client, const std::string& data); virtual void onClose(SIOClient* client); virtual void onError(SIOClient* client, const std::string& data); CREATE_FUNC(HelloWorld); protected: private: int index; SIOClient* _client; TextField* editBox; }; #endif // __HELLOWORLD_SCENE_H__
Phân tích:
- Dòng 7: thêm thư viện để có thể làm việc với Socket.IO.
- Dòng 12: khởi tạo class
HelloWord
có kế thừa public vớiSocketIO::SIODelegate
- Dòng 25-30: các phương thức làm việc với Server.
- Dòng 37: khai báo 1
SocketClient
. Dùng biến này đểconnect
, gửidata
và nhậndata
với Server.
HelloWorldScene.cpp
#include "HelloWorldScene.h" USING_NS_CC; Scene* HelloWorld::createScene() { // 'scene' is an autorelease object auto scene = Scene::create(); // 'layer' is an autorelease object auto layer = HelloWorld::create(); // add layer as a child to scene scene->addChild(layer); // return the scene return scene; } // on "init" you need to initialize your instance bool HelloWorld::init() { ////////////////////////////// // 1. super init first if ( !Layer::init() ) { return false; } Size visibleSize = Director::getInstance()->getVisibleSize(); Vec2 origin = Director::getInstance()->getVisibleOrigin(); // connect to server _client = SocketIO::connect("http://127.0.0.1:8888", *this); _client->on("message", CC_CALLBACK_2(HelloWorld::onReceiveEvent, this)); _client->emit("message", "het hon chua"); return true; } void HelloWorld::onConnect(SIOClient* client) { // SocketIO::connect success } void HelloWorld::onMessage(SIOClient* client, const std::string& data) { // SocketIO::send receive } void HelloWorld::onClose(SIOClient* client) { // SocketIO::disconnect success } void HelloWorld::onError(SIOClient* client, const std::string& data) { // SocketIO::failed } void HelloWorld::onReceiveEvent(SIOClient* client, const std::string& data) { auto lbl = Label::createWithTTF(data, "fonts/Marker Felt.ttf", 24); lbl->setPosition(Vec2(100, 100)); this->addChild(lbl); };
Phân tích:
- Dòng 34: thiết lập tới địa chỉ "
http://127.0.0.1:8888
". Gửi thông điệp tới Server 1 connect. - Dòng 35: thiết lập nhận dữ liệu từ Server. Khi Server gửi dữ liệu tới Client. Lúc này Client sẽ thực thi phương thức
HelloWord::onReceiveEvent();
- Dòng 36: để gửi 1 tin nhắn tới Server. Cũng như Server sử dụng
function emit(eventName, args)
.
Build/Run
Sau khi chạy server cũng như client (project game) có kết quả sau:
Demo
Bài viết đã hoàn thành việc giới thiệu cách tạo 1 Server đơn giản cũng như các function cơ bản về thao tác cơ bản giữa Client (Cocos2d-x) với Server.
Từ đây, có thể sử dụng Socket.IO trong các project game mulitiplayer.
Có thể download toàn bộ mã nguồn trong bài viết này ở phía dưới đây: