title: Libgdx - touchDown/touchUp vs. Gdx.input.isKeyPressed/Gdx.input.isKeyJustPressed
body: <p>Here is my dilemma. I am having problems animating my lightning attack by using my GamePad class (I made this class for a game controller for android devices). </p>
  
  <p>I found out that if using the Gdx.input.isKeyPressed(keyname), the code produces a lightning attack every frame, which stack on top of each other. So, I then used the Gdx.input.isKeyJustPressed() and it only creates one attack, that is animated, which is perfect.</p>
  
  <p>So when making the GamePad class, I made images with listeners to handle touch events. For each button I have a touchDown and touchUp method. When running my character from left to right, these touch events work fine. However, similar to Gdx.input.isKeyPressed(), the lightning attack is created each frame and the attacks get layered on top of each other. I tried a workaround to fix the creation of an attack each frame, and now the image is just static, and does not animate. This is better than the 60 fps, but doesn't solve my problem.</p>
  
  <p>is there a touchDown event similar to Gdx.input.isKeyJustPressed()? How could I fix the GamePad class to work similarly to the Config class?</p>
  
  <p>GamePad.java</p>
  
  <pre><code>public class GamePad implements Disposable{
  
  private Viewport viewport;
  public Stage stage;
  boolean leftPressed, rightPressed, pausePressed, aPressed, bReleased, bPressed, bPreviouslyPressed;
  private Config config = Config.getInstance();
  private Table table;
  
  public GamePad(){
      viewport = new FitViewport(EIUGame.V_WIDTH, EIUGame.V_HEIGHT, new OrthographicCamera());
      stage = new Stage(viewport);
  
      table = new Table();
      table.setFillParent(true);
      table.bottom();
  
      bPreviouslyPressed = false;
  
      // "Left" Button
      Image leftImg = new Image(new Texture("controller/leftButton.png"));
      leftImg.setSize(35, 35);
      leftImg.addListener(new InputListener(){
  
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
              leftPressed = true;
              return true;
          }
  
  
          @Override
          public void touchUp(InputEvent event, float x, float y, int pointer, int button){
              leftPressed = false;
          }
      });
  
      // "Right" Button
      Image rightImg = new Image(new Texture("controller/rightButton.png"));
      rightImg.setSize(35, 35);
      rightImg.addListener(new InputListener(){
  
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
              rightPressed = true;
              return true;
          }
  
          @Override
          public void touchUp(InputEvent event, float x, float y, int pointer, int button){
              rightPressed = false;
          }
      });
  
      // "Pause" Button
      Image pauseImg = new Image(new Texture("controller/pauseButton.png"));
      pauseImg.setSize(15, 15);
      pauseImg.addListener(new InputListener(){
  
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
              pausePressed = true;
              return true;
          }
  
          @Override
          public void touchUp(InputEvent event, float x, float y, int pointer, int button){
              pausePressed = false;
          }
      });
  
      // "A" Button
      Image aImg = new Image(new Texture("controller/aButton.png"));
      aImg.setSize(35, 35);
      aImg.addListener(new InputListener(){
  
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
              aPressed = true;
              return true;
          }
  
          @Override
          public void touchUp(InputEvent event, float x, float y, int pointer, int button){
              aPressed = false;
          }
      });
  
      // "B" Button
      Image bImg = new Image(new Texture("controller/bButton.png"));
      bImg.setSize(35, 35);
      bImg.addListener(new InputListener(){
  
          @Override
          public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
              bPressed = true;
              setBReleased(false);
              return true;
          }
  
          @Override
          public void touchUp(InputEvent event, float x, float y, int pointer, int button){
              setBReleased(true);
              bPreviouslyPressed = false;
              bPressed = false;
          }
      });
  
      table.add(leftImg).size(leftImg.getWidth(), leftImg.getHeight());
      table.add().size(5,35);
      table.add(rightImg).size(rightImg.getWidth(), rightImg.getHeight());
      table.add().size(100, 35);
      table.add(pauseImg).size(pauseImg.getWidth(), pauseImg.getHeight()).bottom();
      table.add().size(100, 35);
      table.add(bImg).size(bImg.getWidth(), bImg.getHeight());
      table.add().size(5,35);
      table.add(aImg).size(aImg.getWidth(), aImg.getHeight());
  
      stage.addActor(table);
  }
  
  // Returns the stage object so that it can be added to a multiplexer
  public Stage getStage() {
      return stage;
  }
  
  public void draw(){
      stage.draw();
  }
  
  public boolean isLeftPressed(){
      return leftPressed;
  }
  
  public boolean isRightPressed(){
      return rightPressed;
  }
  
  public boolean isPausePressed(){
      return pausePressed;
  }
  
  public boolean isAPressed(){
      return aPressed;
  }
  
  public boolean isBPressed(){
      return bPressed;
  }
  
  public boolean isBPreviouslyPressed(){
      return bPreviouslyPressed;
  }
  
  public boolean isBReleased(){
      return bReleased;
  }
  
  public void setBReleased(boolean released){
      bReleased = released;
  }
  
  public void resize(int width, int height){
      viewport.update(width, height);
  }
  
  public void animateChamp(Champion champ, PauseState pause){
      // Move Champion Right
      if (isRightPressed() &amp;&amp; champ.b2body.getLinearVelocity().x &lt;= 2)
          config.runRight(champ);
      // Move Champion left
      if (isLeftPressed() &amp;&amp; champ.b2body.getLinearVelocity().x &gt;= -2)
          config.runLeft(champ);
      // If A button is pressed and we are not jumping or falling, then Jump.
      if (isAPressed() &amp;&amp; (champ.getState() != champState.JUMPING &amp;&amp; champ.getState() != champState.FALLING)){
          config.jump(champ);
          aPressed = false;
      }
      // Toggle Pause Menu
      if (isPausePressed())
          pause.togglePause();
  
      // Precondition for next else-if statement
      if (isBPressed() &amp;&amp; champ.b2body.getLinearVelocity().x == 0 &amp;&amp; champ.b2body.getLinearVelocity().y == 0){
          bPressed = false;
          bPreviouslyPressed = true;
      }
      // If b was pressed down but not released, and champion is not moving, use lightning attack
      else if (bPreviouslyPressed &amp;&amp; !isBReleased() &amp;&amp; champ.b2body.getLinearVelocity().x == 0 &amp;&amp; champ.b2body.getLinearVelocity().y == 0){
          champ.setMobileTrigger(true);        // Sets champion state to attacking region
          config.setMLightningActive(true);
          config.lightningAttack(champ);
      }
      // Exit lightning attack if moved
      else if (!isBReleased() &amp;&amp; (champ.b2body.getLinearVelocity().x != 0 || champ.b2body.getLinearVelocity().y != 0)){
          champ.setMobileTrigger(false);
          config.setMLightningActive(false);
          bReleased = true;
      }
      // Exit lightning attack if button released
      else if (isBReleased() &amp;&amp; config.getMLightningActive()){
          champ.setMobileTrigger(false);         // Does not alter champion state
          config.setMLightningActive(false);
          bReleased = true;
      }
      // Attack when moving
      else if (isBPressed()){
          config.attack(champ);
          bPressed = false;
      }
  
  }
  
  @Override
  public void dispose(){
      stage.dispose();
  }
  }
  </code></pre>
  
  <p>Config.java</p>
  
  <pre><code>public final class Config {
  private static final Config instance = new Config();
  
  private int moveLeft;   
  private int moveRight;      
  private int jump;
  private int attack;
  private String lStr;
  private String rStr;
  private String jStr;
  private String aStr;
  private boolean lightningActive = false;
  private boolean MlightningActive = false;   // Mobile Game
  
  // Default constructor sets the keys to a default schema
  private Config() {
      moveLeft = Input.Keys.A;    
      moveRight = Input.Keys.D;       
      jump = Input.Keys.L;
      attack = Input.Keys.J;
      lStr = "A";
      rStr = "D";
      jStr = "L";
      aStr = "J";
  }
  
  // Return the instance of the class
  public static Config getInstance() {
      return instance;
  }
  
  public void animateChamp(Champion champ){
  
      // Jump!
      if(Gdx.input.isKeyJustPressed(jump) &amp;&amp; (champ.getState() != champState.JUMPING &amp;&amp; champ.getState() != champState.FALLING))
          jump(champ);
  
      // Run Right (and make sure character is not moving faster than 2)
      if(Gdx.input.isKeyPressed(moveRight) &amp;&amp; champ.b2body.getLinearVelocity().x &lt;= 2)
          runRight(champ);
  
      // Run Left (and make sure character is not moving faster than 2)
      if(Gdx.input.isKeyPressed(moveLeft) &amp;&amp; champ.b2body.getLinearVelocity().x &gt;= -2)
          runLeft(champ);     
  
      // Lightning Attack
      if(Gdx.input.isKeyJustPressed(attack) &amp;&amp; champ.b2body.getLinearVelocity().x == 0 &amp;&amp; champ.b2body.getLinearVelocity().y == 0){
          setLightningActive(true);
          lightningAttack(champ);         
      }
      else if (getlightningActive() &amp;&amp; (champ.b2body.getLinearVelocity().x != 0 || champ.b2body.getLinearVelocity().y != 0 || !Gdx.input.isKeyPressed(attack)))
          setLightningActive(false);
  
      else if (Gdx.input.isKeyJustPressed(attack))
          attack(champ);
  }
  
  public void runRight(Champion champ){
      champ.b2body.applyLinearImpulse(new Vector2(0.1f,0), champ.b2body.getWorldCenter(), true);
  }
  
  public void runLeft(Champion champ){
      champ.b2body.applyLinearImpulse(new Vector2(-0.1f,0), champ.b2body.getWorldCenter(), true);
  }
  
  public void jump(Champion champ){
      champ.b2body.applyLinearImpulse(new Vector2(0, 4.5f), champ.b2body.getWorldCenter(), true);
  }
  
  public void attack(Champion champ){
      champ.attack();
  }
  
  public void lightningAttack(Champion champ){
      champ.lightningAttack();
  }
  
  public boolean getlightningActive(){
      return lightningActive;
  }
  
  public void setLightningActive(boolean value){
      lightningActive = value;
  }
  
  // For Mobile Version
  public boolean getMLightningActive(){
      return MlightningActive;
  }
  
  // For Mobile Version
  public void setMLightningActive(boolean value){
      MlightningActive = value;
  }
  
  // sets the key to move left
  public void setMoveLeft(String n){
      moveLeft = Input.Keys.valueOf(n.toUpperCase());
      lStr = n;
  }
  
  // sets the key to move right
  public void setMoveRight(String n) {
      moveRight = Input.Keys.valueOf(n.toUpperCase());
      rStr = n;
  }
  
  // sets the key to jump
  public void setJump(String n) {
      jump = Input.Keys.valueOf(n.toUpperCase());
      jStr = n;
  }
  
  // sets the key to attack
  public void setAttack(String n) {
      attack = Input.Keys.valueOf(n.toUpperCase());
      aStr = n;
  }
  
  // Returns the string representation of the move left key
  public String getMoveLeft(){
      return lStr;
  }
  
  // Returns the string representation of the move right key
  public String getMoveRight() {
      return rStr;
  }
  
  // Returns the string representation of the jump key
  public String getJump() {
      return jStr;
  }
  
  // Returns the string representation of the attack key
  public String getAttack() {
      return aStr;
  }
  
  // Returns the int representation of the attack key
  public int getAttackInt(){
      return attack;
  }
  }
  </code></pre>