2016年12月13日火曜日

.gitignoreが反映されない場合

どうも、俺です。

.gitignoreに除外ファイル/ディレクトリを追記しても反映されない場合の対応方法についてめもめも。

1) キャッシュが効いてしまっているので削除します。
$ git rm --cached /path/to/directory (or file)

2) コミットします。

$ git add .gitignore
$ git add /path/to/directory (or file)
$ git commit -m "COMMIT MESSAGE"

以上でぇぇぇぇぇぇす。

※参照 .gitignore に設定を追加して反映させる: Qiita

2016年11月24日木曜日

htmlにカスタム属性(data-*)を使って、jQueryで簡単アクセスする

どうも、俺です。

HTMLに独自のカスタム属性をつけて、
jQueryで操作できれば便利ということを発見しました。

カスタム属性を使えば、
<img data-hoge="ほげ" src="xxx.png" />

のように、「data-」のあとに好きな文字列を指定して値をセットできます。
data属性には一応仕様が定められており、
1文字以上のアルファベット、数字、ハイフン、アンダースコアが使えるようです。

で、本題はここから。
設定した「data-hoge」にjQueryを使ってアクセスするには、
$("img").data("hoge");

超簡単!!

data属性にJSONをセットもできるので、
<div data-hoge='{"aaaa":"あいうえお", "bbbb":1000}'>
のように指定しておけば、

$("div").data("hoge").aaa;

でアクセス可能!

ちなみに、data属性は複数も指定できます。

<span data-hoge="ほげ" data-fuga="ふが">

以上でぇぇぇす。

2016年11月18日金曜日

Laravel(またはLumen)のクエリビルダーのWHERE条件で、()カッコ付きのSQLを作る

どうも、俺です。

忘れぬうちにメモ。

例えば、
SELECT * FROM user WHERE status=1 AND (type=1 OR type=2);
のようなクエリを作りたい場合。


$query = $userModel->where('status', 1)->where(function($query) use()
{
  $query->where('type', 1)->orWhere('type', 2);
});
になります。

ちなみに、
SELECT * FROM user WHERE status=1 AND (type=1 AND type=2);
の場合は
$query = $userModel->where('status', 1)->where(function($query) use()
{
  $query->where('type', 1)->where('type', 2);
});
になります。

ちょっと読みづらいっす...。


以上でぇぇぇす。

2016年11月2日水曜日

Windows起動すると画面真っ黒でキャレット(アンダースコア)が点滅して先に進まねぇ!って時にやったこと

どうも、俺です。

今日は、Windows8.1を起動しようとしたら
画面が真っ黒になって、画面左上にキャレット(アンダースコアの形をしたカーソル)が点滅したまま
何もできなくなってしまった時にやる対応方法についてメモです。

色々なサイトで調べまくった結果、
どうやら原因はブートセクタが破損してしまったことが原因の可能性が高いようです。


では、直しましょう。

方法1: Windowsインストールディスクで直す

最も手早い方法だと思いますが、
今時インストールディスクを手元に持ってる人って少ないのではないでしょうか。
一応方法は、
コマンドプロンプトからWindowsを復旧する4つの方法 (Vista/7/8/8.1/10)
など参考にしてみて下さい。

方法2: Windows PEを使って直す

今回書きたい内容です。
Microsoftが用意してくれているWindows PEを使って直します。

1) 元気なWinPCでWindows ADKをインストール

から、Windows用アセスメント&デプロイメントキットをDLします。
DLしたadksetup.extを実行し、
・Deployment Tools
・Windows Preinstallation Environment (Windows PE)
の2つを選択しインストールします。

2) ブート用のUSBメモリを作成

スタートメニュー>Windows Kits>展開およびイメージングツール環境を右クリックして「管理者として実行」を選択。
コマンドプロンプトが起動するので、以下のようにコマンドを打ちまくる。

C:¥>copype x86 C:¥winpe_x86
... 略 ...
Success

