bin() in python
こんなの作った。(前から合ったのを完成させた)
github.com
pythonのbin関数があまりにも酷いので
>>> bin(-1) '-0b1'
2の補数対応させた
>>> Bin(-1,4) '0b1111'
Playgroundで独自Viewを表示する為に少し読んでみた話
Playgroundで遊んでみた。
====
0.環境&対象OS
Mac OS X 10.9.5
Android Studio 1.0 RC1
Android NDK 9d
=============
Nexus5
Android 5.0 Lollipop
※あくまで結果を載せてるので参考程度に。
○Labの人ではないので正しいかはわからない。
1.補足説明
Playgroundとは
「Playground」は、マルチプラットフォームな2D/2.5Dゲームを効率的に開発するためのフレームワークです。KLabのゲームタイトルでは株式会社ブシロード(本社:東京都中野区、代表取締役社長:木谷高明)と共同開発した「ラブライブ!スクールアイドルフェスティバル」と、グローバル向けに開発した「Rise to the Throne(ライズ・トゥ・ザ・スローン)」(※1)に使用されています。
とりあえずスクフェスに使われているゲームエンジン。 決してXcodeの中にあるPlaygroundではない
KLab/PlaygroundOSS · GitHub
2.実際にどのようにPlayground上で開発するのか
{ "name":"root", "x":0, "y":0, "priority":0, "sub":[{ "name":"container", "x":1200, "y":210, "class":"task_webview", "width":500, "height":700 }], "width":1024, "height":1024 }
3.どのような形で独自を表示するか
上のコードを見ていただくとわかると思うが「task_webview」と言う物がある。Android開発をしているとこれがWebView
WebView | Android Developers
を使っていると言う事を想像するのはあまり難しい事ではない。なので今回はWebViewを独自Viewに書き換えて動かしてみる方法を載せる。
4 実装
1) Perser部分
jni > source > Assets > CompositeManagement.cpp内に以下のような関数があり、そこで「task_webview」を判定している。
なので自作コンポーネントを組み込む場合、ここに追加すれば良い。同じファイル上にCLASSIDを定義しているenum部分があるのでそこに自作IDを追加する。
// CompositeManagement.cpp int CKLBCompositeAsset::readString(const unsigned char * stringVal, size_t stringLen, int /*cte_pool*/) { bool err = false; switch (m_parserField) { case CLASS_FIELD: if (strncmp("button", (const char*)stringVal,(sizeof("button")-1))==0) { m_pCurrInnerDef->classID = BUTTON_CLASSID; } //======== 中略 ============ if (strncmp("task_webview", (const char*)stringVal, (sizeof("task_webview")-1)) == 0) { m_pCurrInnerDef->classID = WEBVIEW_CLASSID; } else
2) 生成部分
jni > source > Assets > CompositeManagement.cpp内に以下のような関数があり、そこで上のIDに応じたコンポーネントを生成していると予想できる。
(ここではCKLBUIWebArea)。
bool CKLBCompositeAsset::createSubTreeRecursive(u16 groupID, CKLBUITask* pParentTask, CKLBNode* parent, CKLBInnerDef* templateDef, u32 priorityOffset) { //===========中略=========== switch (templateDef->classID) { case WEBVIEW_CLASSID: { const char* url = NULL; const char* cb = NULL; if (templateDef->handler[1]) { url = filterDB(templateDef->handler[1]->string); } if (templateDef->handler[0]) { cb = templateDef->handler[0]->string; } CKLBUIWebArea* tsk = CKLBUIWebArea::create( pParentTask, parent, templateDef->flag[0] ? true : false, templateDef->x, templateDef->y, templateDef->width, templateDef->height, url, // URL cb // Call back. ); setupTask(templateDef,tsk); // Do not authorize creation of sub node for now. pNode = NULL; /* Allow sub system to be created. ---------------------------------- pNode = lNode; pParentTask = tsk; */ res = (tsk != NULL); } break;
3) CKLBUIWebAreaとは
jni > source > UISystem > CKLBUIWebArea.cppで定義されている。
コンポーネントの制御周りを処理していると想定できる。
その中に
CKLBUIWebView* m_pWebView
と言うメンバがあるのでこれがWebViewだと思う。
4) CKLBUIWebViewとは
jni > source > UISystem > CKLBUIWebViewNode.cppで定義されている。
とはいえここでjavaのWebViewを呼び出してうにゃうにゃしている訳ではなく、IWidget型のnativeInputItemと言う変数に
CAndroidWebWidgetと言うAndroidのWebViewを操作するWidgetを入れて動かしている。
コンストラクタをのぞいてみると
CKLBUIWebView::CKLBUIWebView(bool isPageJump, const char * initialURL, const char * token, const char * region, const char * client, const char * consumerKey, const char * applicationId, const char * userID) : nativeInputItem (NULL) , m_width (0) , m_height (0) , m_tx (0) , m_ty (0) , m_bgcolor (0xffffffff) , m_textLen (0) , m_textBuf (0) { IPlatformRequest& pForm = CPFInterface::getInstance().platform(); IWidget::CONTROL control = (isPageJump) ? IWidget::WEBVIEW : IWidget::WEBNOJUMP; const char * url = (initialURL) ? initialURL : ""; CKLBDrawResource& draw = CKLBDrawResource::getInstance(); int px,py; draw.toPhisicalPosition(m_tx, m_ty, px, py); nativeInputItem = pForm.createControl(control , 0, url, px, py, 0, 0, token, region, client, consumerKey, applicationId, userID); if (nativeInputItem) { nativeInputItem->visible(false); } klb_assert(nativeInputItem, "EditBox allocation failed"); }
となっている。IPlatformRequestで実際にCAndroidWebWidgetを生成している。
5) Androidと接続部分とWidget
jni > Android > CAndroidRequestの中で上のIPlatformRequestが定義されている。
CAndroidRequest::createControl内では本当に生成しているだけだった
IWidget * CAndroidRequest::createControl(IWidget::CONTROL type, int id, const char * caption, int x, int y, int width, int height, ...) { IWidget * pWidget = 0; va_list ap; va_start(ap, height); switch(type) { //========中略======== case IWidget::WEBVIEW: case IWidget::WEBNOJUMP: { const char * token = va_arg(ap, const char *); const char * region = va_arg(ap, const char *); const char * client = va_arg(ap, const char *); const char * cKey = va_arg(ap, const char *); const char * appId = va_arg(ap, const char *); const char * userId = va_arg(ap, const char *); CAndroidWebWidget * pWebWidget = new CAndroidWebWidget(this); if(!pWebWidget || !pWebWidget->create(type, id, caption, x, y, width, height, token, region, client, cKey, appId, userId)) { delete pWebWidget; pWebWidget = 0; } pWidget = pWebWidget; break; }
jni > android > CAndroidWidget内
CAndroidWebWidgetでjavaのメソッドをコールしている事がわかる。
bool CAndroidWebWidget::create(IWidget::CONTROL type, int id, const char * caption, int x, int y, int width, int height, const char * token, const char * region, const char * client, const char * consumerKey, const char * applicationId, const char * userID) { jvalue jval; int hIndex = -1; bool nojump = false; m_id = id; switch(type) { default: return false; case WEBNOJUMP: nojump = true; case WEBVIEW: m_pParent->logging("WebView create!"); m_pParent->callJavaMethod(jval, "webview_create", 'I', "IIIISSSSSSSZ", x, y, width, height, caption, token, region, client, consumerKey, applicationId, userID, nojump); hIndex = jval.i; // 背景色設定 m_pParent->callJavaMethod(jval, "webview_setColor", 'V', "III", hIndex, m_bgalpha, m_bgcolor); // ズーム設定 m_pParent->callJavaMethod(jval, "webview_setZoom", 'V', "IZ", m_hIndex, m_bZoom); m_pParent->logging("Create finished.: handle = %d", hIndex); break; } if(hIndex < 0) return false; return init(hIndex, id, x, y, width, height); }
5 C++部実装まとめ
- CompositeManagement.cppにJson perserとオブジェクトを呼んでいる処理がある
- CKLBUIWebArea.cppにコンポーネントの制御が書かれており実態はCKLUIWebViewNodeで動いている
- CAndroidWidgetでWebView(Android)を操作している
とても申し訳ないわかりにくさ。
6 Android部実装
先ほどのwebview_create等は
klb.android.GameEngine.PFInterface に記述されている。
//! WebViewの生成 public static int webview_create(int x, int y, int width, int height, String defURL, String token, String region, String client, String consumerKey, String applicationId, String userId, boolean nojump) { PFInterface pfif = PFInterface.getInstance(); GameEngineActivity context = pfif.m_context; WebViewItem web = new WebViewItem(context, defURL, x, y, width, height, token, region, client, consumerKey, applicationId, userId, pfif.m_tzone, pfif.m_osversion, nojump); for(int i = 0; i < pfif.MAX_WEB_VIEW; i++) { if(pfif.m_webList[i] == null) { pfif.m_webList[i] = web; if(i > pfif.m_webListCount) pfif.m_webListCount = i; return i; } } web = null; return -1; }
WebViewItemはいろいろコーティングされているがWebViewである。なのでPFInterface内で、作りたいviewを操作すれば
良い。
個人的なハッカソンについての考え
こんにちは。
最近ハッカソンが話題になっているので自分にとってのハッカソンを明記しておく。
あくまで初心者の個人的な意見です。この文章を読んだとしてもあなたは価値を得られるかはわかりません。
PlaygroundOSSを使ってAndroidのアプリ作成
動いたので最初から
Playgroundとは
「Playground」は、マルチプラットフォームな2D/2.5Dゲームを効率的に開発するためのフレームワークです。KLabのゲームタイトルでは株式会社ブシロード(本社:東京都中野区、代表取締役社長:木谷高明)と共同開発した「ラブライブ!スクールアイドルフェスティバル」と、グローバル向けに開発した「Rise to the Throne(ライズ・トゥ・ザ・スローン)」(※1)に使用されています。
とりあえずスクフェスに使われているゲームエンジン。 決してXcodeの中にあるPlaygroundではない
0.研究環境&対象OS
Mac OS X 10.9.5
Android Studio 1.0 RC1
Android NDK 9d
=============
Nexus5
Android 5.0 Lollipop
ADTは今年のI/O的に積極的にさけた方が良いと思っているので
早くAndroidStudio対応Docくだしあ><
1.いろいろインストール
Android NDK r10以降で行うとこける事がわかったのでr9代ので行う。とはいえ公式サイトには最新版のリンクしか無いので
/*
今は繋がらない
以下のサイトを参考にした。Where do I find old versions of Android NDK? - Stack Overflow
URL 今は繋がらない
https://dl.google.com/android/ndk/android-ndk-r9d-derwin-x86_64.zip
こっちは繋がった 2015/03/20
https://dl.google.com/android/ndk/android-ndk-r9e-darwin-x86_64.tar.bz2
2015/6/11
今現在、NDK r9を落とせる場所が見当たらないです……
で、NDK r9dをダウンロード。
Path を通す
export ANDROID_NDK_ROOT="/{落とした場所}/android-ndk-r9d" PATH=$PATH:$ANDROID_NDK_ROOT
上の2行を.profileというファイル名で~/の中にかいておく。
公式DocではSDKのインストールをしていたがAndroidStudioを使のでいらないと思う。(最近は別にインストールするのか?)
とりあえず
$ ndk-build -v GNU Make 3.81 Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. This program built for x86_64-apple-darwin
こんな感じなら問題ない
2.cloneする
とりあえずgitは入れておこう
$git clone https://github.com/KLab/PlaygroundOSS.git
3.buildする
中に入って
cd PlaygroundOSS/Engine/porting/Android/GameEngine-android/
権限かえて
$chmod +x ./build.py
build実行
$./build.py --rebuild --project SampleProject
とりあえずSampleProjectと言う名前にしておくと良い)
4.AndroidStudioで開く
AndroidStudio 起動
最初の画面で
Import project
当然いい感じに開ける。しかし現状問題ばかりなのでいろいろ修正する。
1. build.gradleの変更
dependencies { classpath 'com.android.tools.build:gradle:0.6.+' }
gradleのバージョンが古いと怒られるので
dependencies { classpath 'com.android.tools.build:gradle:0.14.+' }
に変更する
compileSdkVersion 17 buildToolsVersion "18.1.0"
古いので
compileSdkVersion 21 buildToolsVersion "21.0.0"
最新版に書き換える
ここで、jniDirなんて知らないと怒られる。Gradle+Androidプラグイン(0.7以降)でNDKプロジェクトをビルドする - やらなイカ?
上のサイトの方でいい感じに対応が書かれているがPlaygroundのファイル構造が対応していないので
全部を書き換えるのは面倒である。
と言う事で
task ndkBuild(type:Exec) { commandLine 'ndk-build', '-j' } task ndkClean(type:Exec) { commandLine 'ndk-build', 'clean' } task libsClean(type:Exec) { commandLine 'rm', '-rf', 'libs/armeabi', 'libs/armeabi-v7a', 'libs/x86', 'libs/mips' } if(new File(projectDir, "jni").exists()){ tasks.withType(JavaCompile) { compileTask -> compileTask.dependsOn ndkBuild } tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask -> pkgTask.jniDir new File(projectDir, 'libs') } clean.dependsOn 'ndkClean' clean.dependsOn 'libsClean' }
を以下だけ残して削除する。以下の分が無いとlibsを読み込んでくれない
tasks.withType(com.android.build.gradle.tasks.PackageApplication) { pkgTask -> pkgTask.jniFolders = new HashSet<File>() pkgTask.jniFolders.add new File(projectDir, 'libs') }
5.Assetsの追加
TODO Windows上の作業を書き込む
$cd /PlaygroundOSS/Tutorial/01.SimpleItem/.publish/android/ $zip -r -0 /PlaygroundOSS/Engine/porting/Android/GameEngine-android/assets/AppAssets.zip ./* $md5 AppAssets.zip | cut -d "=" -f 2 | sed -e 's/ //g' > /Playground0SS/Engine/porting/Android/GameEngine-android/assets/version ./*
assetsと言うフォルダを作成し、中にAppAssets.zipとversionと言うファイルを入れる。
versionの中にはAppAssets.zipのmd5を書き込む
(AppAssetsを更新したらversionの中も書き込まなければ読み込まれない)
PlaygroundOSSとの戦い(2)
こちらでまとめてます。
PlaygroundOSSを使ってAndroidのアプリ作成 - mizukisonoko’s diary
前回のブログ記事\デェン/
動かなかった
今回の内容
動いた
エラーを読む
~$ ndk-build find: ./jni/custom: No such file or directory Android NDK: WARNING:jni/Android.mk:Game: non-system libraries in linker flags: -lcurl -lfreetype2 Android NDK: This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES Android NDK: or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the Android NDK: current module find: ./jni/custom: No such file or directory Android NDK: WARNING:jni/Android.mk:Game: non-system libraries in linker flags: -lcurl -lfreetype2 Android NDK: This is likely to result in incorrect builds. Try using LOCAL_STATIC_LIBRARIES Android NDK: or LOCAL_SHARED_LIBRARIES instead to list the library dependencies of the Android NDK: current module [x86] Compile++ : Game <= KLBPlatformMetrics.cpp [x86] SharedLibrary : libGame.so [x86] Install : libGame.so => libs/x86/libGame.so [x86] Install : libjniproxy.so => libs/x86/libjniproxy.so [armeabi-v7a] Compile++ arm : Game <= KLBPlatformMetrics.cpp [armeabi-v7a] SharedLibrary : libGame.so {HOME}/ndk/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: ./obj/local/armeabi/objs/Game/./libs/Tremolo/dpen.o: requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC {HOME}/ndk/android-ndk-r10d/toolchains/arm-linux-androideabi-4.8/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.8/../../../../arm-linux-androideabi/bin/ld: error: ./obj/local/armeabi/objs/Game/./libs/Tremolo/mdctARM.o: requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC clang++: error: linker command failed with exit code 1 (use -v to see invocation) make: *** [obj/local/armeabi/libGame.so] Error 1
[armeabi-v7a] Compile++ arm で死んでいるっぽい?
中に入ってみる
$ adb shell shell@hammerhead:/ $ run-as klb.android.GameEngine shell@hammerhead:/ $ ls lib/ libjniproxy.so
無いっぽい。終了
NDKをかえてみる
エラー文
requires unsupported dynamic reloc R_ARM_REL32; recompile with -fPIC
をググってみたら以下のサイトを発見した。
CocoaChina 开发讨论区 最热的iOS开发论坛| 最热的Mac开发论坛 | 最热的iPhone开发论坛 | 最热的iPad开发论坛
もしやと思いr9をインストール
公式サイトにリンクがなさそうだったので
Old Versions of Android NDK - Stack Overflow
な形でr9dをインストール。export等を変更、ndk-buildする
結果
動いた
$ adb shell shell@hammerhead:/ $ run-as klb.android.GameEngine shell@hammerhead:/ $ ls lib/ libjniproxy.so libGame.so
できてる。
後ほど動いた版の手順を書きます