アプリ置き場

アプリ置き場

http://www.moreread.net/

Xamarin + CocosSharp を使ってみたい ⑦

AndroidGC発生しまくりでカクカク問題
 
nursery-sizeをでっかく指定しておけばとりあえずGCを我慢してくれるようだけど。。。いろいろパラメータ指定したら、なんかときどき実行中にエラーでて落ちるように。
MONO_GC_PARAMS=bridge-implementation=tarjan,nursery-size=128m,soft-heap-limit=512m
 
The Xamarin.Android garbage collector can be configured by setting the MONO_GC_PARAMS environment variable. Environment variables may be set with a Build action of AndroidEnvironment.
The MONO_GC_PARAMS environment variable is a comma-separated list of the following parameters:
  • nursery-size = size : Sets the size of the nursery. The size is specified in bytes and must be a power of two. The suffixes k , m and g can be used to specify kilo-, mega- and gigabytes, respectively. The nursery is the first generation (of two). A larger nursery will usually speed up the program but will obviously use more memory. The default nursery size 512 kb.
  • soft-heap-limit = size : The target maximum managed memory consumption for the app. When memory use is below the specified value, the GC is optimized for execution time (fewer collections). Above this limit, the GC is optimized for memory usage (more collections).
  • evacuation-threshold = threshold : Sets the evacuation threshold in percent. The value must be an integer in the range 0 to 100. The default is 66. If the sweep phase of the collection finds that the occupancy of a specific heap block type is less than this percentage, it will do a copying collection for that block type in the next major collection, thereby restoring occupancy to close to 100 percent. A value of 0 turns evacuation off.
  • bridge-implementation = bridge implementation : This will set the GC Bridge option to help address GC performance issues. There are three possible values: old , new , tarjan.
  • bridge-require-precise-merge: The Tarjan bridge contains an optimization which may, on rare occasions, cause an object to be collected one GC after it first becomes garbage. Including this option disables that optimization, making GCs more predictable but potentially slower.
For example, to configure the GC to have a heap size limit of 128MB, add a new file to your Project with a Build action of AndroidEnvironment with the contents:
MONO_GC_PARAMS=soft-heap-limit=128m
 
.Androidプロジェクトにテキストファイルを追加して、プロパティウィンドウからタイプを
AndroidEnvironment
にすればよいらしい。要調整。
 

音が鳴らなくなる問題①
 
iOSバイスでしばらく動作テストしてると、必ず音が鳴らなくなって、そのうちフリーズ。ホワッツ
うそやろ……1024回で打ち止めって、しかも2年以上前から直ってないの?
たしかに1024回で「Failed to generate OpenAL data buffer:」と吐き出して、それ以上の再生が不可能になる。何かリークしてるのか?再生途中でストップをかけた分は回収されていて、寿命が延びてる気がする。
CCAudioEngine.SharedEngine.End();
とかしてみたが、特に意味はなかった。
 
自前でAudioエンジンのインスタンスを作ってみる。
CCAudioEngine engine =new CCAudioEngine();
 
~略~
 
engine.End();
engine.Dispose();
engine = new CCAudioEngine();
1024回をカウントして作り直してみるが効果なし。
が、なんということでしょう。CCAudioEngineを作り直したあとにGCかけると復活する。
System.GC.Collect();
 
AudioEngine作り直す度にBGMが止まったらうんこすぎるので、AudioEngineをBGM用とSE用を分けて2個にしてみる。おし、いけた。
余裕のあるタイミングでときどき初期化しとくほうがいいかなー。自前でインスタンス作ったから、PauseとResumeの伝達も自前になるんよね、たぶん。はぁ……。
 

音が鳴らなくなる問題②
 
iOSバイスでBGMが鳴らなくなってフリーズするのは別件だった。Audioは地雷原か……。
MP3をループで再生したところ、終了時点でおかしくなった。ループせず、以降のBGMの再生できず。午後のこ~だをひっぱりだしてきて、MP3→WAV→MP3と再変換してみたが直らず。データが悪いわけではなく、やはり何か問題を抱えてそうだ。
いくつか試した感じだとビットレートなどは関係なく、短めのBGMをループさせると、ちょくちょく再生終了時に死ぬ。誰も使ってないのかよ。
しょうがないので自前でループ機構を作る。終了を検知できないから、曲の再生時間を覚えておいて、フレームカウントから経過時間算出だよ!
いまのところちゃんと動いてる気がする。スリープ、レジュームすると狂いそうだなぁ。
 

