ちょっとFlashではまったので、メモしておくよ。 文字列からクラスインスタンスをダイナミックに生成する際 Function.applyを使いたいと思ったんだけど うまく行かなかったので、いろいろ試してみた。

わかりやすいように、「String」クラスの例だが 実際には[mypackage.MyClass]などでやるのが普通だろう。

そういう場合は、最初に mypackage.MyClass; として、クラスを利用する事を宣言しとかないと、コンパイル時に無視されるので注意。

var className = "String";
var classFunc:Function = eval(className);

var test:String;

// OK
test = new classFunc("a");
trace(test.length); // a

// NG
test = new classFunc.call(null,"a");
trace(test.length); // undefined

// NG
test = new classFunc.apply(null,["a"]);
trace(test.length); // undefined

var returnClass:Function = function( classFunc:Function, args:Array ){
    return classFunc.apply(null,args);
}

// OK
test = new classFunc( returnClass(classFunc,["a"]) );
trace(test.length); // 1

どういう事かというと String.apply(null,args); をリターンする新しい関数をかましてやると、 new しながらFunction.applyも使えるよねって事だ。

Posted in actionscript2.0, flash, programing at 11月 10th, 2006. No Comments.

今日はFlashのライブラリに一つ追加

JavaのSynchronizedを擬似的に実装するクラス

使い方は

var mcloaded = false;
var framenum = 1;

function execute(){

  var checks = [];
  var checks[0] = [mcloaded,true];
  var checks[1] = [framenum,30];

  if( com.func09.events.Synchronizer.check(this,execute,checks) ){
    // 実行する処理
  } else {
    // 処理を実行できなかった場合
  }
}

こんな感じになっている。

クラス内部では、引数のフラグ変数とフラグが完了しているかを照らし合わせて、完了していなかったら前回作ったDelayFrameActionを使って次のフレームでもう一回大本の関数を実行。

つまり実行できる条件がそろうまで何度でも実行するサポートクラス

今思ったけどFlashのsetIntervalってどういうことになってるんだろう? 結局スクリプトを実行できるのはフレームの中だと思うんだけど・・・。

FPS12だと、120ミリ秒に一回関数を走らせるって事は 1フレーム内で10回処理が走るって事かな?? それともsetIntervalだけ別の次元で処理している?まさかなぁ・・。

Posted in actionscript2.0, flash, 日記 at 10月 11th, 2006. No Comments.

複数のフラグをチェックする方法として

  • フラグを必要数だけ用意する方法
  • フラグを配列で管理する方法
  • フラグをビットで管理する方法

などがあると思われる。

フラグの数だけ変数を用意する


var flag0:Boolean = false;
var flag1:Boolean = false;
var flag2:Boolean = false;

// フラグを立てる処理
flag0 = true;
flag1 = true;
flag2 = true;

if( flag0 && flag1 && flag2 ) {
    // フラグが全て立った時の処理
}

と、これはなんかカッコ悪いし
フラグ変数をイチイチ用意するのがもったいない。

フラグを配列にする方法


// 3つ分のフラグ配列
var flags:Array = new Array(3);

// フラグを立てる処理
flags[0] = true;
flags[1] = true;
flags[2] = true;

for( var n0:Number=0; n0<flags.length; n0++ ){

    if( !flags[n0] ) {
        //  フラグが立っていなかったらループを抜ける
        break;
    } else if( n0 == flags.length ) {
        //  フラグが全て立った時の処理
     }
}

フラグをビットで管理する


var flagNum:Number = 0x000;
var flagMax:Number = 0x111;
<br />
// フラグを立てる処理
flagNum += 0x001;
flagNum += 0x010;
flagNum += 0x100;

if( flagNum == flagMax ){
    //  フラグが全て立った時の処理
}
Posted in actionscript2.0, flash, programing at 12月 8th, 2005. No Comments.

ゲーム開発ってすごくプログラミングの勉強になる。 今日はタイルベースでの深度の管理についていろいろ考えていた。

一応その座標での深度は クォータービューについてだが

  • Y軸が大きいほど深度は高い
  • 同Y軸の中ではXが大きいほど深度は高い
  • 同一座標でもさらにZがある

という点から、その座標の深度をあらかじめ予約する場合


Depth = (Y * Y.length * Z.length ) + ( X * Z.length ) + Z

としておけば、被る事がないだろう。 Read More…

Posted in actionscript2.0, flash, programing at 12月 7th, 2005. No Comments.

テトリスでけたー。 ほとんど寝ずにコーディングしたお。

今回ので結構MVCの事、わかった気がするアタイ。

えっと、パッケージ構成は

// デバッグ用 util.Debug

// 基幹クラス mvc.View // Viewインターフェイス mvc.AbstractVew // View抽象クラス mvc.Model // Modelインターフェイス mvc.AbstractModel // Model抽象クラス mvc.Controller // Controllerインターフェイス mvc.AbstractController // Controller抽象クラス