ここで、
fwfiles
media
mount
という3つのフォルダが生成されるはずです。

次に、USBメモリに書き込みます。

C:¥> cd winpe_x86
# 最後の「f:」はUSBがFドライブに刺しこまれている場合です。
# 環境に合わせて書き変えて下さい。
C:¥winpe_x86>makewinpemedia /ufd c:¥winpe_x86 f:
Proceed with Format [Y,N]? Y // ←USBデータはフォーマットされてしまうけど、Yで。
... 略 ...
Success

USBにWindows PEデータが書き込まれました。

3) Windows PEで修復

では、壊れたWindowsマシンにUSBを挿し込み起動させます。
この時、BIOS画面でブートの優先順をUSBを最優先に変更して起動させないと、いつもの壊れた真っ黒画面になってしまいますので注意です。

WindowsPEが起動したら、そのコマンドプロンプト上で、
X:¥windows¥system32> bootsect /nt60 sys mbr

と打ちます。
が、多くの人はここで
The system partition was not found
というエラーに遭遇すると思います。
その場合は、
X:¥windows¥system32> bootsect /nt60 C: /mbr

で問題ないはずです。
途中の「C:」は壊れた対象のHDDドライブ名です。
環境に応じて書き変えて下さい。


これだけで壊れたHDDのブートセクタは直っているはず!

4) それでも直っていない場合

3)が終わったあと、Windowsを起動しようとしてもまた真っ黒にキャレット点滅の場合..。
大丈夫です、3)をもう一度試して起動してみましょう。
それでもダメな場合、今度はPC再起動してみましょう。
きっと動くはずです..。
僕は2回ほど再起動し直すと、無事起動できました。

それでもダメな場合、、
別の原因を探って対応するか、PCを買い換えましょう。


以上でぇぇぇぇぇす!

※参考サイト: 管理者必携のトラブルシューティングツール「Windows PE 5.0」の起動用USBメモリを作成する - @IT

2016年8月19日金曜日

コマンドラインからwgetでログイン認証が必要なページを丸ごとダウンロードする

どうも、俺です。

今日は、wgetを使ってログイン認証先のURLページを丸ごとダウンロードする方法をメモメモ。

■手順1: wgetで認証を行い、セッション(COOKIE)データをローカルへ保存

wget --keep-session-cookies --save-cookies=cookies.txt --post-data 'userId=MY_USER_ID&password=MY_PASSWORD' http://example.com/login

これにより cookies.txtにセッションデータが保存されます。

■手順2: 保存したセッションデータを利用して、認証先のページをダウンロード

wget --load-cookies cookies.txt -p -H -E -nH -k http://example.com/mypage

これで見たいページが丸ごとDL出来ます!


※参考サイト
wgetでWebページをまるごとローカルに保存する: whiskers



以上でぇぇぇぇぇぇす。

2016年7月7日木曜日

[Swift] NSURLSessionでカスタムヘッダーを追加する

どうも俺です。

 NSURLSessionに独自のユーザーエージェントなど、ヘッダー内をカスタマイズする方法。
Swift v2です。

let url = NSURL(string:"http://hogehoge.com")
let config = NSURLSessionConfiguration.defaultSessionConfiguration()

// ここからヘッダー追加
config.HTTPAdditionalHeaders = ["User-Agent": "MyOriginalUserAgent"]
config.hTTPAdditionalHeaders = ["Custom-Header": "This is MyCustomHeader"]

let session = NSURLSession(configuration: config)
let request = NSURLRequest(URL: url)
let task = session.dataTaskWithRequest(request)
task.resume()

これで追加できます。
サーバー側でログを確認すると、
HTTP_USER_AGENT : MyOriginalUserAgent
HTTP_CUSTOM_HEADER : This is MyCustomHeader

のように、
・PREFIXに「HTTP_」が付く。
・全て大文字に変換される。
・「-(ハイフン)」は「_(アンダースコア)」に変換される。
という変換処理が内部的に走るようです。


