[AS][自分用]ActionScript3.0デザインパターンの読書メモ(1)

書籍:ActionScript3.0デザインパターンを読みながらのメモ(自分用)

1.分析フェーズ
→ユースケース作成(フォーマルユースケース)
→→主アクター、事前条件、基本経路、代替経路、特殊用件、検討事項

例)flickrAPIによる検索を使ったスライドショー
◆主アクター:
エンドユーザー
◆事前条件:
エンドユーザーは検索テキストボックス、送信、早送り、巻き戻しボタンの付いた画面を見ている
◆基本経路:
1.検索ワードを入力
2.送信ボタンをクリック
3.flickrがxmlを返す
4.xmlから画像を表示する
◆代替経路
3a.flickrAPIに接続できないときはエラーを表示
4a.検索結果でxmlが空っぽの場合は仮画像を表示
4b.画像の幅が規定サイズより小さい場合は拡大して表示
◆特殊要件
マウス操作以外にキーボードのみでの操作も可能とする
◆検討事項
ローディング処理方法

2.設計フェーズ
→CRCカード作成(Calss:クラス Responsibility:債務 Collaborator:コラボ)
→→クラスに債務を設定したら、当てはまるコラボ(当てはまるクラス)を設定
→クラス関係の精査:関連、集約、継承
→→関連:依存(uses)関係(MAPとMAPDATA)
→→集約:所有(has a)関係(MAPとSTREET)
→→継承:一般的な継承(is a)の概念→ポリモーフィズム
→パブリックAPIの書式を決める:債務のpublic,privateの割り振り

3.実装フェーズ
→コーディング規約の確認(俺流の設定)
→→ローカル変数名の先頭文字にはアンダースコア
→カプセル化:クラスをブラックボックス化するという考え方
→→パブリックなプロパティを使わない
→→→アクセサメソッドを使う
→→外部クラスのオブジェクトを直接参照しない
→→→そのクラスの引数を経由した参照は除く
→→→(駄目な使い方の例がないので、よくわからない p20)
→→配列などはコピーしたものを返すような設計が必要
→継承とコンポジション
→→継承は既知
→→→継承のメリット:利用が簡単
→→→継承のデメリット:サブクラスが良いカプセル化ではない、ひとクラスしか継承できない
→→コンポジション:元のクラスをバックエンドクラス、新しいクラスをフロントエンドクラス
→→→フロントエンドクラスはバックエンドクラスのインスタンスを利用する。
→→コンポジションのメリット:カプセル化が強い
→→コンポジションのデメリット:コーディングが増えて面倒
→→継承か、コンポジションかの判断の仕方
→→→A is BならAはBの継承とする
→→→A has B なら、AはBのコンポジションとする

[AS]getter/setterの明示型と暗黙型について

getter/setterの存在意義としては、オブジェクト指向における
「パブリックなプロパティを使わない」
という概念からあるっぽい。

ということは、プライベートなプロパティへのアクセス方法としてgetter/setter(アクセサメソッド)という概念があるということかな。

明示型のアクセサメソッドについて
パブリックな関数を用意してその戻り値にプライベートなプロパティを設定する。
こんな感じ。

package  {
	public class NewClass {
		
		private _number:Number = 10;
		
		public function getNumber():Number{
			return _number;
		}
		public function setNumber(num:Number):void{
			_number = num;
		}		
	}
}

こんな感じで呼び出す。

//フレームアクションとかで
var newClass:NewClass = new NewClass();
newClass.setNumber(200);
trace(newClass.getNumber) //出力:200

で、暗黙型のアクセサメソッドについて
いわゆる、よく参考書に書かれているアクセサメソッドを使った方法。
こんな感じ

package  {
	public class NewClass {
		
		private var _number:Number = 10;
		
		public function get number():Number {
			return _number; 
		}
		
		public function set number(value:Number):void 
		{
			_number = value;
		}
	}
}

こんな感じで呼び出す

//フレームアクションとかで
var newClass:NewClass = new NewClass();
newClass.number = 200;
trace(newClass.number) //出力:200

二つの違いは、通常通り関数としてアクセスするか、横着してプロパティっぽく使いたいかってことなのかな。

使い勝手として、元来、関数的な処理なので、例外処理とかを追加して使うのが王道っぽい。
たとえば、_numberには正の数値のみという条件があった場合は、
明示的な例

package  {
	public class NewClass {
		
		private var _number:Number = 10;
		
		public function getNumber():Number{
			return _number;
		}
		public function setNumber(num:Number):void{
			if (num < 0) {
				_number = 0;
			} else{
				_number = num;
			}
		}		
	}
}

