0
\$\begingroup\$

So here is my problem. I created an enemy class which extends Sprite in libGDX with a Box2d body in it for collision detection. My code calls the enemy class dynamically within the game in a loop, but the problem is that when after collision I use a different animation sequence to depict a defeated enemy, the animation sequence shows different frame rates for different instances of the same classor just jumps to the last frame. I don't know why that is happening.

Here is the class that is called in a loop.

public class Spearman extends Enemies {
    private Body spearman1;
    private TextureAtlas atlas;
    private Animation approaching,defeated;
    private float time;
    private TextureRegion spearmaninit;

    private int spearmanstate=0;


    public Spearman(Play_State state,float x, float y){
        super(state,x,y);
        atlas=new TextureAtlas();
        atlas=Lone_Warrior1.getAtlas(3);
        time=0f;

        Array<TextureRegion> frames=new Array<TextureRegion>();
        for(int i=0;i<3;i++)
        {
            frames.add(new TextureRegion(atlas.findRegion("Spearman"+i)));
        }
        approaching=new Animation(0.15f,frames);
        frames.clear();
        for(int i=0;i<5;i++)
        {
         frames.add(new                         TextureRegion(atlas.findRegion("Spearmandefeated"+i)));
        }
        defeated=new Animation(2.2f,frames);
        frames.clear();
        spearmaninit=new TextureRegion(atlas.findRegion("Spearman0"));
        setBounds(getX(),getY(),200/ Lone_Warrior1.PPM,170/Lone_Warrior1.PPM);
        setRegion(spearmaninit);

    }

    public void update(float dt){

        if(spearmanstate!=-1) {
            setPosition(spearman1.getPosition().x - getWidth() / 2,        (spearman1.getPosition().y - getHeight() / 2)+13/Lone_Warrior1.PPM);
            if (spearmanstate==0 && spearman1.getLinearVelocity().x>0)
                spearmanstate=1;
            if (spearmanstate==1 && spearman1.getLinearVelocity().x==0) {
                Play_State.bodiesToRemove.add(spearman1);
                Play_State.enemycounter++;
                spearmanstate = -1;

            }
            if(spearmanstate==0)
                spearman1.setLinearVelocity(-2f,0);
            setRegion(getFrame(dt));
        }
    }
    public boolean check(){
        if(spearmanstate!=-1)
             return true;
    else
        return false;
    }
    public TextureRegion getFrame(float dt){
        TextureRegion region=null;
        region=approaching.getKeyFrame(time,true);
        if(spearmanstate==1)
           region=defeated.getKeyFrame(time);
       /* if(!region.isFlipX())
        region.flip(true,false);*/
        time=time+dt;
        return region;

    }

    @Override
    public void defineEnemy() {
        BodyDef bdef=new BodyDef();
        bdef.position.set(getX(),getY());
        bdef.type=BodyDef.BodyType.DynamicBody;
        spearman1=Play_State.world.createBody(bdef);

        FixtureDef fdef=new FixtureDef();
        PolygonShape War1=new PolygonShape();
        War1.setAsBox(60/Lone_Warrior1.PPM,60/Lone_Warrior1.PPM);

        fdef.shape=War1;
        fdef.filter.categoryBits=Lone_Warrior1.BIT_APPROACHING;
               fdef.filter.maskBits=Lone_Warrior1.BIT_GROUND|Lone_Warrior1.BIT_RUN|Lone_Warrior      1.BIT_ATTACK;
        spearman1.createFixture(fdef).setUserData("spearman1");

    }

    }

The abstract class that calls the Spearman:

    public abstract class Enemies extends Sprite {
    World world;
    Body b2body;
    public Enemies(){

    }
    public Enemies(Play_State screen,float x, float y){
        this.world=screen.world;
        setPosition(x,y);
        defineEnemy();
    }

    public abstract void defineEnemy();
    public abstract void update(float dt);
    public abstract boolean check();
}

Here is the code that calls the class.

 switch (a) {
                case 1:
                    System.out.println("creating spearman");
                    spearman.add(new Spearman(screen, (Lone_Warrior1.V_Width /Lone_Warrior1.PPM) + (Lone_Warrior1.x+``(i*500/Lone_Warrior1.PPM)), 100 /       Lone_Warrior1.PPM));
                    break;
                   }

Here is the collision detection and things that are done on collision in the contact listener class:

 if(fb.getUserData()!=null&&fb.getUserData().equals("spearman1")){
            System.out.println("spearman attacked");
            if(fa.getUserData()!=null&&fa.getUserData().equals("warriorhighkick")){
                System.out.println("spearman lost!");
                //Spawner.berserkers.get(0).berserker1.applyForceToCenter(300,100,true);
                fb.getBody().applyForceToCenter(300,100,true);
            }
            else{
                System.out.println("spearman wins");
                //fa.getBody().applyForceToCenter(-300,0,true);
                if(!fa.getUserData().equals("Ground")&&!fa.getUserData().equals("spearman1")){
                Play_State.bodiesToRemove.add(fa.getBody());
                    Warrior.posture=-1;}
            }
        }
\$\endgroup\$
  • \$\begingroup\$ Is all of this information relevant to the question? For example, do we need to know the collision detection code to solve the problem? \$\endgroup\$ – Charanor Mar 26 '17 at 18:18
  • \$\begingroup\$ I really don't know where actually the problem is coming from...the contact listener I think is called in between the step counters of box2d world..so that might be something that messes up the animation...I just posted all the information that might be relevant.. \$\endgroup\$ – noobprogrammer Mar 26 '17 at 18:21
  • \$\begingroup\$ Alrighty just wanted to double check. I'll take a better glance when I get home. \$\endgroup\$ – Charanor Mar 26 '17 at 18:28
0
\$\begingroup\$

Solved!

Yes, the Sprite class is a little troublesome for frame by frame animation but I had already done much of my code and needed to find a patch job for this problem instead of having to rewrite the entire code.

So here is the answer:

 time=currentState==previousState ? time+dt : 0;
    previousState=currentState;

Whenever you update the time using delta time in the update method, make sure to check if the current animation sequence is equal to the previous one, if not then make time zero, then after collision the next animation would play out in the intended sequence.Just put a tracker for the state you are in.

int State=1://the default form for player
    State=2;//the state of animation when the player is hit`
`    currentState=State;
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.