1

我们如何在andengine中创建一种方式的墙壁,即当一个身体从上到下落在墙上时,身体应该与墙壁发生碰撞,而当从下到上时,它会忽略碰撞并允许身体穿过墙壁?我研究了以下教程http://www.iforce2d.net/b2dtut/one-way-walls并尝试在 android 中实现此功能但无法正常工作。这是我到目前为止所做的:

public class JumpingBallActivity extends SimpleBaseGameActivity implements IOnSceneTouchListener, IAccelerationListener, ContactListener {

    private int CAMERA_WIDTH = 480;
    private int CAMERA_HEIGHT = 800;
    private BitmapTextureAtlas mBitmapTextureAtlas;
    private ITextureRegion smileyRegion;
    private Scene mScene;
    private Camera camera;
    private Sprite smileySprite;
    private Body smileyBody;
    private PhysicsWorld mPhysicsWorld;
    private Body slabWallBody;
    private FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(0.6f, 0.0f, 0.0f);
    final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(1, 0.0f, 0.0f);


    @Override
    public EngineOptions onCreateEngineOptions() {
        // TODO Auto-generated method stub

        camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

        return new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
    }

    @Override
    protected void onCreateResources() {
        // TODO Auto-generated method stub
        BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

        mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 84, 84, TextureOptions.BILINEAR);
        smileyRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mBitmapTextureAtlas, getAssets(), "smiley.png", 0, 0);
        mBitmapTextureAtlas.load();
        enableAccelerationSensor(this);

    }

    @Override
    protected Scene onCreateScene() {
        // TODO Auto-generated method stub
        this.mScene = new Scene();
        this.mScene.setBackground(new Background(0, 0, 0));
        this.mScene.setOnSceneTouchListener(this);
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, 15), false);


        final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
        Rectangle rect1 = new Rectangle((CAMERA_WIDTH/2) - 100, (CAMERA_HEIGHT/2) + 50, 200, 10, vertexBufferObjectManager);
        slabWallBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, rect1, BodyType.StaticBody, wallFixtureDef);
        slabWallBody.setUserData("slab");
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rect1, slabWallBody, false, false));


        smileySprite = new Sprite(smileyRegion.getWidth(), smileyRegion.getHeight(), smileyRegion, vertexBufferObjectManager);
        smileyBody = PhysicsFactory.createCircleBody(mPhysicsWorld, smileySprite,  BodyType.DynamicBody, FIXTURE_DEF);
        smileyBody.setUserData("smiley");
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(smileySprite, smileyBody, true, false));


        final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        final Rectangle roof = new Rectangle(0, 0, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
        final Rectangle right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);

        PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef).setUserData("wall");

        mScene.attachChild(smileySprite);
        mScene.attachChild(rect1);
        mScene.attachChild(right);
        mScene.attachChild(left);
        mScene.attachChild(roof);
        mScene.attachChild(ground);

        this.mScene.registerUpdateHandler(this.mPhysicsWorld);
        mPhysicsWorld.setContactListener(this);
        mScene.setOnSceneTouchListener(this);
        return mScene;
    }

    @Override
    public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
        // TODO Auto-generated method stub
        smileyBody.setLinearVelocity(0, -15);
        return false;
    }

    @Override
    public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onAccelerationChanged(AccelerationData pAccelerationData) {
        // TODO Auto-generated method stub
        final Vector2 gravity = Vector2Pool.obtain(0, 15);
        this.mPhysicsWorld.setGravity(gravity);

        Vector2Pool.recycle(gravity);

        smileyBody.setLinearVelocity(pAccelerationData.getX() * 2, smileyBody.getLinearVelocity().y);
    }

    @Override
    public void beginContact(Contact contact) {
        // TODO Auto-generated method stub
//      Log.d("begin contact", "begin contact");
//      Log.d("begin contact", smileyBody.getLinearVelocity().toString() + "");

        Fixture fixtureA = contact.getFixtureA();
        Fixture fixtureB = contact.getFixtureB();

        Fixture platFormFixture = null;
        Fixture ballFixture = null;
        // also could not understand whats going on here in the code coming forward
        if(fixtureA.getBody().getUserData().equals("slab") && fixtureB.getBody().getUserData().equals("smiley")) {
            platFormFixture = fixtureA;
            ballFixture = fixtureB;

        }

        if(fixtureA.getBody().getUserData().equals("smiley") && fixtureB.getBody().getUserData().equals("slab")) {
            platFormFixture = fixtureB;
            ballFixture = fixtureA;
        }


        if(platFormFixture == null) {
            return;
        }

        Body platFormBody = platFormFixture.getBody();
        Body ballBody = ballFixture.getBody();



        int numPoints = contact.getWorldManifold().getNumberOfContactPoints();
        WorldManifold worldManiFold = contact.getWorldManifold();

        for(int i = 0; i < numPoints; i++) {
            Vector2 vector2 = ballBody.getLinearVelocityFromWorldPoint(worldManiFold.getPoints()[i]);
            Vector2 vector3 = platFormBody.getLinearVelocityFromWorldPoint(worldManiFold.getPoints()[i]);
            Vector2 vector4 = platFormBody.getLocalVector(vector2.sub(vector3));
            if(vector4.y < -1) {
//              Log.d("collision ignored", "collision ignored");
                return;
            }
            else if(vector4.y < 1) {
                Vector2 localPoint = platFormBody.getLocalPoint(worldManiFold.getPoints()[i]);
                Log.d("local y", localPoint.y + "");
                float f = 1.1f;
                if(localPoint.y > f - 0.05f) {
                    return;
                }
            }
        }

        contact.setEnabled(false);



    }

    @Override
    public void endContact(Contact contact) {
        // TODO Auto-generated method stub
        contact.setEnabled(true);
//      Log.d("end contact", "end contact");
//      Log.d("end contact", smileyBody.getLinearVelocity().toString());
    }

    Vector2 v;

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {
        // TODO Auto-generated method stub
//      Log.d("presolve", "presolve");
//      Log.d("presolve", smileyBody.getLinearVelocity().toString());

    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {
        // TODO Auto-generated method stub
//      Log.d("postsolve", "postsolve");
//      Log.d("postsolve", smileyBody.getLinearVelocity().toString());
    }

}
4

