がおまる開発ブログ

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

スポンサーサイト

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

ナースと付き合うまでにやった◯◯な事!その2:お見合いパーティで知り合ったとある女性

前回はお見合いパーティに参加して女性に慣れていく所までご紹介しました。
やたらと好評だったので、今回はその続きです。

何度かお見合いパーティに参加して、
遂にメルアドをゲットして、実際に会う所までこぎつけました。

この時もナースでした。←今の彼女ではありません!
この人と出会ってどえらい目に会いました。

顔は可愛くて結構タイプな人でした。
カップルになったわけではなかったのですが、僕が前回話したリトマス試験紙にメルアドを書いて、
後ほどその女性からメールが来ました。


ここから先はグロい話があるので閲覧注意です!



実際に会って、何度か食事していると・・・
「来週は私の誕生日なの・・・何かプレゼントが欲しい!」と言い出しました。
まだ会って3回目のデートでしたが、
まぁ誕生日ならプレゼントぐらいええかぁという気持ちで行きました。

場所は京都です。
雨男で清水寺もずぶ濡れで行きましたよ(´Д⊂ヽ
初めてのデートなんで気がつかないというか必死だったんですね・・・

ひと通り清水寺も見終わって、
四条通りにあるとあるデパートに行きました。
するといきなり、誕生日プレゼント欲しいのがあるの!と言って、
何やらデパートの高級バッグ売り場に連れて行かれるではありませんか・・・

今思い出しても身の毛がよだつ!
確か、ルイ・ヴィ◯ンとかいう茶色のバッグだったような気が・・・

その場の空気に圧倒されながら、とりあえず中に入りました。
その時そのバッグの値段の相場も知る由もなかったので、彼女の言うとおりにあれこれと目の前にバッグが並びました。

二つプレゼント良いかな〜とか言い出して、
値段を知らない僕は初めてのデートで見栄を張ってしまった自分も居たと思います。
ここで断ったらなんかかっこ悪いとか勝手に思ってお店の雰囲気に完全に飲まれた感じでした。


はぁ〜まだまだ若かったですな!
とりあえずカード払いで!と言ってカードを差し出して暫くすると店員が現れて、
「カードの上限を超えており、エラーとなりました」


おぉマジかよ・・・
そこで止めれば良かったのですが、引くに引けなくなり別のカードを併用して支払う事に…

あの時の過去に戻って自分に忠告したいわ(´Д⊂ヽ

未だに例の店から新作バッグのご案内のDMが届きますw

今思えば高い授業料だと思って割り切っています。
他にもグロい話がありますが、興味があれば続けますが・・・

この女性が余りにも曲者でしたわ。
一旦今日はここまで〜
スポンサーサイト

cocos2d-xにExit広告を導入してみる[Android編]

cocos2d-xにビヨンドのExit広告を導入してみましょう!

まずはビヨンドの管理サイトに行って、
アプリの登録を行なってください。

s_20130131_0.png

s_20130131_1.png

アプリの情報を入れ終えたら、タグ取得でSDKやIDを取得してください。
s_20130131_2.png

s_20130131_3.png


戻るボタンの実装は過去の記事を参考にしてください。


void HelloWorld::keyBackClicked()
{
// androidに投げる
CCMessageBox("ExitAd", "command");
}


Eclipseを起動してください。
先ほどダウンロードしたSDKを解凍して、beadsdk-v1.1.0.jarファイルをプロジェクトに追加しましょう

s_20130131_4.png


続いてCocos2dxActivity.javaを編集していきます。
s_20130131_5.png


public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {

private static Cocos2dxActivity myref;
// Exit広告
private Bead mBead;
// Exit広告ID
private final String exitAdID = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

this.init();

Cocos2dxHelper.init(this, this);

myref = this;

mBead = Bead.createExitInstance(exitAdID, ContentsOrientation.Auto);
mBead.requestAd(this);
mBead.setOnFinishClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
// Exit広告終了処理
mBead.endAd();
// アプリを終了させる
android.os.Process.killProcess(android.os.Process.myPid());
}
});
}

@Override
public void showDialog(final String pTitle, final String pMessage) {
if (pTitle.equals("command") && pMessage.indexOf("ExitAd") >= 0) {
myref.dispExitAd();
}
}

// Exit広告を表示する
public void dispExitAd() {
Cocos2dxActivity.this.runOnUiThread(new Runnable() {
@Override
public void run() {
mBead.showAd(Cocos2dxActivity.this);
}
});
}
}



これで実行すれば、Exit広告が表示されるはずです。

s_20130131_6.png

ナースと付き合うまでにやった◯◯な事!その1

何故かこんな流れになったので、
流れに逆らわずせきららに書いて行きましょう。

まだ彼女いねーとか彼女欲しい!とかナースと付き合いたいって人の参考になれば良いです。

26歳の秋
実はこの歳になるまで一度も彼女という存在は居ませんでした。
そんな時に会社の先輩に半強制的に連れられて、お見合いパーティという物に参加しました。

大阪では有名な、とあるお見合いパーティで、
男女20:20とか30:30でお見合いをしていきます。

コの字型のテーブルの奥側に女性がずら~りと座っており、
まず全員と握手していきます。

ここで全員の顔を把握していき、3回気に入った別々の人と話す事ができます。

女性の胸には番号が書かれており、その番号を小さな紙にメモしていきます。
全員と握手し終わると、男性のアプローチタイムが始まります。

先ほどメモした番号の女性の元に行き、簡単なプロフィールカードを交換して、
2〜3分会話をしていきます。
※何故か年収を記入する欄が(´Д⊂ヽ

椅子取りゲーム方式なので、可愛い子のところには複数男性が押しかけます。
作戦を取りながら椅子取りゲームを制さないと何も話す事ができません。

当然最初の頃はぼーっとするだけでした(^_^;)

相手の職業を見てみると、
ナース、介護師、教師、フリーター、学生、など様々な人たちが!

その中でも確実に居たのはナースでした!
過去にもう20回以上行ってますが必ずナースが居てます!
喋り終えると、リトマス試験紙という紙に自分の電話番号やメルアドを書いて
お互いに交換することができます。

その試験紙には3段階の気持ちも記す事が出来て、イイね!普通!無理!の3段階で評価。
その場で開封作業するので、相手がどう思っていたかが一目瞭然!

3回男性からのアプローチが終わると次は女性です。
何故か男性が目をつぶってその場に立たされます。

女性の手には自分の番号が書いているシールが!
そのシールを好きな男性の手に貼っていきます。

この時がかなり緊張!!

シールを貼られればラッキー!
貼られなければ目をつぶったまま永遠立ち続けますw
屈辱ですww

シールを確認して書かれた番号の女性の元に行き会話をしていきます。
シールは全部で3枚あり、3回しゃべることが出来ます。
誰にもシールを貼られなかった場合は空いてる女性に適当に話しかけて、時間を潰します←完全に無駄w

これでお互いのアプローチは終了!
最終的に好きな女性の番号を書いて袋に入れていきます。

女性も男性の首にかけた袋に番号を入れていきます。
袋に入れ終わると開封作業に入って、お互いの番号があれば晴れてカップル成立です!

まぁ〜こんな感じで女性になれて色んな人と関わっていくことになります。
ダブルヘッダーとか(一日に2回パーティー)したな(^_^;)



好評やったら続きも書きますけど…

cocos2d-xにアスタを導入してみる:iOS編

cocos2d-xにアスタを導入してみましょう!
アスタの管理画面に行って、アプリを登録しましょう。

s_20130130_0.png

s_20130130_1.png

s_20130130_2.png

s_20130130_3.png

続いてXCodeを起動して、
プロジェクトにframeworkを追加しましょう。

s_20130130_8.png

s_20130130_4.png

s_20130130_5.png

s_20130130_6.png

s_20130130_7.png
これで追加出来ました。

続いて新規ファイルを作成しましょう。
下記の4つのファイルをiOSフォルダの直下に作成してください。

s_20130130_10.png

IOSSettingsはアイコン型広告のMrdIconLoaderを格納して
色んな所から呼び出すためのファイルです。

#import <Foundation/Foundation.h>
#import <MrdIconSDK/MrdIconSDK.h>

@interface IOSSettings : NSObject {
MrdIconLoader* _iconloader;
}

+(IOSSettings*) sharedSettings;
@property (nonatomic, retain) MrdIconLoader* iconLoader;

@end


#import "IOSSettings.h"


@implementation IOSSettings

static IOSSettings* g_gameSettings = nil;

+(IOSSettings*) sharedSettings
{
if (!g_gameSettings)
{
g_gameSettings = [[IOSSettings alloc] init];

}
return g_gameSettings;
}

@end


#import "UIKit/UIKit.h"

@interface IconAdViewController : UIViewController {

}

@end


#import "IconAdViewController.h"
#import <MrdIconSDK/MrdIconSDK.h>
#import "IOSSettings.h"

#define IF_NO_ARC(x) {x}

@interface IconAdViewController()
@property (nonatomic, retain) MrdIconLoader* iconLoader;
@end

@interface IconAdViewController(MrdIconLoaderDelegate)<MrdIconLoaderDelegate>
@end

@implementation IconAdViewController

@synthesize iconLoader = _iconLoader;

- (id)init
{
self = [super init];
if (self != nil) {
MrdIconLoader* iconLoader = [[MrdIconLoader alloc]init];
self.iconLoader = iconLoader;
iconLoader.delegate = self;
IF_NO_ARC([iconLoader release];)

const CGFloat viewHeight = kMrdIconCell_DefaultViewSize.height;

// The array of points used as origin of icon frame
CGRect frame = [[UIScreen mainScreen] applicationFrame];

/*
// 横一列上に表示する場合
CGPoint origins[] = {
{0, 0},
{80, 0},
{80*2, 0},
{80*3, 0},
};
*/
// 横一列下に表示する場合
CGPoint origins[] = {
{0, frame.size.height-viewHeight},
{80, frame.size.height-viewHeight},
{80*2, frame.size.height-viewHeight},
{80*3, frame.size.height-viewHeight},
};

// addSubviewしていきます
for (int i=0; i < 4; i++)
{
CGRect frame;
frame.origin = origins[i];
frame.size = kMrdIconCell_DefaultViewSize;
MrdIconCell* iconCell = [[MrdIconCell alloc]initWithFrame:frame];

[iconLoader addIconCell:iconCell];
[self.view addSubview:iconCell];
IF_NO_ARC([iconCell release];)
}
}

// アイコン型広告のローダーを保持させておく
[IOSSettings sharedSettings].iconLoader = _iconLoader;

return self;
}

@end

////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
@implementation IconAdViewController(MrdIconLoaderDelegate)

- (void)loader:(MrdIconLoader*)loader didReceiveContentForCells:(NSArray *)cells
{
}

- (void)loader:(MrdIconLoader*)loader didFailToLoadContentForCells:(NSArray*)cells
{
}

- (BOOL)loader:(MrdIconLoader*)loader willHandleTapOnCell:(MrdIconCell*)aCell
{
return YES;
}

- (void)loader:(MrdIconLoader*)loader willOpenURL:(NSURL*)url cell:(MrdIconCell*)aCell
{
}

@end


AppControllerで初期化処理を行います

@class RootViewController;
@class IconAdViewController;

@interface AppController : NSObject <UIAccelerometerDelegate, UIAlertViewDelegate, UITextFieldDelegate,UIApplicationDelegate> {
UIWindow *window;
RootViewController *viewController;
IconAdViewController *iconAdView;

}

@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) RootViewController *viewController;