getter/setterがプロパティもどきと、考えてたから色々こんがらがってた。
けれど元来は関数でやってたことをプロパティっぽく使える便利機能だよって感じだということを知って、ちょっと納得。

[AS]バネの動きの考え方について

とりあえずよくわすれるからメモ
バネの動きについて

原則としては、
単位時間での、「目的位置」 – 「現在位置」を「加速度」と設定する。
この加速度でオブジェクトを動かせばそれはバネの動きとなる。

ステージにball_mcをおいた状態でのフレームアクション
簡単に書くと、

//初速度
var v0x:Number=0;
//速度
var vx:Number=0;

addEventListener(Event.ENTER_FRAME, entarFrameHandler);
vx=v0x;
function entarFrameHandler(e:Event):void {
	//マウス位置とボールの位置の差を加速度とということにする
	//つまりは目的位置 - 現在位置 を加速度にするということ。
	//この加速度は毎フレームごとで当然変化する。
	//良くわからんが、(目的位置 - 現在位置) で求めた加速度はバネの性質を持つ
	var ax = mouseX - ball_mc.x;
	
	//速度に加速度を単位時間毎に足すということ
	vx += ax;
	
	//位置に速度を単位時間毎に足すということ
	//ここでの速度はマウス位置で変化
	ball_mc.x+=vx;
}

ただしこれだと、バネは収束しないので二つのパラメータを設定して制御。
空気抵抗:1以下の数値を設定し、バネの収束する速度を調整
バネ定数:1以下の数値を設定し、バネの硬さを調整(小さい方が軟らかくなる)

//初速度
var v0x:Number=0;
//速度
var vx:Number=0;
//バネ定数(1以下、数値を上げるほど硬いバネ)
var spring:Number = 1;
//空気抵抗(数値を下げるほど、行ったり来たりが短く)
var friction:Number = 0.9

addEventListener(Event.ENTER_FRAME, entarFrameHandler);
vx=v0x;
function entarFrameHandler(e:Event):void {
	//マウス位置とボールの位置の差を加速度とということにする
	//つまりは目的位置 - 現在位置 を加速度にするということ。
	//この加速度は毎フレームごとで当然変化する。
	var ax = mouseX - ball_mc.x;
	//加速度にバネ定数をかける
	//良くわからんが、(目的位置 - 現在位置) * バネ定数で求めた加速度はバネの性質を持つ
	//(目的位置 - 現在位置) (* バネ定数:かけなくてもバネっぽい動き)で求めた加速度、これを忘れないように。
	ax = ax * spring
	
	//速度に加速度を単位時間毎に足すということ
	vx += ax;
	//速度に空気抵抗かける
	vx *= friction;
	
	//位置に速度を単位時間毎に足すということ
	//ここでの速度はマウス位置で変化
	ball_mc.x+=vx;
}

[AS]速度と加速度の考え方について

よくこんがらがるので基本的なまとめ

基本概念
速度とは、単位時間あたりの位置の変化
加速度とは、単位時間あたりの速度の変化
(ここではENTER_FRAMEでの繰り返しを単位時間と設定する)

ステージにball_mcを配置した状態でのフレームアクション

等速運動

//初速度
var v0x:Number=10;
addEventListener(Event.ENTER_FRAME, entarFrameHandler);
function entarFrameHandler(e:Event):void {
	//位置に速度を単位時間毎に足すということ
	ball_mc.x+=v0x;
}

等加速度運動

//初速度
var v0x:Number=10;
//速度
var vx:Number=0;
//初加速度(そんな言い方あるのか)
var a0x:Number=1;

addEventListener(Event.ENTER_FRAME, entarFrameHandler);
//速度に初速度を代入
vx=v0x;
function entarFrameHandler(e:Event):void {
	//速度に加速度を単位時間毎に足すということ
	vx+=a0x;
	//位置に速度を単位時間毎に足すということ
	//ここでの速度はどんどん増えていく
	ball_mc.x+=vx;
}

[AS][?]ドキュメントクラスでの初期化処理のやりかたについて

ドキュメントクラスでの初期化処理の方法について
偉いの人のソースを見るといろいろ方法があるみたい。
でも、どういったケースで使いわけるのかが、よくわからない・・・

★例1:普通にコンストラクタ内に書いちゃう
面倒なときはこれ。

package {
	import flash.display.Sprite;
	import flash.events.Event;
	
	public class Test0 extends Sprite{
		//コンストラクタ
		public function Test0() {
			//↓初期化処理を書く
			trace("init")
		}
	}
}

★例2:ドキュメントクラスがステージに追加されたら実効
よくみる書き方。