3 回答 3

2

它之所以起作用,是因为:

  • contact.setEnabled(false);preSolve功能和
  • contact.setEnabled(true);endContact函数中。

这是有效的,因为如果联系人被禁用,联系人的效果将不会传输到您所涉及的对象。

于 2013-08-14T18:13:46.237 回答
0

我已经实现了所需的功能并在此处给出了解决方案代码。我不知道它是如何工作的,但它现在正在工作。

public class JumpingBallActivity extends SimpleBaseGameActivity implements IOnSceneTouchListener, IAccelerationListener, ContactListener {

    private int CAMERA_WIDTH = 480;
    private int CAMERA_HEIGHT = 800;
    private BitmapTextureAtlas mBitmapTextureAtlas;
    private ITextureRegion smileyRegion;
    private Scene mScene;
    private Camera camera;
    private Sprite smileySprite;
    private Body smileyBody;
    private PhysicsWorld mPhysicsWorld;
    private Body slabWallBody;
    private FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(0.6f, 0.0f, 0.0f);
    final FixtureDef wallFixtureDef = PhysicsFactory.createFixtureDef(1, 0.0f, 0.0f);


    @Override
    public EngineOptions onCreateEngineOptions() {
        // TODO Auto-generated method stub

        camera = new Camera(0, 0, CAMERA_WIDTH, CAMERA_HEIGHT);

        return new EngineOptions(true, ScreenOrientation.PORTRAIT_FIXED, new RatioResolutionPolicy(CAMERA_WIDTH, CAMERA_HEIGHT), camera);
    }

    @Override
    protected void onCreateResources() {
        // TODO Auto-generated method stub
        BitmapTextureAtlasTextureRegionFactory.setAssetBasePath("gfx/");

        mBitmapTextureAtlas = new BitmapTextureAtlas(this.getTextureManager(), 84, 84, TextureOptions.BILINEAR);
        smileyRegion = BitmapTextureAtlasTextureRegionFactory.createFromAsset(mBitmapTextureAtlas, getAssets(), "smiley.png", 0, 0);
        mBitmapTextureAtlas.load();
        enableAccelerationSensor(this);

    }

