ラベル iphoneアプリ の投稿を表示しています。 すべての投稿を表示
ラベル iphoneアプリ の投稿を表示しています。 すべての投稿を表示

2013年6月6日木曜日

cocos2d-xでiOSとAndroidのクロスプラットフォーム環境構築

どうも、俺@残業するフリしてブログ書き中です。


決して仕事をサボってるわけではありません。
今日はcocos2d-xを使ってiOSとAndroidの両方でアプリを動かす最初の環境構築をめもめも。
開発環境はMacOS X 10.8.3です。
Xcodeのインストールとeclipseのインストール、Androidアプリ開発環境は整備済みとします。


ちなみに、Cocos2d xをさらにさわってみよう!のスライドとがおまるさんのcocos2d-x環境構築〜Androidテンプレート起動までその1がとても参考になりますよ!

長いので手順を記しておきます。
1)cocos2d-xをDLしテンプレートインストール
2)Android側の準備
3)Xcode側でHelloWorld作成&起動
4)Android側でプロジェクト作成し、フォルダをXcode側へコピーしbuild_native.shの実行
5)eclipseへ取り込み、Android端末で起動
6)拍手
となります。


まず、お決まりのcocos2d-x本体をDLしましょう。
2013.06.06時点での安定版最新はv2.0.4でした。

解凍して適当なディレクトリへ置きましょう。
$ unzip cocos2d-2.0-x-2.0.4.zip

$ mkdir ~/Documents/cocos2dx

$ mv cocos2d-2.0-x-2.0.4 ~/Documents/cocos2dx/v2.0.4
# 以下は好みに合わせてね
$ ln -s ~/Documents/cocos2dx/v2.0.4 ~/Documents/cocos2dx/current
次にcocos2d-xのテンプレートをインストールしちゃいます。
$ sudo ~/Documents/cocos2dx/current/install-templates-xcode.sh
これでとりあえずXcodeでcocos2d-xのテンプレートを選択できるようになり、そのプロジェクトが作れます。
もちろんHelloWorldアプリも起動しますよ。
とりあえず拍手しましょう。

では、Android側の準備をしましょう。

AndroidNDKをDLして好きなディレクトリへ置きます。※すでにしてる人は要らない。
$ ls -l /Devloper

drwxr-xr-x@ 19 koexuka  staff   646 5 10 14:57 android-ndk-r8d
次にcreate-android-project.shを編集します。
このファイルはAndroidでcocos2d-xプロジェクトを新規作成するときに実行するファイルです。
$ vim ~/Documents/cocos2dx/current/create-android-project.sh
------------------------------------------------------
  7 # set environment paramters
  8 NDK_ROOT_LOCAL="/Developer/android-ndk-r8d"
  9 ANDROID_SDK_ROOT_LOCAL="/Developer/android-sdk-macosx" # Android-SDKの配置されているPATHに
次にtemplate/android以下にあるbuild_native.shを編集します。
$ vim ~/Documents/cocos2dx/current/template/android/build_native.sh
------------------------------------------------------
  1 APPNAME="__projectname__"
  2
  3 # 以下を追加
  4 NDK_ROOT=__ndkroot__
  5 COCOS2DX_ROOT=__cocos2dxroot__
  6 GAME_ROOT=$COCOS2DX_ROOT/__projectname__
  7 GAME_ANDROID_ROOT=$GAME_ROOT/proj.android
  8 RESOURCE_ROOT=$GAME_ROOT/Resources
  9

〜(中略)〜

 46 DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 47 # ... use paths relative to current directory
 48 # 二重定義になっちゃうので以下をコメントアウト(COCOS2DX_ROOT)
 49 #COCOS2DX_ROOT="$DIR/../.."
 50 APP_ROOT="$DIR/.."
これを記述しておくと、Android用プロジェクトを作成するたびにbuild_native.shを編集する手間が減ります。

これでAndroid側の準備も完了。
ではHelloWorldアプリを作りましょう。

まずXcodeで、TestCocos2dxプロジェクトを作成しましょう。