package  {
	import flash.display.Sprite;
	import flash.events.Event;
	
	public class Test1 extends Sprite{
		//コンストラクタ
		public function Test1() {
			this.addEventListener(Event.ADDED_TO_STAGE , init);
		}
		
		private function init(e:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, init);
			//↓初期化処理を書く
			trace("init")
		}
	}
}

★例3:loderInfoプロパティをトリガーにする
たまたま発見。(全部完全に読み込んでからってこと?)

package  {
	import flash.display.Sprite;
	import flash.events.Event;
	
	public class Test2 extends Sprite{
		//コンストラクタ
		public function Test2() {
			this.addEventListener(Event.ENTER_FRAME , enterFrameHandler);
		}
		
		private function enterFrameHandler(e:Event):void {
			if (this.loaderInfo){
				if ( this.loaderInfo.bytesTotal > 0 &amp;amp;&amp;amp; this.loaderInfo.bytesLoaded >= this.loaderInfo.bytesTotal ) {
				  removeEventListener( Event.ENTER_FRAME, enterFrameHandler );
					init();
				}
			}
		}
		
		private function init():void {
			//↓初期化処理を書く
			trace("init")
		}
	}
}

結局のところ、どれが一番ベターな書き方なんだろう???
作ってるモノのレベルで変わるのだろうけど1でも不自由したことがないのでよくわからない・・・

[EV] Flashコンテンツをゲームプラットフォームへ展開する技術、ビジネス

scaleformとADOBEによる共同セミナー
2009/6/18 19:00~21:00

参加メモ

◆ADOBE CS4紹介 西村
ガイドに沿って移動
→鉛筆ツール等で線を書く→コピー→移動対象のオブジェクトのあるレイヤーにペースト

◆ScaleForm紹介 阿部
3Dゲームの2D的な部分
→パネル系、MENU、ゲーム内のミニゲームとか

ベクターグラフィックをテッセレートしてGPUでレンダリング
→高速・低不可

EddgeAA エッジだけアンチエイリアス
クロスプラットフォーム(wii Ps3,Xbox)
ベクターテキスト使える。

メモリ管理が最重要
リッチなSTATS有(AMP)
GFx CLIKのソースは見れる。

ScaleFormVideo
→ビデオ対応、FLASHに張れる

ScaleForm IME
IMEのUIデザイン(スキン変更容易)

◆ホームメディア事例「あいうえ おーちゃん」
ハードウェアとScaleFormを連携させるエンジンを自作
→一番大変

◆Q&A
IPHONE対応は?
→いずれ(ScaleForm)

SWFをgfx対応は簡単?
→簡単らしい(ホームメディア)

NetConnectionとかサーバーにアクセスするのは不可?
→ScaleFormでは不可(ScaleForm)

FLASHERがゲーム開発するには
→ゲーム会社に入るのが一番早い(でもMenuとかだけになっちゃうかも)(ScaleForm)
→業界にAserは少ないみたい。
→FLASH部分の外注ということは一般的ではない
(日本は内向的)

インターフェース部分の互換について
→MainProgramにて変換処理をマッピング(ホームメディア)
→Flash側はいつもどおりに作ればOKにする

FLASHコンテンツ、SDKのライセンス問題
→特に公式にライセンス取り交わしてないけど、ADOBEとは話は通してある。(好意的)
→レンダリングエンジンとか作っても特に問題ないよ

開発コストどれくらい削減できました?
→答えられないけど、もっとも大変なのは、MainProgram(ホームメディア)
→C++で5万行くらい
→ScaleFormを使わなかったら10倍くらい?

FLASHをUVマップできるか?
→できる

[AS]描画モード(blendMode)について

いまだに馴れないのでメモ

いずれも設定したDisplayObjectと、その背景との色関係による。

“normal”
:エフェクトなし

“layer”
DisplayObjectに子要素がある場合はこれになるらしい。
:エフェクトなし(たぶん使わない)

“multiply”
:乗算
RGBの各カラーを乗算して、0XFFで除算した結果を返す
暗い感じになる。
黒を重ねると真っ黒、白を重ねても変化なし。
(真っ白は透過する感じ)
透過して暗くなじむ感じ?

“screen”
:スクリーン
RGBの各カラーの補数(0XFFから引いた値)を乗算して、0XFFで除算した結果を返す
明るい感じになる
白を重ねると真っ白、黒を重ねても変化なし。
(真っ黒は透過する感じ)
透過して明るくなじむ感じ?

