2013年4月30日火曜日

Enumノススメ

ふとしたチャンスで借りて読んだ EffectiveJava. ずっとEnumの使い方を勘違いしていたので矯正を兼ねて
メモメモφ(・ω・ )

Enumノススメ

なんという今更感.
だが, それがいい.

1. Enumって?

日本語に直すと 列挙型. 要するに関連する定数をまとめたもの. もともとは基本的に int値らしい. あらかじめ要素数がわかっている際に効果を発揮し, 別の要素が混ざらなくなる.

たとえば実際 EffectiveJavaにある例から. 
public static final int APPLE_FUJI = 0;
public static final int APPLE_PIPPIN = 1;
public static final int APPLE_GRANNY_SMITH = 2;

public static final int ORANGE_NAVEL = 0;
public static final int ORANGE_TEMPLE = 1;
public static final int ORANGE_BLOOD = 2;
リンゴ, オレンジの種類を定数にしておきたいとする. なにが困るかというと, たとえば品種改良を表すメソッド
public void breed(int variety1, int variety2){}
なんてのがあったとする. このメソッドは引数の2つの品種を掛け合わせる, なんてメソッドだとした時, ちょっとした問題が発生する.
それは, リンゴ×オレンジなんていう異種交配が始まってしまうパターン.
引数は「intかどうか」しかチェックしないため, 間違って (リンゴ,オレンジ) と別の種類の引数を入れてもコンパイルどころか実行まで通ってしまう. おおこわいこわい.
また, 上記例なら,
APPLE_FUJI == ORANGE_NAVEL
が trueを返すミラクル. これを回避するために, いちいち数値が被っていないかチェックが必要だったりとなかなか骨が折れる.
そこでEnum.

2. Enumの作り方

作り方はいたって簡単. 上記例ならリンゴ, オレンジはそれぞれ別物としてほしいので,
  public enum Apple {
    FUJI, PIPPIN, GRANNY_SMITH;
  }

  public enum Orange {
    NAVEL, TEMPLE, BLOOD;
  }
classや interfaceの代わりに enumを使う, 後は名前を列挙してやる. 「,(カンマ)」区切りで並べ, 必ず最後は「;(セミコロン)」でしめる.
こうすると, たとえばFUJIを呼び出したいなら,
Apple.FUJI
で呼び出せる. こうするとbreedメソッドも
public void appleBreed(Apple variety1, Apple variety2){}
とすれば, このメソッドはリンゴ同士でしかコンパイルが通らなくなる. 比較も,
Apple.FUJI == Orange.NAVEL;
Apple.FUJI == Apple.PIPPIN;
上はそもそも比較するものの型が違うとコンパイルエラーを吐いてくれるし, 下はもちろん falseが返る.
後からの追加も名前を足すだけで, 値の被りは名前の被りだけ気にすればいい.

3. 応用

こんな Enumの作り方もできちゃう.
public enum Skill {
  KAMEHAMEHA("かめはめ波", 1000);

  public String name;
  public int power;

  Skill(String name, int power) {
    this.name = name;
    this.power = power;
  }