固有実装
 
いざとなったらごりごり書くのか?書くしかないのか?
  • OnPlatform (XF 1.0 ~)
  • DependecyService (XF 1.0 ~)
  • Plugins for Xamarin
  • Custom Renderer (XF 1.0 ~)
  • Effects (XF 2.1 ~)
  • Native Embedding (XF 2.2 ~)
 

ジョイパッド対応
 
手元のGPD XDでデバッグしやすいようにパッド対応しようと思った。
あっさりできてうれぴ。Xamarinとはあまり関係ないけど。
どこにマッピングするのか試行錯誤がしやすいように割り当てを辞書に入れた。
// MainActivity.cs
public override bool OnKeyDown([GeneratedEnum] Keycode keyCode, KeyEvent e)
{
    if (dicPadmap.ContainsKey(keyCode))
    {
        Pad.getInstance().dwButtons |= dicPadmap[keyCode];//Padは独自クラス
        return true;
    }
    return base.OnKeyDown(keyCode, e);
}
 
public override bool OnKeyUp([GeneratedEnum] Keycode keyCode, KeyEvent e)
{
    if (dicPadmap.ContainsKey(keyCode))
    {
        Pad.getInstance().dwButtons&= ~dicPadmap[keyCode];
        return true;
    }
    return base.OnKeyUp(keyCode, e);
}
 
あとAndroidでステータスバーなしのフルスクリーン。Activityでセット。
Window.AddFlags(WindowManagerFlags.Fullscreen);
 

FPS計測
 
CocosSharpって簡単にFPSとる方法ってあるんだろうか?
よくわからないから自前で実装してみる。
どういう構造になっているかいまだによく理解してないが、VisitRendererとやらが実際に描画されたときに呼ばれるようだ。ここでカウントすればよさげ。
 
protected override void VisitRenderer(ref CCAffineTransform worldTransform)
{
    base.VisitRenderer(ref worldTransform);
 
    frameCounter.nextFrame();
}
 

最適化
 
GCの発生頻度を抑えるべくAndroidEnvironmentに加えて、CCNode系のクラスの生成/破棄をフレームごとに行うのをやめた。さすがに無理があったようだ。
そしたらGPD XD(2015年のミドルクラスくらい?)でも60FPSでるようになったのでこれで十分かな?

 

Xamarin + CocosSharp を使ってみたい ⑥

回転抑制
画面の向きを変えると表示位置がおかしくなる。
手持ちのAndroid機にいたってはフリーズ。どうすれば……。
→ めんどっちいからとりあえず横向き固定化だ!
 
ここを参考にまずiOS
UIViewControllerを継承したクラスにて
public override bool ShouldAutorotate()
{
    return true;
}
 
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
{
    return UIInterfaceOrientationMask.Landscape;
}
としてみるが、シミュレータでは期待通りに動作だが、実機(iPad mini)ではまったく効果なし。回転しまくり。わからん。
[Export("application:supportedInterfaceOrientationsForWindow:")]
public UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, IntPtr forWindow)
{
    return UIInterfaceOrientationMask.LandscapeLeft;
}
各所で見かけたAppDelegateのおまじないも効果なし。
 
解決の糸口がつかめぬまま数時間、あーでもないこーでもない。しかし、ふとiPhoneで試すと問題なく回転を抑制できてた。どういうこと……。iPadで回転しないゲームとかあるよね?iPadiPhoneで何が違うの……。iPadは一旦保留で。
 
Androidマニフェスト弄ればいけた。
<application android:label="RetroAction.Android" android:largeHeap="true">
    <activity
        android:name=".MainActivity"
        android:screenOrientation="landscape" >
    </activity>
</application>
ついでにandroid:largeHeap="true"というおまじないもつけておいた。
 
 
バックグラウンドからのレジューム対応
iOS(ipad mini4)で復帰時に音が戻らないことがある。なんで?
iphone7は問題ないぽいな。性能依存だろうか。
それとも、レジューム周りの処理は自分で書く必要があるのだろうか?
ふむふむ。Androidは勝手にやってくれると。
iOSはテンプレートにCCGameView.pause = true / false は書いてあったな。
 
