Sneh의 반응은 모든 버튼에 대해 별도의 클래스를 만드는 대신 버튼을 만들 때마다 매번 좌표 및 act() 메소드를 지정하여 익명의 내부 클래스를 사용할 수있었습니다. 나는 이것을 할 수있는 가능한 더 짧은 방법으로 람다 문법을 탐구했지만 한계를 보았다. 필자는 유연한 솔루션으로 끝났지 만 결국 내 필요에 맞게 조금 줄였습니다. 두 가지 방법이 아래에 나와 있습니다.
내 게임의 각 게임 화면은 LibGDX의 Screen
을 확장하는 MyScreen
클래스의 하위 클래스이지만 크기 조정시 뷰포트 업데이트, 버튼의 HashMap 포함 등의 범용 기능이 추가되었습니다.MyScreen
클래스에 buttonPressed()
메서드를 추가했습니다.이 메서드는 하나의 매개 변수로 열거 형을 사용합니다. MAINMENU_PLAY, MAINMENU_MAPDESIGNER 등과 같은 가능한 모든 버튼을 포함하는 ButtonValues
enum을 가지고 있습니다. 각 게임 화면에서 buttonPressed()
는 오버라이드 (override)과 스위치가 올바른 작업을 수행하는 데 사용됩니다 :
public void buttonPressed(ButtonValues b) {
switch(b) {
case MAINMENU_PLAY:
beginGame();
case MAINMENU_MAPDESIGNER:
switchToMapDesigner();
}
}
을 다른 솔루션 대신 buttonPressed()
을 요구하는 자체에 대한 작업을 수행 할 수 있도록 버튼이 람다 식을 저장할 수있다 어떤 버튼을 눌렀는지에 따라 올바른 행동을 수행하는 중개자 역할을한다.
버튼을 추가하기 위해서는 그 좌표 입력 (ENUM)로 생성되고, 버튼의 HashMap의 첨가 :
Button b = new Button(this,
new Rectangle(300 - t.getRegionWidth()/2, 1.9f * 60, t.getRegionWidth(), t.getRegionHeight()),
tex, ButtonValues.MAINMENU_PLAY);
buttons.put("buttonPlay", b);
, 그냥 buttons.remove("buttonPlay").
을 제거하고,이 화면에서 사라지는 것 게임에 의해 잊혀 질 수 있습니다.
인수는 게임 화면에서 buttonPressed()
을 호출 할 수있는 게임 화면, 좌표가있는 직사각형, 그리기 위해 사용 된 텍스처 및 그 열거 형 값입니다. 이때 버튼 내에 포함되는지
public class Button {
public Rectangle r;
public TextureRegion image;
private MyScreen screen;
private ButtonValues b;
public Button(MyScreen screen, Rectangle r, TextureRegion image, ButtonValues b) {
this.screen = screen;
this.r = r;
this.image = image;
this.b = b;
}
public void act() {
screen.buttonPressed(b);
}
public boolean isClicked(float x, float y) {
return x > r.x && y > r.y && x < r.x + r.width && y < r.y + r.height;
}
}
isClicked()
방금 (x, y)를 입력 받아 확인 :
그리고 여기 버튼 클래스이다. 마우스 클릭시 모든 버튼을 반복하고 버튼 isClicked
인 경우 act()
으로 전화하십시오.
내가 한 두 번째 방법은 비슷했지만 ButtonValues 열거 형 대신 람다 식을 사용했습니다. Button 클래스도 비슷하지만 다음과 같은 변경 사항이 있습니다 (소리보다 훨씬 간단합니다).
필드가 생성자에서 제거되었습니다. 추가 된 setAction()
메서드는 Runnable
을 사용하고 전달 된 Runnable에 r
을 설정합니다. act()
방법은 단지 r.run()
입니다. 예 :
public class Button {
[Rectangle, Texture, Screen]
Runnable r;
public Button(screen, rectangle, texture) {...}
public void setAction(Runnable r) { this.r = r; }
public void act() { r.run(); }
}
가 나는 다음을 수행하십시오 버튼을 만들려면 :
Button b = new Button(this,
new Rectangle(300 - t.getRegionWidth()/2, 1.9f * 60, t.getRegionWidth(), t.getRegionHeight()),
tex);
b.setAction(() -> b.screen.doSomething());
buttons.put("buttonPlay", b);
는 첫째, 버튼의 포함 된 게임 화면 클래스의 경계 상자, 그 질감 생성됩니다. 그런 다음 두 번째 명령에서 해당 동작을 설정합니다 (이 경우 b.screen.doSomething();). 이 시점에서 b와 b.screen이 존재하지 않기 때문에 생성자에 전달할 수 없습니다. setAction()
은 Runnable
을 취해 act()
이 호출 될 때 호출되는 Button
의 Runnable로 설정합니다. 그러나 Runnable
은 람다 구문을 사용하여 만들 수 있으므로 익명의 Runnable
클래스를 만들 필요가 없으며 클래스가 수행하는 함수를 전달할 수 있습니다.
이 방법을 사용하면 유연성이 훨씬 향상되지만주의해야합니다. screen
필드는 Button
이며 모든 게임 화면이 확장되는 기본 화면 클래스 인 MyScreen
을 보유합니다. 버튼의 기능은 MyScreen
클래스의 일부인 메소드 만 사용할 수 있습니다. 따라서 buttonPressed()
을 MyScreen
에 작성한 다음 람다 식을 완전히 스크랩 할 수 있음을 깨달았습니다.분명한 해결책은 screen
필드를 캐스팅하는 것이지만, buttonPressed()
메서드를 사용할 수있을 때 추가 코드를 쓸 가치가 없었습니다.
내가 (MyScreen
를 확장) 내 MainMenuScreen
클래스의 beginGame()
방법이 있다면, 버튼에 전달 된 람다 식을 MainMenuScreen
에 캐스트 포함해야합니다 : 불행하게도
b.setAction(() -> ((MainMenuScreen) b.screen).beginGame());
을, 심지어 와일드 카드 구문은 '아무튼 여기에서 도와주세요.
그리고 마지막으로, 완성도, 게임 루프의 코드가 작동 할 수있는 버튼 : Scene2D 그것에서
public void drawButtons(HashMap<String, Button> buttons) {
for (HashMap.Entry<String, Button> b : buttons.entrySet()) {
sb.draw(b.getValue().image, b.getValue().r.x, b.getValue().r.y);
}
}
봐 : 헬퍼 클래스에있는
그리고 그들을 그릴, GUI 물건 만들기위한 것입니다. 그것을 사용하거나 게임의 개념을 복사하십시오. –