丢失了不在 AS3 中显示的对象

lost with the objects not displaying in AS3

我有一个 class 可以在舞台上积木。一切似乎都运行良好,没有错误,我什至可以看到创建的砖块对象和在调试器中初始化的碰撞变量 window 但仍然没有任何显示在舞台上,任何帮助将不胜感激我已经花了几个小时来弄清楚我错过了什么但无济于事:(

这是代码

public class Level1 extends Sprite {

    private var worldVar:world = new world();
    public var stageRef:Stage;

    public function Level1(stageRef:Stage) {


        stageRef = stageRef;

        brick(402,431,140,36, stageRef);
        brick(544,431,140,36,stageRef);
        brick(342,396,16,32,stageRef);
        brick(604,396,16,32,stageRef);
        brick(416,347,16,130,stageRef);
        brick(532,347,16,130,stageRef);
        brick(474,273,132,16,stageRef);
        brick(474,257,32,16,stageRef);
        brick(445,199,16,130,stageRef);
        brick(503,199,16,130,stageRef);
        brick(474,125,58,16,stageRef);
        brick(474,100,32,32,stageRef);
        brick(474,67,16,32,stageRef);
        brick(474,404,64,16,stageRef);
        brick(450,363,16,64,stageRef);
        brick(498,363,16,64,stageRef);
        brick(474,422,64,16,stageRef);
    }

    private function brick(pX: int, pY: int, w: Number, h: Number, _stg:Stage): void {
        var sg = _stg; // assign the stage 
        var bric:Sprite = new Brick();
        sg.addChild(bric);
        //trace(worldVar.m_sprite.);
        bric.x = pX;
        bric.y = pY;
        bric.width = w;
        bric.height = h;

        var polygonShape: b2PolygonShape = new b2PolygonShape();
        var polygonFixture: b2FixtureDef = new b2FixtureDef();
        polygonShape.SetAsBox(w / 2 / worldVar.worldScale, h / 2 / worldVar.worldScale);
        polygonFixture.shape = polygonShape;
        polygonFixture.density = 1;
        polygonFixture.restitution = 0.5;
        polygonFixture.friction = 0.9;
        var brickbodyDef: b2BodyDef = new b2BodyDef();
        //brickbodyDef.type=b2Body.b2_dynamicBody;
        brickbodyDef.userData = bric;
        brickbodyDef.position.Set(pX / worldVar.worldScale, pY / worldVar.worldScale);
        var theBrick: b2Body = worldVar.createWorld.CreateBody(brickbodyDef);
        theBrick.CreateFixture(polygonFixture);


    }


}

Based on @null recommendation I did make changes to my document class

package {
import flash.display.Sprite;
import flash.display.Stage;
import flash.events.*;
import Levels.Level1;
import world;

public class Main extends Sprite {

    public var worldVar:world = new world();
    public var bird: birdMc = new birdMc();
    //public var bric:Brick = new Brick();
    public var level:Levels.Level1 = new Levels.Level1();

    public function Main() {

    var bg: backgroundMc = new backgroundMc();

        addChild(worldVar.m_sprite);
        worldVar.m_sprite.addChild(bg);
        worldVar.m_sprite.addChild(bird);
        worldVar.m_sprite.addChild(level);

    }
}

}

一切都完美地呈现在舞台上谢谢你但现在我被困在没有将 box2d 物理应用于砖块的情况下,尽管所有碰撞都对鸟在同台

Here is the code for birdMC class

package  {

import flash.display.MovieClip;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.display.Stage;
import Box2D.Dynamics.*;
import Box2D.Collision.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;
import Box2D.Dynamics.Joints.*;
import world;
import Levels.*;


public class birdMc extends MovieClip {

    public var worldVar:world = new world();
    //public var m:Main = new Main();
    //public var sleep: Boolean = true;
    // public var main:Main; // use this variable to access objects declared with in the main class
    //public var stageRef:Stage;// use this variabel to access the main the stage

    public function birdMc() {



        //this.stageRef = worldVar.m_sprite;
        this.x = worldVar.birdPlacementX;
        this.y = worldVar.birdPlacementY;
        this.buttonMode = true;

        addEventListener(Event.ENTER_FRAME, updateWorld);
        this.addEventListener(MouseEvent.MOUSE_DOWN, birdClicked);
        // constructor code
    }


    private function birdClicked(e: MouseEvent): void {

        addEventListener(MouseEvent.MOUSE_MOVE, birdMoved);
        addEventListener(MouseEvent.MOUSE_UP, birdReleased);
        this.removeEventListener(MouseEvent.MOUSE_DOWN, birdClicked);
    }
    private function birdMoved(e: MouseEvent): void {

        this.x = worldVar.m_sprite.mouseX;
        this.y = worldVar.m_sprite.mouseY;
        var distanceX: Number = this.x - worldVar.birdPlacementX;
        var distanceY: Number = this.y - worldVar.birdPlacementY;
        if (distanceX * distanceX + distanceY * distanceY > 1000) {
            var birdAngle: Number = Math.atan2(distanceY, distanceX);
            this.x = worldVar.birdPlacementX + 100 * Math.cos(birdAngle);
            this.y = worldVar.birdPlacementY + 100 * Math.sin(birdAngle);
        }
    }
    private function birdReleased(e: MouseEvent): void {

        this.buttonMode = false;
        removeEventListener(MouseEvent.MOUSE_MOVE, birdMoved);
        removeEventListener(MouseEvent.MOUSE_UP, birdReleased);
        var sphereShape: b2CircleShape = new b2CircleShape(15 / worldVar.worldScale); // define the shape with the radius
        var sphereFixture: b2FixtureDef = new b2FixtureDef(); // define the fixture
        sphereFixture.density = 1;
        sphereFixture.friction = 6;
        sphereFixture.restitution = 0.5;
        sphereFixture.shape = sphereShape; // glue the shape to fixture
        var sphereBodyDef: b2BodyDef = new b2BodyDef(); // create a body
        sphereBodyDef.type = b2Body.b2_dynamicBody;
        sphereBodyDef.userData = this; // attaching our moviclip to the body
        sphereBodyDef.position.Set(this.x / worldVar.worldScale, this.y / worldVar.worldScale);
        worldVar.birdSphere = worldVar.createWorld.CreateBody(sphereBodyDef);
        worldVar.birdSphere.CreateFixture(sphereFixture);
        var distanceX: Number = this.x - worldVar.birdPlacementX;
        var distanceY: Number = this.y - worldVar.birdPlacementY;
        var distance: Number = Math.sqrt(distanceX * distanceX + distanceY * distanceY);
        var birdAngle: Number = Math.atan2(distanceY, distanceX);
        worldVar.birdSphere.SetLinearVelocity(new b2Vec2(-distance * Math.cos(birdAngle) / 2, -distance * Math.sin(birdAngle) / 2));
    }

    public function updateWorld(e: Event): void {

        var velIterations: int = 10; // times velocity of objects get updated
        var posIterations: int = 10; // adjusts positions to avoid overlap
        worldVar.createWorld.Step(worldVar.timeStep, velIterations, posIterations); // setup the bodies in the world update speed  10, 10 is a safe number
        for (var currentBody: b2Body = worldVar.createWorld.GetBodyList(); currentBody; currentBody = currentBody.GetNext()) {
            if (currentBody.GetUserData()) {
                currentBody.GetUserData().x = currentBody.GetPosition().x * worldVar.worldScale;
                currentBody.GetUserData().y = currentBody.GetPosition().y * worldVar.worldScale;
                currentBody.GetUserData().rotation = currentBody.GetAngle() * (180 / Math.PI);
            }
        }
        worldVar.createWorld.ClearForces(); // clear forces to let the simulation start again
        worldVar.createWorld.DrawDebugData();

    }

}

}

Here is the world class I primarily use it to declare global variables and to add walls with in the b2 world.

package  {
import Box2D.Dynamics.*;
import Box2D.Collision.Shapes.*;
import Box2D.Common.Math.*;

import flash.display.Sprite;

public class world {

    public var gravity: b2Vec2 = new b2Vec2(0, 9.81); // define gravity
    public var createWorld: b2World = new b2World(gravity, true); // add gravity and put to sleep if not active to true
    public var worldScale: int = 30; // convert meters into pixels
    public var birdSphere: b2Body;
    public var timeStep = 1 / 60;
    public var birdPlacementX = 210; 
    public var birdPlacementY = 325;
    public var m_sprite:Sprite = new Sprite();

    public function world() {

        addWall(800, 10, 0, 490);  //floor
        addWall(800, 10, 0, -5);// ceiling
        addWall(10, 600, 0, 0); // left
        addWall(10, 600, 800, 0); // right

    }

    private function addWall(w, h, px, py): void {
        var floorShape: b2PolygonShape = new b2PolygonShape();
        floorShape.SetAsBox(w / worldScale, h / worldScale);
        var floorFixture: b2FixtureDef = new b2FixtureDef();
        floorFixture.density = 0;
        floorFixture.friction = 10;
        floorFixture.restitution = 0.2;
        floorFixture.shape = floorShape;
        var floorBodyDef: b2BodyDef = new b2BodyDef();
        floorBodyDef.position.Set(px / worldScale, py / worldScale);
        var floor: b2Body = createWorld.CreateBody(floorBodyDef);
        floor.CreateFixture(floorFixture);

    }

}

}

问题是鸟和墙的碰撞效果很好,但让我感到困惑的是砖块,尽管它们都是单独实例化的

public var createWorld: b2World = new b2World(gravity, true);

这里有两个问题。我会说它们是 AS3 中使用的两种最常见的反模式。

  • 将对阶段的引用传递给 DisplayObject 这几乎没有意义,因为每个 DisplayObject 都有它的 自己参考阶段在.stage属性。为什么还要创建 另一个 class 成员参考 stage?

    这个属性的特别之处在于null只要 object 不在显示列表中。一旦 object 是 添加,stage 将成为有效参考。如果 class 扩展 DisplayObject 需要引用 stage 这是有效的,简单 侦听 Event.ADDED_TO_STAGE 事件,该事件将被调度 一旦添加 object 且 stage 生效。

  • stage 添加任何内容 in the documentation of addChild(),向 stage 添加任何内容是不应该做的事情。

    So, generally, objects should not be added to the Stage, directly, at all.

很好。因为如果 stage 什么都不应该添加,那么就不需要首先传递对 stage 的引用,这就解决了第一个问题。

如果不应该添加到stage,还应该添加什么? 答案是:主要时间线或您自己创建的 DisplayObjectContainer

在主时间线上,您实例化了一个 Level1(顺便说一句,可怕的 class 名称!)object 并将其添加到显示列表中:

var level:Level1 = new Level1();
addChild(level);

Level1extendsDisplayObjectContainer,意思是可以往里面加东西。在您的情况下,该级别的所有积木都应添加到该级别。该关卡充当该关卡所有内容的容器。

我修改了现有的代码:

public class Level1 extends Sprite 
{
    private var worldVar:world = new world();

    public function Level1() 
    {
        brick(402,431,140,36);
        brick(544,431,140,36);
        brick(342,396,16,32);
        brick(604,396,16,32);
        brick(416,347,16,130);
        brick(532,347,16,130);
        brick(474,273,132,16);
        brick(474,257,32,16);
        brick(445,199,16,130);
        brick(503,199,16,130);
        brick(474,125,58,16);
        brick(474,100,32,32);
        brick(474,67,16,32);
        brick(474,404,64,16);
        brick(450,363,16,64);
        brick(498,363,16,64);
        brick(474,422,64,16);
    }

    private function brick(pX: int, pY: int, w: Number, h: Number): void 
    {
        var brick:Sprite = new Brick();

        addChild(brick); //not adding to stage, but the Level1 instance

        //trace(worldVar.m_sprite.);
        brick.x = pX;
        brick.y = pY;
        brick.width = w;
        brick.height = h;

        var polygonShape: b2PolygonShape = new b2PolygonShape();

        var polygonFixture: b2FixtureDef = new b2FixtureDef();
        polygonShape.SetAsBox(w / 2 / worldVar.worldScale, h / 2 / worldVar.worldScale);
        polygonFixture.shape = polygonShape;
        polygonFixture.density = 1;
        polygonFixture.restitution = 0.5;
        polygonFixture.friction = 0.9;

        var brickBodyDef: b2BodyDef = new b2BodyDef();
        //brickBodyDef.type=b2Body.b2_dynamicBody;
        brickBodyDef.userData = bric;
        brickBodyDef.position.Set(pX / worldVar.worldScale, pY / worldVar.worldScale);

        var brickBody: b2Body = worldVar.createWorld.CreateBody(brickBodyDef);
        brickBody.CreateFixture(polygonFixture);
    }
}

经验法则是:DisplayObjects 从不将自己添加到显示列表,它们只会将其他 children 添加到自己。

这提供了一个严格的层次结构(像树一样),可以清楚地显示如何添加谁以及如何显示。当然,这条经验法则并不适用于所有情况,但在大多数情况下,在这种基本情况下,它应该可以正常工作。


but now I 'm stuck with no box2d physics applied to the bricks though all the collisions working perfectly for the bird on the same stage

问题是每个单独的元素都会创建 world class 的一个新实例。我不知道这个 class 在做什么,因为 box2d 的世界 class 实际上被命名为 b2World。我想你根据 Level1:

中的这一行为 b2World class 创建了某种包装器 class
worldVar.createWorld.CreateBody(brickbodyDef);

但是到目前为止我所看到的所有涉及的 class 都创建了他们自己的实例 class:

public var worldVar:world = new world();

上面这行在birdMCLevel1中都可以找到。所以他们生活在自己的世界里,彼此分开。

问题核心同your other question你需要一个世界object来创建身体。 这与 As3 非常不同,您可以在 As3 中创建 object 然后再决定要将其添加到的位置。

一个解决方案是将世界作为参数传递给每个构造函数。就像你之前用 stage 做的那样。这将允许您创建一个单一的世界并将其传递给所有构造函数,这些构造函数又在同一个世界上创建它们的 box2d body objects。