CCGameViewの中を見るとちゃんとpauseのsetterでAudioのPauseとResumu呼ばれてる。うーん。
public bool Paused
{
    get { return paused; }
    set
    {
        if (gameStarted && paused != value)
        {
            paused = value;
            previousTicks = gameTimer.Elapsed.Ticks;
 
            if (paused)
            {
                AudioEngine.PauseBackgroundMusic();
                AudioEngine.PauseAllEffects();
            }
            else
            {
                AudioEngine.ResumeBackgroundMusic();
                AudioEngine.ResumeAllEffects();
            }
 
            PlatformUpdatePaused();
        }
    }
}
 
いろいろ試してたところ、Preloadしたら直った気がする。原因は不明。メモリ食いそうだからPreloadはSEだけにしてたんだけどまぁいいか。
CCAudioEngine.SharedEngine.PreloadBackgroundMusic(path);
 
端末再起動
テストしてるとiphoneが画面真っ黒操作不能になってびっくり。スリープボタン長押しもきかない。調べたら1段階上の強制終了として[音量下げボタン]+[スリープボタン]長押しがあるそうで。
 
動作を軽くする
CCDrawNodeは可能な限り再利用しつつ、矩形描画等は最小限に、CCLabelもDictionaryにキャッシュした。加えて、フレームレートを30FPSに下げた。
といっても、ロジックは60FPSで組んじゃったので描画だけ間引く。
そしたらそこそこ動いてるかな。
60FPSでぬるぬる動かすにはCocosネイティブ造りにしないと無理そうだ。
 

Xamarin + CocosSharp を使ってみたい ⑤

部分描画(画像の一部を切り出して描画する)
Sprite.TextureRectInPixels = new CCRect(sposx, sposy, sw, sh);
Sprite.ContentSize = new CCSize(sw, sh);
 
文字列の折り返し
CCLabel.Dimensions = new CCSize(w, h);
 
仮想キーパッド(てきとう)
protected override void AddedToScene()
{
var eventListener = new CCEventListenerTouchOneByOne();
eventListener.OnTouchBegan = CCEventListener_TouchBegan;
eventListener.OnTouchCancelled = CCEventListener_TouchEnded;
eventListener.OnTouchEnded = CCEventListener_TouchEnded;
AddEventListener(eventListener, this);
}
 
Dictionary<int, uint> keyDic = new Dictionary<int, uint>();
private Boolean CCEventListener_TouchBegan(CCTouch touch, CCEvent touchEvent)
{
if (button_left.BoundingBox.ContainsPoint(touch.Location))
{
keyDic[touch.Id] = BUTTON_LEFT;
pad.buttons |= BUTTON_LEFT;
}
elseif (button_right.BoundingBox.ContainsPoint(touch.Location))
{
keyDic[touch.Id] = BUTTON_RIGHT;
pad.buttons |= BUTTON_RIGHT;
}
return true;
}
 
private void CCEventListener_TouchEnded(CCTouch touch, CCEvent touchEvent)
{
if (keyDic.ContainsKey(touch.Id))
{
pad.buttons &= ~keyDic[touch.Id];
}
}
 
private void CCEventListener_TouchMoved(CCTouch touch, CCEvent touchEvent)
//TODO
}
 
iPhone実機の接続
なかなかiPhone実機で動かせなくてイライラ。3~4時間かかってしまった。
罠回避ポイント。
  • Info.plistの配置ターゲット
  • .iOSプロジェクト設定のビルド→サポートアーキテクチャ
  • iPhone認証後のMacエージェントの切断、再接続
  • バンドル識別子変更後のソリューションクリーンビルド
  • 他いろいろあったけど忘れた
とはいえなんとか環境は整ったので、あとは作り込むのみ。
 
iPhone実機でマルチタッチが効かない
View.MultipleTouchEnabled =true;
 
iPhone実機で透過PNGが透過されない
ググるiOSでは8bit pngは透過しない?まじか。いや、32bitでも透過されない場合があるぞ。
どうもirfanViewで作ったPNGがよろしくないようだ。透過色、背景色の設定によるんだろうか?
あたらめてirfanViewPNG変換をいろいろやってみると、色がおかしくなったりしてる。PNG変換まわりはなんかおかしい。標準仕様外の最適化でもしてるんじゃろか。違うソフトで変換するかー。
 
あと.iOSプロジェクトのプロパティにあるPNG画像を最適化するにチェックいれると透過できない場合があったのでこれも注意。
 