@end


#import "IconAdViewController.h"
#import "IOSSettings.h"

// 取得したアイコン型広告のID
#define kMEDIA_CODE @"idxxxxxxxxx"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Override point for customization after application launch.

// Add the view controller's view to the window and display.
window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH_COMPONENT16
preserveBackbuffer: NO
sharegroup: nil
multiSampling: NO
numberOfSamples:0 ];

// Use RootViewController manage EAGLView
viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
viewController.wantsFullScreenLayout = YES;
viewController.view = __glView;

// Set RootViewController to window
if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// warning: addSubView doesn't work on iOS6
[window addSubview: viewController.view];
}
else
{
// use this method on ios6
[window setRootViewController:viewController];
}

// アイコン型広告初期化
iconAdView = [[IconAdViewController alloc] init];
[viewController.view addSubview: iconAdView.view];

// アイコン表示スタート
[[IOSSettings sharedSettings].iconLoader startLoadWithMediaCode: kMEDIA_CODE];

[window makeKeyAndVisible];

[[UIApplication sharedApplication] setStatusBarHidden: YES];

cocos2d::CCApplication::sharedApplication()->run();
return YES;
}


正しく設定出来ていればこのように表示されると思います!
s_20130130_9.png

[LevelHelper講座]第11回:タッチイベントを実装する

LevelHelperにはスプライト毎にタッチ処理を割り当てる事が出来ます。
わざわざccTouchesBegan、ccTouchesMoved、ccTouchesEndedなどでダラダラとプログラムを書かなくても良いです。

具体的な実装方法は以下の通り


#include "cocos2d.h"
#include "Box2D.h"
#include "LevelHelperLoader.h"

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

// returns a Scene that contains the HelloWorld as the only child
static cocos2d::CCScene* scene();

void initPhysics();
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);

private:
b2World* world;
LevelHelperLoader* lh;

// 各種タッチ処理を定義
void touchBeganOnSprite(LHTouchInfo* info);
void touchMovedOnSprite(LHTouchInfo* info);
void touchEndedOnSprite(LHTouchInfo* info);

};


void HelloWorld::initPhysics()
{

CCSize s = CCDirector::sharedDirector()->getWinSize();

b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
world = new b2World(gravity);

// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);

// LevelHelper初期化
lh = new LevelHelperLoader("GaomarTest.plhs");
LHSettings::sharedInstance()->setLhPtmRatio(PTM_RATIO);
lh->addObjectsToWorld(world, this);

if(lh->hasPhysicBoundaries())
lh->createPhysicBoundaries(world);

if(!lh->isGravityZero())
lh->createGravity(world);

this->setupCollisionHandling();

LHSprite* spr = lh->createSpriteWithName("0_0_0", "AnimalSheet", "Animal.pshs");
spr->setPosition(ccp(s.width/2, s.height/2));

// スプライトに対してタッチ処理を定義していきます
spr->registerTouchBeganObserver(this, callfuncO_selector(HelloWorld::touchBeganOnSprite));
spr->registerTouchMovedObserver(this, callfuncO_selector(HelloWorld::touchMovedOnSprite));
spr->registerTouchEndedObserver(this, callfuncO_selector(HelloWorld::touchEndedOnSprite));
}

////////////////////////////////////////////////////////////////
// タッチ開始
void HelloWorld::touchBeganOnSprite(LHTouchInfo *info)
{
if(info->sprite)
CCLog("Touch BEGIN on sprite %s", info->sprite->getUniqueName().c_str());
}
////////////////////////////////////////////////////////////////
// タッチ移動
void HelloWorld::touchMovedOnSprite(LHTouchInfo *info)
{
if(info->sprite)
CCLog("Touch MOVED on sprite %s", info->sprite->getUniqueName().c_str());

}
////////////////////////////////////////////////////////////////
// タッチ離す
void HelloWorld::touchEndedOnSprite(LHTouchInfo *info)
{
if(info->sprite)
CCLog("Touch ENDED on sprite %s", info->sprite->getUniqueName().c_str());


}


かなり簡単にタッチ処理が実装出来ちゃいます♪

アイコン型広告「アスタ」ってどやさ!

結果画面やトップページ等の隙間に自由における
アイコン型広告「アスタ」がかなり今アツい!
別に運営元のマルジュさんから一切お金なんてもらってないからね〜

アイコン型広告を導入しているアプリの昨日の広告費を大公開!!

超越カージャンプ! 1.0.0(無料)App
発売日: 2013/01/26
カテゴリ: ゲーム, アクション, エンターテインメント, アーケード
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.5 MB)
全てのバージョンの評価: (2件の評価)
GameCenter対応


[nend]
iOS 1,303imp 13クリック ¥120 CTR:1% ¥9.23(単価)
Android 1,071imp 6クリック ¥63 CTR:0.56% ¥10.5

[iMobile]
Android 922imp 3クリック ¥23 CTR:0.33% ¥7.6

[アスタ]
iOS 19,228imp 203クリック ¥694 CTR:1.06% ¥3.4
Android 50,988imp 108クリック ¥324 CTR:0.21 ¥3

[合計収益]
iOS ¥814
Android ¥410
合計 ¥1,224


見てください!
バナー広告のクリック数が1桁前後をうろうろしているのに対して、
アイコン型広告は10倍以上のクリック数がありますよね!
単価は¥3〜¥4ですが、チリも積もれば山となる!
しかもiOS、Androidが共に同じ現象になっていました!

画面上の広告の配置は以下の通り!
s_20130129_0.png

特にミスクリックを誘うような事はしていませんよね〜
本当に結果画面の隙間が寂しいので出してみたという感じです。

インプレッション数が多いのは、15秒毎に更新を行なっているからです。
↑設定で変えられます
後はアイコン毎にインプレッションが加算されるので、この場合だと一度の表示で、
4impという事になると思います。

自社広告も載せられます!
でも最大配信率は80%までしか設定出来ません。
残りの20%は必ず別の広告が出るようになっています。

後、管理画面も他のアドネットワークに比べると一番綺麗で分かりやすいと思います!
もう一度言っておきますが、マルジュさんの回し者ではありませんのでw


皆さんも隙間が寂しいといった事があれば、これを導入することをオススメします。
これを期にもう少し出てくる広告の種類が増えれば良いなぁ〜
マルジュさん頑張れ!!


後ほどアスタの導入方法をお知らせしましょう。


[LevelHelper講座]第10回:カスタムクラスを使う

LevelHelperにはカスタムクラスという機能があります。
好きなクラスを作成出来て、対象スプライトに定義することができます。

■使用例
・キャラクターの名前
・キャラクターのヒットポイント
・保持しているスコア

こんな感じでデフォルトで何か値を保持したい時に便利です。
もちろんGetter/Setterなので値の取得/変更も可能です。


LevelHelperを開いてCustom Propertiesタグから
カスタムクラスを新規で作成していきましょう。
s_20130128_0.png

設定するスプライトにカスタムクラスをあてがいます。
s_20130128_1.png

カスタムクラスを追加したので、
ソースの出力を行なってください。
s_20130128_4.png


ソースの出力を行うと「CustomClasses」フォルダにカスタムクラスが生成されています
XCodeを開いて、作成されたカスタムクラスをADDしておきます。

s_20130128_2.png


今回のサンプルはANIMALタグで取得して、
画面をタッチした所にスプライトがあれば取得する。
その取得したスプライトのカスタムクラスを取得しようと思います。

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

// ANIMALタグを全て取得
CCArray* spritesWithTag = lh->spritesWithTag(ANIMAL);
CCObject* data = NULL;
CCARRAY_FOREACH(spritesWithTag, data) {
LHSprite* spr = (LHSprite*)data;

// タッチした所にスプライトがあるかどうか確認
if (spr->isTouchedAtPoint(location)) {

// カスタムクラスをuserInfoで取得する
LHAnimalClass* cl = (LHAnimalClass*) spr->userInfo();

if (cl != NULL) {
// 定義したプロパティ名で取得する事が出来ます
CCLog("name=%s", cl->getName().c_str());
CCLog("hp=%f", cl->getHp());

}

}

}
}
}



[LevelHelper講座]第9回:Box2dの衝突処理

Box2dにはオブジェクト同士の衝突を検知する事ができます。
LevelHelperにはそのオブジェクト同士の衝突を簡単に検知と処理できる機能があります。

まずは、SpriteHelperでDynamicなBodyを作りましょう
s_20130127_0.png

LevelHelperを開いて、
新しいタグ「GROUND」を追加しましょう
s_20130127_1.png

今回は地面に当たると消したいので、
Bottom Borderにタグを指定してください。
s_20130127_2.png

Xcodeでソースを編集しましょう。
ヘッダーファイルに衝突の初期化と地面衝突時のメソッドを書きます

#include "cocos2d.h"
#include "Box2D.h"
#include "LevelHelperLoader.h"

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

// returns a Scene that contains the HelloWorld as the only child
static cocos2d::CCScene* scene();

void initPhysics();
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);

private:
b2World* world;
LevelHelperLoader* lh;

// 衝突処理初期化
void setupCollisionHandling();
// 地面と衝突した時の処理
void groundCollision(LHContactInfo* contact);

};



void HelloWorld::initPhysics()
{

b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
world = new b2World(gravity);

// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);

// LevelHelper初期化
lh = new LevelHelperLoader("GaomarTest.plhs");
LHSettings::sharedInstance()->setLhPtmRatio(PTM_RATIO);
lh->addObjectsToWorld(world, this);

if(lh->hasPhysicBoundaries())
lh->createPhysicBoundaries(world);

if(!lh->isGravityZero())
lh->createGravity(world);

// 衝突処理初期化
this->setupCollisionHandling();


}

