cocos2d-xプロジェクト作成+自分用設定など
Cocos2d-xで新しいプロジェクトを作成するときの、自分用メモです。
Androidは、Android Studio用のプロジェクトを使うようにします。
今回使用したバージョン
- Cocos2d-x 3.9
- AndroidNDK r10c
プロジェクト作成
cocos new プロジェクト名 -p パッケージ -l cpp -d プロジェクトディレクトリ --portrait # cocos new TestCocos2dx3 -p jp.milt.cocos2dx3test -l cpp -d /Users/okahiro/Documents/ --portrait
--portraitオプションは画面を縦にしたい時につけます。
sublime textプロジェクトファイル追加
プロジェクトディレクトリ直下にSublimeText2.sublime-projectファイルを追加
{ "folders": [ { "path": ".", "file_exclude_patterns" : ["*.png","*.jpg","*/DelivedData/*"] } ] }
.gitignoreを追加
プロジェクトディレクトリ直下に.gitignoreファイルを追加
.DS_Store *.class *.moved-aside *.xcworkspace *.mode1v3 *.mode2v3 *.pbxuser !default.xcworkspace !default.mode1v3 !default.mode2v3 !default.pbxuser *.perspectivev3 profile xcuserdata .idea/* Backup bin gen obj/ cocos2dcpp_shared libcocos2dcpp.so proj.android/assets proj.android-studio/app/assets TESTFLIGHT_OUTPUT *.sublime-workspace com_crashlytics_export_strings.xml proj.android/libs/armeabi/gdb.setup proj.android/libs/armeabi/gdbserver proj.android-studio/app/libs/armeabi/gdb.setup proj.android-studio/app/libs/armeabi/gdbserver
Android.mkファイル更新
cppファイルの追加をいちいちAndroid.mkに書きたくないので、Android.mkファイルを更新します。
場所:
プロジェクトディレクトリ/proj.android-studio/app/jni/Android.mk
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) $(call import-add-path,$(LOCAL_PATH)/../../../cocos2d) $(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/external) $(call import-add-path,$(LOCAL_PATH)/../../../cocos2d/cocos) LOCAL_MODULE := cocos2dcpp_shared LOCAL_MODULE_FILENAME := libcocos2dcpp FILE_LIST := $(wildcard $(LOCAL_PATH)/../../../Classes/*.cpp) LOCAL_SRC_FILES := hellocpp/main.cpp LOCAL_SRC_FILES += $(FILE_LIST:$(LOCAL_PATH)/%=%) LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../../Classes # _COCOS_HEADER_ANDROID_BEGIN # _COCOS_HEADER_ANDROID_END LOCAL_STATIC_LIBRARIES := cocos2dx_static # _COCOS_LIB_ANDROID_BEGIN # _COCOS_LIB_ANDROID_END include $(BUILD_SHARED_LIBRARY) $(call import-module,.) # _COCOS_LIB_IMPORT_ANDROID_BEGIN # _COCOS_LIB_IMPORT_ANDROID_END
# cocos compile -p android --android-studio
Android向け設定
AndroidManifest.xmlに下記を追加します。
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
Android apk署名設定
# cd proj.android-studio/app # keytool -genkey -v -keystore 鍵ファイル名 -alias エイリアス名 -keyalg RSA -validity 10000 # cocos compile -p android --android-studio -m release 初回のみ最後にキーファイル、エイリアス名、キーパスワードを聞かれるので入力
Android Studioでプロジェクトを開く
このサイトを参考にさせていただきました。
http://studio.cretia.net/blog/462
もしくは「File」ー「New」ー「Import Project」から"proj.android-studio"を選択してもOK。
サーバー上においてある画像をダウンロードして使う(TextureAtlas)
サーバー上においてある画像をダウンロードして、それをそのままSpriteに使う例はそれなりにみかけますが、
TextureAtlas(pngとplist)をダウンロードしてSpriteFrameCacheを使う例は見かけなかったので、自分なりに試してみました。
今回使用したバージョン
- Cocos2d-x 3.2
TextureAtlasを使う場合はpngとplistセットでダウンロードする必要があるので、あらかじめzipファイルに圧縮してサーバーに置いておくようにします。
この方法であれば、一緒に必要なファイルをまとめてダウンロードできるので便利です。
zipファイルの扱いについては、こちらを参考にさせていただきました。
http://qiita.com/kuuki_yomenaio/items/b93b236ed5563adf9c39
// zipファイルから取り出すファイル名一覧 std::string dataNameList[] = {"textureatlas.png","textureatlas.plist"}; ... void HttpAccessManager::downloadFile() { std::string fileUrl = "http://www.example.com/data.zip"; auto request = new HttpRequest(); request->setUrl(fileUrl.c_str()); request->setRequestType(HttpRequest::Type::GET); request->setResponseCallback([&](HttpClient *sender,HttpResponse * response) { if(response->isSucceed()) { std::string filePath = FileUtils::getInstance()->getWritablePath() + "data.zip"; std::vector<char>* buffer = response->getResponseData(); // zipファイルを保存 FILE* fp = fopen(filePath.c_str() , "wb"); fwrite(buffer->data() , 1, buffer->size() , fp); fclose(fp); // zipファイルからそれぞれのファイルを取り出し for(std::string dataFileName : dataNameList) { unsigned long size = 0; unsigned char* buf = FileUtils::getInstance()->getFileDataFromZip(filePath.c_str(), dataFileName, (ssize_t*)&size); std::string writeFilePath = FileUtils::getInstance()->getWritablePath() + dataFileName; FILE* dataFile = fopen(writeFilePath.c_str(),"wb"); fwrite(buf,1,size,dataFile); fclose(dataFile); } // SpriteFrameCache SpriteFrameCache::getInstance()->addSpriteFramesWithFile(FileUtils::getInstance()->getWritablePath() + "textureatlas.plist"); } else { // 通信失敗した時の処理 CCLOG("LoadImage failure."); } }); HttpClient::getInstance()->send(request); request->release(); }
zipファイルをダウンロードしたら保存して、そこから順番にファイルを取り出して保存していきます。
自分用 MacOSXインストールソフトメモ
MacOSXに入れておくといいなと思っているソフトです。
自分用メモです。
ブラウザ
オフィス
- Pages
- Numbers
- Keynote
ユーティリティ
- Google日本語入力
- XtraFinder
- Skitch
- VMWare
- Reflector
- 1Checker
サービス
セキュリティ
プログラム開発など
ゲーム開発
- Texture Packer
- Physics Editor
- Particle Designer
- Glyph Designer
グラフィックス
Cocos2d-xでアプリのバージョンを取得する
Cocos2d-xからiOS,Androidのアプリバージョンを取得する処理を作成したのでメモします。
JNIのクラスなど、ネイティブ連携のクラスはCocos2d-x上からTwitterにツイートする - おかひろの雑記などと同じ形で作成してあるとします。
今回使用したバージョン
- Cocos2d-x 3.2
NativeCodeLauncher.h
// バージョン番号取得 static std::string getVersionNo();
iOS向け
NativeCodeLauncher.mm
// バージョン番号取得 static std::string static_getVersionNo() { NSString *versionNo = [NativeCodeLauncher getVersionNo]; std::string ret([versionNo UTF8String]); return ret; } ... namespace Cocos2dExt { // バージョン番号取得 std::string NativeCodeLauncher::getVersionNo() { return static_getVersionNo(); }
NativeCodeLauncher_objc.h
// バージョン番号取得
+(NSString *)getVersionNo;
NativeCodeLauncher_objc.mm
// バージョン番号取得 +(NSString *)getVersionNo { return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]; }
Android向け
NativeCodeLauncher.cpp
// バージョン番号取得 std::string NativeCodeLauncher::getVersionNo() { return getVersionNoJNI(); }
NativeCodeLauncherJni.h
// バージョン番号取得 extern std::string getVersionNoJNI();
NativeCodeLauncherJni.cpp
// バージョン番号取得 std::string getVersionNoJNI() { JniMethodInfoEx methodInfo; if (!getStaticMethodInfo(methodInfo, "getVersionNo", "()Ljava/lang/String;")) { return ""; } jstring retString = (jstring)methodInfo.env->CallStaticObjectMethod(methodInfo.classID, methodInfo.methodID); // jstringをstd::stringに変換 std::string ret = JniHelper::jstring2string(retString); // 解放処理 methodInfo.env->DeleteLocalRef(retString); methodInfo.env->DeleteLocalRef(methodInfo.classID); return ret; }
AppActivity.java
// バージョン番号取得 public static String getVersionNo() { PackageManager pm = me.getContext().getPackageManager(); String versionName = ""; try { PackageInfo packageInfo = pm.getPackageInfo(me.getContext().getPackageName(), 0); versionName = packageInfo.versionName; } catch(NameNotFoundException e) { e.printStackTrace(); } return versionName; }
戻り値の型はstd::stringがいいと思います。const char*にすると、Androidでうまくいきませんでした。
(私のやり方が良くなかったのかもしれません。)
JNIでJavaからC++のメソッドを実行
ネイティブ連携はC++→Objective-C or Javaの一方向で事足りることが多いですが、
ネイティブ側からC++のメソッドを呼びたいケースもやはりあります。
(課金処理の結果をC++に渡すなど)
JNIは少しややこしいので、メモをしておきます。
JNIのクラスなど、ネイティブ連携のクラスはCocos2d-x上からTwitterにツイートする - おかひろの雑記などと同じ形で作成してあるとします。
今回使用したバージョン
- Cocos2d-x 3.2
AppActivity.java
public class AppActivity extends Cocos2dxActivity { // C++側のメソッドを呼ぶ宣言 private static native void sampleNativeMethod(boolean result,String test); ... // 実際の呼び出し sampleNativeMethod(true,"Test");
NativeCodeLauncherJni.cpp
void Java_org_cocos2dx_cpp_AppActivity_sampleNativeMethod(JNIEnv *env,jobject thiz,jboolean success,jstring test) { const char *testChar = env->GetStringUTFChars(test,0); // ここで処理を行う // 解放 env->ReleaseStringUTFChars(test, testChar); }
JavaからStringを引数にして呼び出す場合は、変換が必要のようです。
Actionに他のターゲットのアクションを混ぜて実行する
Cocos2d-xで、例えば
スプライト1を指定の座標に移動
↓
スプライト2を指定の座標に移動
↓
スプライト1をフェードアウト
のように、他のターゲットのActionを混ぜて実行する方法のメモ。
今回使用したバージョン
- Cocos2d-x 3.2
そんなに難しくなく、runActionを実行する以外のノードではTargetedActionを使うだけでいけそうです。
たとえば上の例であれば
sprite1->runAction(Sequence::create(MoveTo::create(0.5f,Vec2(100,100)), TargetedAction::create(sprite2,MoveTo::create(0.5f,Vec2(200,200))), FadeIn::create(0.5f), NULL));
CallFuncNなどを使った処理もできます。
sprite1->runAction(Sequence::create(TargetedAction::create(sprite2, FadeTo::create(0.5f,100)), CallFunc::create([&]() { // なにか処理を実行 }), DelayTime::create(1.5f), TargetedAction::create(sprite2, FadeOut::create(0.5f)), TargetedAction::create(sprite2,CallFuncN::create([](Node *n) { n->removeFromParentAndCleanup(true); })), NULL));
Cocos2d-x 3.2でスクリーンショットを撮ってツイート
Cocos2d-x3.2で、スクリーンショットを撮るためのメソッドが実装されたので、
これを使ってスクリーンショットをツイートする機能を作ってみたのでメモ。
基本はこの記事と同じです。
Cocos2d-xで撮ったスクリーンショットをTwitterに添付してツイートできないか試してみた - おかひろの雑記
※2014/8/8 iOS6でツイート後に画面操作ができなくなる問題があったため、NativeCodeLauncher_objc.mmを修正しました。
今回使用したバージョン
- Cocos2d-x 3.2
Cocos2d-xでスクリーンショットを撮る方法はこちらhttp://www.cocos2d-x.org/projects/cocos2d-x/wiki/How_to_save_a_screenshotを参考にしました。
ネイティブ連携
ツイートする内容に加え、画像ファイルのフルパスを一緒に渡すようにしています。
共通
NativeCodeLauncher.h
namespace Cocos2dExt { class NativeCodeLauncher { public: static void openTweetDialog(char const *tweet,char const *filePath); }; }
iOS
NativeCodeLauncher.mm
static void static_openTweetDialog(const char* tweet,const char* filePath) { [NativeCodeLauncher openTweetDialog:[NSString stringWithUTF8String:tweet] filePath:[NSString stringWithUTF8String:filePath]]; } namespace Cocos2dExt { void NativeCodeLauncher::openTweetDialog(const char *tweet,const char *filePath) { static_openTweetDialog(tweet,filePath); } }
NativeCodeLauncher_objc.h
@interface NativeCodeLauncher : NSObject
+(void)openTweetDialog:(NSString *)tweet filePath : (NSString *)filePath;
@end
NativeCodeLauncher_objc.mm
※2014/8/8 CompletionHandler内にdismissViewControllerAnimatedメソッドを追加。それに伴う修正。
@implementation NativeCodeLauncher +(void)openTweetDialog:(NSString *)tweet filePath:(NSString *)filePath { if([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]) { AppController *appController = (AppController *)[UIApplication sharedApplication].delegate; NSString *serviceType = SLServiceTypeTwitter; SLComposeViewController *composeCtl = [SLComposeViewController composeViewControllerForServiceType:serviceType]; [composeCtl setInitialText:tweet]; UIImage *image = [UIImage imageWithContentsOfFile:filePath]; [composeCtl addImage:image]; [composeCtl setCompletionHandler:^(SLComposeViewControllerResult result) { [appController.viewController dismissViewControllerAnimated:YES completion:nil]; if (result == SLComposeViewControllerResultDone) { //投稿成功時の処理 NSLog(@"ツイートしました"); } }]; [appController.viewController presentViewController:composeCtl animated:YES completion:nil]; } else { tweet = [NSString stringWithFormat:@"http://twitter.com/home?status=%@",tweet]; tweet = [tweet stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL *url = [NSURL URLWithString:tweet]; [[UIApplication sharedApplication] openURL:url]; } } @end
iOSの場合は画像ファイルをUIImageに読み込むだけなので簡単です。
Social.frameworkを使う形に変更しました。
Android
NativeCodeLauncher.cpp
namespace Cocos2dExt { void NativeCodeLauncher::openTweetDialog(char const* tweet,char const *filePath) { openTweetDialogJNI(tweet,filePath); } }
NativeCodeLauncherJni.h
extern "C" { extern void openTweetDialogJNI(char const* tweet,char const *filePath); }
NativeCodeLauncherJni.cpp
... #define CLASS_NAME "org/cocos2dx/cpp/AppActivity" ... extern "C" { ... void openTweetDialogJNI(char const* tweet,char const *filePath) { JniMethodInfo methodInfo; if (!getStaticMethodInfo(methodInfo, "openTweetDialog", "(Ljava/lang/String;Ljava/lang/String;)V")) { return; } jstring tweetArg = methodInfo.env->NewStringUTF(tweet); jstring filePathArg = methodInfo.env->NewStringUTF(filePath); methodInfo.env->CallStaticVoidMethod(methodInfo.classID, methodInfo.methodID, tweetArg,filePathArg); methodInfo.env->DeleteLocalRef(tweetArg); methodInfo.env->DeleteLocalRef(filePathArg); methodInfo.env->DeleteLocalRef(methodInfo.classID); } }
AppActivity.java
public class AppActivity extends Cocos2dxActivity{ private static Activity me = null; protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); me = this; } static { System.loadLibrary("game"); } // JNIから呼び出すメソッド public static void openTweetDialog(String tweet,String filePath) { final String path = filePath; final String tweetMessage = tweet; me.runOnUiThread(new Runnable(){ @Override public void run() { File f = new File(path); byte[] data; try { data = readFileToByte(path); } catch(Exception e) { Log.e("Debug", e.getMessage()); return; } File savePath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES); File saveFile = new File(savePath,"screenshot.jpeg"); if(!savePath.exists()) { savePath.mkdir(); } FileOutputStream fos = null; try { fos = new FileOutputStream(saveFile); fos.write(data); fos.close(); } catch(Exception e) { Log.e("Debug", e.getMessage()); return ; } Uri uri = Uri.fromFile(saveFile); Intent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_SUBJECT, ""); it.putExtra(Intent.EXTRA_TEXT, tweetMessage); it.putExtra(Intent.EXTRA_STREAM,uri); it.setType("image/jpeg"); me.startActivity(Intent.createChooser(it,"共有")); } }); } private static byte[] readFileToByte(String filePath) throws Exception { byte[] b = new byte[1]; FileInputStream fis = new FileInputStream(filePath); ByteArrayOutputStream baos = new ByteArrayOutputStream(); while (fis.read(b) > 0) { baos.write(b); } baos.close(); fis.close(); b = baos.toByteArray(); return b; } }
画像ファイルを外部ストレージに一旦コピーしています。
そのため、AndroidManifest.xmlにパーミッションが必要になります。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
呼び出し
utils::captureScreen([&](bool succeed,const std::string &fileName){ // ツイート if(succeed) { // スクリーンショット保存成功 Cocos2dExt::NativeCodeLauncher::openTweetDialog(”ツイートメッセージ”,fileName.c_str()); } else { // スクリーンショット保存失敗 } }, "screenshot.jpg");
スクリーンショットを撮った後にコールバックされるようなので、その中でツイートの準備を行います。