비트맵과 쓰레드로 캐릭터가 움직이게 만든 클래스를 하나의 뷰로 넣는 방법이 있을까요??

조회수 1389회

비트맵과 스레드를 이용해서 캐릭터가 움직이고 벽에 부딪힐 때마다 방향을 바꾸게한 클래스를 XML 레이아웃에 하나의 뷰로 넣고 싶은데 어떻게 해야 될까요? 실행 시 뻑이 나는데 에러 메시지를 봐도 이유를 잘 모르겠습니다ㅠㅠ 직관적으로 생각했을 때 이렇게하면 될 것 같은데 어느 부분을 잘 못하고 있는지 알려주신다면 정말 감사하겠습니다.

캐릭터를 움직이게 하는 클래스

class CharacterView extends View {
    int width, height;                                // 화면의 폭과 높이
    int x, y;                                                 // 캐릭터의 현재 좌표
    int dx, dy;                                            // 캐릭터가 이동할 방향과 거리
    int cw, ch;                                           // 캐릭터의 폭과 높이
    int counter;                                        // 루프 카운터
    Bitmap character[] = new Bitmap[2];       // 캐릭터의 비트맵 이미지
    LinearLayout character_field = (LinearLayout)findViewById(R.id.character_field);


    public CharacterView(Context context) {
        super(context);

        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        width = character_field.getWidth();            // 화면의 가로폭
        height = character_field.getHeight();         // 화면의 세로폭
        x = 100;                                      // 캐릭터의 현재 x위치
        y = 100;                                       // 캐릭터의 현재 y위치
        dx = 2;                                        // 캐릭터가 x축으로 이동할 거리
        dy = 3;                                        // 캐릭터가 y축으로 이동할 거리

        // 캐릭터의 비트맵 읽기
        character[0] = BitmapFactory.decodeResource(getResources(), R.drawable.tmp1);
        character[1] = BitmapFactory.decodeResource(getResources(), R.drawable.tmp2);

        cw = character[0].getWidth() / 2;          // 캐릭터의 폭/2
        ch = character[0].getHeight() / 2;          // 캐릭터의 높이/2

        mHandler.sendEmptyMessageDelayed(0, 10);
    }

    //-----------------------------------
    //       실제 그림을 그리는 부분
    //-----------------------------------
    public void onDraw(Canvas canvas) {
        x += dx;                                               // 가로 방향으로 이동
        y += dy;                                                // 세로 방향으로 이동

        if (x < cw || x > width - cw) dx = -dx;    // 좌우의 벽이면 방향을 바꿈
        if (y < ch || y > height - ch) dy = -dy;     // 천정이거나 바닥이면 방향을 바꿈

        counter++;
        int n = counter % 20 / 10;
        canvas.drawBitmap(character[n], x - cw, y - ch, null);
    } // onDraw 끝

    //------------------------------------
    //      Timer Handler
    //------------------------------------
    Handler mHandler = new Handler() {               // 타이머로 사용할 Handler
        public void handleMessage(Message msg) {
            invalidate();                              // onDraw() 다시 실행
            mHandler.sendEmptyMessageDelayed(0, 10); // 10/1000초마다 실행
        }
    }; // Handler
} // GameView 끝

XML 레이아웃

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"   
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <LinearLayout
        android:id="@+id/character_field"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:orientation="horizontal"
        android:gravity="center"
        >

        <helloworld.sdh.com.termex04.CharacterView
            android:layout_height="match_parent"
            android:layout_width="match_parent"

        />

    </LinearLayout>

메인액티비티

public class LockActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_lock);
        //CharacterView cv = new CharacterView(this);
        //LinearLayout character_field = (LinearLayout)findViewById(R.id.character_field);
        //character_field.addView(cv);
    }
}

![이미지][1]

이미지

  • (•́ ✖ •̀)
    알 수 없는 사용자

1 답변

  • 첫번째 에러 화면은 View 클래스의 파리미터가 두개인 생성자를 오버라이드 하지 않아서 발생하는 에러입니다. 작성하신 CharacterView 코드에 다음과 같이 CharacterView(Context context, AttributeSet attrs) 생성자를 오버라이드 해보세요.

    public CharacterView(Context context) {
        this(context, null);
    }
    
    public CharacterView(Context context, AttributeSet attrs) {
        Display display = ((WindowManager) context.getSystemService(Context.WINDOW_SERVICE))
                .getDefaultDisplay();
        width = character_field.getWidth();            // 화면의 가로폭
        height = character_field.getHeight();         // 화면의 세로폭
        x = 100;                                      // 캐릭터의 현재 x위치
        y = 100;                                       // 캐릭터의 현재 y위치
        dx = 2;                                        // 캐릭터가 x축으로 이동할 거리
        dy = 3;                                        // 캐릭터가 y축으로 이동할 거리
    
        // 캐릭터의 비트맵 읽기
        character[0] = BitmapFactory.decodeResource(getResources(), R.drawable.tmp1);
        character[1] = BitmapFactory.decodeResource(getResources(), R.drawable.tmp2);
    
        cw = character[0].getWidth() / 2;          // 캐릭터의 폭/2
        ch = character[0].getHeight() / 2;          // 캐릭터의 높이/2
    
        mHandler.sendEmptyMessageDelayed(0, 10);
    }
    
    

    View의 생성자가 호출되는 시점에 대해 설명하면 첫번째 생성자는 View를 코드에서 생성할 때, 두번째 생성자는 XML을 통해 View를 inflating할 때 호출됩니다. 그렇기 때문에 XML을 통해 View를 생성할 때는 두번째 생성자를 오버라이드 해야 됩니다.

    생성자 관련해서 좀 더 자세한 내용은 다음 링크의 질문과 답변을 참고하세요.

    • (•́ ✖ •̀)
      알 수 없는 사용자
    • 긴 코드에도 불구하고 귀중한 답변 주신것에 감사드립니다. 알 수 없는 사용자 2016.6.4 19:18

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)