水無月の余韻 開発Sc.

プログラミング関連の雑記

加賀ゆびぬき 刺し模様シミュレータをリリースしました

以前のエントリー 加賀ゆびぬき模様シミュレータを作ったで、Webアプリについて書きました。

使い勝手を考えると、iOSアプリだったらいいなと思ったので、iOSアプリにしました。

ダウンロード

どんなアプリなの?

加賀ゆびぬきについては、上述の以前のエントリーを見てもらうとして。

加賀ゆびぬきは、とても美しい模様を作り出すことができますが、その模様を決めるのはおよそ以下の4つの要素です。

  • 土台の割り方(コマ割り)
  • 針の刺し方(トビ)
  • 糸の色
  • 刺す順序

これらの組合せの結果、どのような模様ができあがるかをシミュレートして表示するのが、今回のアプリです。

なにができるの?

簡単に操作方法を知るための動画をつくったので、ご覧いただくといいと思います。

加賀ゆびぬき 刺し模様シミュレータ 基本的な使い方 v1.0 (Youtube)

アプリで作った刺し模様は、iOS標準アプリの写真に出力可能です。 以下の画像は、すべてアプリから出力したものです。

動画内で作成した刺し模様はこちら。

初期設定(新規作成の状態)から、色を少し増やすだけでも雰囲気がかわります。

f:id:ichiko_revjune:20150611124649j:plain

土台を変えると、がらりと雰囲気が変わりますよ。(ヒント: 8コマ3トビ)

f:id:ichiko_revjune:20150611124655j:plain

所感

はじめてのアプリ公開なのでいろいろとドキドキしています。

サポートサイトを作ったり、この記事を書いたりと、リリース準備が暗中模索で大変です。

加賀ゆびぬきを知っている人には、ぜひアプリをさわっていただいて、どこが使えないとか、もっとこうしたらいいとかご意見いただけると助かります。

知らない人もアプリをさわって、加賀ゆびぬきの魅力を知っていただけるとうれしいなぁと思うしだいです。

なにかありましたら、コメント欄でも私のTwitter @ichiko_revjune へのメッセージでも、ご意見いただけると幸いです。

加賀ゆびぬき 刺し模様シミュレータ サポートサイト

werckerのRubyのboxにNode.jsをインストールする

Middlemanで構築している静的Webサイトのデプロイにwerckerを使うことにしました。

アプリは、静的HTMLを出力するのにMiddlemanを使い、javascriptは、npm風に別フォルダで管理しています。 そのため、werckerでのビルド時にRubyとNode.jsが必要になりました。

プロジェクトのフォルダ構成はこんな感じです。

project
   - web
      - source
         - images
         - layouts
         - index.html.erb
      - Gemfile
   - js
      - src
         - ...
      - package.json
   - wercker.yml

wercker.yml

まずは結論を示します。

WerckerのRubyのboxでGruntを動かす設定を参考に、試行錯誤しました。

↑では、最新のNode.jsを入れるための設定もありますが、それは取り入れていません。

# wercker.yml
box: ruby

build:
    steps:
        # Execute the bundle install step, a step provided by wercker
        - script:
            name: set nodejs emvironment
            code: |
              sudo apt-get update
              sudo apt-get -y install nodejs npm
              sudo update-alternatives --install /usr/bin/node node /usr/bin/nodejs 10
        - script:
            # ref. https://github.com/wercker/step-npm-install/blob/master/run.sh
            name: custom npm-install
            code: |
                cd js
                mkdir -p "$WERCKER_CACHE_DIR/wercker/npm"
                npm config set cache "$WERCKER_CACHE_DIR/wercker/npm"
                sudo npm update
                #sudo npm cache clean
                sudo npm install $WERCKER_NPM_INSTALL_OPTIONS
        - script:
            name: custom bundle-install
            code: bundle install --gemfile web/Gemfile
        # Execute a custom script step.
        - script:
            name: test js
            code: cd js; npm run test
        - script:
            name: build js
            code: cd js; npm run build
        - script:
            name: deploy js
            code: cd js; npm run deploy
        - script:
            name: middleman build
            code: cd web; bundle exec middleman build --verbose
deploy:
    〜(省略)〜

boxの指定

boxの指定がなかなか通らなくて苦労しました。

はじめは、box: wercker/rubyとしていたのですが、boxのイメージファイルの取得に失敗しました。

wercker directoryで有志によるbox定義を検索して使うことも考えたのですが、これもイメージファイルが取得できずに断念し、別途インストールする方法にしました。