描画が重い

 
どうしよう、実機でもカックカク。
メインループは60回まわってきてても画面の描画が反映されてるのはかなり少なそう。ダメージを受けたときのエフェクトとして、1フレームごとに表示/非表示の点滅をしたら、消えっぱなしに。
いろいろオーバーヘッドあるけどバッファの解像度は320x180とめっさ小さいので、iPhone7なら余裕だろうと思ってたんだけどなぁ。
 
ちょいとしらべてみるとDrawNodeでDrawRectangleしまくってるのが遅い。画像描画したほうがましだった。描画自体が遅いのか、毎フレームのノードの生成が遅いのか、生成と破棄ともなうGCが遅いのかは調べてないけど。
がんばって最適化するかー。
 
描画のずれ
iPhoneで画像の描画が1ドットずれる。上側1ドットが表示されず、下側1ドットが2ドットに引き延ばされてる。0.5ドットずれてるとかそういうアレだろうか?厳密なドット単位の処理がきついなぁ。とりあえず0.5f足したらなおった気がする。
 
 
 

Xamarin + CocosSharp を使ってみたい ④

我慢できずに中古のMac miniを購入
APPLE Mac mini (2.6GHz Dual Core i5/8GB/1TB/Intel Iris) MGEN2J/A
6万円なり。てか新品でも7万やないか。新品でもよかったな……。
傷もなく良品でテカテカひかってるからまぁいいや。
アルミの削りだしボディはかっこいい。

なにやら画像が乱れて、ジジジッっという異音がしていたが、Thunderboltな口から古いDisplayPort⇔HDMI変換アダプタを経由してディスプレイと接続していたせいかもしれない。しらんけど。HDMIで直接つないだら直ったきがする。
さてもっかいMacをセットアップだ。
 
座標反転
Xamarinを試すまえにC#の標準ライブラリ(と幾何かのWin32API)だけで簡単なアクションゲームを作ってたので移植を試みる。描画まわりはSystem.Drawingだけという男らしい造りだ。
 
とりあえず前回の調査でCCRenderTextureとやらを使えばなんとかなりそうな感触を得ていたのだが、どう考えても描画まわりのロジック全部、Y座標系を逆にするのが面倒すぎる。CocsSharpは左下が基点となる。
いろいろ調べてみたところ、スケールを-1にすればいけそう。
 
Sprite.ScaleY = -1;
 
線描画、矩形描画等はCCRenderTextureにそのまま描画し、画像はYスケールを-1にしてから描画、描画完了したCCRenderTextureをYスケール-1で設置すれば、左上基点の座標系でいける。
 
グラフィックまわりのラッパー的なものをCCRenderTextureを使ってごりごり書いたらなんとなく動いた。Xamarinしゅごい。けど、表示がいろいろおかしい。

 
まず色がおかしかったのだが、CCColor3B、CCColor4Bのコンストラクタの引数の型がfloatで0~1.0ぽい。0~255つっこんだら、もれなく黒か白になってた。ちゃんとByte型のやつもあったのでキャストしたらなおりました。

 
なんかくっそ重いなぁ。大丈夫かなぁ。
画像を切り出して部分描画するところもうまくいってないなぁ。
タッチ入力もよくわからんなぁ。先は長い。
 

Xamarin + CocosSharp を使ってみたい ③

iOSは環境がないのでしばらくほっとくとして、勉強を進める。
Xamarin + CocosSharpのゲーム開発に最低限必要そうな要素メモ。
コーディング時にぱっとググれるようにするためのとっかかりを作る一次調査なので、C++のCocos2d-xの情報なども混じりつつ。
 
データの保存
PCL Storageという便利なライブラリがあるそうな
const string SubFolderName = "SampleData";
const string TextFileName = "Sample.txt";
 
// ユーザーデータを読み取るメソッド
async Task LoadTextAsync()
{
// ユーザーデータ保存フォルダー
PCLStorage.IFolder localFolder = PCLStorage.FileSystem.Current.LocalStorage;
 
// サブフォルダーを作成、または、取得する
PCLStorage.IFolder subFolder
= await localFolder.CreateFolderAsync(SubFolderName,
PCLStorage.CreationCollisionOption.OpenIfExists);
 
// ファイルを取得する
PCLStorage.IFile file = await subFolder.GetFileAsync(TextFileName);
 
// テキストファイルを読み込む
// ※ファイル冒頭に「using PCLStorage;」が必要
return await file.ReadAllTextAsync();
}
 
// 定数定義を再掲
//const string SubFolderName = "SampleData";
//const string TextFileName = "Sample.txt";
 
