2013年9月20日金曜日

cocos2d-xでスクロールするレイヤーCCScrollLayerを使う

どうも、俺@久しぶりの書き込みです。

最近もほぼ毎日iOS/Androidのゲームアプリ開発に精を出しています。

今日はcocos2d-xを使ってスクロール出来るレイヤーの紹介です。
画面をスワイプしてページングする、アレです。
先日リリースしたゲームアプリ「ゴー!ゴー!カート」のコース選択画面で使っています。


GitHubに上がっているyandongliu / CCScrollLayerを使わせて頂きましたが、やりたい事がほぼこれで全て実装できました。
※cocos2d-x v2.0.2での動作保証がされています。それ以上のバージョンのcocos2d-xを使う場合はしっかり動作検証が必要です。

基本的な使い方は、スクロールして表示するコンテンツ(Layer)を配列にaddObject()しておいて、その配列をCCScrollLayerにセットする、という流れです。


ではまずGitHubからCCScrollLayerをcloneします。

git clone https://github.com/yadongliu/CCScrollLayer.git
で、中のCCScrollLayer.hとCCScrollLayer.mをXCodeのプロジェクト内に放り込みます。
これで準備OKです。

それでは表示する各コンテンツ(Layer)を作成しておきます。

// ヘッダ ContentsLayer.h
class ContentsLayer: public cocos2d::CCLayer
{
public:
  ContentsLayer();
  virtual bool init();
};

// 実装 ContentsLayer.m
#include "ContentsLayer.h"

ContentsLayer::ContentsLayer()
{
}
bool ContentsLayer::init()
{
  if (!CCLayer::init()) {
    return false;
  }

  // 適当なSpriteでも載せておく
  CCSprite *sprite = CCSprite::create("hoge.png");
  sprite->setPosition(ccp(200,200));
  this->addChild(sprite);

  return true;
}

次にスクロールさせたいSceneのヘッダファイルでこのファイルを読み込み宣言しておきます。

#include "CCScrolLayer.h"
#include "ContentsLayer.h"
class MyScene: public: cocos2d::CCLayer
{
public:
  MyScene();
  static cocos2d::CCScene *scene();
  // その他の宣言
private:
  // CCScrollLayerをクラス変数としておく(あとあと操作しやすいので、、各自お好みで、、)
  cocos2d::CCScrollLayer *_myScrollLayer;
};

次に実装ファイルに処理を書いていきます。


// コンストラクタやinit()で
bool MyScene::init()
{
  if (!CCLayer::init()) {
    return false;
  }

  // とりあえず4画面スクロールさせる
  CCArray *contentsList = CCArray::create();
  ContentsLayer *contents1 = new ContentsLayer();
  ContentsLayer *contents2 = new ContentsLayer();
  ContentsLayer *contents3 = new ContentsLayer();
  ContentsLayer *contents4 = new ContentsLayer();

  contents1->init();
  contents2->init();
  contents3->init();
  contents4->init();

  contentsList->addObject(contents1);
  contentsList->addObject(contents2);
  contentsList->addObject(contents3);
  contentsList->addObject(contents4);

  // CCScrollLayerへセット
  _myScrollLayer = new CCScrollLayer();

  // 4画面分の配列をセット。
  _myScrollLayer->initWithLayers(contentsList, 0);

  // ページインジケーターのポジション(任意)
  _myScrollLayer->setPageIndicatorPosition(ccp(100, 20));

  // 最初に表示しておくページ番号
  _myScrollLayer->selectPage(0);

  this->addChild(_myScrollLayer);

  // レイヤーは解放しておく
  contents1->release();
  contents2->release();
  contents3->release();
  contents4->release();

  return true;
}

とりあえずこれだけで動きます。 4画面分スクロールできるはずです。 他にも使えそうなメソッドがいくつか用意されていて、
CCArray *getPages() // 表示できる画面を配列で返す
unsigned int getCurrentScreen() // 現在のページ番号を返す

や、CCScrollLayerDelegateという便利なデリゲートもあります。

詳しくはソースを読んでみてください。
すごく短くて読みやすいです。