// コンクリートなクラス game.Game // メインCTRL game.GameModel // Model game.AggregatedModel // 小さいModelの抽象クラス game.Board // 小さいModel game.Timer // 小さいModel game.Block // 小さいModel game.AbstractGameView // Viewクラス game.SimpleGameView // Viewクラス game.state.State // Stateインターフェイス game.state.InitState // State game.state.MoveState // State game.state.WaitState // State

なんか単純なのに、結構な数になってしまったな。 まだバグが多かったり、ゲームオーバー判定つけてなかったりなので、そのへんまとめたら。Blogに解説とソースでもうpしようかと。

僕はAS2Unitとか使ったことないから、モックとかテストとかよくわからないし、mtasc?使うと何がいいのかわからんのですがね。今回作るに当たって、MCは使わない縛りを作った。

FlashはどうしてもView先行の考え方になっちゃうから、それを脱却するために、Viewを完全に切り離してみた。テトリスだから出来たようなものだな。

Viewは二つ用意してあって、util.Debugを通してtraceする文に、ひたすら

ブロックが座標[0,10]に移動しました。 壁に当たりました。 とか、出力するだけのと

テキストフィールドに

「□」「■」「 」(全角スペース)の3つでViewを表現したもの。

どちらともインターフェイスは一緒なので、Viewを変えたければAbstractGameViewを継承して、作ればいいって感じだ。

あー疲れた。ためになった。

Posted in actionscript2.0, flash, programing at 12月 1st, 2005. No Comments.

すごく腑に落ちないバグとの格闘をいま終えた

タイムラインで

import game.*;
var game:Game = new Game(this);

みたいにして、アプリケーションが起動するんだけれども

Key.addEventLister()ごしの時だけ、ロードできないクラスがあって、まったく意味がわからなかったのですよ。よくあるクラスの中のリスナーのスコープの話では片づかない雰囲気。

スコープは正しくthisに渡せているのに、何故かカスタムクラスがロードできないとかいいやがる。

import game.block.Block;
.
// リスナー登録の処理
.
function callback(){
 trace(new Block()); // undefined
}

で、デバッグ用に同じ事を違うパッケージ名でやったら問題なく通った。

で、どうやら起動用のクラス名をGameからMainに変えたら動く。同じものをGameに変えたらやっぱりダメ。

結論としては、唯一タイムラインから呼び出しているクラスがパッケージ名と大文字小文字の違いはあれど、同じだったのが問題だったのかなぁと。腑に落ちない。

ちなみに上記のような疑問から、じゃぁ起動用のクラスをタイムラインのメモリに乗せなきゃどうだろう?という気持ちから、ちょっとGameクラスを変更してタイムラインから

Game.run(this);

と、staticメソッドを通して叩いたら問題なかったよ。 で、結局どういう問題なんだ?パッケージの名前解決がどうFlash Player内で扱われているか知らんし。

Posted in actionscript2.0, flash at 11月 30th, 2005. No Comments.

テトリスを作り始めた。
これなら3日もあれば作れるだろうし、いきなりクォータービューとか作ろうとしたらクラスの関連性とかでつまづいているので簡単なゲームの作り方とMVCの基本を掴んでおこうかと…。

現状は

game.Game
game.UserInterface
game.block.Block
game.block.BlockDeck
game.event.EventBase

みたいな構成になってる。

とりあえずーブロック1マスをBlockとする
さらにBlockがTileみたいなクラスを継承しとくといいかも。

Tileはゲームのマスを表現して
ステージやブロックを構築したり状況を記録したりする場合に使おうかと。で、コンポジットパターンで同一視してみようかと。

ブロックは最小単位を1マスとして
棒や四角や凸を作り出す。基本的にライブラリにはグラフィック的なものは一切存在させない。

例えば、凸なら
□□□□
□□■□
□■■■
□□□□
と2元で表現する。

回転したら
□□□□
□■□□
□■■□
□■□□
こうなるわけだ。

こんな感じで配列を持った

var STICKMAP1:Array = [[0,0,1,0],[0,0,1,0],[0,0,1,0],[0,0,1,0]];
var STICKMAP2:Array = [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]];
var STICKMAP3:Array = [[0,0,1,0],[0,0,1,0],[0,0,1,0],[0,0,1,0]];
var STICKMAP4:Array = [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]];
var BOXMAP1:Array = [[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]];
var BOXMAP2:Array = [[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]];
var BOXMAP3:Array = [[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]];
var BOXMAP4:Array = [[0,0,0,0],[0,1,1,0],[0,1,1,0],[0,0,0,0]];
var CRANKA1:Array = [[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]];
var CRANKA2:Array = [[0,0,1,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]];
var CRANKA3:Array = [[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]];
var CRANKA4:Array = [[0,0,1,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]];
var CRANKB1:Array = [[0,0,0,0],[0,1,1,0],[1,1,0,0],[0,0,0,0]];
var CRANKB2:Array = [[1,0,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]];
var CRANKB3:Array = [[0,0,0,0],[0,1,1,0],[1,1,0,0],[0,0,0,0]];
var CRANKB4:Array = [[1,0,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]];
var CONVEX1:Array = [[0,0,0,0],[1,1,1,0],[0,1,0,0],[0,0,0,0]];
var CONVEX2:Array = [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]];
var CONVEX3:Array = [[0,0,0,0],[0,1,0,0],[1,1,1,0],[0,0,0,0]];
var CONVEX4:Array = [[0,1,0,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]];