////////////////////////////////////////////////////////////////
void HelloWorld::setupCollisionHandling()
{
// 初期化処理これは絶対に要るやつ
lh->useLevelHelperCollisionHandling();

// タグで指定して呼び出すメソッドを指定
lh->registerBeginOrEndCollisionCallbackBetweenTagA(
GROUND,
ANIMAL,
this,
callfuncO_selector(HelloWorld::groundCollision));
}
////////////////////////////////////////////////////////////////
void HelloWorld::groundCollision(LHContactInfo *contact) {
if(LH_BEGIN_CONTACT == contact->contactType ) {

// GROUNDはspriteA()、ANIMALはspriteB()になってるはず
if (contact->spriteB()->getTag() == ANIMAL) {

LHSprite* spr = contact->spriteB();

// 接触したらスプライトを消す
spr->removeSelf();

}
}
}



これで地面にライオンが当たれば、
画像が消えます。
s_20130127_3.png


衝撃度によって処理をかえる
ぶつかった時の衝撃度に応じた処理もあると思います。
Box2dでは計算で求めることも可能です。

先ほどのソースに一部修正を加えます。
衝撃度の計算はそのままコピペすれば使えると思います。

void HelloWorld::groundCollision(LHContactInfo *contact) {
if(LH_BEGIN_CONTACT == contact->contactType ) {
// GROUNDはspriteA()、ANIMALはspriteB()になってるはず
if (contact->spriteB()->getTag() == ANIMAL) {
b2Contact* boxContact = contact->contact;
b2WorldManifold worldManifold;
boxContact->GetWorldManifold(&worldManifold);
b2Vec2 point = worldManifold.points[0];

b2Body* body1 = contact->bodyA;
b2Body* body2 = contact->bodyB;
b2Vec2 vA = body1->GetLinearVelocityFromWorldPoint(point);
b2Vec2 vB = body2->GetLinearVelocityFromWorldPoint(point);
b2Vec2 now = vB-vA;
float32 force = abs(b2Dot(now, worldManifold.normal));

CCLog("force=%f", force);

// 指定した値以上の衝突の場合にだけ消す
if (force >= 10 ) {

LHSprite* spr = contact->spriteB();
spr->removeSelf();

}
}
}
}


衝撃度が取得出来ていると思います。
これを利用して様々な事が出来ますよね。
s_20130127_4.png

hamonさんのアプリ開発者交流会に行ってきた

今日はhamonさんのアプリ開発者交流会に行って来ました!
なかなか濃い内容でしたよ!

会場が奥ばった所にあってここで合ってるのかわかりませんでした(^_^;)

hamonさんからの発表です!
hamonさん曰く間口をもっと広げよう!との事です。

ビール瓶切り 1.4(無料)App
発売日: 2012/04/17
カテゴリ: ゲーム, スポーツ, アーケード, エンターテインメント
販売元: hamon - Naoyuki Hironaka(サイズ: 6 MB)
全てのバージョンの評価: (50件の評価)
GameCenter対応 + iPhone/iPadの両方に対応


とりあえず、気になったワードをピックアップ!
・タブレットにも対応すると収益もアップしたよ
・ビール瓶はインドで大当たり!
・android版も出せよ!
・ortkさんに似ている
・動画広告なんてのもあるよ〜
・月曜日に各広告社配信率を同じにして、成績が良かった所を土日に集中して配信するよ!
・アドメーカーと心中しかけたらしい
・appbankに掲載されたのに広告IDミスってて全然収益にならなかったらしいw
・会場のプロジェクターがMBAに対応してなかって全編ブルーバックでのお届け!
・嫁は美人!

続いてFleximizerさん!

Death Blocks 1.0.3(無料)App
発売日: 2013/01/12
カテゴリ: ゲーム, アドベンチャー, エンターテインメント, アクション
販売元: Fleximizer Co.,Ltd. - Fleximizer Co.,Ltd.(サイズ: 49.9 MB)
全てのバージョンの評価: (9件の評価)
GameCenter対応 + iPhone/iPadの両方に対応


ここでも気になったワード
・3Dゲームにしてから売れてきた
・1日0.2ドル売れたよ
・Death Blocksが2週間で15万DLされたらしい
・海外だとじっくりやるゲームが売れるらしい
・海外なら両手使うゲームも売れるよ

続いてemboss369さん

Divergence Clock 1.1(¥250)App
発売日: 2011/09/15
カテゴリ: ユーティリティ
販売元: smartphone-zine.com - HIROAKI KANEDA(サイズ: 1.3 MB)
全てのバージョンの評価: (34件の評価)



真空管みたいな時計を作った人です。
・4,877DLされて売上80万以上!
・基礎からのAndroidという本を出してるが、全然売れないらしい
・リリース前から事前プロモーションも有効!作ってる最中のものをニコ動とかで上げてた
・シュタゲパクった
・5つ★ばっかり
・本物っぽいのを作れば売れそうよ〜

続いてnohinaさんの発表!

Accel Beat 1.0(無料)App
発売日: 2013/01/11
カテゴリ: ゲーム, アーケード, レーシング, スポーツ
販売元: Hidenari Nohina - Hidenari Nohina(サイズ: 29.1 MB)
全てのバージョンの評価: (6件の評価)
GameCenter対応 + iPhone/iPadの両方に対応


・2週間で2万DLされたらしい
・2人で開発してる
・Unityでガリガリ作ってる
・すみません!難しい話でした!


最後にアプリ野郎Zさんの発表!

・去年の夏からレビューサイトを立ち上げる
・アプリ野郎Z→「アプリやろうぜ!」から
・一日数百PV〜数万のPVがある
・俺の校長が一番アクセスが多かった
・ライターは3人のうち1人がゲーム未経験者
・3人それぞれ好きな記事を書いている
・お金でランキング買えるよ!
・AppBank最強だね!
・リワード広告は直ぐランキング上がるけど、直ぐ下がるよ
・NGワードが一杯だったんで、これ以上書けません(^_^;)
・オレンジ色!
s_20130126_5.png
ゼットアワードのトロフィー見た!


Char Roomさんとも名刺交換!

本日開店レストラン 1.1.0(無料)App
発売日: 2012/11/25
カテゴリ: ゲーム, ファミリー, シミュレーション
販売元: Char Room - Char Room(サイズ: 11.2 MB)
全てのバージョンの評価: (49件の評価)
+ iPhone/iPadの両方に対応


・Flash作ってiOSとAndroidリリースしている
・実は女性!1人でやっている
・広告SDK使わないでweb用の広告を貼ってる


SkipMoreさんもこっそり参加!

無限ラッコカーニバル 1.0.1(無料)App
発売日: 2013/01/11
カテゴリ: ゲーム, アーケード, キッズ
販売元: URARA-WORKS Co., Ltd. - URARA-WORKS Co., Ltd.(サイズ: 10.2 MB)
全てのバージョンの評価: (8件の評価)
GameCenter対応


・今日は来ないと思ったけど、しれっと参加したよ
・次回作がかなり良く出来ていた!めちゃ期待!


またこういう交流会にどんどん参加したい!
次回は昼間をキボンヌ!

[LevelHelper講座]第8回:タグを使用する

LevelHelperにはスプライトをタグで簡単に管理出来ちゃう機能があります。
スプライトにタグを指定するやり方をお知らせしましょう。

LevelHelperを起動してください。
タグ名は必ず大文字になります。

s_20130126_0.png

タグを設定したいスプライトを選択して
タグを決めちゃいます。
s_20130126_1.png

cocos2d-x用にソースの出力を忘れずに!

s_20130126_2.png
s_20130126_3.png

Xcodeを起動してソースを編集します。

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

// spritesWithTag()メソッドで取得します
CCArray* spritesWithTag = lh->spritesWithTag(ANIMAL);
CCObject* data = NULL;
CCARRAY_FOREACH(spritesWithTag, data) {
LHSprite* spr = (LHSprite*)data;
spr->removeSelf();
}
}
}


これで画面をタップすると
「ANIMAL」タグのスプライトは全て削除されると思います。
s_20130126_4.png

[新作] 超越カージャンプ!を本日リリースしました

本日超越カージャンプ!をリリースしました
ジャンプアクションゲームを前々から作ってみたかったんでw

LevelHelperのお陰で3日でメインを作成して、残り2日でAndroid版とテストを行いました。
やっぱりこいつのお陰で開発スピードがめちゃ早いです!
今回も1人で全部作ってますw

絵師キボンヌ!


簡単にゲーム説明!
走ってくる車に当たらないように、ジャンプボタンで避けるだけ!
2段ジャンプもあるよ〜

途中のアイテムを取ると、スコアが加算されます。
そのスコアと移動距離を競い合います。

超越カージャンプ! 1.0.0(無料)App
発売日: 2013/01/25
カテゴリ: ゲーム, アクション, エンターテインメント, アーケード
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.5 MB)
全てのバージョンの評価: 無し(0件の評価)
GameCenter対応




[LevelHelper講座]第7回:LevelHelperの画像にCCScaleやCCCallFuncNを使ってみる

LevelHelperもcocos2d-xでいうCCSpriteを継承してるので、
CCMoveToやCCCallFuncN等を利用する事ができます。

今回のサンプルでは、CCScaleとCCJumpTo、CCCallFuncNを使った動きを試してみましょう。
画面をタッチするとジャンプしながら5秒かけてスケールを大きくして、
処理が終わると画像を消すという流れになっています。

s_20130125_5.png

移動完了後の処理を定義してます

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

// returns a Scene that contains the HelloWorld as the only child
static cocos2d::CCScene* scene();

void initPhysics();
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);

private:
b2World* world;
LevelHelperLoader* lh;

void moveDone(LHSprite* spr);
};



void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);


// LevelHelper中のlionを取得
LHSprite* spr = lh->spriteWithUniqueName("lion");
spr->setScale(0.1);
spr->setPosition(ccp(s.width/2, s.height*0.7));

// 5秒かけてスケールを1にする
CCScaleTo* scale = CCScaleTo::create(5, 1);

// 5秒かけて指定座標に50の高さで5回ジャンプする
CCJumpTo* jump = CCJumpTo::create(5, ccp(s.width/2, s.height/2), 50, 5);

// スケールとジャンプを同時に実行
CCFiniteTimeAction* spwn = CCSpawn::create(scale, jump, NULL);

// moveDoneを実行する
CCCallFuncN* done = CCCallFuncN::create(this, callfuncN_selector(HelloWorld::moveDone));

// アクションが終了したら画像を消す
spr->runAction(CCSequence::create(spwn, done, NULL));

}
}
////////////////////////////////////////////////////////////////////////////////
void HelloWorld::moveDone(LHSprite *spr)
{
// 移動完了後にスプライトを削除する
spr->removeSelf();

}

