CharacterControl move problem

I don’t have a good way to use CharacterControl and animation Cooperate with

The first thing that came to mind

Use onAnalog for control
Because the onAnalog is continuous so I can see if I’m still holding W move when I’m done

But I can’t detect it if I press W when I’m using the attack animation because

        if (FORWARD.equals(name) && !CAS.getCurrentAnimation().equals("sk1")) {     
            System.err.println("w");
            CAS.up = true;//To control the animation
            up = true;//contro mobile
        }else{
        up = false;
        }

I set the button to be invalid when playing the attack animation
I can’t find a good solution for the coordination of movement and animation.
If anyone knows this part of the knowledge Please tell me Thank you very much

video
This video shows the problem with key sequence

I press the left mouse button first to attack, but pressing W does not produce the correct effect

Usually, you do not want to let the characterControl move while an attack animation is playing, unless the attack animation is playing on only the upper body.

But if you want to allow the characterControl to move while playing the “sk1” attack animation then it is simply a matter of splitting up your if statements, which would be considered a more basic java question.

        if (FORWARD.equals(name)) {     
            System.err.println("w");

            if(!CAS.getCurrentAnimation().equals("sk1")){
                  CAS.up = true;//To control the animation
            }
            
            up = true;//contro mobile
        }else{
              up = false;
        }

However, this type of code will become much more complex and, if not handled in an organized and skillful manner, can get very messy as you introduce more attack animations and as your game becomes more complex. So it may be worthwhile studying or practicing more about nested if-statements and conditional logic, so that finding solutions to problems like this will feel more natural to you.

1 Like

It’s logically messy and complicated
I’m trying to describe my problem
Because it’s hard to explain when it comes to logic
The code you just mentioned is still problematic

        if (FORWARD.equals(name)) {     //If this is not controlled, the attack will be pressed and the W will be moved again
            System.err.println("w");

            if(!CAS.getCurrentAnimation().equals("sk1")){
                  CAS.up = true;//To control the animation
            }
            
            up = true;//contro mobile
        }else{
              up = false;
        }

I might need some basic knowledge of the game button controls :thinking:

It is possible that your line of code calling up = false is being called from some other input on the same frame, and is overwriting the true value.

Maybe try adding a System.out.println() call to where you set up = false to see if it that code is being called when you are not expecting it.

        }else{
              up = false;
            System.out.println(" up just set to false!");
        }

If the “up” boolean is what determines if the characterControl moves forward, then the only reason for the characterControl to not move would be if “up” is somehow being set false when you expect it to be true.

Using onAnalog for this is actually wrong I think. The way you had it before in the other thread where you used “onAction()” and set “up” to the isPressed boolean is the better way to do movement like this. Using onAnalog might be causing you trouble.

1 Like

You’ve given me a good idea and I need to calm down and reconsider :kissing_heart:

2 Likes

After a struggle I found the right question

public class CustomAnimationStateManager {
     private AnimComposer animComposer;
   public String currentAnimation = null;
   public boolean left = false, right = false, up = false, down = false;
   public String getCurrentAnimation(){ return currentAnimation; }

   public CustomAnimationStateManager(AnimComposer animComposer){
           this.animComposer = animComposer;
   }
   
   public void playAnimation(String animationString, float speed){
          this.currentAnimation = animationString;
         //code to play your animation here: 
          animComposer.setCurrentAction(animationString);
          animComposer.setGlobalSpeed(speed);
     //can add more code here in the future to determine if the animation should play any doneTweens or if it is a looping or non looping animation
   }