以上でぇぇぇす。

2016年6月30日木曜日

UITableView#reloadData()がうまく動かん

どうも、俺です。
最近はSwiftをいろいろ触っています。

さてタイトルのとおり、
例えば、NSURLSessionを使って
サーバーから取得したデータをUITableViewの各セルに表示させようとして、

  func hoge()
  {
    let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
    let request = NSURLRequest(URL: NSURL("https://xxxx.example.com"))
    let task = session.dataTaskWithRequest(request, completionHandler: self.getData)
    task.resume()
  }

  func getData(data:NSData?, res:NSURLResponse?,error:NSError?)
  {
    // ここで取得したデータをゴニョニョして...


    // ↓reload()してんのに表示変わらん!
    self.tableView.reloadData()
  } 

このような現象になっている場合。
安心してください。大丈夫です。
上記の例の場合、tableViewのreloadData()がメインスレッドから呼ばれていないことが原因なので、
reloadData()の呼び出しは


  dispatch_async(dispatch_get_main_queue(), {
    self.tableView.reloadData()
  })

こうしてやればOKです。

以上でェェェえす。

2016年6月8日水曜日

iOS/Androidアプリ「究極リバーシ」 リリースしました

どうも、俺です。 cocos2d-x v3.10で開発したアプリ「究極リバーシ」をリリースしました。
・iOS
https://itunes.apple.com/jp/app/ultimate-reversi/id1114493417?mt=8 
・Android
https://play.google.com/store/apps/details?id=jp.marge.android.reversi

最近よく耳にする、人工知能(AI)と対戦するリバーシアプリです。



はじめてのcocos2d v3系でしたが、
殆どの部分でv2系と同じような実装ができたので、それほど大きく戸惑う事はありませんでした。
一番困ったのは、CCArrayとCCDictionaryがなくなったことでしょうか。
Vectorクラス or Mapクラスを使うかstd::vectorを使うか、、、
結局std::vectorを一番使いました。

また、今回リバーシAIを実装するということで、
いろんなサイトからリバーシのAIについて勉強しまくりました。
ゲーム機探索や盤面の評価方法、MinMax/AlphaBeta/NegaScout法など、
ゲームのAIを実装する上で必要なノウハウを色々学べました。

あと、6/1からiOS審査でIPv6-only Networkで動作出来ることが必須になったということで、
急遽cocos2d-x v3.11.1でもビルドして試してみたのですが、
なぜかAndroid v4系で、
Jniの呼び出しでクラッシュが発生してしまい、諦めました。

一応、対応方法はここを参考に。



以上でぇぇぇす。

2016年6月7日火曜日

[cocos2d-x] OpenGL error 0x0506が出てフリーズ

どうも、俺です。
cocos2d-x(v3.10)で開発していて、
動画広告(今回はAppLovin)を表示し終わってアプリに戻ってきた時に、

2016-06-07 19:01:38.787 XXXXX-mobile[9739:3517670] cocos2d: surface size: 640x1136
2016-06-07 19:02:15.736 XXXXX-mobile[9739:3517670] failed to call context
2016-06-07 19:02:15.737 XXXXX-mobile[9739:3517670] cocos2d: surface size: 0x0
2016-06-07 19:02:15.737 XXXXX-mobile[9739:3517670] Failed to make complete framebuffer object 0x8CD6
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp saveRenderState 161

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCTextureAtlas.cpp drawNumberOfQuads 691

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp restoreRenderState 192

FrameBuffer Status Error 36054
OpenGL error 0x0506 in -[CCEAGLView swapBuffers] 324
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCFrameBuffer.cpp applyFBO 445

FrameBuffer Status Error 36054
FrameBuffer Status Error 36054
OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp saveRenderState 161

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCTextureAtlas.cpp drawNumberOfQuads 691

