마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

쓰레드와 타이머 질문입니다.

0 추천

인터넷 강좌보면서 게임을 만들어보고 있습니다. 어느정도 강좌를 보다가 응용해서 만들던 중에 막히는 부분이 있어 질문드립니다.

메인 Activity에서

setContentView(new MyGameView(this));
로 서피스뷰를 메인에 표시하고있습니다.

public class MyGameView extends SurfaceView implements Callback {
안에는 쓰레드를 넣었고

public void surfaceCreated(SurfaceHolder arg0) {
          mThread.start();
     }

뷰가 생성될때 쓰레드를 스타트합니다.

쓰레드안의 run에서는 기본적인 이미지들을 화면에 표시합니다.

 public void run() {
               while (true) {
                    Canvas canvas = null;
                    canvas = mHolder.lockCanvas();
                    try {
                         synchronized (mHolder) {
                              canvas.drawBitmap(imageBack, 0, 0, null);
                         }
                    } finally {
                          mHolder.unlockCanvasAndPost(canvas);
                    }
                } // while
          } // run()
(소스는 현제 재가 만든 소스가 아니라 보고있는 강좌의 예제입니다)

질문1.

run()의 while(true)안에 이미지를 배치하면 정확히 모르겠지만 빠른 일정 시간 간격으로 try안에 있는 내용을 실행하는데..

이 동작의 원리가 궁금합니다. 주기적으로 surfaceCreated가 호출되서  쓰레드가 돌아가는건지...아니면 surfaceCreated는 처음 뷰를 호출할때 한번만 호출고 run()이 주기적으로 호출되는건지...아니면 surfaceCreated이랑 run 둘다 한번만 호출되는건데 while(true)로 되어있어서 여기서 계속 표시동작을 하는건지...궁금합니다. 사실 제 생각으론 run은 한번만 호출되고 while이 계속 도니까 계속 쓰레드 안에서 이미지를 표시해 주고 있다고..생각하는데 정확히 알고 싶습니다 ㅠ.

질문2

사실 이게 제가 진짜로 막힌 부분입니다. run안에서  canvas.drawBitmap(imageBack, 0, 0, null);를 0대신에 x--; 이런식으로 변수넣고 루프 돌때마다 바꿔주면 화면상에서 이미지가 이동하는데요...이게 어떤속도로 루프들 돌고있는지 모르겠으나 이걸 시간을 직접 설정하고 싶습니다. 예를들어 1ms마다 1px씩 왼쪽으로 이동하도록 설정하고 싶은데...머리싸매고 생각해봐도 어떤식으로 코딩을 해야할지 잘 모르겠습니다 ㅠ.

자세한 설명을 위해 제가 만들고있는 소스를 일부 올리겠습니다.

 public void run() {
              while (true) {   
                  Canvas canvas = null;
                  canvas = mHolder.lockCanvas();
                  try {
                        synchronized (mHolder) {
                            canvas.drawBitmap(topgaugebar, 0, 0, null);
                            canvas.drawBitmap(touchzone, touchzoneX, touchzoneY, null);
                            canvas.drawBitmap(gauge, gaugeX, gaugeY, null);
                            canvas.drawBitmap(mapView, 0, S_TopGbarY, null);
                            canvas.drawBitmap(caracterView, characterX, characterY, null);
                            canvas.drawBitmap(monsterView, monsterX, monsterY, null);
                        }
                  } finally {
                        mHolder.unlockCanvasAndPost(canvas);
                  }
              } // while
        } // run() 
이런식으로해서 배경과 캐릭터 이미지를 기본적으로 표시하고있습니다.

이때 화면을 한번 터치하면 네모난 박스 이미지를 오른쪽화면 끝에서 왼쪽으로 1ms마다 1px씩 이동시키고 싶습니다. 이럴 경우 어떻게 해야하는지 잘 모르겠습니다..한가지 방법으로는 서피스 뷰안에 전역변수로 쓰레드를 하나 더 만들고. 터치이벤트에서 ACTION_DOWN되면 새로만든 쓰레드를 호출합니다. 그 쓰레드의 run에서 네모박스 이미지를 화면 오른쪽위에 표시하고 1ms마다 루프를 돌면서 width좌표를 -1씩 해줍니다. 이런식의 구현방식이 가능할까요?

그리고 쓰레드안에서 1ms마다 루프를 어떻게 돌리면 되는지 모르겠습니다..인터넷 찾아보니까 sleep(1000)하면 1초마다 쓰레드를 돌린다는 것 같은데...그러면 제가 위쪽에서 적었던 while(true)에서 계속 돌고있는게 아니라 run이 일정 주기로 호출되고 있다는 얘기인 것 같기도하고...머리가 복잡해서 정리가 잘 안됩니다 ㅠ.ㅠ...

기본적인 이해가 부족해서 질문도 좀 두서가 없지만 알려주시면 감사하겠습니다.

블로그에 만들고있는 어플의 실행 이미지를 올렸습니다. 여기 직접 첨부가 가능하지만 회사라서 제가 올린거긴 하지만 가끔 뜬금없는대서 악성코드로 잡아버리는 경우가있어 이미지 다운받기가 좀 무서워서 주소 적어놓겠습니다. 번거로우시겠지만 부탁드립니다.

http://blog.naver.com/ktshas/220035534372

 

gs낭천 (340 포인트) 님이 2014년 6월 20일 질문

3개의 답변

0 추천
 
채택된 답변
질문1. 생각하는게 맞고요.

질문2.  1ms당 1px이동이면 1초면 1000px이동이됩니다. 스마트폰 해상도를 생각하면 1초면 객체는 스마트폰 밖으로 벗어나 버리게됩니다. (매우 빠른 속도임)

그래도 1ms당 1px이동하고 싶으면 그려줄때 시간을 체크해서 걸린 시간 * 1px로 이동 시켜서 그려주면 원하는 속도가 나올겁니다.

한 화면을 그려주는데 최적은 30~40ms 정도 아닐까 생각합니다.

정확히 33ms에 한번씩 그려준다면 이동을 33px로하면  원하는 속도로 이동할것입니다.
q1212 (26,020 포인트) 님이 2014년 6월 24일 답변
gs낭천님이 2014년 6월 24일 채택됨
0 추천

질문1. 님이 알고계신것처럼 while문이 안빠져나가고 계속 루프하면서 그려주는게 맞습니다.

 

질문2. 간단하게 boolean 변수 하나 만들어서 기본적으로 false값을 가지고, touch가 되면 true를 되게 하시면 될겁니다.

while문 맨 마지막에 Thread.sleep(1000);을 넣어주시고 그다음에는

if(bTouch)

    characterX--;

 

머 이런식으로 원하는 변수값 조정해주시면 되요.

마피 (2,970 포인트) 님이 2014년 6월 20일 답변
0 추천
안드로이드가 realtime OS가 아니기 때문에 "정확하게 OO시간 간격마다 일정한 동작을 하고싶다" 는 것은 불가능합니다.

시간간격은 항상 대략적으로만 가능합니다.

 

참고로 기기 성능이 아무리 좋아도 화면 한 번 그리는데 1ms 보다는 시간이 더 걸립니다.

따라서 1ms 마다 뭔가를 수행하는 것은 불가능합니다.
익명사용자 님이 2014년 6월 20일 답변
...