がおまる開発ブログ

cocos2d-xやlevelhelperを使って iPhone/Androidアプリの作り方を解説します

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

cocos2d-xでjniを使ってみる

jniって面倒くさいですよね(^_^;)
でもやっとけばcocos2d-x ⇔ java間のやり取りはかなり楽になると思います。

先ずはファイルを作ってみましょう。
下記例はClassesフォルダにInterfaceJNI.cppとInterfaceJNI.hファイルを新規で作成しています。

2013061401.png


#include <string.h>
#include "cocos2d.h"

using namespace std;
using namespace cocos2d;

class InterfaceJNI
{
public:
static void func1();
};




#include "InterfaceJNI.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>

// 呼び出すメソッドが書かれているパッケージ名とjavaクラス名
#define CLASS_NAME "com/marnishi/jniTest/jniTest"

void InterfaceJNI::func1()
{
JniMethodInfo t;
// クラス名とメソッド名を指定します。
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func1", "()V")) {
// voidなので、CallStaticVoidMethodで呼ぶ
t.env->CallStaticVoidMethod(t.classID, t.methodID);
// 解放
t.env->DeleteLocalRef(t.classID);
}
}



cocos2d-x側のHelloWorldScene.cppとかで呼び出してみましょう。

#include "HelloWorldScene.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "JNICalls/InterfaceJNI.h"
#endif

USING_NS_CC;

bool HelloWorld::init()
{
//////////////////////////////
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}

this->jniLoad();

}

void HelloWorld::jniLoad()
{
// jniはandroid用専用なので、#ifで読み分ける
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
InterfaceJNI::func1();
#endif
}


次にEclipseを起動して、java側の記述を行います。
2013061402.png


package com.marnishi.jniTest;

import org.cocos2dx.lib.Cocos2dxActivity;

import android.os.Bundle;

public class jniTest extends Cocos2dxActivity{

protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}

public static void func1() {
System.out.println("func1 call");
}

static {
System.loadLibrary("game");
}

}


【様々な型の呼び出しや戻り値】
voidだけではなく、他の型などで呼び出す場合のサンプルです。

cocos2d-x側

#include <string.h>
#include "cocos2d.h"

using namespace std;
using namespace cocos2d;

class InterfaceJNI
{
public:
static void func1();
static void func2(int value);
static void func3(bool value);
static void func4(const char *value);
static void func5(const char *value1, int value2, bool value3);
static int func6();
static std::string func7();
};




#include "InterfaceJNI.h"
#include "platform/android/jni/JniHelper.h"
#include <jni.h>
#include <android/log.h>

// 呼び出すメソッドが書かれているパッケージ名とjavaクラス名
#define CLASS_NAME "com/marnishi/jniTest/jniTest"

void InterfaceJNI::func1()
{
JniMethodInfo t;
// クラス名とメソッド名を指定します。
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func1", "()V")) {
// voidなので、CallStaticVoidMethodで呼ぶ
t.env->CallStaticVoidMethod(t.classID, t.methodID);
// 解放
t.env->DeleteLocalRef(t.classID);
}
}

/*
// javaでの呼び出し
public static void func1() {
System.out.println("func1 call");
}
*/

// 引数にint型を与える場合(void)
void InterfaceJNI::func2(int value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func2", "(I)V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID, value);
t.env->DeleteLocalRef(t.classID);
}
}

/*
public static void func2(int value) {
System.out.println("func2 val=" + value);
}
*/

// 引数にbool型を与えた場合
void InterfaceJNI::func3(bool value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func3", "(Z)V")) {
t.env->CallStaticVoidMethod(t.classID, t.methodID, value);
t.env->DeleteLocalRef(t.classID);
}
}
/*
public static void func3(boolean value) {
System.out.println("func3 val=" + value);
}
*/

// 引数にcharを渡す場合
void InterfaceJNI::func4(const char *value)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func4", "(Ljava/lang/String;)V")) {
// ★パラメータがStringの場合はjstringに変換する
// java側は「String」にする。UTF8変換
jstring stringArg1 = t.env->NewStringUTF(value);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1);

t.env->DeleteLocalRef(stringArg1);// ★jstringは解放が必要です。
t.env->DeleteLocalRef(t.classID);
}
}
/*
public static void func4(String value) {
System.out.println("func4 val=" + value);
}
*/

// 引数に、char、int、boolの複数を指定する場合
void InterfaceJNI::func5(const char *value1, int value2, bool value3)
{
JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func5", "(Ljava/lang/String;IZ)V")) {
jstring stringArg1 = t.env->NewStringUTF(value1);
t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1, value2, value3);

t.env->DeleteLocalRef(stringArg1);
t.env->DeleteLocalRef(t.classID);
}
}

/*
public static void func5(String value1, int value2, boolean value3) {
System.out.println("func5 val=" + value1 + " int=" + value2 + " bool=" + value3);
}
*/

// 戻り値がint
int InterfaceJNI::func6()
{
int ret = 0;

JniMethodInfo t;
if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func6", "()I")) {
ret = t.env->CallStaticIntMethod(t.classID, t.methodID);
t.env->DeleteLocalRef(t.classID);
}

return ret;
}

/*
public static int func6() {
return 12345;
}
*/

// 戻り値が文字列
std::string InterfaceJNI::func7()
{
std::string ret;
JniMethodInfo t;

if (JniHelper::getStaticMethodInfo(t, CLASS_NAME, "func7", "()Ljava/lang/String;")) {
jstring jStr = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID);
const char* str = t.env->GetStringUTFChars(jStr, NULL);
ret = str;

t.env->ReleaseStringUTFChars(jStr,str);
t.env->DeleteLocalRef(t.classID);
}

return ret;

}

