別件の見積もりが入って少し開きました。
さて、その後、親子関係のMovieClipを作成してみて親を動かしてみたら、子供がうまく一緒に動いてくれなくてずっとはまっていました。2日くらい実験したものの解決方法が分からず断念。
とりあえず全てのMovieClipは_rootの直接の子供とすることにしました。
また、HogeMan.create_hoge形式がいけてないと思ったので、各クラスに空のMovieClipをキャンバスとして渡して各クラスのdrawメソッドで描くようにしてみました。
後は、drawRect,drawOvalを使って、fillRect,fillOvalも作成しました。
では、

  • fillRectから。以下のファイルをtest.flaと同じ階層に置きます。
fillRect.as
----
#include "drawRect.as"

MovieClip.prototype.fillRect = function(c, x, y, w, h, cornerRadius) {
    if ( c == undefined ) {
        c = 0x000000;
    }
    this.lineStyle();
    this.beginFill(c);
    this.drawRect(x, y, w, h, cornerRadius);
    this.endFill();
}
  • 次にfillOval。同様にtest.flaと同階層に置きます。
fillOval.as
----
#include "drawOval.as"

MovieClip.prototype.fillOval = function(c, x, y, radius, yRadius) {
    if ( c == undefined ) {
        c = 0x000000;
    }
    this.lineStyle();
    this.beginFill(c);
    this.drawOval(x,y,radius,yRadius);
    this.endFill();
}
  • つづいてMCMan、
MCMan.as
----
class info.uebuyahonpo.MCMan {
    private static var hash:Object = new Object();

    public static function create_movie(kind:String):MovieClip {
        if ( hash[kind] == undefined ) {
            hash[kind] = 0;
        }
        else {
            hash[kind]++;
        }
        return _root.createEmptyMovieClip(
            kind+hash[kind], //name0 など
            _root.getNextHighestDepth()
        );
    }
}

中でハッシュを作って、そこにそれぞれの種別の個数を保持して、空のMovieClipを作るときの名前を自動生成します。また、常に_rootの子供としてMovieClipを作成します。

  • つづいてShapeクラス。他の親クラスです。
Shape.as
----
class info.uebuyahonpo.Shape {
    private var canvas:MovieClip;
    private var color:Number;

    function Shape() {}

    public function draw() {
        throw new Error('call abstruct method draw()');
    }

    public function move(x:Number,y:Number) {
        this.canvas._x = x;
        this.canvas._y = y;
    }

    public function x():Number {
        return this.canvas._x;
    }

    public function y():Number {
        return this.canvas._y;
    }

    public function visible() {
        this.canvas._visible = true;
    }

    public function invisible() {
        this.canvas._visible = false;
    }
}
  • 続けて、Background,Panel,Ball,Cursorのサブクラスを4つ。
Background.as
----
import info.uebuyahonpo.Shape;
class info.uebuyahonpo.Background extends Shape {
    public static var l:Number   = 160;
    public static var r:Number   =   3;
    public static var p2p:Number =   2; /* パネル間距離 */

    function Background(mc:MovieClip,c:Number) {
        this.canvas = mc;
        if ( c == undefined ) {
            this.color  = 0x000000;
        }
        else {
            this.color  = c;
        }
    }

    public function draw() {
        this.canvas.fillRect(
            this.color,
            -(Background.l/2),-(Background.l/2),
            Background.l,Background.l,Background.r
        );
    }
}
Panel.as
----
import info.uebuyahonpo.Shape;
class info.uebuyahonpo.Panel extends Shape {
    public static var l:Number   = 76;
    public static var r:Number   =  1;
    public static var hr:Number  =  6;
    public static var h2h:Number = 10; /* 穴間距離 */
    private var hcolor:Number;

    function Panel(mc:MovieClip,c:Number,hc:Number) {
        this.canvas = mc;
        if ( c == undefined ) {
            this.color  = 0xffffff;
        }
        else {
            this.color  = c;
        }
        if ( hc == undefined ) {
            this.hcolor = 0xcccccc;
        }
        else {
            this.hcolor = hc;
        }
    }

    public function draw() {
        this.canvas.fillRect(
            this.color, -(Panel.l/2), -(Panel.l/2),
            Panel.l, Panel.l, Panel.r
        );
        for (var i=0;i<3;i++) {
            for (var j=0;j<3;j++) {
                this.canvas.fillOval(
                    this.hcolor,
                    Panel.get_coordinate(i),
                    Panel.get_coordinate(j),
                    Panel.hr
                );
            }
        }
    }

    public static function get_coordinate(index:Number):Number {
        return (2*Panel.hr + Panel.h2h) * (index - 1);
    }
}
Ball.as
----
import info.uebuyahonpo.Shape;
class info.uebuyahonpo.Ball extends Shape {
    public static var r:Number = 5;

    function Ball(mc:MovieClip,c:Number) {
        this.canvas = mc;
        if ( c == undefined ) {
            this.color  = 0xff0000;
        }
        else {
            this.color  = c;
        }
    }

    public function draw() {
        this.canvas.fillOval(this.color, 0, 0, Ball.r);
    }
}
Cursor.as
----
import info.uebuyahonpo.Shape;
import info.uebuyahonpo.Panel;
class info.uebuyahonpo.Cursor extends Shape {
    public static var size:Number      = 12;
    public static var thickness:Number =  1;
    private var x_ind:Number;
    private var y_ind:Number;
    private var panels:Array;

