Flash with Adobe AIR

GrayrabbiT 2015. 2. 16. 13:53
반응형

레알 불꽃 포스팅입니다. 언능 정리하고 싶어서..ㅡㅡ; 네 이제 7번째 시간..

http://www.youtube.com/watch?v=4iWqRyuo65M

오늘은 하르마 선생님 유툽을 보시는게 좋을 듯 합니다. 일단 Collision Dectection 부분이구요. 기본적으로 우리는 장애물과 만나게 된다면 그 녀석들은 부딪쳤다는 판별을 해야 하는데 여러 가지가 있습니다. 우리는 기본적인 방법으로 테스팅을 해볼 것입니다요. 그런데 진행하기 전에 일단은 터치를 이용해서 우리 영웅을 움직이는 작업을 해 볼 것입니다.

    import starling.events.Touch;

    import starling.events.TouchEvent;

    

    import starling.utils.deg2rad;

    

추가해 주시고.

        private var touch:Touch;//터치 생성

        private var touchX:Number;

        private var touchY:Number;

    

 

변수 추가해 주시고. Lunchhero() 함수에 이벤트를 추가합니다.

        private function launchHero():void

        {

            this.addEventListener(TouchEvent.TOUCH, onTouch);//터치 이벤트 추가

            this.addEventListener(Event.ENTER_FRAME, onGameTick);

        }

        

        private function onTouch(e:TouchEvent):void

        {

            if(e.getTouch(stage)!=null)

            {

                touch = e.getTouch(stage);

            

                touchX =touch.globalX;

                touchY= touch.globalY;

            }

            

        }

한꺼번에 설명드릴께요. 터치 이벤트를 통해서 터치를 감지하도록 하겠습니다. 그러면 터치가 이루어지게 되면 onTouch를 실행하게 될텐데요. 우리가 휴대폰 환경에서는 상관이 없는 것 같은데. 만약에 데스크탑 환경에서 실행할 경우에 마우스가 스테이지를 벗어나게 되면 에러를 발생합니다. 따라서 상당히 귀찮게 되는데요. 예전 포스팅에서 설명드렸지만 이 에러는 getTouch를 통해서 가지고 오는 값이 stage 밖일 경우에는 null 값을 가지고 오게 됩니다. 따라서 이 값을 통해서 참조를 하게되면 null 값에 접근한다는 에러를 발생하게 됩니다. 따라서 우리는 만약에 getTouch의 값이 null 값인지 아닌지를 판단해서 그 값을 통해서 받아오도록 하는거죠. 이렇게 하면 오류가 발생하지 않게 됩니다.

 

그리고 이제 우리가 히어로를 움직이기 위해서는 onGameTick 에서 처리를 해주도록 합니다 . switch 문에서 "flying" 쪽에서 고쳐주는데요. 만약에 장애물에 부딪친게 아니라면,.. 히어로는 움직여야 합니다.

                    if(hitObstacle<=0)

                    {

                        hero.y+=(touchY-hero.y)*0.1                        

                        if(-(hero.y -touchY)<150 && -(hero.y-touchY)>-150)

                        {

                            hero.rotation=deg2rad(-(hero.y-touchY)*.2);

                        }

                        

                        if(hero.y>gameArea.bottom-(hero.height>>1))

                        {

                            hero.y=gameArea.bottom-(hero.height>>1)

                            hero.rotation=deg2rad(0);

                        }

                        if(hero.y<gameArea.top+(hero.height>>1))

                        {

                            hero.y=gameArea.top+(hero.height>>1);

                            hero.rotation=deg2rad(0);

                        }

                        

                    }

 

이렇게요. 일단 hero.y의 좌표값에 계속 누적해서 더해주는데요. (터치좌표-지금좌표) * 비율이 되겠죠? 그리고 만약에 터치와 히어로의 좌표값이 많이 차이가 나게되면 로테이션 시켜주게 되는데요. 로테이션 값은 radius 값을 가지게 되기 때문에 이를 쉽게 바꾸어 줄수 있는 starling.util.deg2rad 를 사용하게됩니다. 그래서 그 값을 바꾸어 주고… 만약에 바닥.. 그러니까 gameArea의 바닥보다 더 아래로 내려가 버리면 강제로 바닥에 붙여 버립니다. 그리고 그때의 로테이션 값을 0으로 만들어 줍니다. 그리고 상위보다 더 올라가 버려도 마찬가지로 그렇게 처리해 주는것이죠. 여기까지가 기본입니다. 테스팅 해보시죠. 아마도 히어로가 잘 따라오고 있을 것입니다.

 

Coliision Dection

 

 

이제는 충돌 감지에 대해서 이야기 해 봅시다. 우리가 충돌을 감지하게 하려면

  1. 두가지의 객체를 사각형으로 만들고 그 사각형 두개가 겹치는지를 확인해 볼 수 있습니다.
  2. 거리를 이용하는 방법이 있습니다. 서로의 원을 그려서 두 객체의 거리가 서로의 원의 반지름의 합보다 작아진다면 충돌로 판별할 수 있을 것입니다.
  3. 포인트로 해결하는 방법이 있습니다. 한가지 객체를 사각형을 그리고 좌표가 거기 안으로 들어가는지를 확인해 봅니다.
  4. 마지막으로 두개의 비트맵을 복제해서 서로 비교하는 방법이 있습니다.

자 이렇게 할 수 있는데요. 가장 간단한 방법인 1번 방법을 선택하겠습니다. 대신 1번 방법의 경우 매우 쉽고, 빠르게 계산되지만 정확성을 떨어집니다. 하지만 전 쉬운게 좋아요.T-T

만약 여러분들이 게임을 설계한다면 4개 중에서 정확히 정해서 하셔야 합니다. 4번 같은 경우에는 많은 비용을 소요하게 될 테니까요.

 