    /**
     *
     * @param animationString
     * @param speed
     */
    public void playOneAnimation(String animationString, float speed){
          this.currentAnimation = animationString;
         //code to play your animation here: 
           Action action = animComposer.action(animationString);
            Tween doneTween = Tweens.callMethod(this, "stopCurrentAnim");
         //  Tween doneTween = Tweens.callMethod(animComposer, "setCurrentAction", animationTransitionString);
           Action actionOnce = animComposer.actionSequence(animationString+"Once", action, doneTween);               
          animComposer.setCurrentAction(animationString+"Once");               
          animComposer.setGlobalSpeed(speed);
     //can add more code here in the future to determine if the animation should play any doneTweens or if it is a looping or non looping animation
    }
    public void stopCurrentAnim(){
        if(up){
            animComposer.removeCurrentAction();
            animComposer.setCurrentAction("Walk"); 
            currentAnimation = "Walk";
        }else{
            animComposer.removeCurrentAction();
            animComposer.setCurrentAction("Stand"); 
            currentAnimation = "Stand";
        }

    }
}
//CAS is CustomAnimationStateManager
 if (BUTTON_LEFT.equals(name)&& isPressed && !CAS.getCurrentAnimation().equals("sk1")) {
                System.err.println("鼠标左键按下");

              CAS.playOneAnimation("sk1", 0.8f);
                
                up = false;
        }else  if (FORWARD.equals(name)) {
                
         if (isPressed&& !CAS.getCurrentAnimation().equals("sk1")) {
             System.err.println("按下w");
             CAS.playAnimation("Walk", 1f);          
             CAS.up = true;
                up = true;
      } else if(!isPressed&& !CAS.getCurrentAnimation().equals("sk1")) {
                System.err.println("弹起w");
               CAS.playAnimation("Stand", 1f);
               CAS.playAnimation("Stand", 1f);
               up = false;
               CAS.up = false;
      }
             

        }
     CAS.playOneAnimation("sk1", 0.8f);
      up = false;

