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

ここで間違った比較が行われる可能性があります。

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 に答える
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 に答える