iPhoneでブラウザ上のキャラを動かそう!cocos2dxでwebsocket通信(ソースコードあり)

cocos2dx_icatch
http://jp.cocos.com/

こんにちは。東川です。

WebSocketで通信するため、iPhone端末同士の通信だけではなく
iPhone ⇔ ブラウザ間で通信することもできます。

今回は、ブラウザに表示するオブジェクトを
cocos2dxで作ったコントローラで操作したいと思います。

以下、ソースコードになります。

server: nodejs

var ws = require('../../lib/websocket.io')

var server = ws.listen(80, function() {
    console.log('running..');
});

server.on('connection', function(socket) {
    socket.on('message', function(data) {

        console.log(data);

        server.clients.forEach(function(client) {
            try {
                client.send(data);
            } catch(e) {
                console.log(e);
            }
        });
    });
});

client: cocos2dx

Scene

#include "OperationScene.h"
#include "Arrow.h"

USING_NS_CC;

Scene* OperationScene::createScene()
{
//    auto scene = Scene::create();
    auto layer = OperationScene::create();
    
//    scene->addChild(layer);
    
    return layer;
}

// on "init" you need to initialize your instance
bool OperationScene::init()
{
    // WebScoket init.
    _websocket = new network::WebSocket();
    _websocket->init(*this, "ws://localhost:8082");

    // window size.
    Size winSize = Director::getInstance()->getWinSize();
    
    auto bgLayer = LayerColor::create(Color4B::WHITE, winSize.width, winSize.height);
    
    // ope arrow.
    Arrow* arrowUp = Arrow::create("arrow.png");
    arrowUp->setDirection(Arrow::Direction::Up);
    arrowUp->setScale(2.0f);
    arrowUp->setPosition( (winSize.width - arrowUp->getContentSize().width)/2
                        ,(winSize.height - arrowUp->getContentSize().height)/2 + arrowUp->getContentSize().height*2);
    
    Arrow* arrowDown = Arrow::create("arrow.png");
    arrowDown->setDirection(Arrow::Direction::Down);
    arrowDown->setRotation(180);
    arrowDown->setScale(2.0f);
    arrowDown->setPosition( (winSize.width - arrowDown->getContentSize().width)/2
                        ,(winSize.height - arrowDown->getContentSize().height)/2 - arrowDown->getContentSize().height*2);

    Arrow* arrowLeft = Arrow::create("arrow.png");
    arrowLeft->setDirection(Arrow::Direction::Left);
    arrowLeft->setRotation(-90);
    arrowLeft->setScale(2.0f);
    arrowLeft->setPosition( (winSize.width - arrowLeft->getContentSize().width)/2 - arrowLeft->getContentSize().width*2
                        ,(winSize.height - arrowLeft->getContentSize().height)/2 );
    
    Arrow* arrowRight = Arrow::create("arrow.png");
    arrowRight->setDirection(Arrow::Direction::Right);
    arrowRight->setRotation(90);
    arrowRight->setScale(2.0f);
    arrowRight->setPosition( (winSize.width - arrowRight->getContentSize().width)/2 + arrowRight->getContentSize().width*2
                        ,(winSize.height - arrowRight->getContentSize().height)/2 );
    
    this->addChild(bgLayer);
    this->addChild(arrowUp);
    this->addChild(arrowDown);
    this->addChild(arrowLeft);
    this->addChild(arrowRight);
    
    return true;
}

void OperationScene::onOpen(network::WebSocket* ws)
{
    log("open.");
}

void OperationScene::onMessage(cocos2d::network::WebSocket* ws, const cocos2d::network::WebSocket::Data& data)
{

}
void OperationScene::onClose(cocos2d::network::WebSocket* ws)
{
    
}
void OperationScene::onError(cocos2d::network::WebSocket* ws, const cocos2d::network::WebSocket::ErrorCode& error)
{
    
}

Sprite

//
//  Arrow.cpp
//  HogeProject
//
//  Created by kouki on 2015/03/11.
//
//

#include "Arrow.h"
#include "OperationScene.h"

USING_NS_CC;

Arrow::Arrow()
{

}