OpenGL error 0x0506 in /Users/XXXXX_name/Documents/cocos2d-x/v3.10/XXXXX-mobile/cocos2d/cocos/renderer/CCRenderer.cpp restoreRenderState 192
こんなエラーが出まくって何もできなくなってしまった場合。

RootViewController.mmに以下を追記しましょう。

-(void)viewWillAppear:(BOOL)animated
{
    cocos2d::Director::getInstance()->resume();
    cocos2d::Director::getInstance()->startAnimation();
}

- (void)viewWillDisappear:(BOOL)animated
{
    cocos2d::Director::getInstance()->pause();
    cocos2d::Director::getInstance()->stopAnimation();
}

Quiteを参照。

以上でぇぇぇす。

2016年4月8日金曜日

[cocos2d-x] 究極マインスイーパー開発しました

どうも、俺です。
cocos2d-x(v2.2.6)で「究極マインスイーパー」というアプリを開発しました。






cocos2d-x v2.2.6で開発するアプリはこれが最後になると思います。
これからはv3系です。

マインスイーパーを開発しよう!と決まってから
ネットでマインスイーパーについて調べてると、
どうやら「マインスイーパー2000」というのがとても難しい、という情報をゲット。
この「マニア」というモードを選択すると、
マスサイズ ... 68x48
爆弾 ... 777個
という難易度だという。。

今回開発した究極マインスイーパーは、最後のLV1000まで進むと、
マスサイズ ... 100x100
爆弾 ... 2594個(だったと思う)
です。

安心してください。
LV1から始められるのでいきなりそんな激ムズではありません。

ただし、これだけほど大きなステージだと、「」でゲームを進めなければならない場面に遭遇します。
そうです、マインスイーパーはたまに運に左右されるゲームなのです。

それを解消するため、究極マインスイーパーでは「虫メガネ」というアイテムを考えました。


虫メガネを使えば、まだ開けていないマスを透かしてみる事ができます。
また、
コンティニューや自動保存機能も実装したので、
タップミスで終わってしまったり、電話が鳴ってゲームが終了してしまっても安心の親切設計。

恐らく地球上最ムズのマインスイーパーだと思います。

・iOS
 https://itunes.apple.com/jp/app/ultimate-minesweeper-challenge/id1093416456?mt=8
・Android
 https://play.google.com/store/apps/details?id=jp.marge.android.minesweeper
・プレイ動画
 https://www.youtube.com/watch?v=Jfl6GP-PADI









以上でぇぇぇぇぇす。

2016年4月7日木曜日

[cocos2d-x] 'stop' is not a member of 'std'が出て困ったとき

どうも、俺です。
最近更新がマメです。

  • cocos2d-x v3.10
  • android-idk-r10e

を使用。

表題の件。
Android側をビルドしようとして、
'stoi' is not a member of 'std'
のエラーが出てしまい困っちんぐな場合の対応方法をメモ。

Android-NDKが std::stoi に対応していないのが原因だそうです。

        int number;
#if CC_TARGET_PLATFORM != CC_PLATFORM_ANDROID
        number = std::stoi("xxxxxxxxfugafuga");
#else
        number = atoi("xxxxxxxxfugafuga");
#endif

こんな感じOK。

以上でぇぇぇぇぇす。

2016年4月5日火曜日

cocos2d-xで画像がちらつく

どうも、俺です。

cocos2d-xで開発してて画像を連続で表示させた時などにチラついてしまう現象をなんとかしましょう。
Director::getInstance()->setDepthTest(false);
Director::getInstance()->setProjection(Director::Projection::_2D);

これを、AppDelegate::applicationDidFinishLaunching()に記述しておけばOKです。
TiledMapで画像がチラつく場合もこの対応でなんとかなるはずです。

以上でぇぇぇぇぇす。

2016年3月31日木曜日

cocos2d-x v3.10にアップデートして行ったEclipseの設定

どうも、俺です。
cocos2d-xをv2.2.6からv3.10にアップデートしたので、忘れないうちにメモ。

