因未在AS3中显示的对象而丢失

时间:2015-08-07 16:02:25

标签: actionscript-3 box2d

我有一个课程,假设在舞台上创建砖块。每件事似乎工作正常,没有错误,我甚至可以看到创建的砖块对象和碰撞变量在调试器窗口中初始化但仍然没有出现在舞台上,任何帮助将非常感谢我花了几个小时来弄清楚我错过了但无济于事:(

这是代码

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);


    }


}
  

根据@null推荐,我确实对我的文档进行了更改   类

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物理应用到砖块上,尽管所有的碰撞都在同一个舞台上完美地为鸟类工作

  

以下是birdMC类的代码

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();

    }

}

}

  

这是世界级的我主要使用它来声明全局变量   并在b2世界中添加墙壁。

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);

1 个答案:

答案 0 :(得分:1)

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

  • 将对舞台的引用传递给DisplayObject 这几乎没有意义,因为每个DisplayObject都有它的 自己对.stage属性中的阶段的引用。为什么要创造呢 另一个类成员引用stage

    关于这个属性的特殊之处在于它只有null 对象不在显示列表中。只要对象是 添加后,stage将成为有效参考。如果是一个扩展的类 DisplayObject只需提及有效的stage即可 听取将要发送的Event.ADDED_TO_STAGE事件 只要添加了对象并且stage生效。

  • stage 添加任何内容,因为可以阅读in the documentation of addChild(),向stage添加内容是我不应该做的事情。
      

    因此,通常情况下,不应将对象直接添加到舞台上。

那很好。因为如果不应该向stage添加任何内容,则无需首先传递对stage的引用,从而解决了第一个问题。

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

在主时间轴上,你实例化一个Level1(可怕的类名btw!)对象并将其添加到显示列表中:

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

Level1 extends DisplayObjectContainer,这意味着可以添加内容。在您的情况下,该级别的所有砖块都应添加到该级别。该级别充当该级别所有内容的容器。

我修改了现有代码:

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永远不会将自己添加到显示列表中,只会将其他子项添加到自己。

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

  

但现在我仍然坚持没有将box2d物理应用到砖块上,尽管所有的碰撞都能在同一个舞台上完美地为鸟类工作

问题是每个单独的元素都会创建world类的新实例。我不知道这个班级在做什么,因为box2d的世界级实际上被命名为b2World。我想你为b2World类创建了某种包装类,按照Level1中的这一行:

worldVar.createWorld.CreateBody(brickbodyDef);

但到目前为止我所见过的所有相关课程都创建了自己的该类实例:

public var worldVar:world = new world();

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

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

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