    function Cursor(mc:MovieClip,c:Number) {
        this.canvas = mc;
        if ( c == undefined ) {
            this.color  = 0xff0000;
        }
        else {
            this.color  = c;
        }
        this.x_ind = 0;
        this.y_ind = 0;
    }

    public function draw() {
        this.canvas.lineStyle(Cursor.thickness,this.color);
        var s = Cursor.size/2;
        var l = Cursor.size/3;
        this.canvas.moveTo(-s  ,-s  );
        this.canvas.lineTo(-s  ,-s+l);
        this.canvas.moveTo(-s  , s-l);
        this.canvas.lineTo(-s  , s  );

        this.canvas.lineTo(-s+l, s  );
        this.canvas.moveTo( s-l, s  );
        this.canvas.lineTo( s  , s  );

        this.canvas.lineTo( s  , s-l);
        this.canvas.moveTo( s  ,-s+l);
        this.canvas.lineTo( s  ,-s  );

        this.canvas.lineTo( s-l,-s  );
        this.canvas.moveTo(-s+l,-s  );
        this.canvas.lineTo(-s  ,-s  );
    }

    public function up() {
        this.y_ind = (this.y_ind + 5) % 6;
    }

    public function down() {
        this.y_ind = (this.y_ind + 1) % 6;
    }

    public function right() {
        this.x_ind = (this.x_ind + 1) % 6;
    }

    public function left() {
        this.x_ind = (this.x_ind + 5) % 6;
    }

    public function set_panels(pa:Array) {
        this.panels = pa;
    }

    public function move() {
        var pind = Math.floor(this.x_ind/3)*2 + Math.floor(this.y_ind/3);
        var x    = this.panels[pind].x();
        var y    = this.panels[pind].y();
        var hx   = Panel.get_coordinate(x_ind%3);
        var hy   = Panel.get_coordinate(y_ind%3);
        super.move(x+hx,y+hy);
    }

    public function get_color():Number {
        return this.color;
    }
}
  • で、これらを使ったmain.as
main.as
----
// MovieClipの拡張
#include "fillOval.as"
#include "fillRect.as"

import info.uebuyahonpo.*;

// 背景の描画
var bg = new Background(MCMan.create_movie("bg"));
bg.move(Stage.width/2, Stage.height/2);
bg.draw();

// パネルの描画
var panels = new Array(4);
var delta = (Background.p2p+Panel.l)/2;
for (var i=0;i<4;i++) {
    panels[i] = new Panel(MCMan.create_movie('p'));
    panels[i].move(
        bg.x() + (Math.floor(i/2)*2-1)*delta,
        bg.y() + (Math.floor(i%2)*2-1)*delta
    );
    panels[i].draw();
}

// カーソルの描画
var cursors = [
    new Cursor(MCMan.create_movie('cur'),0xff0000),
    new Cursor(MCMan.create_movie('cur'),0x0000ff)
];
for (var i=0;i<2;i++) {
    cursors[i].set_panels(panels);
    cursors[i].move();
    cursors[i].draw();
    cursors[i].invisible();
}

var turn = 0;
cursors[0].visible();

findClips(_root,0);

// キーのディスパッチ
var key_disp = [
    function () {}, // 0が押されたら
    function () {   // 1が押されたら
        p0._rotation += 15;
    },
    function () {   // 2が押されたら
        cursors[turn].up();
        cursors[turn].move();
    },
    function () {   // 3が押されたら
        p2._rotation += 120;
    },
    function () {   // 4が押されたら
        cursors[turn].left();
        cursors[turn].move();
    },
    function () {   // 5が押されたら
        var b = new Ball(MCMan.create_movie('b'), cursors[turn].get_color());
        b.move(cursors[turn].x(),cursors[turn].y());
        b.draw();
        cursors[turn].invisible();
        turn = (turn+1)%2; /* ターン交代 */
        cursors[turn].visible();
    },
    function () {   // 6が押されたら
        cursors[turn].right();
        cursors[turn].move();
    },
    function () {   // 7が押されたら
        p1._rotation += 120;
    },
    function () {   // 8が押されたら
        cursors[turn].down();
        cursors[turn].move();
    },
    function () {   // 9が押されたら
        p3._rotation += 120;
    }
];

//メインループ
this.onEnterFrame = function () {
    var k = Key.getCode();
    //最後に押されたキーが数字キーでまだ押されているか
    if ( k >= 48 && k <= 57 && Key.isDown(k) ) {
        key_disp[k-48]();
    }
}

function findClips(theClip,indentSpaces) {
    var indent = ' ';
    for ( var i=0; i<indentSpaces; i++) {
        indent += ' ';
    }
    for ( var property in theClip ) {
        if (typeof theClip[property] == "movieclip") {
            trace(indent + theClip[property]._name + '(' + property + ')');
            findClips(theClip[property],indentSpaces+4);
        }
    }
}

Stageクラスを使って画面中央に背景を置き、各パネルを配置、先行・後攻用のカーソルを書いた。
2,4,6,8でカーソル移動、5でボールを置いて順番交代。1,3,7,9はペンタゴでボールを置いた後にパネルを回転させるので実験用に記述。
findClips関数は、オライリーActionScript実践プログラミングからぱくってきた。

今回はだいぶ変わったので、もう一度実機で確認してもらった。