  public String toString() {
    return name;
  }

}
唐突すぎる例( ゚д゚ )
たとえばかめはめ波という技の持つデータがすべて定数だった場合. これを Enumを使わずに管理するのはおそらく骨.
String KAMEHAMEHA_NAME ="かめはめ波";
int KAMEHAMEHA_POWER = 1000;
うん. 絶対事故る('A`).

そこで 「Enumにデータと振る舞いを持たせる」 ことをやってみる. KAMEHAMEHAは Skill型なので, 7行目からのコンストラクタが使える. 名前 KAMEHAMEHAが()で引数を持つのは, このコンストラクタを使うため. かめはめ波の powerを取り出したいなら,
int power = Skill.KAMEHAMEHA.power;
で取り出せる. 読みやすいし変にいろいろ参照しなくても OKなのは事故が起きにくいはず.
ちなみに12行目からのtoString()はEffectiveJava第 3章 10項「toStringを常にオーバーライドする」参照. 要するに,
System.out.println(Skill.KAMEHAMEHA);
としたときに, 「かめはめ波」と返ってきてくれた方が, 使う人にも優しい, ということ. 技を増やすときは同じように,
KAMEHAMEHA("かめはめ波", 1000),
TAIYOUKEN("太陽拳", 500);
とでも増やしてやればいい.



他にもメソッド持たせたりさらに応用もあるけどまだここまで.



かめはめ波とか出てきたのはだいたいここのせい.
たまに振り返ると固まっていなかった部分が矯正できて気分がいい+(・ω・0)*








まぁこの固めたのもいつまでもつやら…('A`)

2013年4月26日金曜日

UnityプロジェクトをGitHubで管理 -タスク管理編

なにやらGitHubにはタスク管理チックなことができるらしい, みたいな噂だったので調査.

UnityプロジェクトをGitHubで管理

第2幕

1. Issueの作成

プロジェクトのページに入ったら, 
コイツをクリック. 数字がissueの数を表しているらしい.
クリックすると, そこはIssueの一覧画面. New Issueをクリックして新規作成.

こんな画面になるので, タスク名, 担当者やコメント, フィルター…はヨクワカラナイ('A`)を設定して submit.
これでサクッとできました.

2. Issueの操作

一覧に戻るとグリーンなIssueの一覧. グリーンは Open(まだ残っている)タスクの一覧. Closeのボタンを押すと, こちらは Closed(解決済み)タスク一覧に. まだ解決していないのでリストは空のはず. 
では先ほどのIssueを Closeしてみる. 
CloseしたいIssueをクリックすると, 
こんな画面になるはず, 途中経過のコメントとか書けるのかな… 担当なども変えられる. Closeするなら下の Close. それだけで Closeし, 右上の緑の Openが, 赤い Closeに変わるはず. リストに戻れば, Closedのリストに移動しているのがわかるかと. ClosedのIssueを再 Openすることもも可能. 





とりあえずこんなところ. 
意外と簡単かも+(・ω・0)*



って言ってると爆死するフラグ…('A`)


2013年4月24日水曜日

UnityプロジェクトをGitHubで管理 -Git準備編追記

すっかり忘れてたorz
リポジトリに 「共同開発者」 としてチームメイトを登録しないと書き込みしてもらえない(・ω・`)

UnityプロジェクトをGitHubで管理

前回の追記なのでちょびっと

共同開発者の追加

追加するためにはまずチームメイトが GitHubアカウントを持っていることは必須. 当然か(・ω・`)
追加したいプロジェクトの詳細ページに行き, ヘッダにある Settingsをクリック. 

左側にあるこのリストの Collaboratorsをクリック. 
すると入力フォームと Addボタンが出てくるので, チームメイトのアカウントネームを入力して Addする. 
入力フォームにネームを入力しようとすると, 候補がリストで現れるので, 確認してから Addできる. 間違って関係ない人招かないように…
Addはほぼ一瞬で完了する. Addしたことは相手に GitHubからメールでお知らせしてくれる. 届いてなかったら多分別の人追加してる…カモΣ(||゚Д゚)ヒィィィィ
逆に除名したいときは対象のネームの横の (remove). こちらも一瞬. そしてこちらも GitHubからメールが行く. 追加を誤爆すると 追加時のメール+削除時のメール で2通誤爆メールが届きます. 追加の際は相手のアカウントネームをしっかり確認しましょう(・ω・`)





Collaborators がどこにあるか探してしまったのでメモメモφ(・ω・ )

2013年4月18日木曜日

UnityプロジェクトをGitHubで管理 -Git準備編

仲間内で「Unityで共同開発やろうぜ!(意訳)」な話があがり, 何を作るのか盛り上がったところで問題が一つ.
「リソースの共有どうすんの?」
……(;´Д`)('A`)(・д・`)……

「ま、まぁGitとかあるs」「UnityとGit仲悪かった気が…」
……(;´ω`)('A`)(・ω・`)……

若干先行き不安だけどやってみる

UnityプロジェクトをGitHubで管理

※ 前提条件として「コマンドラインでロクにPCとお話しできない人」の行動ログであることをご理解いただいたうえでお読みください.

1. リポジトリ準備

GitHubにて新しいリポジトリを作成する. アカウントはなければ作りましょう. プライベートなリポジトリを作るのでなければ無料. 逆に作りたいなら月々課金が必要. 世の中金か('A`)
ここ. これをクリックするとリポジトリの名前や設定を決める画面に移行する. 


正直 Repository nameと Publicだけ設定しておけばいいと思う. というかわからないorz 先述の通り Privateなリポジトリを立てるには課金が必要. お支払方法の入力フォームがにょきっと出てくるのでおとなしくPublicで.
Repository nameでエラー(既にある名前を使用しようとしている etc...)にひっかからなければ, 下の緑のボタンがクリックできるようになるので, クリックで決定.


できたできた. ちなみにできたリポジトリに行くとご丁寧にreadmeがおいてある. よんでおくといいかも. ちなみにこの画像の右上の「New repository」 でも新規リポジトリの作成ができます.

2. ローカルの準備

正直こっちがめんどくさかった…というか成功してない…1. でできてたreadmeのコマンドを, ここを参考に打ってみたりしてみたけど…なんか繋がらない…('A`)
そこでふと出てきたのが Github for Windows. うん. にも使って挫折したんだ. しかし衝突しなけりゃ使えたなーと思いひっぱり出し使ってみる. ちなみにここからダウンロードできます. またツールを使うには当然ですが Gitのアカウントが必要. 先に1. を済ませておくとスムーズ.

一番左, 自分のアカウントネームをクリックすると, GitHub上にあるアクセス可能なリポジトリ一覧が登場.  画像は既に cloneしてしまっているのでパソコンアイコンが出ているが, cloneしていないリポジトリには青く cloneのアイコン

こんなのが出てくる. クリックすると設定で指定したディレクトリにリポジトリを cloneしてくれる. 楽だ…
設定は上にある tools → optionから. またアカウントネームからGitHubに飛ぶことも可能. default storage directoryに指定した場所に展開されるので, デフォルトの場所が嫌ならここを変更しよう. 

これでリポジトリをローカルに用意できたはず. ちなみに toolsの隣あたりにある addで, ローカルにディレクトリを用意しつつ GitHubに pushしてくれるみたい. ずるい(・ω・`)

これでバージョン管理が開始できる!+(・ω・0)*

3. 共有

自分で作って自分で拾えるのはいいのさ. 問題は共有. 誰かの作ったリポジトリをいただきたい. 
こんどはふらっと見つけた TortoiseGitなるものを使ってみる. 

準備

ちょっとアレだがここも参考に. 
まずはインストーラをここからダウンロード. bit数は注意. 一緒に下の方にある Japaneseを拾っておくと日本語化できます. 英語苦手('A`)
インストールは基本そのまま Next連打. 途中 Pathの設定の際に,
Run Git from the Windows Command Prompt
を選んでおくと, パスも一緒に通してくれる. 一緒に cmdから gitコマンドが使えるようになった?
インストールが完了したら, 今度は日本語化のインストーラも起動. 特に設定もなくインストールが完了するはず.
最後に適当なディレクトリで右クリックすると,

こんなのがふえているはず(既に日本語化終わってるけど最初は英語のまま)なので, 設定から, General → Language を日本語にして決定すると日本語化完了.
詳しくはここ

Clone

上の画像にもあるけど, まんま Gitをクローン.
ダイアログが出るので, 上の URLに貰いたいリポジトリのURLを入力 → 実行 でOK.
非常に楽.






…たったこれだけだったんだけどなぁ…('A`)
まだUnity関係ないし.

超参考 → こちら
04/24追記・共同開発者の追加 → こちら

2013年4月11日木曜日

Conditionのカスタム

ちょっと前にまとめた Wait.until()と、その引数の condition. あの時まとめた既存の物じゃ, 正直今やってるテストがカバーしきれないと思いカスタムしてみたのでメモメモφ(・ω・ )

Conditionのカスタム


といっても正直コピペなんだけどね…

1. 状況

対処したい状況は, 「画像リソースでチェックボックスを表現してる. しかもAjaxで表示を書き換える仕様」といった状況. 
当然 elementToBeSelected系列は使えないし, stalenessOfもページがリロードされるわけでもないから使えない.

なので, 「チェックされているボックスの画像が, x枚になるまで」待機, みたいな形にしてみた.

2. メソッド

ベースにしたのは titleIs. 一番シンプルだし, 戻り値 Booleanだし.
  public static ExpectedCondition<Boolean> countBy(final By by, final int expectedSize) {
    return new ExpectedCondition<Boolean>() {
      public Boolean apply(WebDriver driver) {
        return driver.findElements(by).size() == expectedSize;
      }
    };
  }
本当にちょびっとの改造. 引数は Byロケーターと期待する数.
なんてことはなく, titleIsで「タイトルが引数と一致する」という条件を書いてた部分を, 「Byで指定したWebElementの size()が, 引数の expectedSizeに一致する」に書き換えただけ. この程度なら意外と簡単.
ちなみにちゃんとロケーターを引数にして, 中で driver.findElements()で取得しなおしてやりましょう.
WebElementや List<WebElement>を直で渡そうとすると, 取得のし直しがない = ページの方は変更があっても size()変わらない = ちゃんと動かない なんていうただのストッパーが出来上がります.




とまぁこんな風に近いメソッドをひっぱり出してきてちょこっと改造してやるだけでも, 一層テストしやすくなるかも. +(・ω・0)*

2013年4月8日月曜日

Unityゲームを終了する

UnityでAndroidにビルドしていると思うこと
「ホームボタンでしか戻れないうえにバックグラウンドで生きてんの…?」

当然バッテリーはマッハなため非常によろしくない. が, デフォルトではそんな処理はしてくれない.
なのでスクリプトでつける必要があったのでメモメモφ(・ω・ )


Unityゲームを終了する


1. メソッド

Application.Quit();
これだけ.
このメソッドを呼ぶことでアプリケーションは閉じてくれる.

2. 実際に使ってみる

空の GameObjectを作り, GameManagerとでもしておく. 
void Update(){
    if (Application.platform == RuntimePlatform.Android && Input.GetKey(KeyCode.Escape)){
        Application.Quit();
    }
}
こんな内容のスクリプトを作り, GameManagerに持たせてやると, ゲーム中「戻る」キーを押すことでゲームが終了できる.
プラットフォームが Androidであることを確認してるけど, 「戻る」キーとか iPhoneには無いよなぁ….
毎フレーム呼び出すのが気持ち悪いなら何かしらボタンを作って, そこから反応してやると誤爆も少なくなっていいかも.

3(おまけ). ダイアログっぽい何か作ってみた

いいと思ったのでやってみようとした. ただ…ダイアログってどう作るんだ…?3Dには強いが2Dにはいまいち余計な手間がかかってしまうイメージ.

   3-1. 構想

      ヨクワカラナイのでとりあえず構想.
      ダイアログを開くボタンを押す → ダイアログからYesを選ぶ → ゲームが終わる!
      こうしたいなー(・з・)的な簡単な構想. 
      何やらいろいろやり方はアルっぽいけどよくわかんない('A`)
      AssetStoreにありそうだなー…
      ダイアログっぽいものを書く OnGUIを持ったスクリプトを動的に追加することで「ダイアログを開」き, このスクリプトを削除して「ダイアログを閉じ」たい. 
   

   3-2. ダイアログを開くボタン

      とりあえずボタン. これはシンプル.
using UnityEngine;
using System.Collections;

public class ButtonTest : MonoBehaviour {

 public bool isOpened = false;
 
 void OnGUI(){
  float sw = Screen.width;
  float sh = Screen.height;
  
  if (GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu") && !isOpened) {
   Debug.Log("push!");
   isOpened = true;
  }
  
 }
}
sw, shはそれぞれ現在のスクリーンの幅/高さを取得. 割合でボタンの座標を決定してやると端末変わった時とかに順応しやすいかと.

ボタンを表示させているのが 7行目, GUI.Button(). なお GUIクラスは OnGUI()メソッド以外から呼ぼうとすると怒られる…(・ω・`)
このメソッドはボタンを作りつつ, 押されたときに trueを返すできる子. 一粒で二度おいしい.
最初の引数で表示位置を, 次の引数でボタンに表示するラベルを宣言. なお Rectについてはこんなのもございます(宣伝)

isOpenedはなんてことはない bool. これで制限をかけて, ボタン連打でダイアログ地獄, なんてのを避ける(予定).
これを空の GameObjectでも作って載せてやり, 実行するとボタンが左上に出るはず.

こんな感じ. なおこの状態で押しても, isOpenedをなんとかする方法がないので, ログは一個しか出てこないハズ.


      3-3. 「ダイアログ」を用意する

ここが一番困った. AndroidのDialogクラスみたいなのは見当たらないし, 仕方ないので別のクラスを自作し, そこでOnGUI()でもしてそれっぽく見せてみる.
using UnityEngine;
using System.Collections;

public class TestDialog : MonoBehaviour {
 
 public ButtonTest test;
 
 void Start(){
  test = this.gameObject.GetComponent<buttontest>() as ButtonTest;
 }
 
 void OnGUI () {
  float sw = Screen.width;
  float sh = Screen.height;
  GUI.Box(new Rect(sw / 3, sh / 3, sw / 3, sh / 3),"TestDialog");
  
  if (GUI.Button(new Rect(sw * 2 / 5, sh * 2/ 5, sw / 5, sh / 10), "yes")) {
                        Debug.Log("quite");
                        test.isOpened = false;
                        Destroy (this);
                        Application.Quit();
  }
  if (GUI.Button(new Rect(sw * 2 / 5, sh * 11 / 20, sw / 5, sh / 10), "no")){
                        Debug.Log("cancel");                        
                        test.isOpened = false;
                        Destroy (this);
  }
 }
}
こんなクラス. このスクリプトを 3-2. で作ったスクリプトを載せた空のオブジェクトに動的にくっつけることで表示させよう, という魂胆. menuボタンのイベントで動的にくっつければ, あたかもボタンでダイアログを開いたように見えるという寸法.

Start()はとりあえず 3-2のスクリプトの取得. isOpenedを書き換えて, 「開きっぱなしの状態」をキャンセルする.
15行目, GUI.Boxで, ただの四角い領域を描画. ついでに"TestDialog"とタイトルっぽく入れてみる.
中にはボタン2つ. yesと noボタン. この yesボタンの if()の中で Application.Quit()でも呼んでやれば目的は達成できるはず. でも実機じゃないと確認できない(・ω・`)
そしてDestroy(this)で このスクリプト を破棄することで, ダイアログ(?)を破棄する. アプリ終了する前に Destroy()しておくべきなのだろうか…

後は3-2の方, ボタンのイベントの中を
if (GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu") && !isOpened) {
   Debug.Log("push!");
   this.gameObject.AddComponent<TestDialog>();
   isOpened = true;
  }
と, AddComponent()してやることで, ここで作ったスクリプトを動的に足す.
これで, menuボタンを押すと,
みょん. それっぽいものが出てきてくれました.
Inspectorの方を確認して, 動的にスクリプトが追加されているのも確認しておくといいかも.
ちなみに3-2の方, ボタンの if()文を,
if (!isOpened && GUI.Button(new Rect(0,0,sw * 3/12,sh/12), "menu")) {
   Debug.Log("push!");
   this.gameObject.AddComponent<TestDialog>();
   isOpened = true;
  }
としてみると, ダイアログっぽいものを開く際変化する isOpenedのほうの条件に引っかかるのか, そのあとの条件となっている menuボタン描画メソッドが呼ばれなくなり,

menuボタンが消える. これはこれで使いようがありそうだったのでメモメモφ(・ω・ ).





おまけのが充実してる気がするけど仕様です. ( ´∀`)ノシ キニシナイ

2013年4月3日水曜日

他のGameObjectの持つスクリプトのフィールドを参照する

たとえばライフポイント.
ディスプレイするために表示用クラスで見たいけど, 体力管理としてプレイヤーでも参照したい, でも2か所に持つとかキモすぎる!щ(゚Д゚#щ) 絶対バグる!<(゚Д゚#<)
なんて状態.
なお今回からC#で書いてみます. ほとんど変わらないから問題ないかと.


他のスクリプトのフィールドを参照する


1. 状況

たとえば Playerのタグを持った PlayerObjectがいたとする. 
こいつはこんな LifeManagerという名のスクリプトを持っている. 
public int life = 10;
void Update(){
…
たとえば残りライフを描画する GUIのクラス, LifeMonitorがあったとする.
LifeMonitorは残りライフを表示するために PlayerObjectの残りライフが知りたい.
でもまさかダメージが入るたびに SendMessageメソッドで報告を受けるのもなんかヤダ('A`).
まさか LifeMonitorの方でも同じようにライフを減らすなんてありえない.

たとえばこんなシチュエーション.

2. 対策

LifeMonitorのほうのスクリプトに
GameObject player = GameObject.FindWithTag("Player").gameObject;
LifeManager script = player.getComponent(typeof(LifeManager)) as LifeManager;
int currentLife = script.life;
これで参照できる.
1行目は単純に PlayerのGameObjectを取得しているだけ. やり方は他にもいろいろ.

問題はその下.
1行目で取得した Playerから, コンポーネント名を指定して取得する.
ここが最初の問題.

必要なパーツは2つ. 「型宣言」と「キャスト」. 上記2行目なら,  typeof(クラス名)が型の宣言. as LifeManager がキャスト. 他のやり方もあり,
LifeManager script = (LifeManager)player.getComponent<LifeManager>();
とするパターンも. <LifeManager> で型宣言し, (LifeManager)でキャストするやり方の組み合わせ.
2つのパーツがそろっていればやり方は自由なのだが, 実はUnityScriptなら,
var script: LifeManager = player.getComponent(LifeManager);
とか書けちゃったりする.

あとは3行目のように, 取得したコンポーネントからフィールドの lifeをいただけば一丁上がり.
他のフィールドも同様に参照してやればおk. 意外とイメージはしやすいはず.
まぁディスプレイする側から体力操作し始めるようなことはないだろうけど.

3. 応用?

実は同様に, メソッドの呼び出しも可能. LifeManagerに以下のメソッドを追加してみる.
public void addLife(int inc){
    life += inc;
}
今更だけどたとえが悪かったなぁ…('A`) lifeに引数に指定した incだけ足すだけの簡単なメソッド.
LifeMonitorの方では,
script.addLife(1);
とでもしてやればOK. この後 lifeを読むと, ちゃんと 1加算されている.
戻り値も取り出せるし, 当然複数の引数も渡せる.
また直接,
script.life = 11;
とかぶち込むことも. やりたい放題である.

これらの注意点は,  必ず publicであること. パッケージ分けとかがあるわけではないので, アクセス修飾子に注意. 特に C#のデフォルトは privateな点など, 言語的なところにも注意. protectedも当然NG.

フィールドを参照したい, (基本ないだろうけど)フィールドの値を書き換えたい, 何度も同じスクリプトのメソッドを呼び出したい,戻り値が欲しい, 引数は複数持たせたい!なんて時はこの手法がよろしいのかな?

逆にゲームオーバーのように1回だけ呼べばいいものは, sendMessage()を使えばよろしいかと.





なんか変な文章(・ω・`)

AWS CDKで立てたEC2インスタンスのTimeZoneとかいじりたかった話

EC2を立てることはできたけど、立てたインスタンスは UTCのままだし設定ファイルとかいちいちscpしてくるのはダルい。 当初UserDataでなんとかしようとしたものの、「書く量がヤバいしメンテしにくい」と悩んでいたところ見かけたのが  AWS::CloudFormation:...