// ユーザーデータを書き出すメソッド
async Task SaveTextAsync(string text)
{
// ユーザーデータ保存フォルダー
PCLStorage.IFolder localFolder = PCLStorage.FileSystem.Current.LocalStorage;
 
// サブフォルダーを作成、または、取得する
PCLStorage.IFolder subFolder
= await localFolder.CreateFolderAsync(SubFolderName,
PCLStorage.CreationCollisionOption.OpenIfExists);
 
// ファイルを作成、または、取得する
PCLStorage.IFile file
= await subFolder.CreateFileAsync(TextFileName,
PCLStorage.CreationCollisionOption.ReplaceExisting);
 
// テキストをファイルに書き込む
// ※冒頭に「using PCLStorage;」が必要
await file.WriteAllTextAsync(text);
 
return file.Path;
}
 
Audio
CCAudioEngine
 
再生
//BGM .mp3
CCAudioEngine.SharedEngine.PlayBackgroundMusic (filename:"FruityFalls",loop:false);
//SE .wav
CCAudioEngine.SharedEngine.PlayEffect (filename:"Electricity");
 
プリロード
auto audio = SimpleAudioEngine::getInstance();
 
// pre-loading background music and effects. You could pre-load// effects, perhaps on app startup so they are already loaded// when you want to use them.
audio->preloadBackgroundMusic("myMusic1.mp3");
audio->preloadBackgroundMusic("myMusic2.mp3");
 
audio->preloadEffect("myEffect1.mp3");
audio->preloadEffect("myEffect2.mp3");
 
// unload a sound from cache. If you are finished with a sound and// you wont use it anymore in your game. unload it to free up// resources.
audio->unloadEffect("myEffect1.mp3");
 
音量
auto audio = SimpleAudioEngine::getInstance();
 
// setting the volume specifying value as a float
audio->setEffectsVolume(5.0f);
 
画像表示方法
CCSprite → スプライト
CCSpriteBachNode → パターン描画
TMXTiledMap → BG面
 
自分でゴリゴリとピクセルバッファにBG面書きたいのだがどうすれば?
 
画像読込
Spriteに直接読み込むか、TextureCacheに読み込むか。
テクスチャアトラスという効率的な画像の集合データからの切り出し利用もあるようだが、外部ツールが必要でちょっと面倒そう。CCSpriteSheet
とりあえず利用頻度の高いデータはTextureCacheに放り込むのかな。
 
画像バッファ
CCRenderTexture
CCRenderTexture* texture = CCRenderTexture::create(width, height);
ピクセルバッファ的に使えそう。
これにSpriteとか描画しまくってBG面作ればいいのかしら。
 
 
利用例
 
画像バッファへの基本的な描画命令
画像描画、線描画、矩形描画、文字列描画など。
CCDrawNodeクラス
DrawPoint、DrawLine、DrawRect、DrawStringなどが使えそう。
昔のゲームをベタ移植する際にはこのへんが重要かなぁ。
 
CCDrawNodeひとつで複数のプリミティブの描画が可能ぽい。
for (int i = 0; i < 8; i++)
{
drawNode.DrawCircle (
center: new CCPoint (i*15, 0),
radius: 20,
color: CCColor4B.White);
}
毎フレームCCRenderTextureにBG面を更新して描くのにはClear()メソッドでも呼べばいいのかな。あと画像とか混じる場合に描画順番はどうやって制御したものか。
 
画像バッファの画面反映
CCRenderTexture.BeginWithClear()
CCNode.Visit()
CCRenderTexture.End()
 
CCRenderTexture texture = new CCRenderTexture(ContentSize, ContentSize);
texture.Sprite.Position = new CCPoint(ContentSize.Center.X, ContentSize.Center.Y);
AddChild(texture.Sprite);
 
CCSprite title = new CCSprite("/Resources/Images/Title/Title.png", null);
title.Texture.IsAntialiased = false;
 
CCDrawNode dnode = new CCDrawNode();
 
