cocos2d-xと ネイティブ間の連携 株式会社TKS2 清水友晶
May 10, 2015
cocos2d-xと ネイティブ間の連携
株式会社TKS2 清水友晶
清水 友晶 � 株式会社TKS2 スマートフォンアプリ開発 (iOS, Android, Windows Phone 8) Webコンテンツ開発
� cocos2d-xへの開発参加 cocos2d-xを利用したアプリ開発 講演活動 執筆活動
� Twitter: tks2shimizu � Blog: http://tks2.net/memo
� SlideShare: http://www.slideshare.net/doraemonsss
� Facebook: http://www.facebook.com/doraemonsss
� http://cocos2d-x.jp
� cocos2d-x開発元Chukong Technologies社公認
� cocos2d-xのための自由なコミュニティー
� 入門者から上級者まで誰でもOK!!ぜひご参加を!
� cocos2d-xに関することなら何でも投稿できます!!
� https://www.facebook.com/groups/152840204871454/
� 現在のshinjuku.cocos2d-xハンズオンの問題点 � Macユーザのみを対象としている。 � 徐々にレベルが上がってきているため初心者ついてこれない。
� 将来のshinjuku.cocos2d-xハンズオン � Windowsユーザ, Macユーザを区別しない � レベルはこのまま
� shinjuku.cocos2d-x初心者ハンズオン
� 3/14 第6回 shinjuku.cocos2d-x
� 3/21 shinjuku.cocos2d-x初心者ハンズオン ~MacでAndroidアプリを作ろう!~
� 3/22 cocos2d-x公開講座 in 鹿児島
� 3/23 cocos2d-x実践講座 in 鹿児島
� 4/10 shinjuku.cocos2d-x初心者ハンズオン ~WindowsでAndroidアプリを作ろう!~
� 4/17 第7回 shinjuku.cocos2d-x
� 5/M 第8回 shinjuku.cocos2d-x
� 5/M shinjuku.cocos2d-x初心者ハンズオン ~MacでiOSアプリを作ろう!~
目次 � cocos2d-xとネイティブ間の連携の概要
� C++からObjective-Cへのアクセス � C++からJavaへのアクセス
� Objective-CからC++へのアクセス
� JavaからC++へのアクセス
� ネイティブ間連携を試してみよう! � デバイス名を取得する
cocos2d-xとネイティブ間の連携の概要 � 各OSの機能を利用するには必要となる
� 言語設定・国コード・識別コード(ユーザ, 端末) � ブラウザ・カメラ・マイク・アプリ内課金
� 連携は各OS毎に実装が必要 � cocos2d-x(C++) çè Android(Java) � cocos2d-x(C++) çè iOS(Objective-C) :
� 公式フォーラムで連携方法を聞くと、決まって「CocosDenshionを見てね」と言われる
iOS Android
CocosDenshionの連携方法
SimpleAudioEngine.h
SimpleAudioEngine.cpp
SimpleAudioEngineJni.h
SimpleAudioEngineJni.cpp
SimpleAudioEngine.mm
SimpleAudioEngine_objc.h
SimpleAudioEngine_objc.m
Cocos2dx Music.java
Cocos2dx Sound.java
CDAudioManager.h
CDAudioManager.m Cocos2dxHelper.java
C++からネイティブへのアクセス � 共通のクラスにより各OSの差異を吸収する
� 実装はOS毎で用意する
� CCApplication::getCurrentLanguage()を参照
iOS Android
CCApplication.cpp
Java_org_cocos2dx_lib_Cocos2dxHelper.h
Java_org_cocos2dx_lib_Cocos2dxHelper.cpp
CCApplication.mm
CCApplication.h CCApplication.h
Cocos2dxHelper.java
C++からObjective-Cへのアクセス � .mm形式であればC++とObjective-Cを混在させることができるため比較的容易
� C++の実装部に、Objective-CによりiOSの機能を記述することが可能
C++からJavaへのアクセス � JNI(Java Native Interface)を利用する
� JNIとは、Javaプラットフォームにおいて、Javaで記述されたプログラムと、他の言語(たとえばCやC++など)で書かれた、実際のCPUの上で動作するコード(ネイティブコード)とを連携するためのインタフェース仕様 http://ja.wikipedia.org/wiki/Java_Native_Interface
� JNIを利用するクラスを用意する
� Javaで書かれたクラス上にAndroid SDKを用いAndroidの機能を利用する
iOS Android
ネイティブからC++へのアクセス
CCTouchDispatcher.h
CCTouchDispatcher.cpp
EAGLView.h
EAGLView.mm TouchesJni.cpp
Cocos2dxRenderer.java
CCLayer.h
CCLayer.cpp
CCEGLView.h
CCEGLView.cpp
CCEGLView.h
CCEGLView.cpp
� ccTouches~関数を参照
CCEGLViewProtocol.h
CCEGLViewProtocol.cpp
CCTouchDelegate.h
CCTouchDelegate.cpp
ネイティブからC++へのアクセス � あらかじめDelegateクラスに呼び出される関数をセットしておき、ネイティブから要求があるときにこの関数を呼び出す
� 各OSの差異を吸収するため次のクラスが用意されている � CCTouchesHandlerクラス � CCTouchDelegateクラス � CCTouchDispatcherクラス
Objective-CからC++へのアクセス � .mm形式であればC++とObjective-Cを混在させることができるため比較的容易
� タッチイベントを受けるために次のクラスを用意 � CCEGLViewProtocolクラス � EGLTouchDelegateクラス
JavaからC++へのアクセス � JNIを利用する
� タッチイベントを受けるために次のクラスを用意 � Cocos2dxRendererクラス
� JavaからJNIで定義された関数を呼び出すには、Javaのクラスにおいて同じ関数名のメソッドをnativeで宣言する必要がある
� JNIからCCDispatcherクラスを呼び出す
ネイティブ間連携を 試してみよう! デバイス名を取得する
デバイス名を取得する iOS Android
DeviceInformation.h
DeviceInformation.cpp
DeviceInformationJni.h
DeviceInformationJni.cpp
DeviceInformation.mm
DeviceInformation_objc.h
DeviceInformation_objc.m
DeviceInformation.java
DeviceInformation.h #ifndef _DEVICE_INFORMATION_H_ !#define _DEVICE_INFORMATION_H_ !!#include <stddef.h> !!class DeviceInformation!{ !public: ! static char const* getDeviceName(); !}; !!#endif // _DEVICE_INFORMATION_H_ !
DeviceInformation.mm #include "DeviceInformation.h" !#include "DeviceInformation_objc.h" !!static char const* static_GetDeviceName() !{ ! return [DeviceInformationObjc getDeviceName]; !} !!char const* DeviceInformation::getDeviceName() !{ ! return static_GetDeviceName(); !} !
DeviceInformation_objc.h #import <Foundation/Foundation.h> !!@interface DeviceInformationObjc : NSObject!!+ (char const*)getDeviceName; !!@end !
DeviceInformation_objc.cpp #import "DeviceInformation_objc.h" !#include <sys/sysctl.h> !!@implementation DeviceInformationObjc!!+ (char const*)getDeviceName { ! size_t size; ! sysctlbyname("hw.machine", NULL, &size, NULL, 0); ! char *machine = malloc(size); ! sysctlbyname("hw.machine", machine, &size, NULL, 0); ! NSString *platformName = [NSString stringWithCString:machine encoding:NSUTF8StringEncoding]; ! free(machine); ! ! return [platformName UTF8String]; !} !!@end !
DeviceInformation.cpp #include "DeviceInformation.h" !#include "DeviceInformationJni.h" !!char const* DeviceInformation::getDeviceName() !{ ! return getDeviceNameJNI(); !} !
DeviceInformationJni.h #ifndef __DEVICE_INFORMATION_JNI__ !#define __DEVICE_INFORMATION_JNI__ !!#include <jni.h> !!extern "C" !{ ! extern char const* getDeviceNameJNI(); !} !!#endif // __DEVICE_INFORMATION_JNI__ !
DeviceInformationJni.cpp #include "DeviceInformationJni.h" !#include <jni.h> !#include "platform/android/jni/JniHelper.h" !#include "cocoa/CCString.h" !!#define CLASS_NAME "net/tks2/sampleproject/SampleProject" !!using namespace cocos2d; !using namespace std; !!extern "C" { ! const char* getDeviceNameJNI() { ! JniMethodInfo t; ! ! if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "getDeviceName", "()Ljava/lang/String;")) { ! jstring str = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID); ! t.env->DeleteLocalRef(t.classID); ! CCString *ret = new CCString(JniHelper::jstring2string(str).c_str()); ! ret->autorelease(); ! t.env->DeleteLocalRef(str); ! ! return ret->m_sString.c_str(); ! } ! ! return 0; ! } !} !
DeviceInformation.java package net.tks2.sampleproject; !!import org.cocos2dx.lib.Cocos2dxActivity; !import android.os.Build; !import android.os.Bundle; !!public class SampleProject extends Cocos2dxActivity{ ! protected void onCreate(Bundle savedInstanceState){ ! super.onCreate(savedInstanceState); ! } ! ! static { ! System.loadLibrary("game"); ! } ! ! public static String getDeviceName() { ! return Build.MODEL; ! } !} !
おわり � 次回、cocos2dxにおけるBox2Dの利用方法および便利なツールを紹介します。
� ありがとうございました。