iOS spritekitでアイフォンアプリ作成、講座みたいにメモ(1)はじめに
はじめに
iOS向けのSpriteKitでアイフォンアプリを作成しようと思います。
メモとして、記録していきます。
ゲームアプリ開発講座のようになるとよいのですが。
コードの記述が定石でなかったり、王道的でなかったり、無駄、不要なところもあり、適宜修正が必要です。
続きを読む
iOS向けのSpriteKitでアイフォンアプリを作成しようと思います。
メモとして、記録していきます。
ゲームアプリ開発講座のようになるとよいのですが。
コードの記述が定石でなかったり、王道的でなかったり、無駄、不要なところもあり、適宜修正が必要です。
続きを読む
アイフォンアプリをアンドロイドアプリに移植中です。
アイフォンの開発言語はobjective-cで、アンドロイドはJAVA言語になります。JAVAをベースにしてアンドロイドアプリをつくるとしてもアンドロイドアプリのための固有の開発方法がありそうです。
Description Resource Path Location Type
Not targeting the latest versions of Android; compatibility modes apply. Consider testing and updating this version. Consult the android.os.Build.VERSION_CODES javadoc for details. AndroidManifest.xml
android:targetSdkVersion=”18″
しました。
EclipseからAndroidエミュレータを起動してもアプリが実行されない
この記事を参考にしてようやくハローワールドが表示されました。
AndroidActivity.xmlに
Could not find class ‘com.google.ads.AdView’, referenced from method com.AAA.bentannote2.MainActivity.onCreate
Admobのライブラリの挿入方法が教科書のヘルプであるグーグルの説明と異なり、変わったようです。
正しくは、
libs/GoogleAdMobAdsSdk-XXX.jarとなるように、GoogleAdMobAdsSdk-XXX.jarをコピーします。
私は手動で、コピペしました。
もし、すでに、教科書通りにGoogleAdMobAdsSdk-XXX.jarを挿入していたら、挿入済みを一旦削除してください。
すでに登録されているGoogleAdMobAdsSdk-XXX.jarがあるとエラーになります。
AdMobの使い方
Could not find class ‘com.google.ads.AdView’
宣言だけして、初期化を忘れていました。
myArray=new ArrayList
宣言をしたら、どこにでもいいのでまず、初期化を書くように習慣づけたいと思います。
—
x-code,android アイフォンアプリを作ったのでアンドロイドアプリを作ってみよう
アンドロイドアプリなんて作ることはないと思ってました。
アンドロイドアプリを作成するのに、今度はJAVAを覚えなくてはならないという手間が嫌でした。それに、アンドロイドアプリを作っても果たしてダウンロードをする人がいるのか、作っても無駄な作業にナルト思っていました。
しかし、自分の作ったアイフォンアプリが比較的よくできたと思ってしまったので、アンドロイドアプリを作ることにしました。それに、自分が使うアプリなら、誰もダウンロードしてくれなくても、自分が使えていればそれで十分なのかもしれません。
まずは、作り方から勉強します。
内容と構成はアイフォンアプリと同じなので必要な機能を覚えて行きます。
まずは簡単なアプリからはじめます。
アイフォンアプリのx-codeと比較しながらメモをとっていきます。
いずれ、アンドロイドアプリの作り方をすぐに忘れてしまいます。忘れても良いように書いておきます。
アイフォンアプリは、スマートボードを利用してViewを作成すると便利です。アンドロイドは、1アプリで画面展開を一覧表示する機能はないので、1View1画面毎に表示して、作業をします。
レイアウトXMLがView画面に相当し、JAVAクラスからでもオブジェクトを作成できます。
説明文中で、アイフォンアプリ、iOS, XCODE, objective-Cと書いた場合は、アイフォンアプリについての説明を記載したものです。アンドロイドアプリ、eclipse, JAVAと書いた場合は、アンドロイドアプリについての説明を記載したものです。
開発環境、開発言語と細かく区別せず大きな枠で説明しています。解釈上意味不明なところがあると思います。
アイフォンアプリ,XCODEのログ出力
NSLog(@”DB is OK”);
DB is OK
と出力されます。
↓
アンドロイド, JAVAのログ出力
画像
Log.d(“DB”, “OK”);
最初の引数はタグで、ログキャットのタグの列に表示されます。そして、第2引数はテキストの列に表示されます。
DB OK
として、列に別れて出力されます。こちらの方が見やすいかもしれません。
XCODEの場合は、IBActionのメソッドに記載します。
JAVAの場合は、いくつかあります。
また、以下のコードは、少し、コードが長くなります。他にも、レイアウトxmlのボタンに記載してメソッドのように整理できる記載もあります。今回は書籍でよく見かけるコードにしました。
[c]
Button button;
button=(Button)findViewById(R.id.button1);
button.setOnClickListener(new View.ClickListerner(){
public void onClick(View v){
//here
}
});
[/c]
[c]
Button backButton;
backButton=(Button)findViewById(R.id.backButton);
backButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
}
});
[/c]
と、メソッドの引数の中に、メソッドがあるように記載します。
アイフォンでは、PCで事前に作成したSQLite3のファイルをそのまま利用して読み込みます。
書き込みは、CoreDataが利用できます。なお、CoreDataのエンティティ(テーブルみたいなもの)が増えた場合は、インストールしたアプリを削除しないとアプリが起動しない場合があります。
アンドロイド
データベースSQLite3のファイルを参照のみの利用でも、assetフォルダに保管し、使用するときにSQLite3ファイル自体を一旦コピーしてから利用します。
そして、assetフォルダに配置するファイルは1MB以下にする必要があるとのこと。大きすぎるファイルは要注意です。分割するか圧縮する必要があるようです。
参考サイト
[Android Programming] sqliteのDBファイルをPCでつくってandroidで使う – ipreachableの日記
既存のDBをAndroidで使えるようにする方法 – hentekoのdev日記
既存のsqliteファイルをAndroidに組み込む : ナカノ製作所開発備忘録
Y.A.M の 雑記帳: Android あらかじめ作成した SQLite database をアプリに取り込む
XCODEでは、ボタン等をViewに配置し、ヘッダーファイルにドラッグし紐付けします。プログラムで使用しないオブジェクトは紐付けの必要はありません。
JAVAでは、レイアウトのXMLで配置し、クラスに宣言、命令を記載します。
なお、異なるクラスでも同じレイアウトXMLを利用できます。
アイフォン
オブジェクトを自由に好きなように配置できます。
アンドロイド
レイアウトのXMLに別のレイアウトXMLのオブジェクトを利用できる
レイアウトの自由度は低い。まるでウェブブラウザーで表示するhtmlファイルです。
ただし、様々な画像サイズのタブレットに対応できる柔軟性を持っていますが、デザイン性が低くなるかもしれません。
XCODEでは、デリゲートを使用します。
JAVAでは、Applicationを継承したクラスを作ります。
Activityにまたがってグローバルに変数などのオブジェクトを共有するには
アイフォン
プロジェクトのどの場所でもよいですが、フォルダをプロジェクトに作ってわかりやすく配置します。
例えば、pic/back, number, buttonなど。
アンドロイド
resフォルダに保存し、音声ファイルはres/rawに保存します。
アイフォン
アイフォン、iPadのエミュレータが起動します。
レティナ対応のiPadは大きすぎるので、縮小して表示します。特に難しい設定はありません。
アンドロイド
どのターゲットのエミュレータを起動するのか設定し実行します。
もし、エミュレータが実行しても、アプリが起動しない場合は、、、、、を選択します。
ここが一番わかりにくかったです。
アンドロイド
strings.xmlの文字列を取得したいとき
getString(R.string.year) yearは
アイフォン
テーブルビューを使用します。
アンドロイド
(1)は、レイアウトxmllistview_row.xmlに配置されたtextView1、textView2に、マップのquestion, answerの文字列をそれぞれ与えます。
そして、このコードにはありませんが、listview.xmlのListViewに表示させるものです。
(2)は、マップなしの単純なArrayList
[c]
(1)SimpleAdapter simpleAdapter=new SimpleAdapter(this, globals.contactArrayList, R.layout.listview_row,new String[]{"question, answer"}, new int[]{R.id.textView1,R.id.textView2});
(2)adapterQuestionString=new ArrayAdapter<String>(this, R.layout.listview_row,R.id.listRowTextView,globals.arrayPartStrings);
[/c]
—
メタルギア ソリッド V グラウンド・ゼロズ 通常版(初回生産限定特典:本篇『MGSV:TPP』で使用可能なマザーベース スタッフDLC同梱&Amazon.co.jp限定特典:本篇『MGSV:TPP』で使用可能な特殊ダンボール箱DLC付き)プラットフォーム: PlayStation 4、発売予定日は2014年3月20日
Titan Fallタイタンフォール [オンラインコード] [ダウンロード]発売予定日時は2014年3月13日、ガンダムやバルキリー、装甲騎兵ボトムズみたいに人型ロボットに搭乗して敵を倒すゲーム、コックピットからのカメラ映像がリアリティがあり、まさに未来のロボットを操縦する感覚で遊べるゲーム
グラビアアイドル、清水みさと/恋して、みさと先生!
【GoPro HERO3+】LCDタッチ バックパック(リミテッドエディション)「ALCDB-303」在庫あり
「LCDタッチ バックパック」は、GoProカメラ用のLCDタッチスクリーンです。
カメラ背面に装着し、フレーミングや再生など、LCDスクリーンの利便性を提供します。
脱着式なので、不要な時は取り外してGoProカメラをできるだけ軽く小さくコンパクトにすることができます。
cocos2d for iPhone をcocos2d-xに移植する開発過程の記録メモまとめ、Androidクロスプラットフォーム化へ 、(1)〜(6)分の記事まとめしたもの
フレームワークはcocos2d for iPhoneとcocos2d-xです。
(6)マルチディスプレイ対応のためのディレクトリ配置と画像
(5)タップしたときに画像の領域にあるか、画像をタップしたかの判定
(4)update(float delta)、タップイベント
(3)CCArrayにint型を挿入する方法、これがcocos2d-xに見当たらないので、vectorにする
(2)CCTextuer2DからCCSpriteを使う
(1)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモ
—
cocos2d for iPhoneでは、レティナ対応のとき、画像のファイル名は-hdを付記してファイル名としました。これは、aaa.png,aaa-hd.pngというファイルを用意すると、aaa.pngで指定すれば、あとは勝手に判別してくれました。つまり、いちいち、aaa-hd.pngとして指定する必要はありません。
cocos2d-xでは、その方法が異なります。これはアンドロイドにも対応しなければならないため、-hd,-ipadhdとするだけでは対応しきれないと判断したとのこと。
またまた、移植に手間がかかります。
それぞれのスクリーンサイズ、プラットフォームに対応するフォルダーを個別に作成し、同じファイル名にするそうです。
iOS-folder、Retina4、Retina3.5、Android−A、Android-Bのように分類するみたいです。
iPad,iPadRetina,nomal
Android-folder,type1024,typeB,nomal
みたいにしてみます。
そして、パスを指定するコードを各自用意するようです。
cocos2d-x マルチディスプレイに対応させる | studycocos2dx
ツール(複数の画像を一つの画像にまとめて座標のListにしてくれるソフト等のことをここでは指しています)を使って、画像の座標を自動で設定する場合はソフト側が自動で処理してくれるのでプラットフォームや解像度別に座標の比率を考慮する必要はありません。
しかし、ツールを使わずに、ペイントソフトで目算で座標を取得、メモしたりするときは注意が必要です。なぜツールを使わないのかというと、ツールの使い方を覚えるのが面倒であり、修正があるたびにツールを使って修正しなくてはならないので面倒であるからです。扱う画像やアニメーション画像が少ない場合は、ツールを使わずに、ペイントソフトで座標を取得した方がわかりやすくて早いのです。
cocos2d for iPhoneでは、レティナか非レティナで画像の座標を変更する必要があります。
例えば、レティナ対応の場合、100ピクセルの正方形画像があった場合、実際は50ピクセルとして表示されます。これはレティナの密度が倍の密度だからです。そのため、100ピクセルサイズの座標を取得する場合は、半分の100/2のサイズで取得するようにCGRectMakeを指定します。[c]作成した実サイズの大きさ(領域)で指定するのではなくて、実際に表示される大きさ(領域)で指定すると言うことです。[/c]
(1ピクセル1ドットとして説明していますので、ピクセルとドットの概念を取り違えているかもしれません。)
次に、cocos2d-xでは、100ピクセルの正方形画像があった場合、レティナであっても、そのままのサイズで指定します。つまり、cocos2d for iPhoneとは異なるCGRectMakeを指定することになります。
そのままの画像の座標を指定すればよいのです。
指定したサイズがスプライトして表示されます。レティナであれば、その半分のサイズ(倍の密度)で表示されます。
このように、フレームワークが異なるといろいろと設定が異なってきます。こういった設定をきちんと把握することが必要です。
現在学習中です。
cocos2d for iPhone
[c]
CGRect rect=CGRectMake(x, y, w, h);
[/c]
↓
cocos2d-x ココス2d−x
[c]
CCRect rect=CCRect(x, y, w, h);
[/c]
cocos2d for iPhone
[c]
//locationは、-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)eventのCGPoint
CGRect rect=CGRectMake(x, y, w, h);
if(CGRectContainsPoint(rect, location)){
//
}
[/c]
↓
cocos2d-x
[c]
//locationは、ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)のCCPoint
CCRect rect=CCRect(x, y, w, h);
if (rect.containsPoint(location)) {
//
}
[/c]
2013年7月8日現在で動作未確認、コンパイルエラーなし、実行未確認(画像未作成のため)
cocos2d for iPhone
[c]
// CCSprite namiは、ヘッダーに宣言
nami=[CCSprite spriteWithFile:@"nami1.png"];
nami.position=ccp(-80,windowsSize.height/2);
id namiMove=[CCMoveTo actionWithDuration:8.0f position:ccp(500,windowsSize.height/2)];
id callfuncN_nami=[CCCallFuncN actionWithTarget:self selector:@selector(moveNami:)];
id sequence_nami=[CCSequence actions:namiMove,callfuncN_nami, nil];
[nami runAction:[CCRepeatForever actionWithAction:sequence_nami]];
[self addChild:nami];
[/c]
↓
cocos2d-x
[c]
// CCSprite namiは、ヘッダーに宣言
nami=new CCSprite();
nami->initWithFile("nami1.png");
nami->autorelease();
nami->setPosition(ccp(-80,size.height/2));
CCMoveTo *namiMove=CCMoveTo::create(8, ccp(500, size.height/2));
CCCallFuncN *callfuncN_nami=CCCallFuncN::create(this, callfuncN_selector(HelloWorld::moveNami));
CCSequence *sequence_nami=CCSequence::createWithTwoActions(namiMove, callfuncN_nami);
nami->runAction(CCRepeatForever::create(sequence_nami));
this->addChild(nami);
[/c]
参考サイト
c++ – How to play animations in Cocos2d-x? – Game Development Stack Exchange
2013年7月9日現在で動作未確認、コンパイルエラーなし、実行未確認(画像未作成のため)
cocos2d for iPhone
[c]
//anime
CCSprite *tmpSprite=[CCSprite spriteWithFile:@"hiyoko_256by256_base.png"];
CCSpriteFrame *frame1=[CCSpriteFrame frameWithTexture:tmpSprite.texture
rect:CGRectMake(0, 0, 60, 60 )];
CCSpriteFrame *frame2=[CCSpriteFrame frameWithTexture:tmpSprite.texture
rect:CGRectMake(60, 0, 60, 60 )];
CCSpriteFrame *frame3=[CCSpriteFrame frameWithTexture:tmpSprite.texture
rect:CGRectMake(120, 0, 60, 60 )];
CCSpriteFrame *frame4=[CCSpriteFrame frameWithTexture:tmpSprite.texture
rect:CGRectMake(180, 0, 60, 60 )];
NSArray *animFrames=[NSArray arrayWithObjects:frame1,frame2
,frame3,frame4, nil];
animation_test=[CCAnimation animationWithSpriteFrames:animFrames delay:0.1f];
[/c]
↓
cocos2d-x
[c]
CCTexture2D *animeTexture=new CCTexture2D();
CCImage *animeImg=new CCImage();
animeImg->initWithImageFile("hiyoko_256by256_base.png");
animeTexture->initWithImage(animeImg);
CCSpriteFrame *frame1=new CCSpriteFrame();
CCSpriteFrame *frame2=new CCSpriteFrame();
CCSpriteFrame *frame3=new CCSpriteFrame();
CCSpriteFrame *frame4=new CCSpriteFrame();
frame1->initWithTexture(animeTexture, CCRectMake(0, 0, 60, 60));
frame2->initWithTexture(animeTexture, CCRectMake(60, 0, 60, 60));
frame3->initWithTexture(animeTexture, CCRectMake(120, 0, 60, 60));
frame4->initWithTexture(animeTexture, CCRectMake(180, 0, 60, 60));
CCArray *animFrames=new CCArray();
animFrames->initWithCapacity(4);
animFrames->addObject(frame1);
animFrames->addObject(frame2);
animFrames->addObject(frame3);
animFrames->addObject(frame4);
animation_test->initWithAnimationFrames(animFrames, 0.1, true);
//or CCAnimation *animation = CCAnimation::createWithSpriteFrames(animFrames, 0.3f);
//sprite->runAction(CCRepeatForever::create(CCAnimate::create(animation)));
[/c]
[c]
[SimpleAudioEngine sharedEngine].backgroundMusicVolume=0.3f;
[[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"BGM2-hiyoko_out64k.mp3" loop:YES];
[/c]
↓
cocos2d-x
[c]
SimpleAudioEngine::sharedEngine()->setBackgroundMusicVolume(0.3);
SimpleAudioEngine::sharedEngine()->playBackgroundMusic("BGM2-hiyoko_out64k.mp3", true);
[/c]
4
cocos2d-xの参考になるサイトです。
CCActionを利用する
cocos2d for iPhone
[c]
[[CCDirector sharedDirector]pause];
[/c]
↓
ココス2d−x
[c]
CCDirector::sharedDirector()->pause();
[/c]
cocos2d for iPhone
[c]
CCMenuItemImage *item=[CCMenuItemImage itemWithNormalImage:@"seiseki.png"
selectedImage:@"seiseki_down.png"
target:self selector:@selector(doSeiseki:)];
CCMenu *menu_miss=[CCMenu menuWithItems:item, nil];
menu_miss.position=ccp(windowsSize.width/2,40);
[self addChild:menu_miss];//
[/c]
↓
ココス2d−x
[c]
CCMenuItemImage *item=new CCMenuItemImage();
item->initWithNormalImage("seiseki.png", "seiseki_down.png", "seiseki.png", this, menu_selector(HelloWorld::doSeiseki));
item->autorelease();
CCMenu *menu_miss=CCMenu::create(item,NULL);
menu_miss->setPosition(ccp(size.width/2,40) ) ;
this->addChild(menu_miss,20);
[/c]
cocos2d for iPhone
CCLabelTTF *limiTime;
NSString *limitTimeString=[NSString stringWithFormat:@”%02d”,allCount-tcount];
limitTime=[CCLabelTTF labelWithString:limitTimeString
fontName:@”Helvetica”
fontSize:32 ];
limitTime.position =ccp(140,300);
limitTime.color =(ccc3(200, 0, 0));
[limitTime setString:limitTimeString];
↓
ココス2d−x
const char* string=CCString::createWithFormat(“%d”,allCount-tcount)->getCString();
CCLabelTTF *limiTime;
limiTime->initWithString(climitTimeString, “Helvetica”, 32);
limiTime->autorelease() ;
limiTime->setString(string);
cocos2d for iPhone
ヘッダーファイルには記載なしか必要に応じて記載する
init()内
[self scheduleUpdate];
-(void)update:(ccTime)dt{
//
}
↓
ココス2d−x
ヘッダーファイル
virtual void update(float delta);
C++ファイル
init()に記載
this->scheduleUpdate();
void HelloWorld::update(float delta){
//
}
cocos2d for iPhone
CCArray *array;(初期化、配列数、オブジェクトの追加は省略してます。)
CCSprite *sprite=[array objectAtIndex:i];
↓
ココス2d−x
CCArray *array;(初期化、配列数、オブジェクトの追加は省略してます。)
CCSprite *sprite=new CCSprite();
sprite=(CCSprite*)array->objectAtIndex(i);
sprite->autorelease();
TRUEで表示、FALSEで見えない状態にします。
cocos2d for iPhone
sprite.visible=TRUE;
↓
ココス2d−x
sprite->setVisible(true);
cocos2d for iPhone
宣言.h特に記入なし
シングルタップなので、init()内に記載なし。
[c]
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
return YES;
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint locationInView=[touch locationInView:[touch view]];
CGPoint location=[[CCDirector sharedDirector]convertToGL:locationInView];
//必要に応じてタップの処理を記入
}
[/c]
↓
ココス2d−x
宣言.h バーチャル仮想関数で宣言します。
virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);
init()内に
setTouchEnabled(true);
setTouchMode(kCCTouchesOneByOne);
関数
[c]
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent){
CCDirector *pDirector=CCDirector::sharedDirector();
CCPoint touchPoint=pDirector->convertToGL(pTouch->getLocationInView());
//必要に応じてタップの処理を記入
}
[/c]
topへ
cocos2d for iPhone
background.anchorPoint=ccp(0,0);
↓
ココス2d−x
background->setAnchorPoint(ccp(0,0));
cocos2d for iPhone
CGSize size=[[CCDirector sharedDirector]winSize];
↓
cocos2d-x
CCSize size=CCDirector::sharedDirector()->getWinSize();
size.width
size.height
CCStringはNSStringの変わりのように利用できません。
char型になります。
cocos2d for iPhone
[c]limitTime=[CCLabelTTF labelWithString:limitTimeString
fontName:@"Helvetica"
fontSize:32 ];
limitTime.position =ccp(140,300);
limitTime.color =(ccc3(200, 0, 0));
[limitTime setString:limitTimeString];
[self addChild:limitTime z:60 ];
[/c]
↓
cocos2d-x
CCStringはそのままでは使えません。char型にする必要があります。
アンドロイドへのクロスプラットフォームのことがあるので、余計な道に入らない王道で記載します。
[c]const char* climitTimeString;//
limiTime =CCLabelTTF::create(climitTimeString, "Helvetica", 32);
or
limiTime=new CCLabelTTF();
limiTime->initWithString(climitTimeString, "Helvetica", 32);
limiTime->autorelease() ;
this->addChild(limiTime,30);
limiTime->setPosition(ccp(size.width/2,size.height-30));
limiTime->setColor(ccc3(200, 0, 0));
limiTime->setString(climitTimeString);
[/c]
init側ならばリリースができる。
cocos2d for iPhone
[c] int i;
i=10;
NSString* str;
str = [ NSString stringWithFormat : @"%02d", i];[/c]
↓
cocos2d-x
[c]int i;
i=10;
const char* climitTimeString=CCString::createWithFormat("%d",i)->getCString();[/c]
cocos2d for iPhone
[c]CCSprite *restSprite=[CCSprite spriteWithFile:@"base.png"];
restSprite.contentSize.height;//これを代入したりますがここでは省略してます。[/c]
↓
cocos2d-x
[c]CCSprite * restSprite=new CCSprite();
restSprite->initWithFile("sample.png");
restSPrite->autorelease;
restSprite->getContentSize().height;//これを代入したりますがここでは省略してます。[/c]
たぶんどっちもあり
int tmpRandom=arc4random_uniform(5);
・CCArrayにint型を挿入する方法、これがcocos2d-xに見当たらないので、vectorにする
CCArray型のarrayにintを追加します。
NSNumberオブジェクト使ってINTを配列に入れます。
[c][array addObject:[NSNumber numberWithInt:(30)]];[/c]
↓
cocos2d-x
オブジェクトであれば、CCArrayに追加、挿入できますが、int型なのでできません。
cocos2d-xに見当たらない、探すのが面倒なので、vectorにする
[c] vector<int> v_ar_speed;
vector<int>::iterator begin,end;
v_ar_speed.push_back( 10 );//追加
v_ar_speed[0];//として呼び出し可能[/c]
topへ
(2)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモ、Androidクロスプラットフォーム化へ CCTextuer2DからCCSpriteを使う
2
いろいろと本を3冊買って、cocos2d for iPhone をcocos2d-xに移植する過程を試みていますが、結構進みません。
objective-cをc++にしようとするとかなり時間がかかりそうです。すんなりとはいきません。
C++であるcocos2d-xは、オブジェクトの生成の時にnewを使用します。
一方のobjective-cはそのまま記載して画像を設定します。
[c]
CCSprite *sprite=new CCSprite();
sprite->initWithFile("hiyoko_sample.png");
sprite->setPosition(ccp(0,0);
this->addChild(sprite);
[/c]
[c]
CCSprite *sprite=[CCSprite spriteWithFile:@"hiyoko_sample.png"];
sprite.position=ccp(0,0);
[self addChild:s];
[/c]
[c]
int iTimer;
//schedule 1秒ごとに加算する
bool HelloWorld::init()//この場所にスケジュールをした場合
{
this->schedule(schedule_selector(HelloWorld::timer), 1.0);
this->scheduleUpdate();
}
—
void HelloWorld::timer(){
iTimer++;
}
[/c]
[c]
[self schedule:@selector(timer:) interval:1.0f];
-(void)timer:(ccTime*)delta{
iTimer++;
}
[/c]
[c]
CCSprite *test
int x;
int y;
x=test->getPositionX();
y=test->getPositionY();
[/c]
[c]
CCSprite *test
int x;
int y;
x=test.position.x
y=test.position.y
[/c]
タイトル:Converting snipets of code from Cocos2d-Iphone to Cocos2d-x
>Cocos2d-iphone
CCArray *spiders = [[CCArray alloc] initWithCapacity:5];
>Cocos2d-X
CCArray *spiders=CCArray::createWithCapacity(5);
Texture2dText.cpp
CCTextureCache使うときは、CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo();
が必要
[c]
void TextureMipMap::onEnter()
{
TextureDemo::onEnter();
CCSize s = CCDirector::sharedDirector()->getWinSize();
CCTexture2D *texture0 = CCTextureCache::sharedTextureCache()->addImage("Images/grossini_dance_atlas.png");
texture0->generateMipmap();
ccTexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE };
texture0->setTexParameters(&texParams);
CCTexture2D *texture1 = CCTextureCache::sharedTextureCache()->addImage("Images/grossini_dance_atlas_nomipmap.png");
CCSprite *img0 = CCSprite::createWithTexture(texture0);
img0->setTextureRect(CCRectMake(85, 121, 85, 121));
img0->setPosition(ccp( s.width/3.0f, s.height/2.0f));
addChild(img0);
CCSprite *img1 = CCSprite::createWithTexture(texture1);
img1->setTextureRect(CCRectMake(85, 121, 85, 121));
img1->setPosition(ccp( 2*s.width/3.0f, s.height/2.0f));
addChild(img1);
CCEaseOut* scale1 = CCEaseOut::create(CCScaleBy::create(4, 0.01f), 3);
CCActionInterval* sc_back = scale1->reverse();
CCEaseOut* scale2 = (CCEaseOut*) (scale1->copy());
scale2->autorelease();
CCActionInterval* sc_back2 = scale2->reverse();
img0->runAction(CCRepeatForever::create(CCSequence::create(scale1, sc_back, NULL)));
img1->runAction(CCRepeatForever::create(CCSequence::create(scale2, sc_back2, NULL)));
CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo();
}
[/c]
[c]
UIImage *img =[UIImage imageNamed:filename];
CGImageRef imageRefAll =[img CGImage];
textureOther =[[CCTexture2D alloc]initWithCGImage:imageRefAll resolutionType:kCCResolutioniPhoneRetinaDisplay];
[/c]
CCTexure2Dでの注意、initWithTextureだと autorelease() is oK。しかし、CCSprite::createWithTextureでは、autorelease()を設定すると実行後しばらくしてエラーになる。
半自動か、手動管理のメモリ管理を決めましょう。
[c]
CCTexture2D *testTexure=new CCTexture2D();
CCImage *img=new CCImage();//UIImage
img->initWithImageFile("hiyoko_sample.png");
testTexure->initWithImage(img);
CCSprite *testSprite=new CCSprite();
//Textureの設定ではinitでも::createでもOKでもautoreleaseはinitになる。
testSprite->initWithTexture(testTexure);//OK autorelease() is oK.
//testSprite=CCSprite::createWithTexture(testTexure);//OK //but, not autorerelease()
this->addChild(testSprite);
testSprite->setPosition(ccp(120,240));
testTexure->autorelease();
testSprite->autorelease();//for initWithTexure
[/c]
スマートフォンの市場は、アイフォンとアンドロイドの2つの勢力でほぼ占めています。アイフォンで作ったアプリをAndroidへも展開することで、ごく単純に考えて2倍のダウンロード数が可能になる計算になります(実際は、そこまでいかないでしょうけど)。
アイフォンアプリは、MacOSX上で動作するXCODEでobjective-cを使用します。アンドロイド用アプリは、JAVAを使用します。つまり、objective-cとJAVAなわけですから、かたやオブジェクト指向のC言語(C++ではないのにオブジェクト指向)とオブジェクト指向の本流の言語として、開発環境が異なると言うことになります。ゲームシナリオやアルゴリズム、画像、音楽データ、データベースなどは同じものが使えるとして、コーディングについては、ほぼ別のものを作る必要があります。
コードを共通化したい
そこで、クロスプラットフォームとして、cocos2d-xを使うことにします。
cocos2d for iPhoneとcocos2d-xとは
「cocos2d for iPhone」 とはアイフォンアプリでゲームを作るためのフレームワークで、xcodeでobjective-cを使います。
「cocos2d-x」はアイフォンアプリでゲームを作るためのフレームワークで、xcodeでc++を使います
cocos2d-xのメリットは、Androidアプリを作るためのクロスプラットホームのための効率化です。アイフォン用として動作するアプリ(コード)がAndroidアプリと動作することができます。
つまり、アイフォンアプリを作ってAndroidへ移植する時の効率が非常に優れていることです。「cocos2d for iPhone」で作った場合、Androidへそのままコードをコピペしても動きません。ゼロからJAVA用に書き換える必要があります。こうかくと「cocos2d for iPhone」の利便性が低いように思えますが、「cocos2d for iPhone」はobjective-cでコードを記載するので、MacOSX,iOSアプリを作っている人が利用しやすく、objective-c固有のコードやライブラリを使用することができます。ただ、ゲームの世界でobjective-c固有のコードやライブラリを使用するのは多いことではありません。
クロスプラットフォームとして考えるとどうしても「cocos2d-x」が優位と考えられます。
ゲームメーカーも「cocos2d-x」を利用しているそうです。
cocos2d for iPhoneとcocos2d-xのどちらもcocos2dと冠しているのでコマンドの内容や指定手順はほとんど同じです。objective-cかc++というほんの少し文法が違う点を除けば、同じ感覚でプログラムを作っていくことができます。
まず、以前作成したひよこレスキューというアイフォンアプリcocos2d for iPhone をcocos2d-xに移植しAndroidアプリとして公開しようと思います。
画面
今回が初めての試みですので、途中で挫折するか、別のアプリを作成する方向に変わるかもしれません。そのときはごめんなさい。
<第一回>
キャラクタクラスを作成し、画像を表示する
クラスの作成
CCSpriteクラスを承継するcHiyokoクラスを作成
スプライトを設定し、クラス生成
C++の文法を忘れてます。ほんとに覚えることがあって大変です。
やっとobjective-cのコーディングになれてきたのに。
(正式な方法や正式名称を使わずに、説明しているところがあります。
ご注意ください。)
objective-Cでは、クラスを
voidをかっこで挟んで、マイナスをつけます。
AA.m
-(void)function{//メソッドのあとに、かっこがない
}
となります。
C++ではクラス名があって::をつけてメソッドを書きます。
AA.mm
クラス名::function(){//メソッドの後にかっこ必要
}
まず、C++なので当然ながらプロパティがなくて、マクロを利用します。
CC_SYNTHESIZE(cocos2d::CCSprite, _spriteHiyoko, spriteHiyoko);
こんな感じ。このとき、型の宣言とプロパティ、シンセサイズまでまとめて設定されます。
クラスメソッドは、
ID型がないので、boolかstaticにしてポインタにします。
ここらへんがややこしくなります。
+(CCScene *) scene
は、static cocos2d::CCScene* scene();みたいになります。
インスタンスメソッドは、マイナスのついたメソッドのことですが、boolになります。
<感想>
objective-cからC++への移植は思ったよりも難航しそうです。
まず、何を何から変えてよいのかわからない。
単純にそのまま、表示させる程度のものでも、
(4)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモ、Androidクロスプラットフォーム化へ 、スケジュールupdate(float delta)、タップイベント
cocos2d-xの参考になるサイトです。
CCActionを利用する
・ポーズ
cocos2d for iPhone
[[CCDirector sharedDirector]pause];
↓
ココス2d−x
CCDirector::sharedDirector()->pause();
・メニュー
cocos2d for iPhone
CCMenuItemImage *item=[CCMenuItemImage itemWithNormalImage:@”seiseki.png” selectedImage:@”seiseki_down.png”
target:self selector:@selector(doSeiseki:)];
CCMenu *menu_miss=[CCMenu menuWithItems:item, nil];
menu_miss.position=ccp(windowsSize.width/2,40);
[self addChild:menu_miss];//
↓
ココス2d−x
CCMenuItemImage *item=new CCMenuItemImage();
item->initWithNormalImage(“seiseki.png”, “seiseki_down.png”, “seiseki.png”, this, menu_selector(HelloWorld::doSeiseki));
item->autorelease();
CCMenu *menu_miss=CCMenu::create(item,NULL);
menu_miss->setPosition(ccp(size.width/2,40) ) ;
this->addChild(menu_miss,20);
・CCLabelTTF の文字列設定 setString(const char*)
cocos2d for iPhone
CCLabelTTF *limiTime;
NSString *limitTimeString=[NSString stringWithFormat:@”%02d”,allCount-tcount];
limitTime=[CCLabelTTF labelWithString:limitTimeString
fontName:@”Helvetica”
fontSize:32 ];
limitTime.position =ccp(140,300);
limitTime.color =(ccc3(200, 0, 0));
[limitTime setString:limitTimeString];
↓
ココス2d−x
const char* string=CCString::createWithFormat(“%d”,allCount-tcount)->getCString();
CCLabelTTF *limiTime;
limiTime->initWithString(climitTimeString, “Helvetica”, 32);
limiTime->autorelease() ;
limiTime->setString(string);
・定期スケジュール(1/30、1/60)
cocos2d for iPhone
ヘッダーファイルには記載なしか必要に応じて記載する
init()内
[self scheduleUpdate];
-(void)update:(ccTime)dt{
//
}
↓
ココス2d−x
ヘッダーファイル
virtual void update(float delta);
C++ファイル
init()に記載
this->scheduleUpdate();
void HelloWorld::update(float delta){
//
}
・CCArrayにCCSpriteオブジェクトを追加して、CCSpriteにコピーするとき
cocos2d for iPhone
CCArray *array;(初期化、配列数、オブジェクトの追加は省略してます。)
CCSprite *sprite=[array objectAtIndex:i];
↓
ココス2d−x
CCArray *array;(初期化、配列数、オブジェクトの追加は省略してます。)
CCSprite *sprite=new CCSprite();
sprite=(CCSprite*)array->objectAtIndex(i);
sprite->autorelease();
・表示可否ビジブル
TRUEで表示、FALSEで見えない状態にします。
cocos2d for iPhone
sprite.visible=TRUE;
↓
ココス2d−x
sprite->setVisible(true);
・タップイベント シングルタップ
cocos2d for iPhone
宣言.h特に記入なし
シングルタップなので、init()内に記載なし。
-(BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event{
return YES;
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint locationInView=[touch locationInView:[touch view]];
CGPoint location=[[CCDirector sharedDirector]convertToGL:locationInView];
//必要に応じてタップの処理を記入
}
↓
ココス2d−x
宣言.h バーチャル仮想関数で宣言します。
virtual bool ccTouchBegan(CCTouch *pTouch,CCEvent *pEvent);
virtual void ccTouchEnded(CCTouch *pTouch,CCEvent *pEvent);
init()内に
setTouchEnabled(true);
setTouchMode(kCCTouchesOneByOne);
関数
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
return true;
}
void HelloWorld::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent){
CCDirector *pDirector=CCDirector::sharedDirector();
CCPoint touchPoint=pDirector->convertToGL(pTouch->getLocationInView());
//必要に応じてタップの処理を記入
}
31![]() ドラゴンボールSCultures 造形天下一武道会3 其ノ一 全2種 人造人間18号・チチ在庫あり 店舗名:電脳萬屋弐号館 楽天市場店 |
32![]() ■予約■【フィギュア】モモ・ベリア・デビルーク (2013年11月発売)在庫無し 店舗名:Jam |
33![]() ROBOT魂<SIDE FFN> ファフナー・マークザイン在庫あり 店舗名:トイズボックス楽天市場店 |
34![]() トランスフォーマープライム AM-03 クリフジャンパー【キャラクターセール☆トランスフォーマー】在庫あり 店舗名:トイセルタウン |
35![]() 【再生産】超像可動 ジョジョの奇妙な冒険 第三部 空条承太郎・セカンド(荒木飛呂彦指定カラー) 【税込】 メディコス [ジョジョ3クウジョウジョウタロウ2nd]【返品種別B】【送料無料】在庫あり 店舗名:Joshin web 家電とPCの大型専門店 |
36![]() トランスフォーマープライムAM-11 アーシー【キャラクターセール☆トランスフォーマー】在庫あり 店舗名:トイセルタウン |
CCArrayにint型を挿入する方法がわかりました。
CCIntegerを使うみたいです。以下に記載しました。
(1)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモ
(2)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモCCTextuer2DからCCSpriteを使う
cocos2d for iPhone
background.anchorPoint=ccp(0,0);
↓
ココス2d−x
background->setAnchorPoint(ccp(0,0));
cocos2d for iPhone
CGSize size=[[CCDirector sharedDirector]winSize];
↓
cocos2d-x
CCSize size=CCDirector::sharedDirector()->getWinSize();
size.width
size.height
CCStringはNSStringの変わりのように利用できません。
char型になります。
cocos2d for iPhone
limitTime=[CCLabelTTF labelWithString:limitTimeString
fontName:@”Helvetica”
fontSize:32 ];
limitTime.position =ccp(140,300);
limitTime.color =(ccc3(200, 0, 0));
[limitTime setString:limitTimeString];
[self addChild:limitTime z:60 ];
↓
cocos2d-x
CCStringはそのままでは使えません。char型にする必要があります。
アンドロイドへのクロスプラットフォームのことがあるので、余計な道に入らない王道で記載します。
const char* climitTimeString;//
CCLabelTTF *limiTime =CCLabelTTF::create(climitTimeString, “Helvetica”, 32);
or
limiTime=new CCLabelTTF();
limiTime->initWithString(climitTimeString, “Helvetica”, 32);
limiTime->autorelease() ;
this->addChild(limiTime,30);
limiTime->setPosition(ccp(size.width/2,size.height-30));
limiTime->setColor(ccc3(200, 0, 0));
limiTime->setString(climitTimeString);
init側ならばリリースができる。
cocos2d for iPhone
int i;
i=10;
NSString* str;
str = [ NSString stringWithFormat : @”%02d”, i];
↓
cocos2d-x
int i;
i=10;
const char* climitTimeString=CCString::createWithFormat(“%d”,i)->getCString();
cocos2d for iPhone
CCSprite *restSprite=[CCSprite spriteWithFile:@”base.png”];
restSprite.contentSize.height;//これを代入したりますがここでは省略してます。
↓
cocos2d-x
CCSprite * restSprite=new CCSprite();
restSprite->initWithFile(“sample.png”);
restSPrite->autorelease;
restSprite->getContentSize().height;//これを代入したりますがここでは省略してます。
たぶんどっちもあり
int tmpRandom=arc4random_uniform(5);
CCArray型のarrayにintを追加します。
NSNumberオブジェクト使ってINTを配列に入れます。
[array addObject:[NSNumber numberWithInt:(30)]];
↓
cocos2d-x
オブジェクトであれば、CCArrayに追加、挿入できますが、int型なのでできません。
cocos2d-xに見当たらない、探すのが面倒なので、vectorにする
vector
vector
v_ar_speed.push_back( 10 );//追加
v_ar_speed[0];//として呼び出し可能
その後、CCIntegerを使えば良いみたいです。
[cocos2d-x入門 クロスプラットフォームによるゲーム開発 クロスプラットフォームによるゲーム開発]に書いてありました。
それを参考にしました。
int i=10;
(CCArrayの生成は省略します。)
INT型の追加
array->addobject(CCInteger::create(i));
取り出し
int n=2;
int f=( (CCInteger*)array->objectAtInteger(n) )->getValue();
でもかなり面倒なので、INT型はC++なのでvectorベクターを使った方が簡単に扱えます。
(さらに追記)
なお、vectorは実行速度がlistよりも遅いという記事を読みましたので、今後はlistを使った方が良いかもしれません。
vectorを使ったのは、使った事があったからで、特別の理由はありません。
他の関連記事cocos2d-xに移植する過程の記録メモまとめ、Androidクロスプラットフォーム化へ 、(1)〜(6)分
—
いろいろと本を3冊買って、cocos2d for iPhone をcocos2d-xに移植する過程を試みていますが、結構進みません。
objective-cをc++にしようとするとかなり時間がかかりそうです。すんなりとはいきません。
C++であるcocos2d-xは、オブジェクトの生成の時にnewを使用します。
一方のobjective-cはそのまま記載して画像を設定します。
・C++ , cocos2d-x
1 2 3 4 5 |
CCSprite *sprite=new CCSprite(); sprite->initWithFile("hiyoko_sample.png"); sprite->setPosition(ccp(0,0); this->addChild(sprite); sprite->autorelease(); |
・objective-C, cocos2d for iPhone
1 2 3 |
CCSprite *sprite=[CCSprite spriteWithFile:@"hiyoko_sample.png"]; sprite.position=ccp(0,0); [self addChild:s]; |
C++ , cocos2d-x
int iTimer;
//schedule 1秒ごとに加算する
1 2 3 4 5 6 7 8 9 |
bool HelloWorld::init()//この場所にスケジュールをした場合 { this->schedule(schedule_selector(HelloWorld::timer), 1.0); this->scheduleUpdate(); } -- void HelloWorld::timer(){ iTimer++; } |
objective-C, cocos2d for iPhone
1 2 3 4 |
[self schedule:@selector(timer:) interval:1.0f]; -(void)timer:(ccTime*)delta{ iTimer++; } |
C++ , cocos2d-x
1 2 3 4 5 |
CCSprite *test int x; int y; x=test->getPositionX(); y=test->getPositionY(); |
objective-C, cocos2d for iPhone
1 2 3 4 5 |
CCSprite *test int x; int y; x=test.position.x y=test.position.y |
タイトル:Converting snipets of code from Cocos2d-Iphone to Cocos2d-x
>Cocos2d-iphone
CCArray *spiders = [[CCArray alloc] initWithCapacity:5];
>Cocos2d-X
CCArray *spiders=CCArray::createWithCapacity(5);
Texture2dText.cpp
CCTextureCache使うときは、CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo();
が必要
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
void TextureMipMap::onEnter() { TextureDemo::onEnter(); CCSize s = CCDirector::sharedDirector()->getWinSize(); CCTexture2D *texture0 = CCTextureCache::sharedTextureCache()->addImage("Images/grossini_dance_atlas.png"); texture0->generateMipmap(); ccTexParams texParams = { GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }; texture0->setTexParameters(&texParams); CCTexture2D *texture1 = CCTextureCache::sharedTextureCache()->addImage("Images/grossini_dance_atlas_nomipmap.png"); CCSprite *img0 = CCSprite::createWithTexture(texture0); img0->setTextureRect(CCRectMake(85, 121, 85, 121)); img0->setPosition(ccp( s.width/3.0f, s.height/2.0f)); addChild(img0); CCSprite *img1 = CCSprite::createWithTexture(texture1); img1->setTextureRect(CCRectMake(85, 121, 85, 121)); img1->setPosition(ccp( 2*s.width/3.0f, s.height/2.0f)); addChild(img1); CCEaseOut* scale1 = CCEaseOut::create(CCScaleBy::create(4, 0.01f), 3); CCActionInterval* sc_back = scale1->reverse(); CCEaseOut* scale2 = (CCEaseOut*) (scale1->copy()); scale2->autorelease(); CCActionInterval* sc_back2 = scale2->reverse(); img0->runAction(CCRepeatForever::create(CCSequence::create(scale1, sc_back, NULL))); img1->runAction(CCRepeatForever::create(CCSequence::create(scale2, sc_back2, NULL))); CCTextureCache::sharedTextureCache()->dumpCachedTextureInfo(); } |
objective-C, cocos2d for iPhone
1 2 3 |
UIImage *img =[UIImage imageNamed:filename]; CGImageRef imageRefAll =[img CGImage]; textureOther =[[CCTexture2D alloc]initWithCGImage:imageRefAll resolutionType:kCCResolutioniPhoneRetinaDisplay]; |
COCS2d-x
CCTexure2Dでの注意、initWithTextureだと autorelease() is oK。しかし、CCSprite::createWithTextureでは、autorelease()を設定すると実行後しばらくしてエラーになる。
半自動か、手動管理のメモリ管理を決めましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
CCTexture2D *testTexure=new CCTexture2D(); CCImage *img=new CCImage();//UIImage img->initWithImageFile("hiyoko_sample.png"); testTexure->initWithImage(img); CCSprite *testSprite=new CCSprite(); //Textureの設定ではinitでも::createでもOKでもautoreleaseはinitになる。 testSprite->initWithTexture(testTexure);//OK autorelease() is oK. //testSprite=CCSprite::createWithTexture(testTexure);//OK //but, not autorerelease() this->addChild(testSprite); testSprite->setPosition(ccp(120,240)); testTexure->autorelease(); testSprite->autorelease();//for initWithTexure |
(1)cocos2d for iPhone をcocos2d-xに移植する過程の記録メモ、Androidクロスプラットフォーム化へ、まず第一歩
AndEngineによるアンドロイドゲームアプリ「ひよこレスキュー」を作成しました。こちらからダウンロードできます。
ダウンロードはこちらからです。無料です。広告収入のためにADMOBを入れています。(2014年1月11日追記)
スマートフォンの市場は、アイフォンとアンドロイドの2つの勢力でほぼ占めています。アイフォンで作ったアプリをAndroidへも展開することで、ごく単純に考えて2倍のダウンロード数が可能になる計算になります(実際は、そこまでいかないでしょうけど)。
アイフォンアプリは、MacOSX上で動作するXCODEでobjective-cを使用します。アンドロイド用アプリは、JAVAを使用します。つまり、objective-cとJAVAなわけですから、かたやオブジェクト指向のC言語(C++ではないのにオブジェクト指向)とオブジェクト指向の本流の言語として、開発環境が異なると言うことになります。ゲームシナリオやアルゴリズム、画像、音楽データ、データベースなどは同じものが使えるとして、コーディングについては、ほぼ別のものを作る必要があります。
コードを共通化したい
そこで、クロスプラットフォームとして、cocos2d-xを使うことにします。
cocos2d for iPhoneとcocos2d-xとは
「cocos2d for iPhone」 とはアイフォンアプリでゲームを作るためのフレームワークで、xcodeでobjective-cを使います。
「cocos2d-x」はアイフォンアプリでゲームを作るためのフレームワークで、xcodeでc++を使います
cocos2d-xのメリットは、Androidアプリを作るためのクロスプラットホームのための効率化です。アイフォン用として動作するアプリ(コード)がAndroidアプリと動作することができます。
つまり、アイフォンアプリを作ってAndroidへ移植する時の効率が非常に優れていることです。「cocos2d for iPhone」で作った場合、Androidへそのままコードをコピペしても動きません。ゼロからJAVA用に書き換える必要があります。こうかくと「cocos2d for iPhone」の利便性が低いように思えますが、「cocos2d for iPhone」はobjective-cでコードを記載するので、MacOSX,iOSアプリを作っている人が利用しやすく、objective-c固有のコードやライブラリを使用することができます。ただ、ゲームの世界でobjective-c固有のコードやライブラリを使用するのは多いことではありません。
クロスプラットフォームとして考えるとどうしても「cocos2d-x」が優位と考えられます。
ゲームメーカーも「cocos2d-x」を利用しているそうです。
cocos2d for iPhoneとcocos2d-xのどちらもcocos2dと冠しているのでコマンドの内容や指定手順はほとんど同じです。objective-cかc++というほんの少し文法が違う点を除けば、同じ感覚でプログラムを作っていくことができます。
まず、以前作成したひよこレスキューというアイフォンアプリcocos2d for iPhone をcocos2d-xに移植しAndroidアプリとして公開しようと思います。
画面
今回が初めての試みですので、途中で挫折するか、別のアプリを作成する方向に変わるかもしれません。そのときはごめんなさい。
クラスの作成
CCSpriteクラスを承継するcHiyokoクラスを作成
スプライトを設定し、クラス生成
C++の文法を忘れてます。ほんとに覚えることがあって大変です。
やっとobjective-cのコーディングになれてきたのに。
(正式な方法や正式名称を使わずに、説明しているところがあります。
ご注意ください。)
objective-Cでは、クラスを
voidをかっこで挟んで、マイナスをつけます。
AA.m
-(void)function{//メソッドのあとに、かっこがない
}
となります。
C++ではクラス名があって::をつけてメソッドを書きます。
AA.mm
クラス名::function(){//メソッドの後にかっこ必要
}
まず、C++なので当然ながらプロパティがなくて、マクロを利用します。
CC_SYNTHESIZE(cocos2d::CCSprite, _spriteHiyoko, spriteHiyoko);
こんな感じ。このとき、型の宣言とプロパティ、シンセサイズまでまとめて設定されます。
クラスメソッドは、
ID型がないので、boolかstaticにしてポインタにします。
ここらへんがややこしくなります。
+(CCScene *) scene
は、static cocos2d::CCScene* scene();みたいになります。
インスタンスメソッドは、マイナスのついたメソッドのことですが、boolになります。
<感想>
objective-cからC++への移植は思ったよりも難航しそうです。
まず、何を何から変えてよいのかわからない。
単純にそのまま、表示させる程度のものでも。
2014年1月11日追記
現在のところ、cocos2dXについての開発を中止しました。
アンドロイドアプリではダウンロードされそうにないみたいなので、無理して、クロスプラットフォームで開発する必要がなくなりました。
今後はアイフォン向けアプリとUnityの開発にしようと思います。
今日のアイフォンアプリ開発記録日誌、不明なエラー”_OBJC_CLASS_$_Stats”, referenced from
今日のエラー
アイフォンアプリを実行中の使用メモリ、CPU負荷を知りたくて、Stats.m,Stats.hを追加し、コンパイルすると
“_OBJC_CLASS_$_Stats”, referenced from
云々かんぬんのエラーが発生しました。
コードの記載が間違っているのかと思っていたら、XCODEの設定だそうです。
Target Membershipを設定すると良いそうです。
画像 targetmembership.jpg
今回のメモリ表示は、「達人のレシピ100」に記載されているものを自分コードに合うように変更しました。
cocos2dの場合はAppDelegate.m,hに記載しました。
サンプルコードのままでは表示されなくて、Admobで動作した記載を参考にしたら、表示されました。
画像、アイフォンキャプチャ画像
こんな感じで表示されます。
メモリ使用量を見ると、なんどもゲームを繰り返し遊んでいると、メモリがどんどん増えているのがわかりました。どこかのタイミングでメモリを解放しないと増え続けそうです。
今日のアイフォンアプリ開発記録日誌、iPhoneシミュレータの判別方法メモ
開発に関する記事複数のiOS機器の登録
(1)iPhoneシミュレータの判別方法メモ
シミュレータでアイフォン、アイパッドのRetinaレティナかどうかの判定ができないか探していますが、見つかりません。シミュレータでは、非RetinaにしてもRetinaが返ってくるので、解像度に合わせた確認ができないでいます。理由は、CGRectMakeで座標座業を取得しているので、Retinaかどうかで、画像を切り替える必要があるからです。スプライト一つに一つの画像を用いれば、もっと楽ですが、頻繁にファイルを読み込むので、電力消費と、FPSの低下が心配なので、テクスチャを一つにしてます。なお、切り替えるテクスチャ数が少ないので、info.plistは使っていません。
参考サイト
iPhone iPad iPhoneシミュレータの判別方法
ProgrammerDidFinishWorking : iOSSDKで実機とシミュレータ実行の判別の仕方
シミュレータか実機か判別 / iPhoneOSか判別 – haneda部屋
アプリケーションを iPhone 4 の Retina Display に対応するための方法いろいろ – 24/7 twenty-four seven
(2)今日のアイフォンアプリ開発記録
1.アイパッドのデバイスを登録しました。これで、アイフォンとアイパッドで実機確認ができます。
2.アイパッドで実機確認をして、画像が正常に表示されていないバグ(コードのミスではない)がありました。
これは、ipadhd,ipad,hdという風に、ファイル名をつけますが、その通りになっていてもcocos2dの方で、正常に判別できていませんでした。そこで、アプリを実行する現在の機器がどの機種であるのかを表示サイズと比率で判別して画像を選別するようにしました。これは、画像単体をそのままスプライトにする場合は、問題ありません。
判別はちょっと面倒でした。シミュレータ上では、レティナタイプと非Retinaタイプの判別はわかりませんでした。
この問題が発生するのは、CGRectMakeを使用して1枚のテクスチャから部分領域を切り取ってスプライト設定する場合に発生する問題です。
その理由は、Retina対応によるものです。Retinaは2倍の密度を持つために、画像のピクセルが100ピクセルあるとすると、実際の表示は、50ピクセルになります。1対1の場合は、100ピクセルのサイズとなりますが、Retinaになると1:2になり、凝縮された画像のようになって半分の50ピクセルで表示されます。そのため、CGRectMakdeで領域を指定するときは、実際の半分の座標で領域を指定する必要があるのです。例えば、左上側から50ピクセルの高さと幅の画像領域を指定したいとすると、(0,0,50/2,50/2)または、(0,0,25,25)のように指定します。実際の大きさの半分のサイズで指定することで、Retina対応の機器は画面上で、25ピクセルの画像として表示します。
そのため、Retinaの場合の領域指定と非Retinaの場合の領域指定は異なります。今回は、アイフォンRetinaとiPad非Retina,iPadRetinaの画像を用意しました。
アイフォンのRetinaとアイパッド非Retinaはほぼ同じサイズとして使用しましたので、実質は2種類の画像を用意して、ファイル名を変更することにより、効率化しました。ただし、全体の画像容量は、単純にアイフォン1種類に比べて、3倍以上になります。
しかし、できるだけ高解像度の画像を用意することで、実機で確認したときに、きれいな画像が表示されるのを確認するとやはり高解像度を使用した方が良いと実感しました。ドット絵を使用する賢いやり方もありますが、その場合は、キャラクターがカクカクしすぎてせっかくの高解像度が台無しになったような気がするからです。
info.plistを使用していれば、たぶん問題とならないでしょう。ではなぜ、info.plistを使用しないのかというと、info.plistを使用するほど、スプライト数が多くないからです。また、画像の変更も多くて、いちいちinfo.plistを変更するのが、面倒だからです。また、扱うソフトを覚えるのも面倒というのも理由です。
<検討中>
3.ccTouchMovedで、スワイプしてもキャラが動かないシーンがありました。
1面ではEndのみ正常、ボス面は正常にスワイプできました。
1面とボス面は同じコードをコピペしていて、Diffでも同じでした。
原因は不明です。
とりあえず、同じコードといいながら違うコードを記載していることもあるので、動いてる方を動いていない方のコードに入れ替えてみます。
これで、動かないときは、どうしましょうか。
>いまここ
4.一時停止中にホームボタンを押して、アプリを切り替えるとアプリが勝手にアニメーションを開始していました。本来は、復帰後も一時停止となるはずです。
AppDelegate.mのapplicationDidBecomeActiveにシングルトンを設定しました。
ぐーぐるAdMobが表示されないエラー、コードを代えて成功、アイフォンアプリ開発
前回のエラー、広告が表示されないはこちら
アイフォンで広告表示
AdMobのSDKをGoogleAdMobAdsSdkiOS-6.4.1としました。6.3.0から。
しかし、広告は表示されず。残念
<<<<>>>>>
環境:cocos2d-iphone v2.1-rc1
XCODE 4.6.2 : Deployment Target 4.3
AdMob 6.4.1 4/18/2013 Fixed a crash that occurred when the Advertising Identifier is nil.
症状:AdMobが表示されない。つまり、ビューが表示されない。
エラー:
<<<<>>>>>
以下、検討、結論(成功、AdMob表示されるようになりました。)
AdMobが正常に表示されない改善
1.最新版のAdMobSDKにする
結果:だめでした。
2.参考コードを参考にしてみる(成功)
結果:広告が表示されました。(1)を参考にしました。
結論として、
AppController *app = (AppController*)[[UIApplication sharedApplication] delegate];
を追加して、app.navControllerを与えました。
変更したコード
1 2 3 4 |
AppController *app = (AppController*)[[UIApplication sharedApplication] delegate]; gadbanner_.rootViewController=app.navController; [app.navController.view addSubview:gadbanner_]; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
-(void)adMob{ <font color=red> AppController *app = (AppController*)[[UIApplication sharedApplication] delegate]; </font> CGRect rect = CGRectMake(0, 0, 320, 50);//top objective-cは左上座標系でcocos2dは下が原点 gadbanner_ = [[GADBannerView alloc] initWithFrame:rect]; gadbanner_.adUnitID = @"a1------hiden------b";//publisher ID //gadbanner_.rootViewController =[[[UIApplication sharedApplication] keyWindow] rootViewController]; <font color=red> gadbanner_.rootViewController=app.navController;</font> gadbanner_.delegate = self; <font color=red> [app.navController.view addSubview:gadbanner_];</font> //[[[CCDirector sharedDirector] view] addSubview:gadbanner_];変更 GADRequest *request = [GADRequest request]; //GADRequestError *error;//=[GADRequestError initialize]; request.testing = YES;//YESにしないと開発時はでません。NOは実機かな [gadbanner_ loadRequest:request]; } |
参考
(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
-(void)createAdmobAds { AppController *app = (AppController*)[[UIApplication sharedApplication] delegate]; // Create a view of the standard size at the bottom of the screen. // Available AdSize constants are explained in GADAdSize.h. mBannerView = [[GADBannerView alloc] initWithAdSize:kGADAdSizeSmartBannerLandscape]; // Specify the ad's "unit identifier." This is your AdMob Publisher ID. mBannerView.adUnitID = MY_BANNER_UNIT_ID; // Let the runtime know which UIViewController to restore after taking // the user wherever the ad goes and add it to the view hierarchy. mBannerView.rootViewController = app.navController; [app.navController.view addSubview:mBannerView]; // Initiate a generic request to load it with an ad. [mBannerView loadRequest:[GADRequest request]]; CGSize s = [[CCDirector sharedDirector] winSize]; CGRect frame = mBannerView.frame; frame.origin.y = s.height; frame.origin.x = (s.width/2.0f - frame.size.width/2.0f); mBannerView.frame = frame; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.5]; [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; frame = mBannerView.frame; frame.origin.y = s.height - frame.size.height; frame.origin.x = (s.width/2.0f - frame.size.width/2.0f); mBannerView.frame = frame; [UIView commitAnimations]; } |
(2)これは試していません。
1 2 3 4 5 6 7 |
AppController *app = (AppController*) [[UIApplication sharedApplication] delegate]; [admobBannerView setRootViewController:[app navController]]; [[CCDirector sharedDirector].view addSubview:admobBannerView]; [admobBannerView loadRequest:[GADRequest request]]; |