[LevelHelper講座]第6回:LevelHelperでParallaxを指定する

LevelHelperで横スクロールのような背景を移動させる動きも簡単に実装する事が出来ます。

SpriteHelperで動かす背景を設定
SpriteHelperで動かしたい背景を設定しましょう。
1枚だけあればOKです。

s_20130125_0.png

LevelHelperでParallaxを設定する
背景なのでZオーダーを「-1」等にして一番後ろに配置しましょう。

s_20130125_1.png

「+」マークで前後に画像を複製出来ます。
合計3枚の背景画像をコピーして作成しましょう。
s_20130125_2.png

Parallaxタブを押して、
New Parallaxで新規作成して、背景にしたい画像を選択してからAdd Selected Scene Sprite(s)を
押してください。

移動する向きも自由に変えられます。
左から右、右から左、上から下、下から上という4種類が設定可能です。

s_20130125_4.png

再生すると右から左に背景が動いていると思います。
s_20130125_3.png

cocos2d-xにAdWhirlを導入する (iOS編)

あぷまがさんのお陰でブログのアクセス数がいつもの3倍にあがりました!

あぷまがさん!この場をお借りしてありがとうございます!


今回はcocos2d-xにAdWhirlを導入する方法をお知らせします。
結構分かり辛いですもんね〜

AdWhrilにアプリを新規登録する
AdWhirlにアクセスしてください。
s_20130124_0.png

s_20130124_1.png

s_20130124_2.png

s_20130124_3.png

s_20130124_4.png

こちらからAdWhirlのSDKをダウンロードしましょう。


AdWhirlを組み込む
SDKをそれぞれのフォルダにコピーしていきます。
「AdViewController.h」「AdViewController.m」は新規で作成しましょう!
このファイルに色々書き込んでいきます。

s_20130124_7.png

AdWhirlフォルダ内のadaptersフォルダの中身を「AdWhirlAdNetworkAdapter.h」だけにしましょう。
それ以外は削除してください。

s_20130124_10.png


他社アドネットワークのSDKを手に入れる
今回iMobileとNendを使ったサンプルです。
各社のSDKをダウンロードしてください。

今回使用したバージョンは以下の通りです。
iMobile: imobile_for_SP_app_iOS_AdWhirl_SDK_1.3.8
Nend: NendSDK_iOS1.3.2

それぞれのSDKをプロジェクトにコピーします。

iMobileの場合
s_20130124_8.png

Nendの場合
s_20130124_9.png


コードを追加する
Xcodeを起動してコードを追加していきましょう。

まず必要なフレームワークを追加します。
ビルドに必要なものは下記の通りです。
s_20130124_5.png

Other Linker Flgsに「-ObjC」「-all_load」を追加しましょう!
s_20130124_11.png


AdViewController.h、AdViewController.mを新規で作成する

s_20130124_6.png


#import <UIKit/UIKit.h>
#import "AdWhirlView.h"
#import "AdWhirlDelegateProtocol.h"
#import "NADView.h"
#import "imobileAds/IMobileAdDelegateProtocol.h"
#import "imobileAds/IMAdWhirlBannerView.h"

#define GAD_SIZE_320x50 CGSizeMake(320, 50)
#define GAD_SIZE_480x50 CGSizeMake(480, 50)

@interface AdViewController : UIViewController<AdWhirlDelegate, NADViewDelegate, IMobileAdDelegate> {
AdWhirlView *awView;
NADView *nadView;
NADView *appBankView;
}

@property (nonatomic, retain) AdWhirlView *awView;
@property (nonatomic, retain) NADView *nadView;
@property (nonatomic, retain) NADView *appBankView;

- (void)imAdViewDidFinishReceiveAd:(IMAdView *)imAdView;
- (void)imAdViewDidFailToReceiveAd:(IMAdView *)imAdView;

@end



#import "AdViewController.h"

// AdWhirlSDKキー
#define ADWHIRL_KEY @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

// Nend用キー
#define NEND_ID @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define NEND_SPOT_ID @"xxxxx"

// AppBank用キー
#define APPBANK_ID @"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#define APPBANK_SPOT_ID @"xxxxx"

// iMobike用キー
#define IMOBILE_PUD xxxx
#define IMOBILE_MEDIA_ID xxxxx
#define IMOBILE_SPOT_ID xxxxx


@interface AdViewController ()

@end

@implementation AdViewController
@synthesize awView;
@synthesize nadView;
@synthesize appBankView;

- (NSString *)adWhirlApplicationKey{
return ADWHIRL_KEY;
}

- (UIViewController *)viewControllerForPresentingModalView{
return self;
}

- (id) init {
self = [super init];
if (self != nil) {

//nend------------
nadView = [[NADView alloc] init];
[nadView setNendID:NEND_ID spotID:NEND_SPOT_ID];
[nadView setDelegate: self];
[nadView setRootViewController: self];
[nadView load: nil];

//nend------------

//appbank------------
appBankView = [[NADView alloc] init];
[appBankView setNendID:APPBANK_ID spotID:APPBANK_SPOT_ID];
[appBankView setDelegate: self];
[appBankView setRootViewController: self];
[appBankView load: nil];

//appbank------------

//adwirl----------
self.awView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
self.view = awView;

// 下に出したい場合はコメントアウトしてください
/*
CGRect frame = [[UIScreen mainScreen] applicationFrame];
int yPos = 430;
if (frame.size.height==568.0) { // iPhone 4inch (568 - 20 px)
yPos +=88;
}
*/
awView.frame = CGRectMake(0,0,GAD_SIZE_320x50.width, GAD_SIZE_320x50.height);

awView.delegate = self;
//adwirl----------

}
return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];
}

//// AdWhirlで設定したカスタムイベント
//// nend
- (void)nend:(AdWhirlView *)adWhirlView {
[awView replaceBannerViewWith:nadView];

}

//// AdWhirlで設定したカスタムイベント
//// app bank
- (void)appbank:(AdWhirlView *)adWhirlView {
[awView replaceBannerViewWith:appBankView];

}

//// AdWhirlで設定したカスタムイベント
//// i-mobile
- (void)iMobile:(AdWhirlView *)adWhirlView {
IMAdWhirlBannerView *imAdWhirlBannerView =
[IMAdWhirlBannerView imAdWhirlBannerViewWithFrame:kAdWhirlViewDefaultFrame withDelegate:self];
[imAdWhirlBannerView setWithPublisherId: IMOBILE_PUD
mediaId:IMOBILE_MEDIA_ID
spotId:IMOBILE_SPOT_ID];
[imAdWhirlBannerView start];
}

//// nend
- (void)nadViewDidFinishLoad:(NADView *)adView{

}

- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

// i-moible広告画像の取得が完了した時
- (void)imAdViewDidFinishReceiveAd:(IMAdView *)imAdView {
[awView replaceBannerViewWith:imAdView];
}
// i-moible広告画像の取得が失敗した時
- (void)imAdViewDidFailToReceiveAd:(IMAdView *)imAdView {
[awView rollOver];
}

-(void) dealloc {
[nadView setDelegate: nil];
[nadView release];

[appBankView setDelegate: nil];
[appBankView release];

[awView release];

[super dealloc];

}
@end



AppControllerを編集する
AppController.hとAppController.mmを編集しましょう
2行目、7行目で広告関係の変数を指定

@class RootViewController;
@class AdViewController;

@interface AppController : NSObject <UIAccelerometerDelegate, UIAlertViewDelegate, UITextFieldDelegate,UIApplicationDelegate> {
UIWindow *window;
RootViewController *viewController;
AdViewController *adViewController;

}

@property (nonatomic, retain) UIWindow *window;
@property (nonatomic, retain) RootViewController *viewController;

@end




35行目で広告の初期化を行います。

#import "AdViewController.h"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

// Override point for customization after application launch.

// Add the view controller's view to the window and display.
window = [[UIWindow alloc] initWithFrame: [[UIScreen mainScreen] bounds]];
EAGLView *__glView = [EAGLView viewWithFrame: [window bounds]
pixelFormat: kEAGLColorFormatRGBA8
depthFormat: GL_DEPTH_COMPONENT16
preserveBackbuffer: NO
sharegroup: nil
multiSampling: NO
numberOfSamples:0 ];

// Use RootViewController manage EAGLView
viewController = [[RootViewController alloc] initWithNibName:nil bundle:nil];
viewController.wantsFullScreenLayout = YES;
viewController.view = __glView;

// Set RootViewController to window
if ( [[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// warning: addSubView doesn't work on iOS6
[window addSubview: viewController.view];
}
else
{
// use this method on ios6
[window setRootViewController:viewController];
}

// 広告
adViewController = [[AdViewController alloc] init];
[viewController.view addSubview: adViewController.view];

[window makeKeyAndVisible];

[[UIApplication sharedApplication] setStatusBarHidden: YES];

cocos2d::CCApplication::sharedApplication()->run();
return YES;
}



これでビルドが通れば広告が表示されると思います。
AdWhirlで表示率を切り替えてそれぞれの広告が表示されるか確認してみましょう!
s_20130124_12.png

[LevelHelper講座]第5回:LevelHelperで画像にアニメーションを指定する:初級編

がおまる@風邪です。
皆さんも気をつけてください!

今回は画像にアニメーションを指定するやり方をお知らせします。

SpriteHelperでアニメーションの情報を登録する
SpriteHelperを起動してください。

s_20130123_0.png

s_20130123_1.png

LevelHelperでアニメーションを指定する
ステージに画像を設置して、画像を選択した状態で
Animationの指定をします。
LevelHelperでもアニメーションの動きを変更することが可能です。
s_20130123_2.png

これで動くと思います。

s_20130123_3.png


ソースからアニメーションを制御する
次にソースからSpriteHelperのアニメーションにアクセスして、
好きなフレーム番号を設定してみましょう。

Xcodeに今回作成したSpriteHelperファイルを追加するのを忘れずに!

s_20130123_4.png


HelloWorldScene.cppを編集します。
画面タッチするとアニメーションを取得して、
ループ設定しているアニメなので、一度アニメを停止させてから、フレーム番号を指定するサンプルです。


void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

LHSprite* spr = lh->spriteWithUniqueName("run");

// SpriteHelperファイルから指定アニメーション名を取得
spr->prepareAnimationNamed("run_frame", "Run.pshs");

// これでアニメを停止
spr->stopAnimation();

// 好きなフレーム番号を指定できます
spr->setFrame(0);

}
}


こんな感じで簡単にアニメーションを制御する事が出来ます。
他にもアニメに関するメソッドがあるので、おいおい紹介していきます。


[LevelHelper講座]第4回:LevelHelperでBox2dを使ってみる:初級編