MCの当たり判定とかを使わない事でよりMVCを分けて考えられるかなぁと。ちなみに1個単位のブロック群をブロックデッキと呼び、このへんはフライウェイトパターンかなぁと…。

コンポジットもフライウェイトも使ったことないので、できるか心配だけど、ポリモーフィズムの良い勉強になるやも。

ゲームのアルゴリズムとしては、ステージに置かれているブロックを2元で表現したstageMap:Mapと操作されるblockDeck:BlockDeck

conpaire( stageMap, Map(blockDeck) );

みたいに、ステージのマップとブロックデッキのマップと位置から比較してやる方向で。

Posted in actionscript2.0, flash at 11月 29th, 2005. No Comments.

キャラクターの振る舞いはSTATEパターンよりも コマンドとかインタプリタの方が良い?

そうなるとやはり、新キャラの投入とかの時に本体もアップグレードする必要があるか?

むしろSTATEはゲーム世界の状態を表現するときに使った方が正しいのかも。朝とか昼とか夜とかで世界の状況がガラッと変わる必要があるから。

今月中にマップの構築関連とキャラクター関連のモックを作って、そのクラスをSTATEでくるむようにして、あとはサーバとの連動うんぬんを考えたり…かなぁ。がんばろっと。

Posted in actionscript2.0, flash, 日記 at 11月 28th, 2005. No Comments.

どうしようか悩んでた所、思いついたかもざっくりメモ

58437724_222.jpg
画像のような5×5マスのクォータービューで、2×2マスの底面積をもったオブジェクト(Desk)を配置する場合


&lt;map&gt;
&lt;types&gt;
&lt;itemtype name="Tile" src="tile.swf" /&gt;
&lt;itemtype name="Desk" src="desk.swf" /&gt;
&lt;/types&gt;
&lt;items&gt;
&lt;item type="Tile" xtile="0" ytile="0" /&gt;
&lt;item type="Tile" xtile="1" ytile="0" /&gt;
&lt;item type="Tile" xtile="2" ytile="0" /&gt;
.
.
.
&lt;item type="Desk" xtile="3" ytile="2" /&gt;
&lt;/items&gt;
&lt;/map&gt;&lt;/code&gt;&lt;/pre&gt;

みたいなXMLで持っておいて。。


new ArrangeItem("Desk",3,2);
new ArrangeItem("Tile",0,0);

と処理していって


class ArrengeItem{
public var walkable:Boolean;
public function ArrengeItem(nam,x,y){ 処理 }
public function isWalkable():Boolean{ return walkable }
}

class Desk extends ArrengeItem{
public var walkable:Boolean = false;
public static var colspan = 2;
public static var rowspan = 3;
public function Desk(nam,x,y){super(nam,x,y)}
}

class Tile extends ArrengeItem{
public var walkable:Boolean = true;
public static var colspan = 1;
public static var rowspan = 1;
public function Tile(nam,x,y){super(nam,x,y)}
}



var Map:Array = [
["Tile","Tile","Tile","Tile","Tile"],
["Tile","Tile","Tile","Tile","Tile"],
["Tile","Tile","Desk","Desk","Tile"],
["Tile","Tile","Desk","Desk","Tile"],
["Tile","Tile","Tile","Tile","Tile"],
];

みたいな、2元配列に持って行ければいいんじゃないかい?これなら、カスタマイズ的なマップ変更だって、新規アイテムにだって対応できんじゃねーの?

でもさ、外部SWFが本体SWFと同じクラスを継承してるってのがちょっと気になる。コンフリクトしそうな気がする。大丈夫なのか…、試す気にもならない。

実際クォータービューを安請け合いしたものの
Flashでやるとややこしいですよ…。
キャラクタや配置されたオブジェクトのMC深度が
移動するキャラクタによってガンガン変更しなきゃならない。
だってオブジェクトの前に居るときはキャラの方が深度が高くて、後ろに回ると深度が低くなきゃ、それっぽく見えない。

あとはきっちりとMVCを気にしながらやればなんとかなるかなぁ…不安だなぁ。メディエタとオブザバの使い方を間違えなかったら、後は力業でもなんとかなるだろうけどなぁ。

Posted in actionscript2.0, flash, programing, 日記 at 11月 28th, 2005. No Comments.