プロジェクト名は「TestCocos2dx」にします。

で最後にCreateしちゃいましょう。

できたぜ、Hello World!


次はAndroidで動くようにします。

さっき編集したcreate-android-project.shを実行します。
$ ~/Documents/cocos2dx/current/create-android-project.sh

# 1)パッケージ名入力。
jp.blogspot.koexuka.app.test

# 2)AndroidターゲットIDの入力。なぜか僕はいつもid:2(android v2.2以上)を選択します。
2

# 3)最後にプロジェクト名。iOS側と合わせておいたほうが分かりやすいかも。
TestCocos2dx
そうすると配置したcocos2dxディレクトリ以下にプロジェクトディレクトリができます。
$ ls -l ~/Documents/cocos2dx/current
drwxr-xr-x   5 koexuka  staff    170  6  6 17:22 TestCocos2dx
できたプロジェクトディレクトリの中にproj.androidというディレクトリがあります。
$  ls -l ~/Documents/cocos2dx/current/TestCocos2dx

drwxr-xr-x   6 koexuka  staff  204  6  6 20:22 Classes
drwxr-xr-x   5 koexuka  staff  170  6  6 20:22 Resources
drwxr-xr-x  17 koexuka  staff  578  6  6 20:22 proj.android
これをXcodeのプロジェクトディレクトリ側へ持っていきます。

ここが分かりにくいですが、Finderを二つ並べてドラッグ&ドロップします。
別に問題ないとは思いますが、Xcode側のプロジェクトが無駄に大きくなってしまうので
proj.androidフォルダをXcode上へドロップしないようにしましょう。


もう1つ面倒な作業をします。
cocos2d-xのAndroid用javaプログラムファイルを、先ほどのXcode側のフォルダへ移します。
$ cp -R ~/Documents/cocos2dx/current/cocos2dx/platform/android/java/src/org/cocos2dx/lib ~/Documents/XcodeProject/TestCocos2dx/proj.android/src/org/cocos2dx
図解すると以下の様な感じ。


ここまで来れば90%出来たも同然!
ではAndroid用にビルドさせます。
$ cd ~/Documents/XcodeProject/TestCocos2dx/proj.android
$ ./build_native.sh
最初は時間がかかるので、しばらくジーッと画面を見つめておきます。

