androidcoderookie
androidcoderookie

Reputation: 57

AndEngine animate and count score once, then ignore

I have an almost compete game on AndEngine. The only issue is animating a sprite on contact, counting the score once, then ignoring any further updates. When my player entity contacts the object, I can get AndEngine to count the score and animate, but then it keeps counting until the objects aren't touching. This is fixed with setIgnoreUpdates ();, but then it won't animate the object. Any ideas how to fix this?

This is my code so far:

private int score = 0;

AnimatedSprite wooden_crate = new AnimatedSprite(0, 0, resourceManager.wooden_crate_region, vbom);
private void animateCrate()
{
    final long[] CRATE_ANIMATE = new long[] {0, 25, 25, 25, 25, 15000};
    wooden_crate.animate(CRATE_ANIMATE, 0, 5, true);
}
private void addToScore(int i)
{
    score += i;
    scoreText.setText("Score: " + score);
}

private PhysicsWorld physicsWorld;

private void createPhysics()
{
    physicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0, -24), false); 
    physicsWorld.setContactListener(contactListener());
    registerUpdateHandler(physicsWorld);
}

private static final String TAG_ENTITY = "entity";
private static final String TAG_ENTITY_ATTRIBUTE_X = "x";
private static final String TAG_ENTITY_ATTRIBUTE_Y = "y";
private static final String TAG_ENTITY_ATTRIBUTE_TYPE = "type";

private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_FLOOR = "floor";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLAYER = "player";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_STEEL_CRATE = "steelCrate";
private static final Object TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_WOODEN_CRATE = "woodenCrate";

private Player player;

private void loadLevel(int levelID)
{
    final SimpleLevelLoader levelLoader = new SimpleLevelLoader(vbom);

    final FixtureDef FIXTURE_DEF = PhysicsFactory.createFixtureDef(0, 0.01f, 0.5f);

    levelLoader.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(LevelConstants.TAG_LEVEL)
    {
        public IEntity onLoadEntity(final String pEntityName, final IEntity pParent, final Attributes pAttributes, final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData) throws IOException 
        {
            final int width = SAXUtils.getIntAttributeOrThrow(pAttributes, LevelConstants.TAG_LEVEL_ATTRIBUTE_WIDTH);
            final int height = SAXUtils.getIntAttributeOrThrow(pAttributes, LevelConstants.TAG_LEVEL_ATTRIBUTE_HEIGHT);

            // TODO later we will specify camera BOUNDS and create invisible walls
            // on the beginning and on the end of the level.
            camera.setBounds(0, 0, width, height); // here we set camera bounds
            camera.setBoundsEnabled(true);

            return GameScene.this;
        }
    });

    levelLoader.registerEntityLoader(new EntityLoader<SimpleLevelEntityLoaderData>(TAG_ENTITY)
    {
        public IEntity onLoadEntity(final String pEntityName, final IEntity pParent, final Attributes pAttributes, final SimpleLevelEntityLoaderData pSimpleLevelEntityLoaderData) throws IOException
        {
            final int x = SAXUtils.getIntAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_X);
            final int y = SAXUtils.getIntAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_Y);
            final String type = SAXUtils.getAttributeOrThrow(pAttributes, TAG_ENTITY_ATTRIBUTE_TYPE);

            final Sprite levelObject;

            if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_FLOOR))
            {
                levelObject = new Sprite(x, y, resourceManager.platform1_region, vbom);
                PhysicsFactory.createBoxBody(physicsWorld, levelObject, BodyType.StaticBody, FIXTURE_DEF).setUserData("floor");
            }
            else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_STEEL_CRATE))
            {
                levelObject = new Sprite(x, y, resourceManager.steel_crate_region, vbom);
                PhysicsFactory.createBoxBody(physicsWorld, levelObject, BodyType.StaticBody, FIXTURE_DEF).setUserData("steelCrate");
            }
            else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_WOODEN_CRATE))
            {
                levelObject = new AnimatedSprite(x, y, resourceManager.wooden_crate_region, vbom)
                {
                    @Override
                    protected void onManagedUpdate(float pSecondsElapsed) 
                    {
                        super.onManagedUpdate(pSecondsElapsed);

                        if (player.collidesWith(this))
                        {
                            addToScore(1);
                            animateCrate();
                            setIgnoreUpdate(true);

                };}};
            }
            else if (type.equals(TAG_ENTITY_ATTRIBUTE_TYPE_VALUE_PLAYER))
            {
                player = new Player(x, y, vbom, camera, physicsWorld)
                {                       
                    @Override
                    public void onDie()
                    {
                        // TODO Latter we will handle it.
                        if (!gameOverDisplayed)
                        {
                            displayGameOverText();
                            this.setIgnoreUpdate(true);
                        }
                    }
                };
                levelObject = player;
            }
            else
            {
                throw new IllegalArgumentException();
            }

            levelObject.setCullingEnabled(true);

            return levelObject;
        }
    });

    levelLoader.loadLevelFromAsset(activity.getAssets(), "level/" + levelID + ".lvl");
}
private boolean firstTouch = false;

public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent)
{
    if (pSceneTouchEvent.isActionDown())
    {
        if (!firstTouch)
        {
            player.setRunning();
            firstTouch = true;
        }
        else
        {
            player.jump();
        }
    }
    return false;
}
private ContactListener contactListener()
{
    ContactListener contactListener = new ContactListener()
    {
        public void beginContact(Contact contact)
        {
            final Fixture x1 = contact.getFixtureA();
            final Fixture x2 = contact.getFixtureB();

            if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
            {
                if (x2.getBody().getUserData().equals("player"))
                {
                    player.increaseFootContacts();
                }
            }
        }

        public void endContact(Contact contact)
        {
            final Fixture x1 = contact.getFixtureA();
            final Fixture x2 = contact.getFixtureB();

            if (x1.getBody().getUserData() != null && x2.getBody().getUserData() != null)
            {
                if (x2.getBody().getUserData().equals("player"))
                {
                    player.decreaseFootContacts();
                }
                if (x1.getBody().getUserData().equals("steelCrate") && x2.getBody().getUserData().equals("player"))
                {
                    player.onDie();
                }
            }
        }

        public void preSolve(Contact contact, Manifold oldManifold)
        {

        }

        public void postSolve(Contact contact, ContactImpulse impulse)
        {

        }
    };
    return contactListener;
}

Note that I have added the animateCrate() method as a stab in the dark at another fix. Still only counting score then ignoring animation.

I have tried to implement the example in the first answer, but am not sure given the above code.

Upvotes: 0

Views: 106

Answers (1)

asherbret
asherbret

Reputation: 6038

How about this solution: Have a boolean flag which is set when contact occurs and reset when contact is finished. Something like this:

public class MyContactListener implements ContactListener {
    boolean mContactFlag;
    public MyContactListener() {
        mContactFlag = false;
    }

    @Override
    public void beginContact(Contact arg0) {
        if (mContactFlag){
            // Don't animate...
        }
        else{
            // Animate and add score...
            mContactFlag = true;
        }
    }

    @Override
    public void endContact(Contact arg0) {
        mContactFlag = false; // Reset the flag here        
    }

    @Override
    public void postSolve(Contact arg0, ContactImpulse arg1) {}

    @Override
    public void preSolve(Contact arg0, Manifold arg1) {}
}

Upvotes: 1

Related Questions