/*
public static String func7() {
return "本日は晴天なり";
}
*/



これで基礎的部分は抑えられたと思います。
次回はjava→cocos2d-xのメソッドを呼び出す方法です。



スポンサーサイト

5/30 Goodia潜入&勉強会レポ

先日5/30に名古屋で行われた勉強会のレポです。

以前Goodiaさんにandroid化でアドバイスしたら、
その後からandroid名誉アドバイザーとか勝手に言われてw(^_^;)
名古屋で勉強会があったので、ついでにGoodiaさんとこに顔を出しに行って来ました。

前日にBBQが行われてその時にもGoodia重鎮3人ともそこで顔合わせしており、
社長の深野さんが高いスイカを持ってこられて、お返しに高いメロンを持って参上しました。

最初に矢場とん行って味噌カツ丼を食らう!
2013053005.png
やっぱ矢場とんはうまいわ!

そこからGoodiaさんの開発拠点まで歩いて移動。
名古屋のコワーキングスペースで開発されています。

2013053001.png
Goodiaどーん!

2013053002.png
右側にいてる方がGoodia統括ディレクターの樗澤さん
真面目に仕事してるフリをして頂きましたw

2013053003.png
ここの絨毯緑色の部分がGoodiaスペースだそうです。
手前がデザイナーさん。

日々棒人間ばかり描かされて可哀想に(´Д⊂ヽ
中央に居てるのが社長の深野さんです。

こちらも真面目に仕事してるフリw
ジュースも飲み放題で快適な環境で日々あの面白いゲームが生まれているのですね〜

1週間に1本ペースで今後もアプリを出し続けるようです!
それが2チーム現在あるので、2本という事ですな(^_^;)
もうGoodiaが止まらない!お仕事の手伝いさせて!


名古屋勉強会

夕方に解散して勉強会に参加してきました。
気になったキーワードを箇条書き!

・自分にあったリフレッシュレートを探そう
 とあるアプリではリフレッシュレートを15秒→30秒に変えると収益があがった事例もあった模様。
・広告実装位置も工夫しよう
 ボタンの側とかCPCが激下がる可能性もあるよ
・海外ではサウンド広告もあるよ
・リリースタイミング
 LINEアプリは水曜日と日曜日が多いらしい。その日のリリースは避けるか…
・リワードは週末・連休前が多い
・レビュー媒体
 誰かに紹介したくなるようなアプリ要素があるとイイネ!
 土曜日〜月曜日にレビュー依頼メールは避けよう!
 ↑担当者もサラリーマン!休みのメールが溜まって見過ごされる可能性もあるよ!気をつけて
・ストア内SEO
 なんかHITしないなぁ〜と思ったら、説明文中のキーワードを変えてみて!
 ユーザーの行動を想像して仮説検証を繰り返そう!
・アイコン最適化
 一番悪かったのはグリーのアイコンがついた奴…←登録しないといけないってユーザーが思うらしい
・スクリーンショットのファーストビュー
 インパクトがあって、アテンションが強いのがいいよね!
・説明文すごく大事!
 できるだけ続きを読むを押さなくてもアプリの概要が分かるように完結に説明しよう!

いやぁ〜とても参考になる勉強会でしたね!
帰りは3時間かけて車で帰りましたw

また名古屋であれば是非参加させて頂きます!

hamonさん家に行ってきた

先ほどまでhamonさん家にご招待されて行って来ました!
メンバーは

くらべるぞう 】の @BracchoKurotanさん
俺の校長】の @sn630さん

の3人でhamon夫妻の自宅に行って来ました


早速大失態!
開発に集中しすぎて、出る時間ミスって集合時間に全然間に合わなくなるという早速残念なスタート
ヒゲもそる時間も無く、頭もボサボサで完全なニートスタイルで自宅へ行くことにww

お土産も忘れて完全に遅れてやってきて飯だけ食って帰った感じになってしまった(´Д⊂ヽ
次はちゃんとお土産持っていきます(^_^;)

30分も遅刻して、いざhamon御殿へ!
家の近所に橋下徹市長の家があるらしい

はぁ〜ここがあのおは朝で取材に来た家なのか〜と思いつつ潜入!
もう既に木村さんと中西さんがお待ちだった(´Д⊂ヽ
遅刻して申し訳ないっすm(_ _)m

もうhamonさんの奥様が既に料理を色々と作って頂き誠にありがとうございます!
ここで幾つか写真をお見せしましょう!

2013060604.png
このサラダが美味しかったです!
一番左のゴマ豆腐ですが、男どもが群がって1/3ぐらい食べてからタレが出てきて、
あまりのスピードに驚かれてしまったww

2013060603.png
メイン料理っす!
このお肉が物凄く柔らかくて美味しかった!!
ワインボトルほぼ使って煮込んだやつらしいっす

2013060602.png
可愛いお寿司に、サンドイッチ的なやつ
さっきのお肉でだいぶお腹いっぱいw


暫く談笑していると、@yukiyama800930さんが奥から何やら出して来ました。
2013060601.png

奥さんの嫁入り道具らしいっす!
懐かしのファミコンソフトが大量に!!

借りパクしたソフトなどがあり、裏に従兄弟の名前が書かれていたソフトもありました。

スーファミとファミコンがいつでも出来る体制になっており、
マリオカートも当然あって、急遽マリカー対戦が始まりました!

hamonさんは流石強い!ノコノコ使い!
マリオサーキット1でタイムアタック対戦もしましたが、ゴーストが抜かせなくて全く勝てず…
懐かしいマリカーでとても楽しめました!

その後も夜遅くまで色々と語り、
とても楽しい時間を過ごせました♪

今度はちゃんとお土産もって参上致しますm(_ _)m
今日はありがとうございました!

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。