texture.BeginWithClear(CCColor4B.Orange);
{
title.Position = new CCPoint(0, 0);
title.Visit();
 
title.Position = new CCPoint(ContentSize.Center.X, ContentSize.Center.Y);
title.Visit();
 
dnode.DrawRect(new CCRect(ContentSize.Center.X, ContentSize.Center.Y, 50, 50), CCColor4B.Green);
 
dnode.DrawRect(new CCRect(ContentSize.Center.X + 50, ContentSize.Center.Y, 50, 50));
 
dnode.DrawRect(new CCRect(ContentSize.Center.X + 100, ContentSize.Center.Y, 50-1, 50-1),
CCColor4B.Transparent,0.1f, CCColor4B.Yellow);
 
dnode.Visit();
}
texture.End();
CCRenderTextureの確認のついでにCCDrawNodeをテスト。DrawRectがなんか外枠がY軸だけ1ドットずれる……すっきりしない。

座標系は左下基点、Spriteなどのオブジェクトの座標指定は中心座標のようだ。
CCRenderTexture内に描いたCCDrawNodeにおける座標は左下だった。
 
フレーム制御(60FPS)
CCMoveToクラスなどでスプライトのアクションを設定するようだ。
更新間隔と目的地を設定するとか。ほほーなるほど。
面白そうだけど、今回は昔ながらの作り方をしたい。
固定FPSでフレームごとの処理とかはできるんだろうか?
→ 第二引数なしのCCNode.Schedule()で毎フレーム処理できそう。
  勝手に60FPSになってるぽいけど、どこかで設定できるんだろうか。
 
class TestLayer : CCLayerColor
{
CCRenderTexture texture ;
CCSprite title;
CCDrawNode dnode;
Random rnd = new Random();
 
protected override void AddedToScene()
{
base.AddedToScene();
 
texture = new CCRenderTexture(ContentSize, ContentSize);
texture.Sprite.Position = new CCPoint(ContentSize.Center.X, ContentSize.Center.Y);
AddChild(texture.Sprite);
 
title = new CCSprite("/Resources/Images/Title/Title.png", null);
title.Texture.IsAntialiased = false;
 
dnode = new CCDrawNode();
 
//毎フレーム実行
this.Schedule(t => this.mainloop());
 
}
 
private void mainloop()
{
dnode.Clear();
 
texture.BeginWithClear(CCColor4B.Orange);
{
title.Position = new CCPoint(0, 0);
title.Visit();
 
title.Position = new CCPoint(ContentSize.Center.X + rnd.Next(50),
ContentSize.Center.Y + rnd.Next(50));
title.Visit();
 
dnode.DrawRect(new CCRect(ContentSize.Center.X, ContentSize.Center.Y, 50, 50),
CCColor4B.Green);
 
dnode.DrawRect(new CCRect(ContentSize.Center.X + 50, ContentSize.Center.Y, 50, 50));
 
dnode.DrawRect(new CCRect(ContentSize.Center.X + 100, ContentSize.Center.Y, 50, 50),
CCColor4B.Transparent, 0.1f, CCColor4B.Yellow);
 
dnode.Visit();
}
texture.End();
}
}
これ勝手にダブルバッファリングになってるんだろうか。
 
 
 
 
バックグラウンド処理
 
// This function will be called when the app is inactive. When comes a phone call,// it's be invoked toovoid AppDelegate::applicationDidEnterBackground() {
Director::getInstance()->stopAnimation();
 
// if you use SimpleAudioEngine, it must be pause
// SimpleAudioEngine::getInstance()->pauseBackgroundMusic();}
 
// this function will be called when the app is active againvoid AppDelegate::applicationWillEnterForeground() {
Director::getInstance()->startAnimation();
 
// if you use SimpleAudioEngine, it must resume here
// SimpleAudioEngine::getInstance()->resumeBackgroundMusic();}
 
 
タッチ入力の検知
 
var eventListener = new CCEventListenerTouchOneByOne();
 
// OnTouchBegan で true を返却しないと、OnTouchEndedが発動しない。
eventListener.OnTouchBegan = (t, e) => true;
 
eventListener.OnTouchEnded = (t, e) =>
{
// 移動先のシーン(ゲーム画面)を作成
var newScene = new CCScene(GameView);
 
var gameLayer = new GameLayer();
newScene.AddChild(gameLayer);
 
// シーン切り替え時の効果を設定
CCTransitionScene transitionScene = new CCTransitionFade(4.0f, newScene);
 
// ゲーム画面へシーン切り替え
Director.ReplaceScene(transitionScene);
};
AddEventListener(eventListener, this);
 
その他
 
ドキュメント日本語訳
 
Cocos2d-x APIリファレンス
 
CocosSharp APIリファレンス
 
CocosSharp Guides
 
 
 
 

Xamarin + CocosSharp を使ってみたい ②

