본문 바로가기
창고/Backup_2013_0121

정현이도 할 수 있는 안드로이드 어플 개발 - 5 : 충돌체크 및 블럭쌓기 그리고 기타등등

by 가능성1g 2011. 2. 25.
반응형
저번 포스팅하고 시간이 좀 흐른듯 하다 -ㅁ-;; 생업에 바쁘다 보니 포스팅을 못했다;;

어찌됐든~!!
오늘은 저번에 약속한거 같이 충돌체크와 블럭쌓기
그리고 테트리스 게임이 그러하듯이 계속 블럭 밑으로 내려가게 하기(?) 를 해보도록 하겠다.

다들 조금은 생각하고 왔을꺼라 믿고 =ㅅ=;; (아닌거 아니까 긴장하지 말고;;)

자 그럼 충돌체크 부터 해보자.

음.. 어떻게 해야할까?
상식적인 선에서 바로 나올것이다.
이동했을때 선넘어가면 안움직이면 되는것이다 ㅡㅠㅡ;; 간단하다..

이를 위해서 일단 블럭이 자유롭게~ 노닐수 있는 공간이 필요하다.
난 arBlockMap 이라 이름 지었다.
요기에 생성되는 블럭의 위치를 표시하고 이미 쌓인 블럭의 위치를 기록하여 충돌체크에 이용할 것이다.

크기는 자신의 에뮬레이터 크기에 따라 적당히 선언하자.
단순하게 화면 스케일을 가져와서 블럭사이즈로 나누면 된다.

하지만 주의점!! 이 블럭맵이 배열이다 보니 마이너스 값을 갖게 되면 사망하신다.
C 로 따지면 치명적 메모리 오류-ㅅ-;; 그러므로 매우 잘 생각해서  크기를 생각하고,
그 크기에 따라 블럭의 위치를 체크하자.

나는 블럭 사이즈를 20으로 했기에
320 * 240 화면이므로
12 * 20 배열로 선언했다.

그리고 이제 중요한 충돌 체크~
충돌체크를 할곳은
1. 왼쪽-_-벽
2. 오른-_-쪽벽
3. 바닥
4. 먼저 쌓여있는 블록들

이다..
바보같이 천장은 왜 안해요? 하면 화낼꺼다-_-;;

1,2,3은 간단하다. 그래서 생략~ 하지만 블럭크기가 4*4 라는걸 생각하며 체크하는걸 잊지마시고~
4는 기존의 블럭 정보를 arBlockMap에 잘기록하면 쉽다~

그럼 나흐 충돌체크 로직을 보여주겠다
  int START_X = bl.getCurrentX() / Block.BLOCK_SIZE;
  int START_Y = bl.getCurrentY() / Block.BLOCK_SIZE;
  int[][] currentBlock = bl.getCurrentBlock();
  
  int check_x = 0;
  int check_y = 0;
  
  for(int i=0;i<currentBlock.length;i++)
  {
   for(int j=0;j<currentBlock[i].length;j++)
   {
    if(currentBlock[i][j] == 1 )
    {
     check_x =j + START_X;
     check_y =i + START_Y;
     
     Log.d("BLOCK_COLIDE","check_x: "+check_x+"check_y: "+check_y);
     Log.d("BLOCK_WALL",(arBlockMap.length-1)+","+(arBlockMap[check_x].length-1));
     
     /* Left Wall */
     if( check_x < 0) return true;
     if( check_y < 0) return true;
     /* Right Wall */
     if( check_x > arBlockMap.length-1 ) return true;
     /* Bottom */
     if( check_y > arBlockMap[check_x].length-1) return true;     
     /* MapBlock Checking */
     if( arBlockMap[check_x][check_y] == 1) return true;
    }
   }
  }

블럭이 가지고 있는 x,y위치는 맵좌표로 가지고 있기때문에 배열 인덱스로 바꿔주기위해 블럭사이즈로 나눠주면 된다. 그리고 현재 블럭의 모양을 가져와서 1인 부분을 체크 해준다.
당근 4*4 배열에서 채워진부분과 안채워진 부분중 채워진 부분을 체크하는거다.
그래서 1칸짜리 블럭의 배열의 인덱스 위치는 check_x, check_y 가 된다.
다음은 이제 1,2,3 을 간단하게 체크해주고
끝으로 4 를 체크하면 된다.

