0

私には 2 つのクラスがあります。私の Main クラスと BlockPlace というクラスです。Main クラスを使用して BlockPlace を実行したいのですが、何らかの理由で機能しません。両方のコードを変更しようとしましたが、エラーになるだけです。タイムラインでテストしたので、コードが機能することはわかっています。全体を再構築する必要がありますか、それとも別の解決策がありますか? ここに私のクラスがあります:

メインクラス:

package  
{  
    import flash.display.*;
    import source.map.*;

    public class Main extends MovieClip{
        public function Main()  
        {  
            BlockPlace();
        }  
    }  
}

ブロック場所:

package source.map{

    import flash.display.MovieClip;
    import flash.display.Stage;

    public class BlockPlace extends MovieClip{

        public function BlockPlace(){
            var db:MovieClip = new dbox();
            stage.addChild(db);
            db.x = stage.stageWidth / 2;
            db.y = stage.stageHeight / 2;
        }
    }
}
4

2 に答える 2

4

私が見ることができるいくつかの問題があり、それがあなたが見ている動作を説明している可能性があります。

まず、これを呼び出しているのは、コンストラクターではなく関数です。

この関数を静的に参照する場合は、少し変更する必要があります。

package source.map{

    import flash.display.Stage;

    public class BlockPlace {
        public static function create(stage:Stage){
            var db:MovieClip = new dbox();
            stage.addChild(db);
            db.x = stage.stageWidth / 2;
            db.y = stage.stageHeight / 2;
        }
    }
}

そして、次を使用して呼び出します。

BlockPlace.create(stage);

クラスが MovieClip を拡張しなくなり、メソッドが static としてマークされていることに注意してください。つまり、クラスのインスタンスなしでクラスから直接参照できることを意味します。また、関数のシグネチャが変更されていることにも注意してください。外部から渡される 1 つの引数 (ステージ) を受け入れるようになりました。

このアプローチを使用して、Mainインスタンスからステージへの参照をこのユーティリティ関数に渡して、何らかの作業を行います。これはおそらく、問題に対する最も簡単な解決策です。


逆に、これを MovieClip を拡張するクラスとして維持したい場合 (それが何を意味するかについてはいくつかの意味があります)、クラスのインスタンスをインスタンス化する必要があります。

var blockPlace:BlockPlace = new BlockPlace();

次に、セージでそれを取得する必要があります。

this.addChild(blockPlace);

しかし、ステージに関してはまだニワトリが先か卵が先かという問題があります。クラスをインスタンス化するとき、そのコンストラクターでstageプロパティを参照しています。ただし、この時点ではDisplayObjectContainers、ステージに接続されている人には追加されていません。したがって、stageプロパティは になりますnull。そのため、ステージに何も追加したり、 または を取得しstageHeightたりすることはできませんstageWidth

それが起こるまで待つ必要があります - これは評価されるまで起こりませんaddChild(blockPlace)

したがって、アーキテクチャを少し再考する必要があります。ロジックがステージにアタッチされていることを確認したら、明示的に呼び出される別の関数にロジックを移動できます。何かのようなもの:

package source.map{

    import flash.display.Stage;

    public class BlockPlace {
        public function BlockPlace() {

        }

        public function initialize():void {
            var db:MovieClip = new dbox();
            stage.addChild(db);
            db.x = stage.stageWidth / 2;
            db.y = stage.stageHeight / 2;
        }
    }
}

そして、次のようなものを使用して消費されます:

var blockPlace:BlockPlace = new BlockPlace();
addChild(blockPlace);
blockPlace.initialize(); // safe to call because its on the stage now given that `this` is on the stage

ただし、より慣用的なアプローチは、イベントを使用して MovieClip がステージに追加されるまで待機してから、何らかの作業を実行することです。例えば:

package source.map{

    import flash.display.Stage;

    public class BlockPlace {
        public function BlockPlace() {
            this.addEventListener(Event.ADDED_TO_STAGE, stageAvailable);

        }

        private function stageAvailable(e:Event):void {
            var db:MovieClip = new dbox();
            stage.addChild(db);
            db.x = stage.stageWidth / 2;
            db.y = stage.stageHeight / 2;
        }
    }
}

コンストラクターが、「ステージに追加されたら、 という別の関数にある作業を行ってください」というイベント リスナーを設定していることに注意してくださいstageAvailable

注意が必要な小さな注意点がいくつかあります。表示オブジェクトがステージ上で直接構築される可能性があります。これはフラッシュ IDE によって行われます。イベントがアタッチされるまでに、イベントはすでにステージ上にあるため、これらのアイテムに対してイベントは発生しません。したがって、イベントは発生しません。それを書くための最も防御的な方法はこれです:

package source.map{

    import flash.display.Stage;

    public class BlockPlace {
        public function BlockPlace() {
            if(stage) stageAvailable()
            else this.addEventListener(Event.ADDED_TO_STAGE, stageAvailable);

        }

        private function stageAvailable(e:Event = null):void {
            if(event) this.removeEventListener(Event.ADDED_TO_STAGE, stageAvailable);
            var db:MovieClip = new dbox();
            stage.addChild(db);
            db.x = stage.stageWidth / 2;
            db.y = stage.stageHeight / 2;
        }
    }
}

コンストラクターでは、ステージがあるかどうかを確認し、ステージがある場合はすぐに関数を呼び出します。そうでない場合は、それが発生するまで待機するようにリスナーを設定します。次に、ハンドラーで、イベントが原因で呼び出された場合は、それ自体をクリーンアップしてリスナーを削除します。

于 2012-07-24T17:45:27.877 に答える
1

変化する:

BlockPlace();

に:

var blockPlace:BlockPlace = new BlockPlace();

実際にインスタンス化する必要があります。

于 2012-07-24T17:17:39.573 に答える