EclipseじゃなくてAndroidStudio使おうぜ、という指摘もあると思いますが、
EclipseでもAndroidStudioでも、両方でビルド出来るようにしたいのです。

まず、v2系で使っていたbuild_native.shはbuild_native.pyに置き換わり、スクリプトの中身を自分で変更しなくても良くなりました。
jni/Android.mkは適宜編集が必要です。


EclipseのRun実行時にbuild_nativeが自動で走らない。

そうです、なぜか自動でbiuld_nativeが走ってくれないので、その設定をば。
プロジェクトを選択し「Properties」>「Builders」を選択。
その中にあるCDT Builderにチェックが入っていないのでチェックします。



これに気づくまでは、手動で./build_native.pyを叩いていたのですが、
なぜかそうすると、libcocos2dx.jar(v3.10)とgoogle-play-services_lib.jarが毎回削除されてしまっていたので、
それぞれのプロジェクトも手動で「Build Project」する必要がありました。。


sh: cocos: command not found的なエラーが出る。

ビルド時にこのエラーが出て先にすすめません。
build_native実行時に呼ばれるcocosコマンドが見つからないそうなので、設定してやります。
先と同じく、プロジェクトを選択し「Properties」から「C/C++ Build」>「Environment」を選択します。
右側の「Add...」から
  • ANDROID_SDK_ROOT = 「ANDROID_SDKのパス」
  • ANT_ROOT = 「ANTのパス」
※例) /usr/local/Cellar/ant/1.9.5/libexec/bin
  • COCOS_CONSOLE_ROOT = 「cocosコマンドのあるパス」
※例) /PATH/TO/COCOS2DX/v3.10/tools/cocos2d-console/bin
  • PATH = 「${PATH}:${COCOS_CONSOLE_ROOT}:${ANDROID_SDK_ROOT}」
を設定します。


今のところ、このくらいです。
また出てくれば追記していきます。

2016年3月29日火曜日

C++で簡易マルチスレッド (C++98 / C++03)

どうも、俺です。

今日はC++を使ってのマルチスレッド実装をメモメモ。
※C++11より前のバージョンの話です。C++11ではもっと簡単に実装できます。


// mutexの定義。排他制御。
pthread_mutex_t mutex;

// Hogeクラスのコンストラクタ
HogeClass::HogeClass()
{
}

// マルチスレッド呼ばれる関数を定義
static void *hogeThreadFunc(void *param)
{
  pthread_mutex_lock(&mutex);

  // 何か重たい処理を行う。
  ....................

  pthread_mutex_unlock(&mutex);
  pthread_mutex_destroy(&mutex);

  return 0;
}

// スレッドを生成して呼び出すメソッド
static void HogeClass::hogeMethod()
{
  // スレッドID(識別子)
  pthread_t threadId;

  pthread_mutex_init(&mutex, NULL);

  // スレッド生成
  pthread_create(&threadId, NULL, hogeThreadFunc, NULL);
  pthread_detach(threadId);
}


こんな感じです。
複数のスレッドからいろんなインスタンスにアクセスするような場合は、
もっと慎重に排他制御を行う必要があると思います。


以上でぇぇぇぇぇす。

2016年3月17日木曜日

[cocos2d-x] C++で年月日時分秒を取得

どうも、俺です。

cocos2d-xを使っていて、C++で年月日を取得するtips。

time_t now = time(NULL);
struct tm *nowtime = localtime(&now);

・年 ... nowtime->tm_year+1900
・月 ... nowtime->tm_mon+1
・日 ... nowtime->tm_mday
・時 ... nowtime->tm_hour
・分 ... nowtime->tm_min
・秒 ... nowtime->tm_sec
で値が取れるので、

CCString *ymd = CCString::createWithFormat("%04d/%02d/%02d", nowtime->tm_year+1900, nowtime->tm_mon+1, nowtime->tm_mday);
int ymdInt = ymd->intValue();

とやると、
例えば20160317となる。

以上でぇぇぇぇぇす。