以上でぇぇぇぇぇす。

2013年8月28日水曜日

sftpで鍵認証する際のオプション

どうも、俺@仕事中です。

 いつも忘れるのでめもめも。 sftpコマンドを使ってサーバ接続する際に、公開鍵認証にしているときに鍵ファイルを指定する方法。
sftp -oIdentityFile=/path/to/鍵ファイル username@example.jp
オプションの -oIdentityFile= は username@example.jp の前に書かないとアカンで!


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

2013年8月22日木曜日

nginxにデフォルトの文字コードをセットしちゃる

どうも、俺@眠いです。

nginxでデフォルト文字コードをセット、というか自動でレスポンスヘッダに
Content-Type: text/html; charset=UTF-8
を追加させる方法についてメモメモ。

設定ファイル(/path/to/nginx.confなど)の
http, server, location
いづれかのディレクティブ内に
charset UTF-8;
を追加しちゃって
# service nginx reload
してやればOKです。

これを記述していない場合はデフォルトで
Content-Type: text/html;
だけがレスポンスヘッダに含まれます。


以上でぇぇぇぇぇぇす。

2013年7月23日火曜日

cocos2d-x Xcodeで"Symbol not found: ___CFObjCIsCollectable"というエラーが出る、でも大丈夫

どうも、俺@家です。

タイトルの件ですが、Xcodeでcocos2dxなアプリを開発しててiOSシュミレータで実行しようとすると、
Error loading /System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn:  dlopen(/System/Library/Extensions/AudioIPCDriver.kext/Contents/Resources/AudioIPCPlugIn.bundle/Contents/MacOS/AudioIPCPlugIn, 262): Symbol not found: ___CFObjCIsCollectable
  Referenced from: /System/Library/Frameworks/Security.framework/Versions/A/Security
  Expected in: /Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.0.sdk/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
 in /System/Library/Frameworks/Security.framework/Versions/A/Security
のようなエラーメッセージが出まくる場合。
問題ない、大丈夫。no problem。
だってほら、シュミレータ実行できてるでしょ。
iOSシュミレータのバグだそうです。

Error: symbol not found: __CFObjCIsCollectable - stack overflow

以上でぇぇぇぇぇす。

2013年7月1日月曜日

tcpdumpじゃないtcpセッションツールmiruoが凄すぎた

どうも、俺@家です。 

最近、ネットワーク関連の調査でtcpについて調べたり、tcpdumpを使って通信のやり取りを見まくっていました。
 ネットワークについてボトルネックを調べるときは、Linuxサーバのカーネルの設定を見なおしたり、tcpdumpでtcpセッションの内容を確認したりします。
ググればたくさん出てきますが、ネットワーク関連については割と新しめのポストで
Linux Books Support Siteなどが参考になりした。

ところでtcpdumpですが、当然ながらとても便利です。
オプションも豊富で自分の知りたい情報を知ることができます。
ただし、大量アクセスのあるサイトで使うとあらゆるオプションを駆使してフィルタリングしても、ログが大量に出力されて解析が大変ですね。

「どこかの天才がもっとシンプルにTCPセッションを見れるツール作ってないかなぁ」と思っていたら、いました天才が。
高負荷サイトのボトルネックを見つけるには
しかも日本人、しかも2年も前。KLabの開発すげー。
miruoというツールです。

早速インストールしましょう。
※CentOS 6.2


git clone https://github.com/KLab/miruo.git
cd miruo
./configure
make
〜略〜
make[1]: *** [miruo.o] エラー 1
make[1]: ディレクトリ `/usr/local/src/miruo' から出ます
make: *** [all] エラー 2
ありゃ、エラーが出た。

makeのログをたどってみると、

miruo.h:24:17: error: pcap.h: そのようなファイルやディレクトリはありません
きっとpcapらしきライブラリが足りないみたい。


yum install libpcap-devel
よし、インストールを続けよう。


make
make install
make[1]: ディレクトリ `/usr/local/src/miruo' に入ります
test -z "/usr/local/sbin" || /bin/mkdir -p "/usr/local/sbin"
  /usr/bin/install -c miruo '/usr/local/sbin'
