게임 프레임과 컴포넌트 클래스의 관계

목차

    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