拡大処理について
 
古いmac miniを引っ張り出してOSをアップしている間に、AndroidのほうでCocosSharpの勉強をしてみる。
 
内部解像度を指定すれば、あとは勝手にハードウェアに合わせて拡大してくれるようだ。超便利。
var gameView = sender as CCGameView;
gameView.DesignResolution = new CCSizeI(320, 180);
gameView.ResolutionPolicy = CCViewResolutionPolicy.ShowAll;
 
低解像度のバッファを想定して下記の画像を表示した。

が、いい具合に勝手にスムージングされている。
nearest neighborで拡大はできないのか?Webで情報がみつけられない。
 
 
そしてがんばってインテリセンス眺めてたら、なんかそれっぽいパラメータを見つけた。
ccsprite.Texture.IsAntialiased = false;

う~ん?たぶん目的を達成した気がする。
 
 
 
mac miniのセットアップ
 
とりあえず引っ張り出してきたmac miniのOSをアップデートした。
ちなみに一緒に買って放置されてたキーボードとマウスの電池は奇跡的に液漏れしてなかった。
 
2009年モデルのmac miniOS X El Capitanとやらまでしか入らないらしい。
そしてきゃぴたんはXcode 8.2までしか使えないらしい。
大丈夫なのか。。。
 
SierraMac mini Mid 2010以降が必要
 
WindowsのVisualStudio上からmacにリモートで接続してデバッグするようだ。
とりあえずXamarinがmac上にも必要らしいので、入れてみる。
 
XamarinのページにいくとXamarin Studioが見当たらない。
もうVisualStudioからしか利用できないのかな?
VisualStudioのインストールを進めるとXcode9が必要とか不穏なメッセージが流れる。
 
そして……
 
うん、ダメっぽい。Xcodeが古いって怒られる。
Xamarin Live Playerもダメだった。Build Errorとか出る。
 
新型がうわさされる時期にmac miniとか買いとうない。
されどノートはいらないんだよなー。中古で2014年モデル買ってくるか……。
結構いいお値段するなぁ。
 
 

Xamarin + CocosSharp を使ってみたい

久しぶりにゲームを作ろうと思ったけど浦島太郎状態。
できればWindowsAndroidiOSクロスプラットフォーム開発がしたい。
さらに言えばJavaとかC#でコード書きたい。
 
そして、グーグル先生からVisualStudio+Xamarin+CocosSharpという啓示を受けたのだった。
とりあえずVisualStudio2017がタダで使えるようだ。ふむふむ。
ということで、メモった作業経過を少しばかりブログに残してみようと思う。
 

 作業メモ

Hello World的なものに取り掛かるが、セットアップにいろいろとひっかかる。
CocosSharpがなかなか入らず。。
Web上に情報すくなすぎぃ。。アメリカ語は読めません。

上記設定でインストールに成功した。
ソリューションを右クリック→NuGet→CocosSharpを検索してインストール。

なんとか入ったと思ったが今度はAndroidエミュレータが動かない。

ずっとこのまんま。起動失敗してるぽい。
Android SDK Managerからアップデートを行って、その後エミュレータを作り直したら起動はした。

が、画面はずっと真っ黒なまま。。
API Level25で作ってるはずが、26がインストールされてないぞとかエラーでててイミフ。
とりあえず26も入れてみる。
そしてIA版のほうが速そうなのでIA版を作って起動してみる。
 
そしたら今度はHAXMないって言われたのでダウンロードしてきて入れてみる。
Android SDK Managerからも関連項目が見えたが、なぜか利用できないようだ。
直接入れる。

おお、がんばれ!

やったー!つД`)・゚・。・゚゚・*:.。..。.:*・゚
でも作ったアプリ起動しないよ……?
 
なんかうまく動かないしまだ重いしなので、Androidバージョン4.4で作り直す。

 
ここを参考に画像を出すだけのプログラムを書いてみる。貴重な情報大変ありがたい。
 
が、OpenTKの参照がうんぬんでエラーいわれてビルドできない。
参照追加しようとしてみるが、どれやねんくそ。//心が荒んできた
大量にあったけど2回目で当たり引いた。
試行錯誤した末にできた参照のゴミだろうか。。。

そしてようやっと起動!ぱちぱちぱち。

 
次はiOSだなー。iOS版はやっぱmacいるのかー。
ほこりかぶった2009年モデルのmac miniしかないよー……?