make[1]: `install-data-am' に対して行うべき事はありません.
make[1]: ディレクトリ `/usr/local/src/miruo' から出ます
これで/usr/local/sbin/miruoがインストール完了です!
〜に対して行うべき事はありません、と注意されますが、
心のなかで「そうなんですね」と返事しておきましょう。

このmiruoですが、「怪しいTCP通信」だけをピックアップして表示してくれるツールです。
なのでtcpdumpのように全TCPパケットを表示することもないので、解析がしやすくなります。
例えば
1392             0.343 |   (Client IP):50861 == (My Server IP):80    | Total 3 segments, 126 bytes
1392:0000 19:27:28.800 |          SYN_SENT >----S-> SYN_RECV          | 9098F675/00000000   78 - <mss=1410, wscale=4, timestamp 560465119 0, sackOK>
1392:0001 19:27:28.801 |       ESTABLISHED <-a--s- -="" 1392:0002="" 19:27:29.144="" 2e7570d5="" 66="" closed="" lt="" mss="1460," sackok="" syn_recv="" wscale="7>">---R--> CLOSED            | 9098F676/00000000   60 - <>

の場合だと、
1)クライアント→SYN→サーバ
2)サーバ→SYN+ACK→クライアント
3)クライアント→RST(強制終了)
のようなやり取りが行われていたり、

1431             0.345 |   (Client IP):48646 == (My Server IP):80    | Total 13 segments, 2185 bytes
1431:0000 19:27:28.824 |          SYN_SENT >----S-> SYN_RECV          | 6F591A36/00000000   74 - <mss=1420, sackOK, timestamp 14126836 0, wscale=5>
1431:0001 19:27:28.824 |       ESTABLISHED <-a--s- -="" 1431:0002="" 19:27:28.830="" 66="" b1fea867="" established="" lt="" mss="1460," sackok="" syn_recv="" wscale="7>">----S-> SYN_RECV          | 6F591A36/00000000   74 - <mss=1420, sackOK, timestamp 14126936 0, wscale=5>
1431:0003 19:27:28.830 |       ESTABLISHED <-a--s- -="" 1431:0004="" 19:27:28.903="" 66="" b1fea867="" established="" lt="" mss="1460," sackok="" syn_recv="" wscale="7>">-A----> ESTABLISHED       | 6F591A37/B1FEA868   60 - <>
1431:****              |                                              |
1431:0010 19:27:29.074 |         FIN_WAIT1 >-A---F> ESTABLISHED       | 6F591B62/B1FEACEE   60 - <>
1431:0011 19:27:29.074 |         FIN_WAIT2 <-a---f -="" 1431:0012="" 19:27:29.169="" 54="" b1feacee="" gt="" last_ack="" lt="" time_wait="">-A----> CLOSED            | 6F591B63/B1FEACEF   60 - <>
の場合は
1)クライアント→SYN→サーバ
2)サーバ→SYN+ACK→クライアント
3)クライアント→SYN (またSYNかよっ!
4)サーバ→SYN+ACK→クライアント (ほらよっ、二度目やで!
5)クライアント→ACK (やっと接続
のようなやり取りが行われていたり、一目瞭然です。



/usr/local/sbin/miruo --live
と打てば通常のtcpdumpコマンドと同等の結果を得ることも出来ます。
※ポートやホストの指定はできますが、tcpdump独自のオプション(-xや-v、-nなど)は使えませんので、
それらを使いたい場合はtcpdumpを使いましょう。

サーバ側のネットワーク関連のカーネルパラメータのチューニング不足や、クライアントからの不自然なパケット(または攻撃)などを捉える事が用意に出来ます。

SYN再送を補足するかどうか、RSTフラグのパケットを補足するかどうか、到達に◯ミリ秒以上かかった通信を補足するかどうか、などいくつか使えそうなオプションも用意されているので用途に合わせてオプション駆使することも可能です。
超便利。


以上でぇぇぇぇす。