LevelHelperにはBox2dという仮想重力を使った面白い動きをする機能があります。
簡単に導入できますので、まずは初級編としてご紹介しましょう!

SpriteHelperで設定する
Box2dの細かい設定はSpriteHelperで設定することができます。
s_20130122_3.png
自動選択
Create New Auto Tracedをクリックすると、
スプライトの形を自動選択してくれます。

s_20130122_4.png
■Static
重力の影響は受けないが、設定した形は有効になる

■Kinematic
Box2dじゃない重力設定だったと思う

■Dynamic
Box2dで重力設定をする

s_20130122_12.png

Dynamicの指定なので、そのまま重力を受けて下に落ちていく


丸い形にする
丸い形にしてボールのような形にしてくれます。
指先リフティングのボールもこの設定をしています。

s_20130122_5.png

s_20130122_14.png


四角形にする
s_20130122_6.png

s_20130122_13.png


自由選択
自由な形に設定することができます。
好きな所にタッチして型どっていきましょう。

s_20130122_7.png


s_20130122_8.png


壁を設置する
通常のままではスプライトを設置すると、そのまま落ち続けてしまいます(´Д⊂ヽ
見えない壁を設置して落下するのを食い止めましょう!

今度はLevelHelperで指定します
s_20130122_9.png

s_20130122_11.png


簡単に壁を設置できました。
色々設定して動きを確認してみてください!!


[新作] ヒツジの毛を本日リリースしました

僕の会社には携帯事業部なるものがあり、現在3人で様々なアプリを作ってます。

僕がほぼメインで作成しており、
残りの2人はカメラアプリの研究、
もう一人はAndroidアプリをiOSに移植する作業を行なっています。

本日そのアプリが遂にiOSに移植されリリースされました!

その名も「ヒツジの毛」
ヒツジの毛を刈ってその刈った毛を売って様々なアイテムが購入出来ます。
餌を上げて良質な毛を生やすと、刈って売った時の値段も上がります。

簡単な育成アプリで、今後もアップデートしていく模様です!
良かったら遊んでみてね♪

価格: 無料 (記事公開時)
カテゴリ: ゲーム
App Storeでダウンロードする。

[LevelHelper講座]第3回:LevelHelper内のスプライトにアクセスする

前回はcocos2d-xに組み込む所まで説明しました。

今回はLevelHelper内に設置した画像にアクセスする方法をお知らせします。


ユニーク名を付ける
設置しているキリンにユニーク名を付けましょう。
s_20130121_0.png


cocos2d-xからアクセスする
前回作成したプロジェクトを起動してください。
まだ無い人は前回の記事を参考してください。


void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

LHSprite* spr = lh->spriteWithUniqueName("kirin");
spr->setPosition(location);

}
}


spriteWithUniqueNameメソッドでLevelHelperで指定したユニーク名を記述します。
setPositionでタッチした所に画像を移動させています。

キーポイントは「LHSprite」ですね
CCSpriteみたいなもんです。
結構汎用性の高いクラスですわ。


s_20130121_1.png

かなり簡単にアクセス出来ますよね〜


画像を増やす
次はタッチした所にキリンをどんどん表示させていきましょう。

17行目をcreateBatchSpriteWithUniqueNameメソッドに書き換えればOKです。
これでタッチした所にキリンが表示されます。

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

LHSprite* spr = lh->createBatchSpriteWithUniqueName("kirin");
spr->setPosition(location);

}
}


s_20130121_2.png


キリンを削除する
次は削除してみましょう!

17行目で画像にアクセスして、
18行目のremoveSelf()で削除します。


void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

LHSprite* spr = lh->spriteWithUniqueName("kirin");
spr->removeSelf();

}
}



これで画面のどこでも良いのでタッチすると、
キリンの画像が消えます。


2012年作成アプリダウンロード数ワースト5

前回はダウンロードTOP10をご紹介しましたが、
今回は戒めの為にワーストもご紹介しましょう!

本当は発売日から算出すりゃいいんだけど、
単純にダウンロード数で算出してます。

恥ずかしいので、5位まで大発表!

第5位 1,331ダウンロード

小銭の箱 1.0.1(無料)App
発売日: 2012/11/02
カテゴリ: ゲーム, エンターテインメント, アクション, キッズ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 2.9 MB)
全てのバージョンの評価: (3件の評価)
GameCenter対応


落ちゲーブームの波に全く乗れず、
ソッコー撃沈したアプリです。
全体的にマ◯オっぽいしwww

第4位 1,105ダウンロード

サンタのプレゼント 1.1.0(無料)App
発売日: 2012/12/10
カテゴリ: ゲーム, キッズ, ファミリー, エンターテインメント
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.1 MB)
全てのバージョンの評価: (8件の評価)
GameCenter対応


クリスマス前にギリギリリリースできたのですが、
全然認知されず、しかもパクってる!?
来年に期待します!

第3位 952ダウンロード

けん玉花火 1.0.0(無料)App
発売日: 2012/08/17
カテゴリ: ゲーム, アクション, キッズ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.2 MB)
全てのバージョンの評価: (4件の評価)
GameCenter対応


ここから一気にダウンロードが3桁突入!
これが法人で作ってるアプリの実力か!?
花火大会がひと通り終わってからリリースされた、
とても残念なアプリ。。。
ゲームも糞やしこれも終わってる…

第2位 885ダウンロード


傘たわー 1.0.0(無料)App
発売日: 2012/07/03
カテゴリ: ゲーム, アクション, パズル
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.3 MB)
全てのバージョンの評価: (4件の評価)
GameCenter対応


梅雨の季節に作ったアプリ。
もうこれ全然何が面白いのかさっぱりイミフ(^_^;)
アイコンもしょぼいし、踏んだり蹴ったりなアプリでした。
因みに、12月のダウンロード数は46で一番最悪(´Д⊂ヽ

第1位 841ダウンロード


火中天津甘栗拾い 1.1.0(無料)App
発売日: 2012/09/25
カテゴリ: ゲーム, アクション, キッズ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 2.7 MB)
全てのバージョンの評価: (4件の評価)
GameCenter対応


ら◯ま1/2ネタを分かってくれればそれで良いです。
「超くりひろい」がリリースされてコンセプトが似てるwwwと
1人でニヤニヤしていました。
そこまで悪くないと思ったけど、売れませんでした!


売れたアプリに比べると差があり過ぎる!!!
もっと頑張ります!


[LevelHelper講座]第2回:cocos2d-xに組み込む

前回はプロジェクトの作成までお知らせしました。
次はcocos2d-xにLevelHelperを組み込みましょう。

cocos2d-xで使うにはLevelHelper用のソースファイルを書き出す必要があります。
Supporting Codeタブを選択して、書きだすコードの種類を選択してください。
s_20130120_18.png

s_20130120_19.png

File→GenerateCode→Cocos2d-xを選択してください。
s_20130120_20.png

s_20130120_21.png

これで書き出しは完了です。

書き出すタイミング
毎回書き出す必要はありません。

・新しいタグを追加した時
・新しい独自クラスを追加した時
・LevelHelperの最新版を指定した時

それ以外は書き出す事はありません。
画像を動かしたら、LevelHelperを保存するだけで反映されます。


Xcodeに追加していく
Xcodeを起動して、今までサンプルで使用していた「GaomarTest」プロジェクトを選択してください。
ResourcesフォルダにLevelHelperファイルとSpriteHelperファイルを追加していきます。
s_20130120_24.png

s_20130120_25.png

ソースの編集
HelloWorldScene.hとHelloWorldScene.cppファイルを編集します。

LevelHelperLoader.hをインクルードして、変数を指定します。

#ifndef __HELLO_WORLD_H__
#define __HELLO_WORLD_H__

// When you import this file, you import all the cocos2d classes
#include "cocos2d.h"
#include "Box2D.h"
#include "LevelHelperLoader.h"

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

// returns a Scene that contains the HelloWorld as the only child
static cocos2d::CCScene* scene();

void initPhysics();
virtual void draw();
virtual void ccTouchesEnded(cocos2d::CCSet* touches, cocos2d::CCEvent* event);
void update(float dt);

private:
b2World* world;
LevelHelperLoader* lh;

void keyBackClicked();
void keyMenuClicked();
void twitterTapped();
};

#endif // __HELLO_WORLD_H__




//
// HelloWorldScene.cpp
// gaomarTest
//
// Created by hirophilip on 2013/01/12.
// Copyright __MyCompanyName__ 2013年. All rights reserved.
//
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
// Android Includes
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
#include "JNICalls/InterfaceJNI.h"
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "ObjCCalls.h"
#endif
#include "LHSettings.h"

using namespace cocos2d;
using namespace CocosDenshion;

#define PTM_RATIO 32

enum {
kTagParentNode = 1,
};

HelloWorld::HelloWorld()
{
setTouchEnabled( true );
setKeypadEnabled( true );

CCSize s = CCDirector::sharedDirector()->getWinSize();
// init physics
this->initPhysics();

scheduleUpdate();
}

HelloWorld::~HelloWorld()
{
delete lh;
lh = NULL;

delete world;
world = NULL;

//delete m_debugDraw;
}

void HelloWorld::initPhysics()
{

CCSize s = CCDirector::sharedDirector()->getWinSize();

b2Vec2 gravity;
gravity.Set(0.0f, -10.0f);
world = new b2World(gravity);

// Do we want to let bodies sleep?
world->SetAllowSleeping(true);
world->SetContinuousPhysics(true);

// LevelHelper初期化
lh = new LevelHelperLoader("GaomarTest.plhs");
LHSettings::sharedInstance()->setLhPtmRatio(PTM_RATIO);
lh->addObjectsToWorld(world, this);

if(lh->hasPhysicBoundaries())
lh->createPhysicBoundaries(world);

if(!lh->isGravityZero())
lh->createGravity(world);



}

void HelloWorld::draw()
{
//
// IMPORTANT:
// This is only for debug purposes
// It is recommend to disable it
//
CCLayer::draw();
ccGLEnableVertexAttribs( kCCVertexAttribFlag_Position );
kmGLPushMatrix();
world->DrawDebugData();
kmGLPopMatrix();
}


void HelloWorld::update(float dt)
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/

int velocityIterations = 8;
int positionIterations = 1;

// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
world->Step(dt, velocityIterations, positionIterations);

//Iterate over the bodies in the physics world
for (b2Body* b = world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite* myActor = (CCSprite*)b->GetUserData();
myActor->setPosition( CCPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO) );
myActor->setRotation( -1 * CC_RADIANS_TO_DEGREES(b->GetAngle()) );
}
}
}