    @Override
    protected Scene onCreateScene() {
        // TODO Auto-generated method stub
        this.mScene = new Scene();
        this.mScene.setBackground(new Background(0, 0, 0));
        this.mScene.setOnSceneTouchListener(this);
        this.mPhysicsWorld = new PhysicsWorld(new Vector2(0, 15), false);


        final VertexBufferObjectManager vertexBufferObjectManager = this.getVertexBufferObjectManager();
        Rectangle rect1 = new Rectangle((CAMERA_WIDTH/2) - 100, (CAMERA_HEIGHT/2) + 50, 200, 10, vertexBufferObjectManager);
        slabWallBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld, rect1, BodyType.StaticBody, wallFixtureDef);
        slabWallBody.setUserData("slab");
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(rect1, slabWallBody, false, false));


        smileySprite = new Sprite(smileyRegion.getWidth(), smileyRegion.getHeight(), smileyRegion, vertexBufferObjectManager);
        smileyBody = PhysicsFactory.createCircleBody(mPhysicsWorld, smileySprite,  BodyType.DynamicBody, FIXTURE_DEF);
        smileyBody.setUserData("smiley");
        mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector(smileySprite, smileyBody, true, false));


        final Rectangle ground = new Rectangle(0, CAMERA_HEIGHT - 2, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        final Rectangle roof = new Rectangle(0, 0, CAMERA_WIDTH, 2, vertexBufferObjectManager);
        final Rectangle left = new Rectangle(0, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);
        final Rectangle right = new Rectangle(CAMERA_WIDTH - 2, 0, 2, CAMERA_HEIGHT, vertexBufferObjectManager);

        PhysicsFactory.createBoxBody(this.mPhysicsWorld, ground, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, roof, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, left, BodyType.StaticBody, wallFixtureDef).setUserData("wall");
        PhysicsFactory.createBoxBody(this.mPhysicsWorld, right, BodyType.StaticBody, wallFixtureDef).setUserData("wall");

        mScene.attachChild(smileySprite);
        mScene.attachChild(rect1);
        mScene.attachChild(right);
        mScene.attachChild(left);
        mScene.attachChild(roof);
        mScene.attachChild(ground);

        this.mScene.registerUpdateHandler(this.mPhysicsWorld);
        mPhysicsWorld.setContactListener(this);
        mScene.setOnSceneTouchListener(this);
        return mScene;
    }

    @Override
    public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
        // TODO Auto-generated method stub
        smileyBody.setLinearVelocity(0, -15);
        return false;
    }

    @Override
    public void onAccelerationAccuracyChanged(AccelerationData pAccelerationData) {
        // TODO Auto-generated method stub

    }

    @Override
    public void onAccelerationChanged(AccelerationData pAccelerationData) {
        // TODO Auto-generated method stub
        final Vector2 gravity = Vector2Pool.obtain(0, 15);
        this.mPhysicsWorld.setGravity(gravity);

        Vector2Pool.recycle(gravity);

        smileyBody.setLinearVelocity(pAccelerationData.getX() * 2, smileyBody.getLinearVelocity().y);
    }

    @Override
    public void beginContact(Contact contact) {
        // TODO Auto-generated method stub
//      Log.d("begin contact", "begin contact");
//      Log.d("begin contact", smileyBody.getLinearVelocity().toString() + "");

    }

    @Override
    public void endContact(Contact contact) {
        // TODO Auto-generated method stub
        contact.setEnabled(true);
//      Log.d("end contact", "end contact");
//      Log.d("end contact", smileyBody.getLinearVelocity().toString());
    }

    Vector2 v;

    @Override
    public void preSolve(Contact contact, Manifold oldManifold) {
        // TODO Auto-generated method stub
//      Log.d("presolve", "presolve");
//      Log.d("presolve", smileyBody.getLinearVelocity().toString());
        Fixture fixtureA = contact.getFixtureA();
        Fixture fixtureB = contact.getFixtureB();

        Fixture platFormFixture = null;
        Fixture ballFixture = null;

        if(fixtureA.getBody().getUserData().equals("slab") && fixtureB.getBody().getUserData().equals("smiley")) {
            platFormFixture = fixtureA;
            ballFixture = fixtureB;

        }

        if(fixtureA.getBody().getUserData().equals("smiley") && fixtureB.getBody().getUserData().equals("slab")) {
            platFormFixture = fixtureB;
            ballFixture = fixtureA;
        }


        if(platFormFixture == null) {
            return;
        }

        Body platFormBody = platFormFixture.getBody();
        Body ballBody = ballFixture.getBody();

        WorldManifold worldManiFold = contact.getWorldManifold();
        int numPoints = contact.getWorldManifold().getNumberOfContactPoints();
        for(int i = 0; i < numPoints; i++){
            Vector2 vector2 = ballBody.getLinearVelocityFromWorldPoint(worldManiFold.getPoints()[i]);
            if(vector2.y < 0) {
                contact.setEnabled(false);
            }
        }

//      WorldManifold worldManiFold = contact.getWorldManifold();
//      Vector2 normal = worldManiFold.getNormal();
//      
//      if(normal.y != -1) {
//          contact.setEnabled(false);
//      }
    }

    @Override
    public void postSolve(Contact contact, ContactImpulse impulse) {
        // TODO Auto-generated method stub
//      Log.d("postsolve", "postsolve");
//      Log.d("postsolve", smileyBody.getLinearVelocity().toString());
    }

}
于 2012-09-07T11:58:06.790 回答
0

您可能会在这里得到错误的比较:

if(fixtureA.getBody().getUserData().equals("slab") && fixtureB.getBody().getUserData().equals("smiley")) {
            platFormFixture = fixtureA;
            ballFixture = fixtureB;

        }

        if(fixtureA.getBody().getUserData().equals("smiley") && fixtureB.getBody().getUserData().equals("slab")) {
            platFormFixture = fixtureB;
            ballFixture = fixtureA;
        }

尝试这个:

    if(fixtureA == wallFixtureDef) {
        platFormFixture = fixtureA;
        ballFixture = fixtureB;

    }

    if(fixtureB ==wallFixtureDef ) {
        platFormFixture = fixtureB;
        ballFixture = fixtureA;
    }
于 2012-09-07T03:15:49.217 回答