Drop the Beat 모드의 판정 구현

목차

    1. 노트 생성 방식

    Drop the Beat 모드와 TryCatch 모드의 코드 적으로 가장 큰 차이점은 PlayerService 클래스가 Runnable을 구현 유무이다.

    그 중 Drop the Beat 모드는 Runnable을 구현 하는 클래스 이고, run() 메서드을 살펴보면

    public void run() {
        while (GameSelectFrame.isNoteRunning()) {
            createNote();
            Random random = new Random();
            // 노트 빈도 조절 코드
            delay = random.nextInt(700) + 200;
    
            try {
                Thread.sleep(delay);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

     

     

    랜덤한 주기로 createNote() 메서드를 반복적으로 호출 하도록 되어있고, createNote() 메서드는 

    public void createNote() {
        new Thread(new DropNote(this, player, noteSpeed)).start();
    }

     

    새로운 쓰레드로 노트를 생성하는 형태이다. 당연히 DropNote()도 Runnable을 구현 하는 클래스이고 그 run()을 보면,

    public void run() {
        while (GameSelectFrame.isGameRunning()) {
            if (drop) {
                drop();
                try {
                    Thread.sleep(5);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            } else {
                break;
            }
        }
    }
    public void drop() {
        if (y <= 850) {
            y += noteSpeed;
            setLocation(x, y);
        } else if (y > 850) {
            setIcon(null);
            isMiss = true;
            drop = false;
            playerService.getScore().miss();
        }
    }

     

    생성과 동시에 일정한 속도로 y 좌표가 증가, 즉 화면상에서 떨어지는 형태로 보이게 된다.

    2. 노트 판정 방식

    노트가 판정되는 순간은 당연하게도 키보드가 입력되었을 때이기 때문에 KeyListener의  keyPressed() 메서드 부분을 보면된다.

    public void keyPressed(KeyEvent e) {
        if (player == Player.SOLO) {
            switch (e.getKeyCode()) {
            case KeyEvent.VK_A:
                if (place == LEFT && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_W:
                if (place == UP && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_D:
                if (place == RIGHT && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_S:
                if (place == DOWN && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_LEFT:
                if (place == LEFT && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_UP:
                if (place == UP && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_RIGHT:
                if (place == RIGHT && !isJudged) {
                    judge();
                }
                break;
            case KeyEvent.VK_DOWN:
                if (place == DOWN && !isJudged) {
                    judge();
                }
                break;
            default:
                break;
            }
        }
    }

    솔로 모드를 예시로 가져왔고, wasd 와 방향키 ↑←↓→ 모드 지원하는 형태이다.

     

    먼저 switch문으로 현재 입력 받은 키가 무엇인지 확인 한 다음 if문의 조건을 확인하게 되는데

    place 변수는 최초 노트가 생성될 당시 4개의 방향 중 하나를 랜덤으로 부여 받은 것이고, 모든 노트가 가지고 있는 속성이라고 생각할 수 있다.

    그래서 if문의 조건은 현재 입력받은 키와 노트의 속성이 일치하는지 확인 하는 것이고, 논리곱의 우측은 중복 판정을 방지하기 위한 불리언 변수이다.

    조건을 만족했을 때 호출되는 judge() 메서드를 보면

    public void judge() {
        // 일정 높이 이상에서는 판정 하지 않음
        if (y < 650) {
            return;
        }
        if (perfectZone()) {
            isPerfect = true;
            System.out.println("퍼펙트");
            playerService.getScore().judgeScore(ScoreType.PERFECT);
            isJudged = true;
            drop = false;
            setIcon(null);
        } else if (excellentZone()) {
            isExcellent = true;
            System.out.println("엑설런트");
            playerService.getScore().judgeScore(ScoreType.EXCELLENT);
            isJudged = true;
            drop = false;
            setIcon(null);
        } else if (goodZone()) {
            isGood = true;
            System.out.println("굿");
            playerService.getScore().judgeScore(ScoreType.GOOD);
            isJudged = true;
            drop = false;
            setIcon(null);
        } else if (badZone()) {
            isBad = true;
            System.out.println("배드");
            playerService.getScore().judgeScore(ScoreType.BAD);
            isJudged = true;
            drop = false;
            setIcon(null);
        }
    }
    public boolean perfectZone() {
        if (y >= 705 && y <= 745) {
            return true;
        }
        return false;
    }

     

    각 스코어에 따라 지정해둔 범위에 해당하는지 확인해서 Score 클래스의 메서드를 호출해 점수를 올리게된다.