자~ 그럼 이제 충돌체크를 했으니 무얼해야할까?
바로 충돌했을때 이동못하게 하기+ㅁ+!!

충돌났는데 계속가면 뚫고 들어가면 이상하니까=ㅁ=!!

이전 값을 가지고 있다가 충돌나면 복구하면 된다. (소스 참조 )

이를 위해서 이동전에 x,y  좌표를 알아야 하고 복구를 위해 set 도 가능해야 하므로
get,set 함수를 Block 에 추가 하였다.

방법은 간단~ 먼저만든 충돌체크함수를 써서 충돌이 판명나면 이동전에 저장시킨 변수를
다시 set 해주면 된다~

자이제 충돌함수를 완성했으니 블럭쌓기와 라인완성시 삭제까지 해보도록 하자.

이 두가지 만 완성하면 이제 테트리스 기본골격은 끝이다.
오류및 기타 해야될것들이 많지만 =ㅁ=/ 그런건

여러분들에게 맡기고 =ㅠ=;;

블럭쌓기는 블럭을 쌓을 조건이 중요하다. ( 내생각에=ㅁ=;;)

내가 테트리스게임을 좋아하지 않은관계로;;;
일반적인 생각이 아닐수도 있지만;;

블럭이 맵에 정지되고 다음 블럭이 생성되는 조건을

블럭이 일정시간마다 하강을 시도하다가 3차례 실패하면 하도록 했다.

이미 있는것들을 잘활용하면 만들수 있는것이다 -ㅁ-ㅋ

중요한것은 아래로 하강하는 작업을 일정시간을 두고 계속 해야 된다는것!

Visual Basic 잠깐해본사람이라면 Timer 가 바로 생각날것이다~ (아님 말고 -ㅅ-)

Java 에도 비슷한게 있다.
아니 이름도 같다;; Timer Class
사용법은 역시 JDK 를 살펴보시고=ㅅ=;;

Timer 클래스를 생성해서 TimerTask 로 현대 블럭을 하강하는것을 등록해주자~
나는 BlockManager 에 코드를 추가 하였다.실제 사용방법은 검색으로도 알수 있고 내가 작성한 소스를 봐도 되니 생략-_-한다 ㅎㅎ

이걸 만들면서 중요한점이 하강후에 블럭을 redraw 하는것이다.
이것땜에 한 이틀을 해맸던것 같다-_-;;

TimerTask 에 하강후 아무생각없이 Invalidate() 를 호출해 놨는데
RunTime 에서 항상 오류가 나는것이었따 ㅠㅠ

이유를 모르고 3~4시간을 해매다가
배추포기-_- 를 생각하고 있을무렵;;

한 블로그의 글을 발견했다!!

그글인 즉~, Thread 에서 UI 의 업데이트는 불가하다는 것이었다.
이유는 역시 syncronize 때문이다.;;

그래서 Handler 라는 것을 써야한다!! 까지 친절하게 써져있었었는데 감사한 블로그 주소를 까먹었다 ㅠㅠ;; 이자리를 빌어 죄송;;

그래서 소스를 보면 TimerTask 의 아래쪽에
    mHandler.sendEmptyMessage(0);
이게 있는데 , 이게 바로 핸들러에 업데이트 하라는 메시지 이다.

기타 설명하지 않고 Class 나 메소드이름을 바꾼것도 있으니 소스를 잘보길 바란다 =ㅁ=ㅋㅋ
질문은 항상 댓글로 하시면 될것이고~ㅎㅎ

이상 1차 테스트리스 개발을 여기서 마치도록 하겠다.
좀더 발전시켜서 멋지게 개발완료 하시면 저한테도 보내주면 감사하겠다 ㅎㅎ

그럼 담엔 더좋은걸 개발해보자+ㅁ+!! 그때까지 안뇽~ㅎ



반응형