0
\$\begingroup\$

I'm making a simple 2D game for android using LibGDX. My game needs to have many buttons in it that fire off a method when pressed, and I was wondering what the best way to do this would be.

I tried a simple solution using an InputProcessor and a bunch of if statements but it seems really unscalable and inefficient. Here's my attempt:

InputProcessor inputProcessor = new InputProcessor() {
        @Override
        public boolean keyDown(int keycode) {
            return false;
        }

        @Override
        public boolean keyUp(int keycode) {
            return false;
        }

        @Override
        public boolean keyTyped(char character) {
            return false;
        }

        @Override
        public boolean touchDown(int screenX, int screenY, int pointer, int button) {
          //  message = "Touch down: " + screenX + ", " + screenY;
            if (screenY >= 2280) {
                if(screenX >= 31 && screenX <= 281) {
                    yellowButtonPressed = true;
                } else if(screenX >= 313 && screenX <= 563) {
                    redButtonPressed = true;
                } else if(screenX >= 595 && screenX <= 845) {
                    blueButtonPressed = true;
                } else if(screenX >= 877 && screenX <= 1127) {
                    greenButtonPressed = true;
                } else if(screenX >= 1159 && screenX <= 1409) {
                    orangeButtonPressed = true;
                } else {
                    //regular click
                    if (monster.isAlive()) {
                        monster.takeDamage(1);
                    }
                }


            } else if(screenY <= 1690 && screenY >= 1510 && screenX <= 1430 && screenX >= 1280) {
                    xPressed = true;

            } else {

                    //regular click
                    if (monster.isAlive()) {
                        monster.takeDamage(1);
                    }

                }

            return true;
        }

        @Override
        public boolean touchUp(int screenX, int screenY, int pointer, int button) {
     //       message = "Touch up: " + screenX + ", " + screenY;
            if(yellowButtonPressed) {
                if(screenX >= 31 && screenX <= 281) {
                    xButton.show();
                    menuShown = true;
                    tempCurrentMenu = "Heroes";
                }
                yellowButtonPressed = false;
            } else if(redButtonPressed) {
                if(screenX >= 313 && screenX <= 563) {
                    xButton.show();
                    menuShown = true;
                    tempCurrentMenu = "Fighters";
                }
                redButtonPressed = false;
            } else if(blueButtonPressed) {
                if(screenX >= 595 && screenX <= 845) {
                    xButton.show();
                    menuShown = true;
                    tempCurrentMenu = "Researchers";
                }
                blueButtonPressed = false;
            } else if(greenButtonPressed) {
                if(screenX >= 877 && screenX <= 1127) {
                    xButton.show();
                    menuShown = true;
                    tempCurrentMenu = "Artifacts";
                }
                greenButtonPressed = false;
            } else if(orangeButtonPressed) {
                if(screenX >= 1159 && screenX <= 1409) {
                    xButton.show();
                    menuShown = true;
                    tempCurrentMenu = "Purchases";
                }
                orangeButtonPressed = false;
            } else if(xPressed) {
                if(screenY <= 1690 && screenY >= 1510 && screenX <= 1430 && screenX >= 1280) {
                    menuShown = false;
                    xButton.hide();
                    tempCurrentMenu = "";
                }
                xPressed = false;
            }
            return true;
        }

        @Override
        public boolean touchDragged(int screenX, int screenY, int pointer) {
            return false;
        }

        @Override
        public boolean mouseMoved(int screenX, int screenY) {
            return false;
        }

        @Override
        public boolean scrolled(int amount) {
            return false;
        }
    };

Is there a better way to do this?

\$\endgroup\$
0
\$\begingroup\$

A much better option is to create a small class (or reuse a suitable one like Rectangle) and keep them in a list, the code becomes simpler and it will be easy to add more buttons over time.

InputProcessor inputProcessor = new InputProcessor() {

  private final static List<Button> buttons = ...
  private Button lastButton = null;

  abstract class Button {
    public final int top, left, bottom, right;
    public boolean isHit(int x, int y) {
      return top <= y && bottom >= y && left <= x && right >= x;
    }
    public void doClick() {}
    public boolean performDrag() { return false; }
  }

  public boolean touchDown(int screenX, int screenY, int pointer, int button) {
    for (Button b : buttons) {
      if (b.isHit(screenX, screenY) {
        b.doClick();
        lastButton = b;
        return true;
      }
    }
    // No button was clicked, perform other checks
  }
  public boolean touchUp(int screenX, int screenY, int pointer, int button) {
    if (lastButton.performDrag(screenX, screenY)) {
      lastButton = null;
      return true;
    }
    lastButton = null;
    // Button didn't accept the drag gesture, check other things
  }
}

As you can see Button has doClick and performDrag that can be overridden in the classes for each specific button, as an example for your yellow button

class YellowButton extends Button {
  @override
  public boolean performDrag() {
    if(screenX < 31 || screenX > 281)
      return false;

    xButton.show();
    menuShown = true;
    tempCurrentMenu = "Heroes";
    return true;          
  }
}

Another thing is that you could implement doClick as boolean doClick(x,y) instead of having an isHit function to check with first, in the same way as the performDrag function works, whichever way you feel more comfortable with. In this case I made it two functions mostly because then you don't need to implement the coordinate checkup in your specific button classes.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks! This was really helpful. I had one more question, what is the point of returning true or false in all of the input methods? \$\endgroup\$ – mongy910 Mar 5 '15 at 21:15
  • \$\begingroup\$ @mongy910 You mean in touchUp/-Down? It's to signal that your application knew what the gesture meant and made use of it, I'm afraid I don't know exactly why this is necessary in this situation, but usually it's to prevent other controls from receiving the input; parent containers, or possibly even iOs itself. \$\endgroup\$ – Daniel Carlsson Mar 6 '15 at 14:43

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.