void HelloWorld::ccTouchesEnded(CCSet* touches, CCEvent* event)
{
//Add a new body/atlas sprite at the touched location
CCSetIterator it;
CCTouch* touch;

for( it = touches->begin(); it != touches->end(); it++)
{
touch = (CCTouch*)(*it);

if(!touch)
break;

CCPoint location = touch->getLocationInView();
location = CCDirector::sharedDirector()->convertToGL(location);

}
}


CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();

// add layer as a child to scene
CCLayer* layer = new HelloWorld();
scene->addChild(layer);
layer->release();

return scene;
}



41行目で解放処理をしてます

HelloWorld::~HelloWorld()
{
delete lh;
lh = NULL;



LevelHelperのファイルを指定して初期化しています。
65行目はおまじないです。今の最新版は書かなくても良さげですが、
Box2d周りでこの1行が無かったら結構苦労したんで、書いておきます。

69行目は見えない壁です。
70行目は重力再設定です。LevelHelperで指定した重力に設定し直します。

// LevelHelper初期化
lh = new LevelHelperLoader("GaomarTest.plhs");
LHSettings::sharedInstance()->setLhPtmRatio(PTM_RATIO);
lh->addObjectsToWorld(world, this);

if(lh->hasPhysicBoundaries())
lh->createPhysicBoundaries(world);

if(!lh->isGravityZero())
lh->createGravity(world);



これでビルドして実行すればLevelHelperファイルが読み込まれて、
設置したキャラクターが表示されると思います。
s_20130120_26.png


結構簡単に導入出来ますよ〜
色々LevelHelperを触って試してみましょう!


[LevelHelper講座]第1回:プロジェクトの作成

今日からLevelHelper講座をスタートしたいと思います!
LevelHelperは画像関係の管理を驚くほど簡単にしてくれるすんごいツールです。
細かいことが知りたい方は公式HPでも見てください。

LevelHelperって何?
LevelHelperはcocos2d、cocos2d-x、Corona SDKに対応しています。

LevelHelperは単体では役にたちません(´Д⊂ヽ
SpriteHelperとセットで効果を初めて発揮します。

価格: ¥2,200 (記事公開時)
カテゴリ: 開発ツール
App Storeでダウンロードする。


価格: ¥1,500 (記事公開時)
カテゴリ: 開発ツール
App Storeでダウンロードする。


2つで3,700円程度しますが、購入して全く損はしません!
Free版もありますが、機能がほとんど制限されており、本気でやろうと思っている人は
購入をおすすめします。

SpriteHelperは画像を管理するツールです。
アニメーションの管理や、Box2dの管理もしてくれます。

LevelHelperはSpriteHelperで作成した画像を利用して配置などをしていくツールです。

プロジェクトの作成
さっそくLevelHelperを使ってみましょう。
先ずはプロジェクトの作成から。

New Projectを選択
s_20130120_0.png


s_20130120_1.png

s_20130120_2.png

s_20130120_3.png


LevelHelperの画面が起動します。
s_20130120_5.png

LevelHelperを保存する。
s_20130120_6.png

「GaomarTest.plhs」という名前で保存しましょう。
cocos2d-xでは、Resourceフォルダの直下に保存してください。
s_20130120_7.png

これで保存されました。
s_20130120_8.png

LevelHelperを使ってみよう!
LevelHelperはSpriteHelperとセットで使って、
初めて力を発揮します。

SpriteHelperを起動して画像を登録していきましょう。
s_20130120_9.png

シート名を入力して、Auto Layout Spritesでシートを保存します。
s_20130120_10.png

最後にSpriteHelperを保存します。
s_20130120_11.png

s_20130120_13.png

LevelHelperのファイルと同じ所に保存します。
s_20130120_14.png

LevelHelperの左下にある更新ボタンを押すと、SpriteHelperのファイルが読み込まれました。
s_20130120_15.png

ドラッグアンドドロップで好きな位置に画像を配置できます。
見ながらできるから直感的!
s_20130120_16.png

SceneTesterを押すと、シミュレータが起動して、
簡単な動きを確認することが出来ます。

s_20130120_17.png

cocos2d-xからツイートする [Android版:JNI編]

前回はcocos2d-xからツイートする [Android版:簡易編]で簡単なツイート機能をお知らせしました。
今回はJNIというc++⇔Javaのやり取りが出来る機能を使ってみましょう。

今日お知らせするのは、c++→Javaという方向です。
Javaにあるメソッドを直接実行させてみましょう。

前回のサンプルに少し手を加えます。

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

private:
void twitterTapped();

};



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

HelloWorld::HelloWorld()
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

CCMenuItemImage* btnTwitter = CCMenuItemImage::create("btnTwitter_OFF.png",
"btnTwitter_ON.png",
this,
menu_selector(HelloWorld::twitterTapped));
CCMenu* menu = CCMenu::create(btnTwitter, NULL);
menu->setPosition(ccp(s.width/2, s.height/2));
this->addChild(menu);

}

void HelloWorld::twitterTapped()
{
CCString* sendMsg = CCString::create("つぶやきテスト");

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
InterfaceJNI::postMessageToTweet(sendMsg->getCString());
#endif

}



次にClassesに「JNICalls」フォルダを作成して、
その中に「InterfaceJNI.cpp」、「InterfaceJNI.h」ファイルを作成してください。
s_20130118_1.png


#ifndef __INTERFACE_JNI_H__
#define __INTERFACE_JNI_H__

#include "cocos2d.h"

class InterfaceJNI
{
public:
static void postMessageToTweet(const char *msg);

protected:

};

#endif // __INTERFACE_JNI_H__




#include "InterfaceJNI.h"
#include "platform/android/jni/JniHelper.h"
#include
#include

// Eclipse側のパッケージ名とjavaファイル名を指定
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxActivity"
// 呼び出すメソッド名
#define METHOD_NAME "tweet"


using namespace cocos2d;

//static JavaVM *gJavaVM;
//static jmethodID mid;
//static jclass mClass;

void InterfaceJNI::postMessageToTweet(const char *msg)
{
JavaVM* jvm = JniHelper::getJavaVM();
int status;
JNIEnv *env;
jmethodID mid;

bool isAttached = false;

CCLog("Static postMessageToTweet");

// Get Status
status = jvm->GetEnv((void **) &env, JNI_VERSION_1_6);



if(status < 0)
{
//LOGE("callback_handler: failed to get JNI environment, " // "assuming native thread");
status = jvm->AttachCurrentThread(&env, NULL);
CCLog("Status 2: %d", status);
if(status < 0)
{
// LOGE("callback_handler: failed to attach " // "current thread");
return;
}
isAttached = true;
CCLog("Status isAttached: %d", isAttached);
}
//-----------------------------------------------------------

CCLog("Status: %d", status);

jclass mClass = env->FindClass(CLASS_NAME);

CCLog("jClass ");

mid = env->GetStaticMethodID(mClass, METHOD_NAME, "(Ljava/lang/String;)V");
jstring stringArg = env->NewStringUTF(msg);
CCLog("mID: %d", mid);

if (mid!=0)
env->CallStaticVoidMethod(mClass, mid, stringArg);

CCLog("Finish");
if(isAttached)
jvm->DetachCurrentThread();

return;
}


7行目にEclipse側で呼び出すパッケージ名とjavaファイル名を指定します。
メソッド名も指定してね〜

// Eclipse側のパッケージ名とjavaファイル名を指定
#define CLASS_NAME "org/cocos2dx/lib/Cocos2dxActivity"
// 呼び出すメソッド名
#define METHOD_NAME "tweet"


51行目でクラスをみつけろ〜

jclass mClass = env->FindClass(CLASS_NAME);

55行目でメソッド名と引数を指定します。
今回はStringを渡したいのでこんな指定。(Ljava/lang/String;)V
最後の「V」は「void」っていう意味だってさ。
他にもあるから気になる人はググレカス

56行目で文字列をUTFに変換するぜ!

mid = env->GetStaticMethodID(mClass, METHOD_NAME, "(Ljava/lang/String;)V");
jstring stringArg = env->NewStringUTF(msg);

60行目で実行!

if (mid!=0)
env->CallStaticVoidMethod(mClass, mid, stringArg);

次はEclipseを編集っす!
あちこち行って申し訳ございませんm(_ _)m
s_20130116_3.png


public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
/////省略////
private static Cocos2dxActivity myActivity;

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

this.mHandler = new Cocos2dxHandler(this);

// Activityを保持する
myActivity = this;

this.init();

Cocos2dxHelper.init(this, this);
}

// InterfaceJNI.cppで設定したメソッド名が呼ばれる
public static void tweet(String msg)
{
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, msg);
myActivity.startActivity(intent);

}



つぶやきボタンを押すと下記のようにダイアログが表示されます。
JNIを使って、前回よりも更にややこしい事になってます。
無理やったら、簡易編でやることをおすすめしますね。

s_20130116_0.png

s_20130116_1.png

s_20130116_2.png

2012年作成アプリダウンロード数TOP10

2012年に僕がiOSの世界に突入してもうじき1年が経ちます。
cocos2d-xは夏ぐらいから触り始めてまだ半年程度ですなぁ〜

日々修行!

さて、2012年に僕が作成したアプリのダウンロード数を大発表しちゃいます(・ω<)

第10位 3,870ダウンロード(Android: 1,412ダウンロード)

ハチャメチャ!糞闘ダービー! 1.0.0(無料)App
カテゴリ: ゲーム, アクション, スポーツ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 4.4 MB)
全てのバージョンの評価: (63件の評価)
GameCenter対応

競馬も若干好きだったんで、作ってみたアプリ。
走ってる競走馬に鳥の糞をぶつけて連鎖を狙うゲーム。
連鎖が綺麗に決まると気持ちいいっ!
糞がついているので、リジェクトされるかビビったけど無事リリース出来た。



第9位 5,907ダウンロード

色鉛筆とがらせ工場 1.0.0(無料)App
カテゴリ: ゲーム, アクション, エンターテインメント, スポーツ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 4 MB)
全てのバージョンの評価: (62件の評価)
GameCenter対応