バージョンが書いてあるわけではないので混同したいたのですが、old-devcenter.wercker.comを見ていました。

Docker Hubを使うようになってから、形式が変更になっているようです。

wercker - lean Introduction to the wercker.yml

Ubuntu上の問題

Ubuntuだと、apt-get installでNode.jsをインストールすると、コマンドがnodejsとなってしまうので、nodeで通るように変更しています。

これをしないと、npmコマンドが動作しませんでした。

Node.jsのキャッシュ

ローカルでboot2docker+VirtualBoxを使って、試していたのですが、繰り返しているとnodejsのモジュールがあやしくなってきます。

npm installが通らなくなり、npm cache cleannode_modulesフォルダを削除することで、通りました。

加賀ゆびぬきの模様シミュレータを作った

「加賀ゆびぬき」の刺し模様をシミュレートするツールを作りました。

以下のURLに公開しています。

加賀ゆびぬき 刺し模様シミュレータ - 水無月の余韻

「加賀ゆびぬき」とは

加賀ゆびぬきとは、石川県金沢に伝わる、裁縫道具です。

縫い物をするときに使う、ゆびぬきはわかりますか? 家庭科の授業で見たのは、革や金属で作られたものが多いでしょう。

加賀ゆびぬきは、裁縫道具としてのゆびぬきに、糸をめぐらせ、丈夫に、そして美しくなったものです。

どんなものかというと、見るのが早いです。 ググってもたくさんの画像が出てきますが、拙作を載せておきます。

f:id:ichiko_revjune:20150105103727j:plain

数がないので、一番はじめに作ったものから。(なかなかひどいw) 右にいくほど新しいです。

加賀ゆびぬきは、針の運びは単純でいながら、幾何学模様を作り出せるおもしろいものです。

キットの販売もありますが、もともとは端切れや、余った糸を使っていたであろう副道具です。 はじめのひとつは、家にあるものでできるかもしれません。

参考図書

今回、参考にした本。

開発過程のメモ

図形の描画と、各種入力があるものの、アクセスが簡単なところに公開したかったので、Webアプリにしました。

ただし、バックグラウンドはなくて、javascriptで完結させています。

Knockout.jsを使いつつ、コードはCoffeeScriptで記述しました。

Knockout.jsは、MVVMパターンのUIフレームワークです。 本家のチュートリアルが充実していてよいです。

アプリケーションのコードは、githubで公開しています。

http://github.com/ichiko/kgyubinuki

ひっかかったこと

使う上で、ひっかかったのは、Knockout.jsを経由したアクション呼び出しの際に、thisの中身が変わるということ。 javascriptorには当然なのかもしれないが、CoffeeScriptなどで便利に記述しているとつい忘れてしまう。

画面には、ViewModel KomaVMの配列をもとにリストを生成しています。 リストの各要素の KomaVM のメソッド addNewIto を呼び出す際、thisの参照解決ができずにはまりました。 (addNewIto のメソッドは見つかるものの、実行時エラー)

アクションに指定するメソッドは、独立したfunctionとして成立するように定義したほうがよいようです。

# viewmodel.coffee (だめパターン)

class KomaVM
    (略)

    addNewIto: ->
        @addIto(DefaultIto.Color, DefaultIto.Round)

    (略)

    addIto: (color, roundNum) ->
        ito = new ItoVM(color, roundNum)
        @itoArray.push ito
        return ito
# viewmodel.coffee (使えるパターン)

class KomaVM
    constructor: (offset, type, komaKagari, config, setDefault = true) ->
        (略)

        @addNewIto = ->
            self.addIto(DefaultIto.Color, DefaultIto.Round)

        (略)

    addIto: (color, roundNum) ->
        ito = new ItoVM(color, roundNum)
        @itoArray.push ito
        return ito

実装上の工夫

始めのバージョンでは、ViewModel-Viewの2階層で考えていました。 しかし、Knockout.jsは、監視対象のオブジェクトに専用のオブジェクトを使用するため、jsオブジェクトの中身が煩雑になりがちです。

Knockout.jsは、ko.observable()などの関数を通して監視対象オブジェクトを生成するため、バインディングがあるメンバには関数を通したアクセスが必要で、バインディングがないメンバには直接の値アクセスができるという状態になります。 バインディングの有無が入り乱れていると、かなり煩雑です。

そのため、だいたいの見通しがたったところで、Model-ViewModel-Viewの3階層で考え直しました。

アプリの根幹は、Modelオブジェクトに保持した設定にしたがって、View(HTML)に模様を描画することにあります。 入力のバインディングを一度排除して、Modelを構成し、それをラップする形でViewModelでバインディングを定義することにしました。