“lighten”
:比較(明)
RGBの各カラーを比較して、明るい方の値を返す
白を重ねると真っ白、黒を重ねても変化なし。
(真っ黒は透過する感じ)
明るい感じになる

“darken”
:比較(暗)
RGBの各カラーを比較して、暗い方の値を返す。
黒を重ねると真っ黒、白を重ねても変化なし。
(真っ白は透過する感じ)
暗い感じになる

“difference”
:差の絶対値
RGBの各カラーの明るい方の値から暗い方の値を差し引いた値を返す
鮮やかな感じになるらしい

“add”
:加算(覆い焼きリニア)
RGBの各カラーを加算した結果を返す。上限0XFF(白)
白を重ねると真っ白、黒を重ねても変化なし。
(真っ黒は透過する感じ)
明るくなる

“subtract”
:減算
RGBの各カラーを減算した結果を返す。上限0X00(黒)
黒を重ねると真っ黒、白を重ねても変化なし。
(真っ白は透過する感じ)
暗くなる

“invert”
:反転
背面のカラーを反転して表示
ネガっぽい表現のとき?

“alpha”
:アルファ
DisplayObjectのアルファ値を背景画像にも適用
背景を表示させたくないとき?

“erase”
:消去
DisplayObjectのアルファ値にしたがって背景画像を切り抜き
(alphaの逆?)
DisplayObjectで背景を切り抜きたいとき

“overlay”
:オーバーレイ
背景が50%グレーより明るいときはスクリーン、暗いときは乗算した値を返す
DisplayObjectが背景いい感じになじむ感じ?

“hardlight”
:ハードライト
DisplayObjectが50%グレーより明るいときはスクリーン、暗いときは乗算した値を返す
(オーバーライトの逆)
あまりなじまずにDisplayObjectが浮く感じ。

参考
超・初心者のためのフォトショップ講座5 描画モード(改良版)

[AS](キーボード入力の際とかで)、キーコードを取り出す方法

StringクラスのcharCodeAt()メソッドで簡単にできたのね。。。
わざわざ変換クラス作っていました。

trace("S".charCodeAt());//出力:83
trace("A".charCodeAt());//出力:65
trace("K".charCodeAt());//73

[AS]デザインパターン「Adapter」の練習

矢沢久雄の早わかりGoFデザインパターン(2) のAdapterの項をAS3で書いてみた。
こんなかんじでいいんだろうか?

Kyuuyoprog.as(ドキュメントクラス)

package  {
	import flash.display.Sprite;
	
	/**
	 * ...
	 * @author 393
	 */
	public class KyuuyoProg extends Sprite {
		
		public function KyuuyoProg() {
			init();
		}
		
		private function init():void{
			var shacho:Shacho = new Shacho(10000);
			var shainAdapter:ShainAdapter = new ShainAdapter(shacho);
			
			var shachokyuuyo:Number = getKyuuyo(shainAdapter);
			
			var shain1:Shain = new Shain(90, 80);
			
			var kyuuyo:Number = getKyuuyo(shain1);
			trace( "shachokyuuyo : " + shachokyuuyo );
                       //出力:shachokyuuyo : 10000
			trace( "kyuuyo : " + kyuuyo );
                       //出力:kyuuyo : 5670
		}
		
		private function getKyuuyo(obj:Shain):Number{
			return obj.getJikan() * obj.getJikyu();
		}
		
	}
	
}

Shain.as

package  {
	
	/**
	 * ...
	 * @author 393
	 */
	public class Shain {
		private var _jikyu:Number;
		private var _jikan:Number;
		
		public function Shain(jikyu:Number = 0, jikan:Number = 0) {
			this._jikyu= jikyu;
			this._jikan= jikan;
		}
		public function getJikan():Number {
			//搾取
			return _jikan - 10;
		}
		public function getJikyu():Number {
			//搾取
			return _jikyu * 0.9;
		}
		
	}
	
}

Shacho.as

package  {
	
	/**
	 * ...
	 * @author 393
	 */
	public class Shacho {
		private var _koteikyu:Number;
		
		public function Shacho(koteikyu:Number) {
			_koteikyu = koteikyu
		}
		
		public function get koteikyu():Number { return _koteikyu; }
		
	}
	
}

ShainAdapter.as(アダプタークラス)

package  {
	
	/**
	 * ...
	 * @author 393
	 */
	public class ShainAdapter extends Shain {
		private var shachoObj:Shacho;
		
		public function ShainAdapter(obj:Shacho) {
			shachoObj = obj;
		}
		
		public override function getJikan():Number {
			return 1;
		}
		public override function getJikyu():Number {
			return shachoObj.koteikyu;
		}
		
	}
	
}