이제 직접 코드를 만져주도록 하겠습니다 먼저. 에니메이션 부분에 들어가죠. 먼저 onGameTick에서 animateObstacle에서 장애물의 좌표를 수정하게 합니다. 여기에서 처음에 충돌감지를 넣어 보도록 하겠습니다.

                if(obstacleToTrack.alreadyHit==false&&obstacleToTrack.bounds.intersects(hero.bounds))

                {

                    obstacleToTrack.alreadyHit=true;

                    obstacleToTrack.rotation=deg2rad(70);

                    hitObstacle=30;

                    playerSpeed*=.5;

                    

                }

여기 보시면. 일단 alreadyHit를 false 여야 합니다. 왜냐하면 이게 없으면 이미 부딪친 장애물에 대해서도 반응을 하게 만들면 안되니까요 ., 부딪친 경우이 없는 장애물 중에서 장애물의 bounds 하면 Rectangle 을 반환합니다. 이 사각형이 히어로의 사각형과 만났는지 판단하게 됩니다. 만약 만나게 된다면

alreadyHit 를 true 로 바꾸어 주고 로테이션을 70 도 시킵니다. 그리고 플레이어의 속도를 반을 감소시킵니다. 그리고 중요한 hitObstacle=30 으로 세팅합니다. 이렇게 세팅해 놓으면 멈춤 상태가 30정도 지속이 되는거죠. 또 게임스피드를 줄여도 flying 에 보시면 게임 속도를 MIN_SPEED로 다시 돌려놓기 때문에 괜찮습니다. 그리고 잊으셨는지 모르겠지만 Obstacle 클래스에서는 만약 alreadyHit 이 true 가되면 일단 애니메이션의 visible =false 로 만들고 충돌 이미지를 넣도록 되어있었습니다. 그러면 이제 충돌후에 다시 원상태로 돌려놓기 위한 작업을 하도록 하죠.

onGameTick에 flying 부분입니다.

                    if(hitObstacle<=0)

                    {

                        hero.y+=(touchY-hero.y)*0.1;

                        

                        if(-(hero.y -touchY)<150 && -(hero.y-touchY)>-150)

                        {

                            hero.rotation=deg2rad(-(hero.y-touchY)*.2);

                        }

                        

                        if(hero.y>gameArea.bottom-(hero.height>>1))

                        {

                            hero.y=gameArea.bottom-(hero.height>>1)

                            hero.rotation=deg2rad(0);

                        }

                        if(hero.y<gameArea.top+(hero.height>>1))

                        {

                            hero.y=gameArea.top+(hero.height>>1);

                            hero.rotation=deg2rad(0);

                        }

                        

                    }

                    else

                    {

                        hitObstacle--;

                        camearaShake();

                    }

 

위에 코드에서 추가된 부분은 else 구문입니다. 여기서 hitObstacle을 – 로 줄여주게 됩니다. 따라서 줄다보면 다시 정상상태를 찾게 되구요. 그담에는 camearaShake 입니다.

        private function camearaShake():void

        {

            if(hitObstacle>0)

            {

                this.x=Math.random()*hitObstacle;

                this.y=Math.random()*hitObstacle;

            }

            else if(x!=0&&y!=0)

            {

                this.x=0;

                this.y=0;

            }

        }

 

이렇게 해주죠. 일단 hitObstacle이 0보다 크게 된다면 랜덤으로 화면의 좌표를 마구 흔들어 줍니다.

그리고 만약 hitObstacle이 다 떨어진 상태에서 좌표가 안맞는 경우에는 다시 0으로 세팅을 해 주는 것이죠. 간단하죠?

그래서 테스팅 해 보시면….

뭔가 이상합니다…. 무엇인가.. 잘못되었다? 아무리 아까 1번 방법이 간단하다고 해도 오차가 너무 나는걸 확인하실 수 있으실 겁니다. 잘 생각해 보세요. 무엇때문에 그럴지를요. …. 네 맞습니다. watchOut 때문에 그렇습니다. 우리는 이 watchOutAnimation을 visible 값만 조정해서 안보이게 해 주었습니다. 그런데. 생각해 보면 눈에 안보인다 뿐이지 Obstacle의 사각형을 그렸을 때 그 녀석도 포함되고 있는 상태이기 때문에 우리 눈에는 부딪치지 않은 것으로 보이지만 부딪쳤다고 판단하게 됩니다. 그러니 Obstacle 클래스를 약간 바꿔 주도록 하죠. 우리는 일정 시간이 지나고 나면 watchOut 값을 통해서 watchOutAnimation을 통제했습니다.

 

        public function set watchOut(value:Boolean):void

        {

            _watchOut = value;

            

            if(watchOutAnimation)

            {

                if(value) watchOutAnimation.visible=true;

                else

                {

                    watchOutAnimation.visible=false;

                    this.removeChild(watchOutAnimation);

                }

            }

        }

 

자 여기서 그냥 경고 메세지는 없에 버리죠 뭐.. 그냥 사라지는 겁니다 보여주는것만 안보여주는 것이 아니라.

그렇게 하면 좀 더 정확하게 충돌 감지가 될 것 같네요.

네 오늘은 여기까지 하구요. 혹시나… 지금까지 한것들을 소스파일이 필요하실까봐 오늘은 올려 놓겠습니다.

 

 

 

 

 

 

 

 

 

반응형

'Flash with Adobe AIR' 카테고리의 다른 글

Starling-03 TouchEvent  (0) 2015.02.16
Starling-Hungry Hero-05  (0) 2015.02.16
Starling-Hungry Hero-04  (0) 2015.02.16
Starling-Hungry Hero-03  (0) 2015.02.16
Starling-HungryHero-02  (0) 2015.02.16