ラップすることによる冗長さはあるものの、Model層で機能の担保がし易くなりました。

(MVVMパターンを習得した人にとっては、これが当然のかたちなのかもしれないな ^ ^;)

色を合わせて撃ち落とす、「Ship Trails」をリリースしました(その2)

前回の記事で、「Ship Trails」のゲームについてはお話ししました。

今回は、開発サイドの話をします。

告知が間に合ってませんが、同様の内容で、今日 Picotachi#19 に参加してきます。 Picotachiは吉祥寺にあるPico Pico Cafeさんで、開催されるクリエイターのためのイベントです。

(11/15 Picotachi#19で使用したスライドを追加)

発端

今回のゲームは、「飛行機雲で、飛行機の軌跡が見えるのいいよね」というところから始まりました。

どうゲームにするかというところでは、「難しいけど面白い」ゲームにしたいという方向性になりました。Super HexagonやWAVE WAVEみたいな、とっても難しいのにはまってしまうやつです。

そのため、かなり難しめのゲームになっています。

(その分、長く遊んでもらえたらいいなぁ。)

開発スペック

前回つくったゲーム「ヤミからの逃走」に比べると、開発規模はだいぶ大きくなりました。

@slightairとの分担も変更しています。メインプログラムを私が担当し、BGM/SEと背景設定を@slightairが担当しました。

フレームワーク& ツール

Cocos2d-xは3.x系になってから更新速度が爆速で、開発中にもどんどんバージョンがあがっていきました。最終的に、Cocos2d-x v3.2を使っています。

あわせてCocosBuilderも使って、一部の画面を構築しました。CocosBuilderは、さっくり作ってすぐに動くという点は便利ですが、変更が入ったときには、手間が増えがちですね。今回のアプリでは、タイトル画面とそこから遷移するOPTIONメニューから下をCocosBuilderで実装しましたが、ボタンが増えて、ボタン位置を変更する、となるとアニメーションの再設定が大変でした。

ツールとしてあげた、KORG M01dは、nintendo 3DS で動くシーケンサーです。各ステージのBGMを@slightairが作曲しており、そのツールとなりました。持ち運べるし、便利に使えるソフトです。

開発期間:約7ヶ月

開発期間が長いですが、挑戦したことが多かったのと、難易度調整に時間がかかったことが大きいです。中だるみもありました。

挑戦したこと

挑戦したことは大きく5つあります。

  1. BGM自作
    実は、これまでのゲームは、SEは用意したもののしっかりとBGMを用意していませんでした。今回はステージ制ということもあり、各ステージに欲しいとなったので、曲数が増えました。雰囲気を変えて曲を用意するのって大変です。@slightair様々です。

  2. プレイデータの収集
    Google Analyticsを使い、プレイ状況を把握できるようにしました。どのステージを遊んだか、クリアできたかといった情報を収集しています。
    その結果、想定外に難しいらしいということがわかっています。。。

  3. プレイ結果のシェア機能
    アプリを知ってもらう機会を増やしたいので、みんなに広めてもらおうという魂胆です。プレイ結果を画像としてシェアできます。
    iOS では、TwitterFacebookへの投稿に対応しました。 Androidでは、Twitterなど、画像投稿に対応しているアプリへ連携するようにしました。
    ハイスコアを更新したら、ぜひ投稿してください。

  4. 広告
    収益化を図るというほどではありませんが、広告を導入しています。今回はAdMobのみの導入です。AdMobメディエーションの機能を使用して、各社の広告を使えるようにすると、いいのかもしれません。

  5. 広告除去アイテムの販売
    初めてのアプリ内課金です。実装は大変でした。
    そして、リストアできないという理由でリジェクトされました。
    リストアボタンを置いていないアプリは散見されたので、購入ボタンひとつで申請したのですが、リジェクトされました。App Storeの仕様で、購入済みアイテムを再度購入しようとしても、再決済は走らないので「購入動作」しか実装していなかったためと思われます。ユーザにリストアできることがわかるとか、明らかにリストアが実行されたと明示しないといけないようです。

難易度調整

ステージの難易度調整は難しかったです。

ここがコンテンツの肝なので、気を抜く訳にもいきません。

ステージデータは、外部ファイルに定義して、アプリで読み込む形式にしています。専用のエディタを作って、ステージ名からオブジェクトの色まで定義しました。

始めは、何が落ちてくるかを完全固定にして作りました。

完全固定では、一度クリアしたらおわり、になりがちです。また、スコア画面に表示する軌跡の模様を重視して構築すると、単調になりがちでした。これは、軌跡の模様を美しくしようとすると、規則的な繰り返しになるためです。

そこで、数種類のパターンを用意して、ランダムに使用することにしました。

これにより、面白みはでたものの、ランダムに抽出するプールが大きくなると、難しすぎてゲームになりませんでした。

パターンをグルーピングして、ランダムに抽出するプールを小さくすることで、現状の難易度を実現しています。

一見矛盾しているのですが、ステージの定義は「簡単なステージを作るのが難しい」というのが感想です。

テスター:7人+α

開発のいろいろな段階で、友人たちにプレーしてもらいました。難易度調整のための気づきは、テストプレイの中から得ることができました。感謝しています。

今後

「Ship Trails」は、出して終わりじゃなく、バージョンアップを繰り返して、アプリをよりよくしていきたいと思っています。

@shiptrails_game で、みなさんのプレイを共有したり、アップデート告知を行っていく予定です。よければフォローしてください。

さらに、貢献してやろうというお方は、@shiptrails_game までフィードバックをいただけると助かります。

よろしくお願いします。

Picotachi#19で使用したスライド

(11/15 追記)

Picotachi#19で使用したスライドをあげておきます。

発表後は、たくさんの反応をいただけました。面白いといっていただけてうれしかったです。 音ゲーとして認識する人もいて、面白かったです。

しっかり育てていかねばな。

色を合わせて撃ち落とす、「Ship Trails」をリリースしました

f:id:ichiko_revjune:20141105092725p:plain

色を合わせて撃ち落とす、「Ship Trails」をリリースしました。

今回も @slightair と共作です。

ダウンロード(無料)

Android版を先行リリース中です。iOS版はしばしお待ちを。 iPhone/iPad版も公開になりました!(11/12)

for Android

Get it on Google Play

for iOS

どんなゲーム?

今回は、ざっくりどんなゲームかを紹介していきます。

f:id:ichiko_revjune:20141105095947p:plain

シューティングゲームに似ていますが、パズル的な要素を含んだゲームです。

自軍は4機の船。船を動かして、敵を的確に落としていくとステージをクリアすることができます。

f:id:ichiko_revjune:20141105100021p:plain

船は、船と同じ色の弾を撃ちます。 敵と同じ色の弾をぶつけることで、敵を撃ち落とすことができます。

敵の動きに合わせて、すばやく船の位置を動かしていきましょう。

f:id:ichiko_revjune:20141105100029p:plain

60秒生き残れたら、ステージクリア!

それぞれのステージで100%を目指してください。

いろいろな雰囲気でステージを用意しているので、ぜひ制覇してくださいね。

スコア画面では、'SHARE' ボタンを押すことで、画像とともに投稿が可能です。

ハイスコアを更新したら、どんどんツイッターなどに投稿してね。

大量のパーティクルを描画する場合のヒント

COCOS2D-X 3.0 を使用してゲームを作っています。

iOS版から着手して、あらかた形ができたのでAndroid版の対応をしだしたところで問題が発生しました。

問題

エフェクトを表示するために、大量に同じパーティクルを使用する場面があります。その場面を表示する際、Androidで一部の描画がされなくなるのです。

例えば、壁にボールをぶつけて、衝突したときのエフェクトをパーティクルで描画しているとしましょう。

ボールがひとつで、パーティクルもひとつ描画するときには、きれいに表示されました。 ボールをどんどん増やして、あちこちで衝突が起きるようになると、パーティクルやボール、または壁が表示されなくなってしまうのです。

解決策

ボールの数を減らすと発生しないため、ボールまたはパーティクルの描画方法を変えることで解決できそうです。

既にボールはSpriteBatchNodeで描画していたため、パーティクルの描画を変更したいです。

パーティクルの描画をまとめる方法を探してみると、 ParticleBatchNodeというクラスがあることがわかりました。

cocos2d-x: ParticleBatchNode Class Reference

(描画の高速化関連の記事ではほとんど言及されていないクラスです。ParticleSystemを使うことって少ないの?)

サンプルコード

Scene::init() 内で、パーティクルで使用する画像ファイル名を指定して、ParticleBatchNodeを生成します。 メンバ変数に格納しておくとよいでしょう。

// Scene::init()
_effectNode = ParticleBatchNode::create("hit_effect.png");
this->addChild(_effectNode);

パーティクルを追加する際には、生成しておいた、ParticleBatchNodeに対して行います。

auto hitEffect = ParticleSystemQuad::create("hit.plist");
hitEffect->setAutoRemoveOnFinish(true);
hitEffect->setPosition(someX, someY);

_effectNode->addChild(hitEffect);

この方法でパーティクルの描画をしたところ、Androidでも描画されるようになりました。

パーティクルの描画が多くて、重くなっている場合にもこの方法が使えるかもしれません。

Mavericksにアップデートしたら、rbenvが消えた件

備忘録です。

MBPのOSをMavericksにアップデートしたら、terminal上で、rbenvが見えなくなりました。
$ which rbenv
rbenv not found

rbenvは、Homebrewを使ってインストールしたので、brewコマンドで存在を確認します。 brewによると、rbenvは存在するようです。

$ brew list rbenv
/usr/local/Cellar/rbenv/0.4.0/bin/ruby-local-exec
/usr/local/Cellar/rbenv/0.4.0/bin/rbenv
/usr/local/Cellar/rbenv/0.4.0/completions/ (2 files)
/usr/local/Cellar/rbenv/0.4.0/libexec/ (25 files)
brewの状態を確認した

--

依存関係がおかしかったり、問題はあるのですが、rbenvが見えなくなった件とは関係ありませんでした。

--

brewがおかしいのかもしれないので、まずチェックしました。

$ brew doctor
Warning: Some installed formula are missing dependencies.
You should `brew install` the missing dependencies:

    brew install freetype libpng

Run `brew missing` for more details.
Error: Homebrew doesn't know what compiler versions ship with your version
of Xcode (5.1). Please `brew update` and if that doesn't help, file
an issue with the output of `brew --config`:
  https://github.com/mxcl/homebrew/issues

Thanks!

Warning: Your Homebrew is outdated.
You haven't updated for at least 24 hours, this is a long time in brewland!
To update Homebrew, run `brew update`.

依存関係の解決が必要なのと、Homebrew自体が古いと言われました。

先にupdateしたほうがいいかと思ったのですが、エラーになりました。しかも、解決しにくい。

$ brew update
Error: undefined method `to_sym' for nil:NilClass
Please report this bug:
    https://github.com/mxcl/homebrew/wiki/troubleshooting
/usr/local/Library/Homebrew/cmd/update.rb:134:in `report'
/usr/local/Library/Homebrew/cmd/update.rb:132:in `each_line'
/usr/local/Library/Homebrew/cmd/update.rb:132:in `report'
/usr/local/Library/Homebrew/cmd/update.rb:36:in `update'
/usr/local/Library/brew.rb:91:in `send'
/usr/local/Library/brew.rb:91

brewのupdateは置いといて、指示された順番に、依存関係の解決からやりましょう。

コマンドも指示されているので、そのまま実行。

$ brew install libpng freetype
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/libpng-1.6.10.mavericks.bottle.tar.gz
######################################################################## 100.0%
==> Pouring libpng-1.6.10.mavericks.bottle.tar.gz
🍺  /usr/local/Cellar/libpng/1.6.10: 17 files, 1.3M
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/freetype-2.5.3_1.mavericks.bottle.tar.gz
######################################################################## 100.0%
==> Pouring freetype-2.5.3_1.mavericks.bottle.tar.gz
🍺  /usr/local/Cellar/freetype/2.5.3_1: 60 files, 2.5M

この後、update実行かと思ったのですが、チェックするとエラーなくなってる。

$ brew doctor
Your system is ready to brew.
brewインストールしたコマンドが入る場所が空になってた

brewでインストールしたコマンドは通常、/usr/local/binに入ります。 が、見てみたらbrewしかいなかった。

$ ls -l /usr/local/bin
-rwxr-xr-x  1 hoge  admin   813B  3 25 11:50 brew

brewのインストール済みリストと違う。

$ brew list
autoconf    git     jpeg        lua     phantomjs   rbenv       sbt
freetype    gnuplot     libpng      mysql       pidof       readline    scala
gd      imagemagick libtool     openssl     pkg-config  ruby-build

エイリアスは消えちゃったみたいです。

再インストールしようにも、インストール済みの場合は、なにもしてくれない。 (インストールには、Xcode Command Line Toolsも必要です。)

$ brew install rbenv
Warning: rbenv-0.4.0 already installed

なので、アンインストールしてから、インストールしました。

$ brew uninstall rbenv
Uninstalling /usr/local/Cellar/rbenv/0.4.0...
$ brew install rbenv
  (中略)
$ which rbenv
/usr/local/bin/rbenv

地味に手間取ってしまった。残念。

--

追記 brew上ではインストール済みだったので、リンクだけ復活させればよかったかも。

brew link rbenv