bool Arrow::init()
{
    // dispatch touch event.
    auto listener = EventListenerTouchOneByOne::create();
    listener->setSwallowTouches(true);
    listener->onTouchBegan = CC_CALLBACK_2(Arrow::onTouchBegan, this);
    listener->onTouchMoved = CC_CALLBACK_2(Arrow::onTouchMoved, this);
    listener->onTouchEnded = CC_CALLBACK_2(Arrow::onTouchEnded, this);
    this->getEventDispatcher()->addEventListenerWithSceneGraphPriority(listener, this);
    
    // update.
    this->scheduleUpdate();
    
    return true;
}

Arrow* Arrow::create(const std::string &filename)
{
    Arrow* sprite = new (std::nothrow) Arrow();
    if (sprite && sprite->initWithFile(filename))
    {
        sprite->init();
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

void Arrow::update(float delta)
{
    std::string directionType = "";
    
    if(_onmouseFlg) {
        
        switch (_direction) {
            case Up: directionType = "up"; break;
            case Down: directionType = "down"; break;
            case Left: directionType = "left"; break;
            case Right: directionType = "right"; break;
        }
        
        OperationScene* scene = (OperationScene*)Director::getInstance()->getRunningScene();
        scene->getWebSocket()->send("{\"type\" : \""+directionType+"\"}");
    }
}


bool Arrow::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event)
{
    cocos2d::Vec2 p = touch->getLocation();
    cocos2d::Rect rect = this->getBoundingBox();
    
    if(rect.containsPoint(p))
    {
        _onmouseFlg = true;
        return true;
    }
    
    return false;
}

void Arrow::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *event)
{
    
}

void Arrow::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *event)
{
    _onmouseFlg = false;
}

void Arrow::onTouchCancelled(cocos2d::Touch *touch, cocos2d::Event *event)
{
    
}

Arrow::~Arrow()
{

}

WebSocket部分のみ、抜粋。

まず、WebSocketのコネクションを確立させます。

_websocket = new network::WebSocket();
_websocket->init(*this, "ws://localhost:8082");

ソケットに対してデータを送る場合は、以下のようにします。

OperationScene* scene = (OperationScene*)Director::getInstance()->getRunningScene();
scene->getWebSocket()->send("{\"type\" : \""+directionType+"\"}");

client: js

enchant.jsで実装しています。
WebSocketからメッセージを受け取り、
typeに指定された方向へキャラクターを歩かせます。

enchant();

var ws = new WebSocket('ws://localhost:8082/');

ws.onerror = function(e){
  console.log('error.');
}

ws.onopen = function() {
  console.log('open.');
};

ws.onmessage = function(event) {
  var data = JSON.parse(event.data);

  switch(data.type) {
    case 'up'    : moveUp();    break;
    case 'down'  : moveDown();  break;
    case 'left'  : moveLeft();  break;
    case 'right' : moveRight(); break;
  }
};

window.onload = function(){

    var game = new Core(320, 320);

    game.fps = 15;

    game.preload("chara1.png");

    game.onload = function(){

        bear = new Sprite(32, 32);

        bear.image = game.assets["chara1.png"];
        bear.x = 0;
        bear.y = 0;
        bear.frame = 5;

        game.rootScene.addChild(bear);

        window.moveRight = function() {
            bear.x += 1;
            bear.frame = bear.age % 2 + 6;
            bear.scaleX = (bear.scaleX > 0) ? bear.scaleX : bear.scaleX * -1;
        };

        window.moveLeft = function() {
            bear.x -= 1;
            bear.frame = bear.age % 2 + 6;
            bear.scaleX = (bear.scaleX < 0) ? bear.scaleX : bear.scaleX * -1;
        };

        window.moveUp = function() {
            bear.y -= 1;
            bear.frame = bear.age % 2 + 6;
        };

        window.moveDown = function() {
            bear.y += 1;
            bear.frame = bear.age % 2 + 6;
        };

        bear.addEventListener("touchstart", function(){
            game.rootScene.removeChild(bear);
        });
    };

    game.start();
};

実際に動かしてみましょー。

websocket-cocos2dx

お疲れ様でした!

コメントを残す

メールアドレスが公開されることはありません。