フリック操作で次々流れてくる色鉛筆を削っていくゲーム。
フリック操作のテストのつもりで作ったけど、意外とダウンロード数が伸びた。
同じような感じで「マッチに火をつけろ」が出て、パクられた!とか1人で思ってた(*´σー`)エヘヘ


第8位 6,300ダウンロード

ビールで黄金比率 1.0.0(無料)App
カテゴリ: ゲーム, アクション, アーケード
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 4.8 MB)
全てのバージョンの評価: (143件の評価)
GameCenter対応

夏場にリリースした事もあって、一気にダウンロードされました。
ゲームとしてはもう少し面白く出来たのでは?と反省してます。
まぁ自分がお酒全く呑めないのが原因でもあるけど(´Д⊂ヽ
今でも1日30DLぐらいはある。
次のビールシーズンに期待!!


第7位 6,485ダウンロード(Android: 6,229DL)

ボールで壁当て 1.1.0(無料)App
カテゴリ: ゲーム, スポーツ, エンターテインメント, アクション
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 3.5 MB)
全てのバージョンの評価: (22件の評価)
GameCenter対応

ボールで手軽に壁当てが出来るゲームです。
結構こういう単純なゲームの方が受け入れられるのかしら?
このアプリからアイコンにも力を入れなくちゃと思い始めます。
運動音痴なのに、スポーツ系アプリばっかり作ってるなぁ〜


第6位 7,775ダウンロード(Android: 3,829DL)

プルバックチキンレース 1.0.0(無料)App
カテゴリ: ゲーム, アクション, レーシング
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 3.1 MB)
全てのバージョンの評価: (66件の評価)
GameCenter対応

cocolo-bitさんにアイデアが良いね!って褒められたアプリです(*´σー`)エヘヘ
チキンレース系のアプリが無いと思い作りました。
車は固定ファンがいるから結構ダウンロードいくね。
これももう少しアイデア次第で面白くなったかもしれません。


第5位 15,769ダウンロード(Android: 5,986DL)

紳士でホッピング 1.2.0(無料)App
カテゴリ: ゲーム, エンターテインメント, スポーツ, アクション
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 8.3 MB)
全てのバージョンの評価: (313件の評価)
GameCenter対応

作ったゲームアプリの中で一番好きかもしれない。
走ってる車に向かってジェントルマンがホッピングで破壊していきます。
アイテムを取ると広告を表示するという何もユーザーにとって嬉しくないアイテムがあったりします。


第4位 20,617ダウンロード(Android: 38,178DL)

ドッキリ!いないいないばあ! 1.0.0(無料)App
カテゴリ: エンターテインメント, ゲーム, さいころ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 6.8 MB)
全てのバージョンの評価: (13件の評価)


近接センサーを利用していないいないばあをするアプリ。
これ実は4回ほどリジェクトされました。
理由はシンプル過ぎるからだって(;´д`)トホホ…
カメラ撮影機能を入れたらすんなり審査通りました。
もしシンプルでリジェクト食らってる人は、カメラ機能を入れてみては?
Androidで一番最初に作ったアプリかもw


第3位 44,905ダウンロード(Android: 54,777DL)

金魚すくいアプリ 1.1.0(無料)App
カテゴリ: ゲーム, アクション, スポーツ
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.4 MB)
全てのバージョンの評価: (1,251件の評価)
GameCenter対応

Android版がめちゃくちゃヒットしたんで、移植しました!
iOS版でも夏場に一気にダウンロードされました♪
今年も期待!


第2位 182,630ダウンロード(Android: 123,719DL)

ぶっ飛び!車でハンマー投げ! 1.4.0(無料)App
カテゴリ: ゲーム, アクション, スポーツ, エンターテインメント
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 3.9 MB)
全てのバージョンの評価: (8,868件の評価)
GameCenter対応

iOSで初めて開発したアプリがいきなり総合23位をとったアプリです。
完全なビギナーズラック!!
Android版は1年半前に出したのですが、最近アップデートをして更にダウンロード数が伸びました!
アップデート大事ね〜


第1位 213,379ダウンロード(Android: 8,244DL)

指先リフティング 1.4.0(無料)App
カテゴリ: ゲーム, スポーツ, スポーツ, アクション
販売元: fuate Co., LTD. - fuate Co., Ltd.(サイズ: 5.8 MB)
全てのバージョンの評価: (3,934件の評価)
GameCenter対応

第1位はやっぱりこれ!
総合6位まで一気に上り詰めたアプリです。
リフティングゲームが無いと思って作ったのが始まりでした。
結構あちこちから面白いの声が聞けて、かなり勇気付けられたアプリです。

しかし、Android版はiOSで当たったのにも関わらず全くダウンロードされませんでした。
難しい世界やね〜

2012年はこんな感じでした。
iOSアプリ全26本 総ダウンロード数:533,528
Androidアプリ全36本 総ダウンロード:567,838

2つでようやく100万ダウンロードを突破しました!!
今年は更に売れるアプリを目指して頑張ります!


cocos2d-xで縦画面対応する

twitterで話題に上がっていたので、
僕が行なっている縦画面対応は以下の通りです。

■環境
cocos2d-x 2.0.4

RootViewController.mmを編集します。

s_20130117_0.png

// Override to allow orientations other than the default portrait orientation.
// This method is deprecated on ios6
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// 縦の場合
return UIInterfaceOrientationIsPortrait( interfaceOrientation );

}

// For ios6, use supportedInterfaceOrientations & shouldAutorotate instead
- (NSUInteger) supportedInterfaceOrientations{
#ifdef __IPHONE_6_0
// 縦の場合
return UIInterfaceOrientationMaskPortrait;
#endif
}


この2箇所を編集すれば、縦画面になります。
簡単やね(∩´∀`)∩
これで縦画面のゲームも思いのまま!


cocos2d-xからツイートする [Android版:簡易編]

Android側でつぶやきをしてみましょう。
cocos2d-x→Android特有のIntentを起動させてみましょう!

