목차
1. 컴포넌트 클래스의 생성자 구조
public ComboBox(PlayerService playerService, Player player) {
this.playerService = playerService;
mContext = playerService.getmContext();
this.player = player;
initData();
setInitLayout();
new Thread(new ComboNum(Digit.ONES)).start(); // 일의 자리수 실시간 출력
new Thread(new ComboNum(Digit.TENS)).start(); // 십의 자리수 실시간 출력
new Thread(new ComboNum(Digit.HUNDREDS)).start(); // 백의 자리수 실시간 출력
}
public HpBox(PlayerService playerService, Player player) {
this.playerService = playerService;
mContext = playerService.getmContext();
this.player = player;
hpFull = new ImageIcon(Define.IMG_HP_HPFULL);
hpHalf = new ImageIcon(Define.IMG_HP_HPHALF);
new Thread(new Heart(FIRST_HEART)).start();
new Thread(new Heart(SECOND_HEART)).start();
new Thread(new Heart(THIRD_HEART)).start();
}
public ScoreBox(PlayerService playerService, Player player) {
this.playerService = playerService;
mContext = playerService.getmContext();
this.player = player;
initData();
setInitLayout();
new Thread(new ScoreNum(Digit.ONES)).start();
new Thread(new ScoreNum(Digit.TENS)).start();
new Thread(new ScoreNum(Digit.HUNDREDS)).start();
new Thread(new ScoreNum(Digit.THOUSANDS)).start();
}
모두 PlayerService 라는 클래스의 객체를 생성자 의존 주입으로 받는 형태이다.
public abstract class PlayerService {
public PlayerService() {
}
public abstract Score getScore();
public DropNoteFrame_2P getDropNoteFrame_2P() {
return null;
}
public DropNoteFrame_1P getDropNoteFrame_1P() {
return null;
}
public TryCatchFrame_2P getTryCatchFrame_2P() {
return null;
}
public TryCatchFrame_1P getTryCatchFrame_1P() {
return null;
}
public abstract GameSelectFrame getmContext();
public abstract Player getPlayer();
}
PlayerService 클래스는 추상 클래스이고 이를 구현한 클래스 중 하나의 예시를 보면
public DropNote_2P_PlayerService(DropNoteFrame_2P gameFrame, Player player) {
this.gameFrame = gameFrame;
mContext = gameFrame.mContext;
this.player = player;
noteSpeed = DropNote.DEFAULT_SPEED;
score = new Score(mContext, player);
new ComboBox(this, player);
new ScoreBox(this, player);
new HpBox(this, player);
}
이렇게 각 게임 모드에 해당하는 프레임의 주소를 받아 각종 컴포넌트를 생성하는 역할을 한다.
2. 컴포넌트를 프레임에 add 하는 방법
위에서 보면 알 수 있듯 PlayerService 클래스는 컴포넌트 객체를 생성하는 역할을 하는데 전체 코드를 보아도 add된 적은 없다.
언제 add 되는 지를 살펴보면
public void setInitLayout() {
setIcon(comboBox);
setSize(100, 100);
setLocation(x, y);
switch (mContext.getSelectNumber()) {
case GameSelectFrame.GAMENAME_DROPNOTE_1P:
playerService.getDropNoteFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_DROPNOTE_2P:
playerService.getDropNoteFrame_2P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_1P:
playerService.getTryCatchFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_2P:
playerService.getTryCatchFrame_2P().add(this);
break;
}
}
public void setInitLayout() {
setIcon(hpFull);
setSize(50, 50);
setLocation(x, y);
switch (mContext.getSelectNumber()) {
case GameSelectFrame.GAMENAME_DROPNOTE_1P:
playerService.getDropNoteFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_DROPNOTE_2P:
playerService.getDropNoteFrame_2P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_1P:
playerService.getTryCatchFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_2P:
playerService.getTryCatchFrame_2P().add(this);
break;
}
}
public void setInitLayout() {
setIcon(scoreBox);
setSize(304, 157);
setLocation(x, y);
switch (mContext.getSelectNumber()) {
case GameSelectFrame.GAMENAME_DROPNOTE_1P:
playerService.getDropNoteFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_DROPNOTE_2P:
playerService.getDropNoteFrame_2P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_1P:
playerService.getTryCatchFrame_1P().add(this);
break;
case GameSelectFrame.GAMENAME_TRYCATCH_2P:
playerService.getTryCatchFrame_2P().add(this);
break;
}
}
컴포넌트 클래스 본인이 생성자에서 호출한 메서드인 setInitLayout()에서 직접 게임 프레임에 접근해 add 하는 방식이다.
여기서 현재 어떤 게임이 실행되었는지 확인하고 그 게임에 맞는 프레임에 add를 시켜주도록 되어있는데,
어떤 게임이 실행되었는지 확인하는 방법이 게임 선택 화면에서 게임을 선택할 때 사용했던 인덱스 번호를 이용하는 것이다.
즉 게임이 시작되는 순간 그 인덱스 번호는 이후에 변하지 않도록 되어있고, getter로 그 값에 접근을 함으로써 어떤 게임이 실행 되었는지 컴포넌트가 알 수 있게 된다.
3. 아쉬운 점
1. 우선 PlayerService 자체가 player라는 enum 타입을 필드에 지니고 있는데 굳이 한번더 생성자에서 받아 왔다는 점인데, 그 부분을
public ComboBox(PlayerService playerService) {
this.playerService = playerService;
mContext = playerService.getmContext();
this.player = playerService.getPlayer();
initData();
setInitLayout();
new Thread(new ComboNum(Digit.ONES)).start(); // 일의 자리수 실시간 출력
new Thread(new ComboNum(Digit.TENS)).start(); // 십의 자리수 실시간 출력
new Thread(new ComboNum(Digit.HUNDREDS)).start(); // 백의 자리수 실시간 출력
}
이렇게 고쳤다면, 좀 더 코드가 깔끔해 지지 않았을까 싶다.
2. 프레임 클래스도 플레이어 서비스 클래스처럼 상속을 이용했다면 매우매우 깔끔해질 수 있었을 것 같다.
현재 게임 프레임에 컴포넌트를 add 하는 시점 뿐만 아니라 게임 종료 프레임에서 조차 조건문으로 각종 모드에 따라 다른 코드를 진행하도록 작성되었는데, 프레임 클래스도 하나의 클래스로 바라 볼 수 있게 상속을 이용했다면, 이런 저런 복잡한 조건을 달 필요 없이 알아서 하나의 메서드 만으로도 모든 것을 구현 할 수 있었을것이라 생각된다.
'My Project > Java Swing 멀티 쓰레딩 프로그램' 카테고리의 다른 글
TryCatch 모드의 판정 구현 (0) | 2024.06.09 |
---|---|
Drop the Beat 모드의 판정 구현 (0) | 2024.06.08 |
게임 화면 구성 (0) | 2024.05.21 |
게임 선택 화면 구성 (0) | 2024.05.16 |
메인 화면 구성 (0) | 2024.05.16 |