Here, the attack will set UP to false to stop progress
If I press W during an attack I won’t be able to move forward after the attack animation finishes.
I can’t make “up=true” after the attack animation.
StopCurrentAnim () is used to determine if the animation has ended but cannot affect the Up Boolean
(Any guidance or advice)
(Thank you in advance :kissing_heart:

I looked through your code but I don’t see anything incorrect that stands out to me.

I think it could help if you posted the rest of the code for the class that contains the action listener, and maybe there could be something there that’s causing it that’s going overlooked.

The only other thing I can think of is to mention that it is slightly confusing how both of your classes have booleans identically named “up” and that made it slightly more difficult to tell what is going on and could be a likely source of confusion that makes it easier for the source of the problem to elude you.

also maybe try adding another else{ } block after your last if statement to check the state of all your variables whenever your other if statements you that you expect to be triggered are potentially getting passed over.

Whenever this last else{ gets triggered, you might find the variables have unexpected values and that might help you determine the cause of the problem

....
...
....
}
else if(!isPressed&& !CAS.getCurrentAnimation().equals("sk1")) {
                System.err.println("弹起w");
               CAS.playAnimation("Stand", 1f);
               CAS.playAnimation("Stand", 1f);
               up = false;
               CAS.up = false;
      }
      else{
           System.out.println(isPressed);
           System.out.println(CAS.getCurrentAnimation());
           System.out.println(CAS.up);
           System.out.println(up);

   }

For troubleshooting situations like this its always good to add System.out.printlns to print out the values of your important variables in as many useful places as possible, and that will almost always lead you towards the source of the problem.

I’ll put together a code list

code
Contains all the code
image
Most of the discussion is in the Role/ modelsyana.java file

381 line

 public void stopCurrentAnim(){
        if(up){
            animComposer.removeCurrentAction();
            animComposer.setCurrentAction("Walk"); 
            currentAnimation = "Walk";
        }else{
            animComposer.removeCurrentAction();
            animComposer.setCurrentAction("Stand"); 
            currentAnimation = "Stand";
        }

CustomAnimationStateManager class “Up” is used to limit animation playback

If you press W, then the “UP = True” SK1 animation will play the “Walk” animation after playing
If you release W, then the “UP = false” SK1 animation will play the “Stand” animation after playing

After a few hours of thinking about it, I think what I might need is to play the “SK1” animation
Determine whether the key W is pressed after the animation
But I’m using stopCurrentAnim() to determine if the animation is over and there’s no way to detect the button, okay
Any suggestions and tips:thinking:

hi~,yaRnMcDonuts
I’m glad to tell you that I succeeded…half
But the ideas you provide do most of the work :wink: :wink: :wink:

1 Like

That’s great! I’m always happy to help whenever I can :slightly_smiling_face:

1 Like

When logic starts to get complicated and deeply nested like this, a “finite state machine” is something that can greatly simplify the logic.

Might be worth reading about them.

Edit: and note that you don’t need any special library to implement them. Implementing a finite state machine is really easy. Could be done with an array of Runnables.

Edit 2: if anyone needs me to go into more detail then let me know and I’ll try to give a simple example.

2 Likes

This is a new knowledge and vocabulary for me :wink:

Well if people want a quick tutorial on making a simple finite state machine in Java then let me know. I think I could show a simple one with “walk”, “attack”, “jump” and it would make it pretty clear why nested if statements become really messy really quickly.

1 Like

Oh yes I need!!
I need a Finite State Machine tutorial
I was wondering how to use Finite State Machine in JME :pray: :pray: :pray: :pray:

public void onAction(String name, boolean isPressed, float tpf) {

   
        if (BUTTON_LEFT.equals(name) && isPressed && !CAS.getCurrentAnimation().equals("sk1")) {
            System.err.println("鼠标左键按下");

            CAS.playOneAnimation("sk1", 0.8f);

            up = false;
            CAS.up = false;
            down = false;
            CAS.down = false;
            left = false;
            CAS.left = false;
            right = false;
            CAS.right = false;
        } else if (DEBUG.equals(name) && isPressed) {

            System.err.println("按下F1");
            boolean debugEnabled = bulletAppState.isDebugEnabled();
            bulletAppState.setDebugEnabled(!debugEnabled);

        } else if (DEBUG1.equals(name) && isPressed) {
            System.err.println("按下F2");

            boolean debugEnabled = DACbulletAppState.isDebugEnabled();
            DACbulletAppState.setDebugEnabled(!debugEnabled);
        } else if (LEFT.equals(name)) {
            
            if (isPressed) {
                a=isPressed;
                if( !CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("按下 A ");
                CAS.playAnimation("Walk", 1f);
                }

                CAS.left = true;
//                up = true;
            } else if (!isPressed ) {
                a=isPressed;
                if(!down&&!up&&!right){
                if(!CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("弹起 A "+System.nanoTime());
                
                CAS.playAnimation("Stand", 1f);
      
                }
                }
                left = false;
                CAS.left = false;
            } 
            
        } else if (RIGHT.equals(name)) {
            
            if (isPressed) {
                d=isPressed;
                if( !CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("按下 D ");
                CAS.playAnimation("Walk", 1f);
                }

                CAS.right = true;
//                up = true;
            } else if (!isPressed ) {
                d=isPressed;
                if(!down&&!up&&!left){
                if(!CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("弹起 D "+System.nanoTime());
                
                CAS.playAnimation("Stand", 1f);
   
                }
                }
                right = false;
                CAS.right = false;
            } 
           
        } else if (FORWARD.equals(name)) {
            
            if (isPressed) {
                 w=isPressed;
                if( !CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("按下 W ");
                CAS.playAnimation("Walk", 1f);
                }

                CAS.up = true;
//                up = true;
            } else if (!isPressed ) {
                w=isPressed;
                if(!down&&!right&&!left){
                if(!CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("弹起 W "+System.nanoTime());
                CAS.playAnimation("Stand", 1f);
                }
                }
                up = false;
                CAS.up = false;
            } 
       
        } else if (BACKWARD.equals(name)) {
                
            if (isPressed) {
                s=isPressed;
                if( !CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("按下 s ");
                CAS.playAnimation("Walk", 1f);
                }

                CAS.down = true;
//                up = true;
            } else if (!isPressed ) {
                s=isPressed;
                if(!up&&!right&&!left){
                if(!CAS.getCurrentAnimation().equals("sk1")){
                System.err.println("弹起 s "+System.nanoTime());
                CAS.playAnimation("Stand", 1f);
                }
                }
                down = false;
                CAS.down = false;
            } 
        }
        }

It’s already very chaotic

Ok, I will try to put one together today.

1 Like