今回のは簡易編として本来ならJNIとかでやり取りすべきなんですが、
それは別の機会にします。
こんなやり方もあるよって事で(∩´∀`)∩ワーイ


class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

private:
void twitterTapped();

};


ポイントはCC_PLATFORM_ANDROIDですね。
Androidのみここの部分がビルドされて実行されます。

HelloWorld::HelloWorld()
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

CCMenuItemImage* btnTwitter = CCMenuItemImage::create("btnTwitter_OFF.png",
"btnTwitter_ON.png",
this,
menu_selector(HelloWorld::twitterTapped));
CCMenu* menu = CCMenu::create(btnTwitter, NULL);
menu->setPosition(ccp(s.width/2, s.height/2));
this->addChild(menu);

}

void HelloWorld::twitterTapped()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
CCMessageBox("twitter@つぶやきテスト", "command");
#endif

}



この18行目にあるCCMessageBoxはcocos2d-xの機能です。
簡易的なダイアログボックスを表示することができます。

#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
CCMessageBox("twitter@つぶやきテスト", "command");
#endif


上記を実行するとCocos2dxActivity.javaにある、
showDialogが呼ばれます。

これを利用して次はAndroid側のソースもいじってみましょう♪
Eclipseを起動してくださいね。

s_20130116_3.png

public abstract class Cocos2dxActivity extends Activity implements Cocos2dxHelperListener {
/////省略////
private static Cocos2dxActivity myActivity;

@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

this.mHandler = new Cocos2dxHandler(this);

// Activityを保持する
myActivity = this;

this.init();

Cocos2dxHelper.init(this, this);
}

@Override
public void showDialog(final String pTitle, final String pMessage) {
if(pTitle.equals("command")&&pMessage.indexOf("twitter") >= 0) {
//「twitter@つぶやきテスト」が飛んできます
// @マークで分割してます。
String[] str = pMessage.split("@");

// ツイッター処理をする
myActivity.twitterPost(str[1]);
} else if (pTitle.equals("command") && pMessage.indexOf("ExitAd") >= 0) {
// Exit広告の処理など

}
}

public void twitterPost(final String message) {
// UIスレッドで実行
Cocos2dxActivity.this.runOnUiThread(new Runnable() {

@Override
public void run() {
// インテント投げて起動するアプリを選択させる
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, message);
startActivity(intent);
}
});

}



つぶやきボタンを押すと下記のようにダイアログが表示されます。
ちょっと初めての方にはややこしいかもしれません。

これを使えば、このタイミングで広告を消したり等、色んな使い方が出来ます。
s_20130116_0.png

s_20130116_1.png

s_20130116_2.png

cocos2d-xからツイートする [iOS版]

cocos2d-xからiOSの資産であるツイート機能を利用して、
つぶやきをしてみましょう。

まず、下記のフレームワークを追加します。

Twitter.framework

objective-c関係のファイルはiOSフォルダに格納します。
今回はObjCCalls.hとObjCCall.mmファイルを新規作成して、そこにツイート機能を組み込んでいきます。

s_20130115_0.png

class ObjCCalls
{
public:
void TwitterPost();

};


#include "ObjCCalls.h"
#import <Twitter/Twitter.h>

void ObjCCalls::TwitterPost()
{
NSString* tweet = [NSString stringWithUTF8String:"tweetTest"];

if([TWTweetComposeViewController canSendTweet])
{
UIViewController *myViewController = [UIApplication sharedApplication].keyWindow.rootViewController;

TWTweetComposeViewController *twitterVC = [[TWTweetComposeViewController alloc]init];
[twitterVC setInitialText: tweet];
twitterVC.completionHandler = ^(TWTweetComposeViewControllerResult res){

[myViewController dismissViewControllerAnimated:YES completion: nil];

};

[myViewController presentViewController: twitterVC animated:YES completion: nil];

}
else {
tweet = [NSString stringWithFormat: @"%@%@",@"http://twitter.com/intent/tweet?text=",tweet];
tweet = [tweet stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:tweet]];
}

tweet = nil;

}


次にcocos2d-x側を編集します

class HelloWorld : public cocos2d::CCLayer {
public:
~HelloWorld();
HelloWorld();

private:
void twitterTapped();

};


キーポイントはCC_PLATFORM_IOSでiOS専用にファイルをインクルードしている所ですな。

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#include "ObjCCalls.h"
#endif

HelloWorld::HelloWorld()
{
CCSize s = CCDirector::sharedDirector()->getWinSize();

CCMenuItemImage* btnTwitter = CCMenuItemImage::create("btnTwitter_OFF.png",
"btnTwitter_ON.png",
this,
menu_selector(HelloWorld::twitterTapped));
CCMenu* menu = CCMenu::create(btnTwitter, NULL);
menu->setPosition(ccp(s.width/2, s.height/2));
this->addChild(menu);

}

void HelloWorld::twitterTapped()
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
ObjCCalls* objc = new ObjCCalls();
objc->TwitterPost();
delete objc;
objc = NULL;
#endif

}



他にもこの機能を利用してGameCenterでスコアを呼び出したり、
送信したり今までの資産を利用出来ると思います。
#ifで囲っているので、Android側にはObjCCalls.hやObjCCalls.mmファイルをコピーする必要はありません。



setKeypadEnabledでAndroidの戻るキーを有効にする

iOSと違いAndroidには戻るキーが存在します。
僕がAndroidをメインに使いたい理由がこの戻るキーの存在です。

戻るキーを押してもアプリが終了しない物があり、
ユーザー的には結構イライラしてしまいます。
なんで戻んないだよ糞が!!ってね(^_^;)

戻るキーを有効にする
cocos2d-xではデフォルトの設定は有効ではありません。
下記を記述して戻るキーを有効にしましょう。


// キーパッドを有効にする
setKeypadEnabled( true );


実際に使用例は以下のとおりです。
まずヘッダーにメソッドを記述します。
このメソッド名は決まっているので、変えないようにしましょう。

class HelloWorld : public cocos2d::CCLayer {
}
private:
// 戻るキー押された時
void keyBackClicked();
// メニューキーで何か実行したい場合は書いてください。必須ではないです。
void keyMenuClicked();
};


HelloWorld::HelloWorld()
{
// 画面タッチを有効にする
setTouchEnabled( true );
  // キーパッドを有効にする
setKeypadEnabled( true );

}

void HelloWorld::keyBackClicked()
{
// 戻るキーを押すとゲームを終了させる
CCDirector::sharedDirector()->end();
}

void HelloWorld::keyMenuClicked()
{
// メニューキーで何か実行する場合

}


これでOKです。
戻るキーでExit広告を表示することも可能になりますよ〜
Exit広告のやり方は別の機会にお知らせします。



解像度の設定:setDesignResolutionSizeを使用する

画面解像度がややこしいAndroidでは必ずぶち当たる問題です。
cocos2d-xではこのへんの面倒くさい事を数行で解決してくれます。

AppDelegate.cppのapplicationDidFinishLaunchingで設定します。
s_20130113_0.png


bool AppDelegate::applicationDidFinishLaunching()
{
// initialize director
CCDirector *pDirector = CCDirector::sharedDirector();
pDirector->setOpenGLView(CCEGLView::sharedOpenGLView());

// turn on display FPS
pDirector->setDisplayStats(true);

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
CCEGLView* view = CCDirector::sharedDirector()->getOpenGLView();
CCSize frame = view->getFrameSize();
if (frame.height==1136.0) {
// iPhone5などの解像度
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 568, kResolutionExactFit);
} else {
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionExactFit);
}
#else
// Android用
CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionExactFit);
#endif

// set FPS. the default value is 1.0/60 if you don't call this
pDirector->setAnimationInterval(1.0 / 60);

// create a scene. it's an autorelease object
CCScene *pScene = HelloWorld::scene();

// run
pDirector->runWithScene(pScene);

return true;
}



setDesignResolutionSizeなし
画像サイズそのまんまで表示されます。
設置したブロックとか、画像がちっさいですよね〜
s_20130113_1.png

kResolutionShowAllの場合
縦横比を保って画面一杯に表示されます。
上下が空いちゃってます(^_^;)

CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionShowAll);


s_20130113_2.png

kResolutionExactFitの場合
縦横比を保たないで、引き伸ばされた感じで表示されます。
基本的にこれを利用するとよいでしょう♪

CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionExactFit);


s_20130113_3.png

kResolutionNoBorderの場合
縦横比を保って、全体表示する感じです。
設置したブロックがはみ出ちゃう(´Д⊂ヽ

CCEGLView::sharedOpenGLView()->setDesignResolutionSize(320, 480, kResolutionNoBorder);

s_20130113_4.png

どれを使うかはあなた次第!?

更新したAppDelegate.cppはAndroid側に上書き保存して、
ビルドしてください。
色々設定して実機での表示がどうなるか試してみよう!


cocos2d-x環境構築〜Androidテンプレート起動までその2

前回はcocos2d-x環境構築〜Androidテンプレート起動までその1を解説しました。

今回はその続きです。
iOSで動かしていたClassesファイル、ResourcesファイルをAndroidにあるClasses、Resourcesに上書きしちゃいましょう。

※Android側のタイムスタンプが新しいとビルドがうまく走らない
適当にiOS側のソースを更新してタイムスタンプを新しくしましょう。

s_20130112_9.png



■Android.mkファイルの編集

次にAndroid.mkファイルの編集を行います。
(/Users/hirophilip/Documents/Project/iOS/cocos2d/cocos2d-2.1beta3-x-2.1.0/GaomarTest/proj.android/jni/Android.mk)
下記のように変更してください。

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := game_shared

LOCAL_MODULE_FILENAME := libgame

LOCAL_SRC_FILES := hellocpp/main.cpp ¥
../../Classes/AppDelegate.cpp ¥
../../Classes/HelloWorldScene.cpp

LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes ¥
$(LOCAL_PATH)/../../../cocos2dx/platform ¥
$(LOCAL_PATH)/../../../external ¥
$(LOCAL_PATH)/../../../external/Box2D


LOCAL_WHOLE_STATIC_LIBRARIES := cocos2dx_static cocosdenshion_static cocos_extension_static box2d_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,CocosDenshion/android) ¥
$(call import-module,cocos2dx) ¥
$(call import-module,extensions) $(call import-module,external/Box2D)


編集が終われば保存して、
ターミナルからビルドを行います。
「build_native.sh」を実行しましょう。

# ./build_native.sh

ビルドが失敗すると、9行目〜16行目のパスの位置を再確認しましょう。

ここでビルドが通れば、Androidで実行してみましょう。
画面をタッチするとブロックがポンポン出てくると思います。

s_20130112_10.png

起動出来ればOKです!
おめでとうございます!

画面を縦向きにしたい場合は下記を編集しましょう!
「AndroidManifest.xml」ファイルを編集します。
"landscape"から"portrait"にします。
s_20130112_11.png


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.co.fuate.gaomartest"
android:versionCode="1"
android:versionName="1.0">

<uses-sdk android:minSdkVersion="8"/>

<application android:label="@string/app_name"
android:icon="@drawable/icon">

<activity android:name=".GaomarTest"
android:label="@string/app_name"
android:screenOrientation="portrait"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
android:configChanges="orientation">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<supports-screens android:largeScreens="true"
android:smallScreens="true"
android:anyDensity="true"
android:normalScreens="true"/>
</manifest>



これで縦向きもOK!
s_20130112_12.png

cocos2d-x環境構築〜Androidテンプレート起動までその1

前回はcocos2d-x環境構築〜iOSテンプレート起動までを解説しました。

今回はiOSで作成したテンプレートをAndroidでも動かしてみようと思います。
Androidのエミュレータは動かないので、試すには実機が必須です。

今回のバージョン
・cocos2d-2.1beta3-x-2.1.0
・Eclipse3.7

【環境準備】
Eclipseのインストールはググレカス
AndroidSDKをAndroid SDK | Android Developersからダウンロードして解凍します。

解凍したやつは僕の場合は下記に保存してみました。

/Users/hirophilip/Developer/android-sdks

次にcocos2d-xはc++で開発するので、AndroidNDKを
Android NDK | Android Developersからダウンロードして解凍します。

解凍したやつは僕の場合は下記に保存してみました。

/Users/hirophilip/Developer/android-ndk-r8b



■create-android-project.shの編集

次にcocos2d-xのフォルダにある、
(僕の場合は/Users/hirophilip/Documents/Project/iOS/cocos2d/cocos2d-2.1beta3-x-2.1.0/)

「create-android-project.sh」のNDK_ROOT_LOCALとANDROID_SDK_ROOT_LOCALの
パスを変更します。

# set environment paramters
NDK_ROOT_LOCAL="/Users/hirophilip/Developer/android-ndk-r8b"
ANDROID_SDK_ROOT_LOCAL="/Users/hirophilip/Developer/android-sdks"

NEED_BOX2D=true

Box2dを使うので、NEED_BOX2Dを「true」にしています。


■build_native.shの編集

次にtemplateフォルダにある、
(/Users/hirophilip/Documents/Project/iOS/cocos2d/cocos2d-2.1beta3-x-2.1.0/template/android/)
「build_native.sh」ファイルを編集します。

一番先頭部分に下記を追加してください。

APPNAME="__projectname__"

NDK_ROOT=__ndkroot__
COCOS2DX_ROOT=__cocos2dxroot__
GAME_ROOT=$COCOS2DX_ROOT/__projectname__
GAME_ANDROID_ROOT=$GAME_ROOT/proj.android
RESOURCE_ROOT=$GAME_ROOT/Resources

# options



■copy_files.shの編集

次に同じくtemplateフォルダにある、
(/Users/hirophilip/Documents/Project/iOS/cocos2d/cocos2d-2.1beta3-x-2.1.0/template/android/)
「copy_files.sh」を編集します。

一番下の行に下記を挿入します。

copy_library_src(){
cp -rf $COCOSJAVALIB_ROOT/src/* $APP_DIR/proj.android/src/
}

copy_cpp_h
copy_resouces
copy_src_and_jni
copy_library_src
copy_build_native
copy_ndkgdb
modify_project_classpath
modify_androidmanifest
modify_applicationdemo
modify_layout
copy_icon


【Android用プロジェクト作成】
create-android-project.shをターミナルから実行します。

# ./create-android-project.sh


最初にパッケージ名を入力します。

jp.co.fuate.gaomartest


次に対象とするAndroidのバージョンをIDで指定します。
Android2.2以上を要求しますので、「5」を入力してください。

id: 5 or "android-8"
Name: Android 2.2
Type: Platform
API level: 8
Revision: 3
Skins: HVGA, QVGA, WQVGA400, WQVGA432, WVGA800 (default), WVGA854
ABIs : armeabi


次にプロジェクト名を入力してください。

GaomarTest


スクリプトが実行して、フォルダが作成されていると思います。
s_20130112_4.png

ここでターミナルから作成したフォルダに移動して、
ビルドを行います。
「build_native.sh」を実行しましょう。

# cd ./GaomarTest/proj.android
# ./build_native.sh

最初はビルドに時間がかかります。
AppStoreの審査で待つのは慣れてるでしょうけど、温かい目でビルドが終わるのを待ちましょう。

ここでビルドが失敗した人はパスがミスってませんか?
通るまで必死に調べましょう〜

以降、Androidで動かす場合は必ずこの「build_native.sh」が必要になります。


次にEclipseにプロジェクトをインポートします。
s_20130112_5.png

既存プロジェクトをワークスペースへ
s_20130112_6.png


作ったフォルダを選択して完了をクリック!
※プロジェクトをワークスペースにコピーのチェックは外してください。
s_20130112_7.png

これで実行すればアプリが起動すると思います。
s_20130112_8.png

この画面が実機で出ればOK!
おめでとうございます!

ここでBox2dで動かすって言ってたやんけ!って突っ込まないでください(´Д⊂ヽ
続きはcocos2d-x環境構築〜Androidテンプレート起動までその2で!!


次のページ

FC2Ad

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