うまくいくと最後に
Compile++ thumb  : box2d_static <= b2World.cpp
Compile++ thumb  : box2d_static <= b2WorldCallbacks.cpp
Compile++ thumb  : box2d_static <= b2Rope.cpp
StaticLibrary  : libbox2d.a
SharedLibrary  : libgame.so
Install        : libgame.so => libs/armeabi/libgame.so
make: Leaving directory `/Users/koexuka/Documents/XcodeProject/TestCocos2dx/TestCocos2dx/proj.android'
のような表示になります。

もしここでコケる場合、build_native.shの内容を見なおす必要があります。
PATHの指定とか間違えてるかも!?

では出来たファイルをeclipseへ取り込むぜ。
eclipseを起動し、「File」→「New」→「Project...」と進み、

「Android」内にある「Android project from Existing Code」を選択しNext!

「Root Directory」は先ほどのXcodeプロジェクト内のproj.androidを選択します。

オッケー!!これでeclipseにプロジェクトが組み込まれたはず!


ではAndroid端末をPCへ接続しドキドキしながらRunボタンを押下仕様じゃないか!
ほら動いた!
あ、ちなみにcocos2d-xはAndroidエミュレータで起動できませんのであしからず。。。


開発手順ですが、基本的にはXcodeで開発します。
Android端末での動作を確認したい場合は、
1)build_native.shを実行
2)eclipse画面へ
3)eclipseのRunボタン押下
だけでOKです。
Resourceフォルダ以下へ画像や音声ファイルを追加しても、勝手にbuild_native.shが取り込んでlibgame.soを生成してくれるので
その辺は気にしなくてOKですよ!

あー、長かった!


※2013.06.20 Android.mkについて追記
とても大事な事を書き忘れていました(汗
上記のようにiOS/Androidでのクロスプラットフォーム向け開発環境を構築して開発開始してからですが、
上述したとおり基本的にはXcodeで開発をします。

Androidへの転送手順も上述のとおりなのですが、その際に「Android.mkの編集」という作業が必要になります。
このファイルは、新しくクラスファイルを追加した場合など、都度編集しなければいけません。
vim proj.android/jni/Android.mk
---------------------------------------
LOCAL_SRC_FILES := hellocpp/main.cpp ¥
  ../../Classes/AppDelegate.cpp ¥
  ../../Classes/HelloWorldScene.cpp ¥
  ../../Classes/MyClass.cpp ¥         # ←のように自作ファイル(.cppのみ)を追記
  ../../Classes/Utils/MyUtil.cpp ¥    # ←どんどん追記していく
〜(略)〜

もしBox2Dを使っている場合などは、
vim proj.android/jni/Android.mk
--------------------------------------
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../Classes ¥
  $(LOCAL_PATH)/../../libs/cocos2dx/Box2D ¥    # ←とか
  $(LOCAL_PATH)/../../libx/cocos2dx/cocoa ¥    # ←必要だったこれとか
〜(略)〜
のように書いていく必要があります。

ちなみに未確認ですが、

Cocos2d-xで新しく作ったクラスを毎回Android.mkに追加せずに済ます

のようにして簡略化させることもできるそうです。

以上でぇぇぇぇぇえええす。


2013年1月21日月曜日

Objective-Cでファイルのタイムスタンプや属性を取得

どうも、俺@家です。
21日ですが、明けましておめでとうございます。
今年もよろしくお願いしマウス。チューチュー。

NSFileManagerでとあるディレクトリ以下にあるファイルを一覧で取得し、作成された日付順に並び替えたい場合。
// Cacheディレクトリ

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];


// ファイル一覧(サブディレクトリは除外)
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:nil];


// 属性情報を格納する配列
NSMutableArray *attributes = [NSMutableArray array];


// ファイル配列をループ
for (NSString *file in files) {

  // ファイル属性にファイルパスを追加するためにDictionaryを用意しておく
  NSMutableDictionary *tmpDictionary = [NSMutableDictionary dictionary];

  NSString *filepath = [path stringByAppendingPathComponent:file];
   // ファイル情報(属性)を取得
   // 取得できる情報については csoulsの日記 を参考に!
  NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:nil];


  // tmp配列に属性を格納
  [tmpDictionary setDictionary:attr];

  // tmp配列にファイルパスを格納
  [tmpDictionary setObject:filepath forKey:@"FilePath"];

  [attributes addObject:tmpDictionary];
}


// ソートさせる
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:NSFileCreationDate ascending:NO];
NSArray *sortarray = [NSArray arrayWithObject:sortDescriptor];

// 並び替えられたファイル配列
NSArray *resultarray = [attributes sortedArrayUsingDescriptors:sortarray];

[sortDescriptor release];


なぜわざわざtmpDictionaryを用意するか?についてですが、
属性を取得する
  NSDictionary *attr = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:nil];
は、NSDictionaryなためファイルパスが追加できないためです。


以上でぇぇぇえぇす。

2012年3月3日土曜日

無料iPhoneアプリ「なむぞう」リリースしました!

どうも、俺@スノボから帰ってきました。
今回はちょっと技術ネタから外れますが。。。

さてさて、やっとiPhoneアプリ「なむぞう」をリリースすることができました^^

http://itunes.apple.com/jp/app/namuzou/id499190444?mt=8







デザインも自分で担当したため、オシャレなUIとまではなりませんでしたが
配色サンプルを色々試して何回も試行錯誤しながらUI全体の色イメージをつくっていきました。

あと、どうでも良いですが
アイコン画像にいるイモムシのようなやつが「なむぞう」というキャラクターという設定です。


リリース直後にGameCenterにつながらない不具合が見つかったり、その他色々。。。。
初めてのアプリ開発で色々戸惑いも多かったですが、もう大丈夫です!!


紹介動画です^^
http://www.youtube.com/watch?v=yxUu9crJtas
動画編集ソフトやYoutubeの機能を駆使してつくりました!


Objective-Cについて、色々とスキルを身につけられましたが
それと同様にドローソフトや動画編集ソフトの使い方に詳しくなれました。



以上でぇぇぇぇす。

2012年2月9日木曜日

NSLocalizedStringとstringWIthFormatを使ってiPhoneアプリの多言語化

どうも、俺@仕事中です。
今日はiPhoneアプリをNSLocalizedString()とNSString stringWithFormatを使って多言語対応する方法のめもめもです。

日本語環境のみに作ったアプリを
NSString *str = @"にほんご";
英語圏で使うようにするには

NSString *str = NSLocalizedString(@"key", @"comment");
としておき、ターミナルから

genstrings -a $(find ./ -name "*.m");
とすればLocalizable.stringsファイルができるので、Xcode内にドラッグ&ドロップ(Xcode4では「Supporting Files」が適当かな)します。
Localizable.stringsはUtilitiesのFile Inspectorから作成する言語とText−Encoding(UTF-16)を設定します。
Localizable.strings内では
・Localizable.strings(English)
"key" = "Japanese;"

・Localizable.strings(Japanese)
"key" = "にほんご"
としておけば、"key"と記述した部分をそれぞれの言語に変更してくれます。
※ここでは"Japanese"と"にほんご"に置換してくれる。

これら詳しい説明は
NSLocalizedStringでiphoneアプリ多言語対応 Xcode4 - はるかなる熊がとても参考になりました。


ところで、英語と日本語では文法的に単語の出てくる順番が異なるときが出てくる。
例えば
私は「テトリス」で「100」pt取った。
という日本語を英語にすると
I took 「100」pt in 「Tetris」.
となる。「」で囲まれた単語が異なる場合がある。
こういう場合、まずobjective-cのソースコードでは英語に合わせて作ったほうが分かりやすい。

NSString *str = [NSString stringWithFormat: NSLocalizedString(@"long sentence", @"some comment"), @"100", @"Tetris"]
こうしておいた上で、それぞれのLocalizable.stringsでは
・Localizable.strings(English)
"long sentence" = "I took %d pt in %@.";

・Localizable.strings(Japanese)
"long sentence" = "わたしは%$2@で%1$d取った。";
とする。
stringWithFormat の%$n@でフォーマットに入れる変数の順番を変更できるのです。(nは整数)


以上でぇぇぇぇぇぇす。

2012年1月31日火曜日

Xcode 実機で動作しなくなる('NSInternalInconsistencyException', reason: ' Could not load NIB in bundle...)

どうも、俺@絶賛objective-c中です。

Xcode ver.4.2で開発してて、iPhoneシュミレーターでは動作確認できるのですが急に実機で動作しなくなった!という場合の対処法めもです。
場合によっては原因が異なると思うので、これが解決法の全てではないかもしれませんが。。

iPhone実機(5.0.1)に繋いでXcodeからビルド&実行すると以下のようなエラーが出てしまい、ビルドはできるのですが実行できません。

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle (loaded)' with name 'ViewController'
つい5分前までは動いてたのに!
原因はよく分かりませんでしたが、以下をやることで実機でも動作するようになりました。

エラーログにある「ViewController.xib」を開き、右側の「Utilities」>「File Inspector」内にある「Localization」の部分を見ます。
僕の場合は
English
の1つのみが書かれていたので、「Japanese」を追加します。

するとViewController.xibが
ViewController.xib(English)
ViewController.xib(Japanese)
の2つになります。
この状態で実機転送すると動作します。

このあと、なぜか先ほどのLocalizationにある
Japanese
は削除しても実機で動作しちゃいます。

理由はよくわかりませんが、もしトラブった人は試してみて下さい。


以上でぇぇぇぇぇぇす。

UIViewアニメーションで一時停止

どうも、俺@コーディング中です。
今日はObjective-Cでアプリ開発をしてて、UIViewのアニメーションを使うことはよくあるのですが、今日はそのアニメーションを一時停止させる方法をめもめもします。
// hogeLabelの座標は(0, 0)
hogeLabel.frame = CGRectMake(0, 0, 100, 100);

// アニメーション開始
[UIView beginAnimations:nil context:nil];

// アニメーション時間
[UIView setAnimationDuration:1.0f];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];

// hogeLabelを(200, 200)の位置へ動かす
hogeLabel.frame = CGRectMake(200, 200, 100, 100);

[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(hogeLabelStopped:finished:context:)];
[UIView commitAnimations];
とりあえずこれでhogeLabelは座標(0, 0)から(200, 200)へ1秒かけて動くアニメーションができました。
このあとセレクターメソッド(hogeLabelStopped)内で、一旦停止させるには

- (void)hogeLabelStopped:(NSString *)animation finished:(BOOL)finished context:(void *)context
{
  // 一時停止(0.5秒)
  [NSThread sleepForTimeInterval:0.5];

  // その他の動作はこれ移行に記述
}
こんな感じです。[NSThread sleepForTimeInterval:(double) interval]はスレッドをsleepさせる静的なメソッドです。

以上どっぇぇぇぇぇえっぇぇす。

2012年1月20日金曜日

UIViewのアニメーションで画面遷移

どうも、俺@仕事中です。久々のObjective-Cです。
アプリでUINavigationControllerを使わずに画面をアニメーションさせて遷移させる方法を調べたのでメモメモ。

右から左へスライドインする処理
■元画面(FirstView: UIVIewControllerを継承)
// 遷移先UIViewを画面外に生成(SecondView: UIVIewを継承)
secondView = [[SecondView alloc]initWithFrame:CGRectMake(self.view.frame.size.width + 1, 0, self.view.frame.size.width, self.view.frame.size.height)];

// アニメーション開始
[UIView beginAnimations:nil context:nil]:
[UIView setAnimationDuration:0.5]; // 0.5秒かけて
[UIView setAnimationCure:UIViewAnimationCurveLinear]; // 一定速度で
[self.view addSubview:secondView]; // addSubviewする

secondView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); // 画面内へ動かす
[UIView commitAnimations]; // アニメーションコミット
これで右から画面内へスライドインする遷移ができます。

今度は戻るボタンなどで元画面へ戻る処理です。
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveLInear];
[UIView setAnimationDelegate:self]; // デリゲートをselfで指定
[UIView setAnimationDidStopSelector:@selector(animationStopped:finished:context:)]; // アニメーションが完了した時の処理

secondView.frame = CGRectMake(self.view.frame.size.width + 1, 0, self.view.frame.size.width, self.view.frame.size.height); // 画面外へ
[UIView commitAnimations];
/**
 * アニメーション停止後の処理
 */
- (void)animationStopped:(NSString *)animation finished:(BOOL)finished context:(void *)context
{
  [secondView removeFromSuperview]; // secondViewをremoveFromSuperviewする
}
こうなります。
secondViewをremoveFromSuperviewする場合は、UIViewのsetAnimationDidStopSelectorを使ってアニメーション停止後の処理をセレクターを使って処理させて下さい。そうしないとアニメーションが動きません。
またその場合はUIViewのsetAnimationDelegateメソッドを呼んでおく必要があります。
以上でぇぇぇぇぇぇす。

2011年11月12日土曜日

NSNumberとNSValueとCGRect,CGPoint,CGSIzeについて

どうも、俺@家帰っても勉強中です。
Objective-CでNSNumberとNSValueという不思議なクラスにぶち当たりました。

NSNumberは数値を表すオブジェクト型で、プリミティブなintやNSIntegerとは少し意味合いが違います。
つまりintとNSIntegerはイコールですが、NSNumberはイコールではありません。
使い方は
int i = 10;
NSInteger i = 10;
NSNumber *i = 10;
のようになります。
使いどころですが、例えばオブジェクト型で数値を表現したい場合はNSNumberを、そうでない場合はintやNSIntegerを使いましょう!というそのままなのですが、
具体的には、NSArrayなどに格納できる要素はオブジェクト型である必要があります。
NSArrayやNSMutableArrayにどうしても数値を格納する必要があれば、NSNumberを使えばOKです。

int i =10;
NSNumber *num = [NSNumber numberWithInt: i];
としてやればintをNSNumber型に変換できます。
他にも
NSNumber *num = [NSNumber numberWithFloat: 10.0f];
のような使い方もできます。
逆にNSNumber型をint型として取り出すには
int i = [num intValue];
でOKです。

またNSValueですが、これはCGRectやCGPoint、CGSizeなど構造体を表すオブジェクト(NSObjectを継承していない)を扱う場合に利用します。
CGRectとかCGPointなどはクラスの引数の型などに設定できないんですね。あとは上の例のように、NSArrayの要素として追加したい場合など。
CGrect rect = CGRectMake(0, 0, 100, 100);
NSValue *val = [NSValue valueWIthCGRect:rct];
CGPoint point = CGPointMake(100, 100);
NSValue *val = [NSValue valueWIthCGPoint:point];
CGSize size = CGSizeMake(100, 100);
NSValue *val = [NSValue valueWIthCGSIze:size];
こんな感じです。

逆にNSValue型のオブジェクトからCGRectなどを取り出す場合は
CGRect rect = [val CGRectValue];
CGPoint point = [val CGPointValue];
CGSize size = [val CGSizeValue];
使い方はNSNumberの場合とほとんど一緒です。


以上でぇぇぇぇす。

2011年11月10日木曜日

UIView UILayout UITextViewを角丸にする

どうも、俺@アプリ開発中です。
今日はタイトル通り「UIView」「UILayout」「UITextView」の角を丸く描画する方法についてめもめもです。

まず、ヘッダファイルで

#import <QuartzCore/QuartzCore.h>
とQuartzCore.frameworkをインポートします。
別のサイトとかではQuartzCore.frameworkを追加して、とかあるのですが僕の環境ではそんなことしなくても普通に使えました。
なぜだ。(XCode4.2)
次に対象のオブジェクトに対し

UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(100, 100, 50, 50);
[btn setTitle:@"test" forState:UIControlStateNormal];

// 角丸の処理
[[btn layer] setCornerRadius:5.0f];

// または
// btn.layer.cornerRadius = 5.0f;
こんな感じです。
UILayoutやUITextViewでも同様に作れます。


以上でぇぇぇえす。

2011年11月9日水曜日

Objective-Cでprivateメソッドを定義したい

どうも、俺です。
ようやくobjective-c(cocoa)な話題です。

objective-cで自作クラスを作り、javaやphpのようにprivateなメソッドを定義したい!という時のめもめもです。
objective-cは基本的には定義されたメソッドはpublicになってしまいます。
面倒なのであえてprivateなメソッドにする必要もなさそうですが。

ちなみにprivateなプロパティは

// MyClass.h
@interface MyClass: NSObject
{
 @private
   id hoge;
}
-(void)methodA;
@end
のような形で定義できちゃいます。

privateなメソッドを定義するには、カテゴリを使って何とか実装できます。、、なので面倒です。

// MyClass.m
@interface MyClass () // ←が無名カテゴリの定義
-(void) privateMethod;
@end

@implemention MyClass
// ここにクラスの実装を行う。
// privateMethodもここに作成する。
-(void) prrivateMethod
{
  // メソッドの内容
}
@end
こんな感じです。
MyClasss.hに変更を食わえる必要はありません。

Objective-Cにprivateメソッドの仕組みが組み込まれてないんでしょうね。
なんか冗長な気がするので、どうしてもprivateじゃないとアカン!という場合でなければ使わなくても良いかなと思いました。
アプリ開発とかでもあまり大規模開発になることもなさそうですし。

以上でぇぇぇぇぇぇぇす。