Java

자바 Swing 예제. 플래포머 게임 만들기 3.바닥구현

조충희 2025. 5. 7. 18:08

버전3. https://notion6780.tistory.com/62

버전5. https://notion6780.tistory.com/63

 

버전6에서는 캐릭터가 바닥에 플로어에 닿으면 딛고 설 수 있도록 세팅해봤다.

 

이를위해..

 

BubbleFrame(메인)
이단점프 방지기능 개발
BackgroundPlayerService
바닥감지기능 개발

+
Player
down 메서드 버그 해결

 

.. 등의 작업을 수행했다.

 

 

1. 이단점프 방지기능 개발

"위쪽 키보드 입력 이벤트 발생시"

"위로 간다"는 내용의 구문을

 

"위쪽 키보드 입력 이벤트 발생시"

1)이미 점프상태가 아니고

2)이미 낙하상태가 아니면

"위로 간다"고 수정

 

버전5(키보드 이벤트 수정전)

//키를 누르고 있을 때 이벤트 발생
            @Override
            public void keyPressed(KeyEvent e) {
//                System.out.println(e.getKeyCode() + "입력");

                //조건문 switch
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_LEFT:

                        //Player 클래스에 정의한 left() 메서드 호출
//                        player.left();

                        if (player.isLeft() == false && player.isLeftWallCrash() == false) {
                            System.out.println("좌측 버튼 가동");
                            player.left();
                        }

                        break;

                    case KeyEvent.VK_RIGHT:
                        /*
                        만약 오른쪽으로 가는 상태가 아니었다면 right() 수행해
                        만약 오른쪽으로 가고 있었다면 right() 수행하지마
                         */
                        if (player.isRight() == false && player.isRightWallCrash() == false) {
                            System.out.println("우측 버튼 가동");
                            player.right();
                        }

                        break;

                    case KeyEvent.VK_UP:
                        player.up();
                        break;
                }
            }

 

버전6(해당부분 수정후)

case KeyEvent.VK_UP:
    /*
    만약 점프 상태가 아니었다면 up() 수행해
    만약 낙하 상태가 아니었다면 up() 수행해
     */
    if (player.isUp() == false && player.isDown() == false) {
        System.out.println("점프 버튼 가동");
        player.up();
    }

    break;

 

 

2.바닥 감지 기능 개발

 

바닥을 감지하게 하려면
좌표값이 파란색이나 빨간색을 인식할때 낙하하지 않도록 하면 된다.

반대로 좌표값이 하얀색을 인식할때만 낙하하도록 할 수도 있다.

 

하얀색은 RGB값으로 표현하면 '255,255,255'인데

16진수로는 '-1'이다.

여기서는는 간략히 -1로 표현한다.

 

 

버전5(수정전)

지난버전까지 별도의 감시작업자(쓰레드)가

캐릭터의 좌표에 해당하는 부분의 맵의 색깔을 인식해

캐릭터가 좌우벽에 부딪혔는지 여부를 계산하고

벽에 닿았다면 전진하지 못하도록 하는 코드를 짜봤다.

//start() 메서드가 호출되면 동작하는 부분
    @Override
    public void run() {

        while (true) {

            //플레이어 좌표의 RGB 값을 인식하게 하기
            Color leftColor = new Color(image.getRGB(player.getX(),player.getY()+25));
//            System.out.println("왼쪽 벽 확인:"+leftColor);

            //플레이어 좌표에 보정값 추가
            Color rightColor = new Color(image.getRGB(player.getX()+60,player.getY()+25));
//            System.out.println("오른쪽 벽 확인:"+rightColor);

            /*
            플레이어의 좌표값에 따라
            빨간색, 파란색, 하얀색을 구분할 수 있다.

            논리적으로
            leftColor가 255, 0, 0 이면 왼쪽 벽에 충돌함
            또 RightColor가 빨간색이면 오른쪽 벽에 충돌한 것으로 판단한다.
             */

            if (leftColor.getRed() == 255 && leftColor.getGreen() == 0 && leftColor.getBlue() == 0) {
                //RGB 255,0,0 빨간색으로 판별 = 왼쪽벽에 충돌했다.
                System.out.println("왼쪽 벽에 충돌");

                //왼쪽 벽 충돌 판정
                player.setLeftWallCrash(true);

                //충돌시 왼쪽이동 종료
                player.setLeft(false);


            } else if (rightColor.getRed() == 255 && rightColor.getGreen() == 0 && rightColor.getBlue() == 0) {
                //RGB 255,0,0 빨간색으로 판별 = 오른쪽벽에 충돌했다.
                System.out.println("오른쪽 벽에 충돌");

                //오른쪽 벽 충돌 판정
                player.setRightWallCrash(true);

                //충돌시 오른쪽이동 종료
                player.setRight(false);

            } else {
                player.setLeftWallCrash(false);
                player.setRightWallCrash(false);
            }

            //위 두 조건이 아니면 하얀색 = 마음대로 움직이세요

            try {
                Thread.sleep(5);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }

        }//while
    }//run

 

 

버전6.(바닥감지기능 추가)

int bottomColorLeft = image.getRGB(player.getX() +10, player.getY() + 55);
System.out.println("bottomColorLeft:" + bottomColorLeft);
int bottomColorRight = image.getRGB(player.getX() + 50, player.getY() + 55);
System.out.println("bottomColorRight:" + bottomColorRight);

 

50X50 크기 캐릭터를 나타내는 이미지라벨 왼쪽 위 좌표(0.0)로부터 (10.55)를 왼쪽발끝, (50.55)를 오른쪽발끝이라고 어림잡았다.

 

양쪽 bottomColor 좌표가 하얀색(-1)이 아닐때

즉, 바닥에 닿아있다면 낙하하지 않는다.

 

양쪽 bottomColor 좌표가 하얀색(-1)이면서

1)점프중이 아니고

2)낙하중도 아니라면 낙하한다. down()

            if (bottomColorLeft + bottomColorRight != -2) {
                player.setDown(false);
            } else {

                /*
                점프하는 순간 bottomColor 값이 -1이 되기 때문에
                바로 player.down() 메서드가 호출된다.
                 */
//                player.down();
                if (player.isUp() == false && player.isDown() == false) {
                    player.down();
                }
            }

 

 

3. 버그 수정

캐릭터가 2층 바닥에 닿았음에도 멈추지 않고 1층 바닥에 다시 내려오는 문제가 발생했다.

 

원인은 기존 코드가 for문으로 작성돼

기존 점프 메서드가 끝까지 수행되는 데 있었다.

 

이를 while문으로 작성하고

낙하 메서드 수행 도중 바닥에 닿았다면

반복문을 중단하도록 고쳐봤다.

 

버전5(수정전)

@Override
public void down() {

    down = true;

    new Thread(new Runnable() {
        @Override
        public void run() {
            for (int i = 0; i < (130 / JUMP_SPEED); i++) {

                y += JUMP_SPEED;

                setLocation(x, y);

                try {
                    Thread.sleep(3);
                } catch (InterruptedException e) { // 일단멈춤
                    throw new RuntimeException(e);
                }
            }// for

            //상태값을 잘 다뤄야 버그가 없다.
            down = false;

        }
    }).start();

}//down

 

버전6(수정후)

@Override
public void down() {

    down = true;

    new Thread(new Runnable() {
        @Override
        public void run() {

            while (down) {
                y += JUMP_SPEED;
                setLocation(x, y);

                try {
                    Thread.sleep(3);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }//while

            //상태값을 잘 다뤄야 버그가 없다.
            down = false;

        }
    }).start();

}//down

캐릭터가 바닥에 올러설 수 있게 됐다.