2009-09-22 42 views
13

Tôi đang cố gắng tạo một trò chơi android.Tại sao không phải là view.invalidate ngay lập tức vẽ lại màn hình trong trò chơi android của tôi

Tôi có một lớp trò chơi mở rộng hoạt động và xử lý tất cả các thao tác nhập của người dùng. Sau đó, tôi có một lớp missionView mở rộng tầm nhìn và nó vẽ mức trên màn hình.

Khi người dùng nhấp vào cửa, tôi muốn thêm một số hoạt ảnh.

Điều gì xảy ra là: Trò chơi gọi door.open. Thay đổi trạng thái sao cho hàm view.onDraw sẽ vẽ cửa mở một nửa. Trò chơi gọi view.invalidate, sẽ vẽ lại màn hình. Sau đó, trò chơi sẽ ngủ trong nửa giây. Sau đó, nó gọi door.open một lần nữa. Lần thứ hai hàm được gọi là nó thay đổi trạng thái sao cho hàm view.onDraw vẽ cửa hoàn toàn mở. Sau đó, trò chơi gọi lại view.invalidate.

Vấn đề là nó không vẽ lại màn hình khi nó được xem.không hợp lệ. Nếu tôi đặt một điểm ngắt trên dòng và chạy trình gỡ lỗi và nhấp vào bước đó, nó sẽ không chuyển sang hàm view.onDraw của tôi. Nó thậm chí không thể cho tôi thấy mã nó đang thực thi.

Những gì tôi có là: lớp Door:

public boolean open() 
{ 
    if (doorState == DoorState.Closed) 
    { 
     doorState = DoorState.Opening; 

     return true; 
    } 
    else if (doorState == DoorState.Opening) 
    { 
     doorState = doorState.Open; 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

lớp Trò chơi:

if (tile instanceof DoorTile) 
{ 
    DoorTile doorTile = (DoorTile) tile; 
    Door door = doorTile.getDoor(); 

    if (door.isClosed()) 
    { 
     door.open(); 
     selectedEntity.openDoor(); 
     view.invalidate(); // This line does not work 

     try 
     { 
      Thread.sleep(500); 
     } 
     catch (InterruptedException e1) 
     { 
      // TODO Auto-generated catch block 
      e1.printStackTrace(); 
     } 
     door.open(); 

     // Handled touch event so break switch statement 
     break; 
    } 
} 
+0

Tôi đã đọc cuộc thảo luận này, nhưng tôi đã không hiểu những gì tôi đã làm để làm cho mã của tôi hoạt động. Tôi đã không hiểu cách sử dụng "Trình xử lý" và "Thông báo". –

+0

Bạn có thể muốn xem thảo luận liên quan tại http://stackoverflow.com/questions/2801877/android-why-wont-invalidate-update-my-buttons-immediately –

Trả lời

22

Quan điểm thứ vô hiệu kể hệ thống để vẽ lại (thông qua onDraw) quan điểm càng sớm càng thread chính đi nhàn rỗi. Tức là, gọi vô hiệu hóa lịch trình xem của bạn để được vẽ lại sau khi tất cả các công việc ngay lập tức khác đã hoàn thành. Nếu mã trong lớp Trò chơi của bạn đang được gọi từ chủ đề chính và nó đặt chuỗi đó vào chế độ ngủ, bạn không chỉ tạm dừng hiển thị, bạn đang tạm dừng xử lý đầu vào tất cả cùng nhau (thường là ý tưởng tồi). Như một quy tắc của ngón tay cái, không bao giờ ngủ một sợi mà bạn không đẻ trứng mình trừ khi bạn biết những gì bạn đang làm.

Nếu bạn muốn logic trò chơi của bạn định kỳ trì hoãn bằng cách sử dụng Thread # sleep thì hãy chạy nó trong một chuỗi riêng biệt và sử dụng view.postInvalidate() để báo hiệu luồng chính để đánh thức và gọi onDraw.

+2

Chỉ cần thêm ... trừ khi bạn thực hiện chủ đề của riêng tất cả các mã của bạn thực hiện trong chuỗi giao diện người dùng. Nếu bạn ngủ hoặc làm rất nhiều tính toán trong chủ đề này, nó sẽ gặp một giao diện người dùng ít đáp ứng hơn và cuối cùng bạn sẽ nhận được một hộp ứng dụng không trả lời (ANR). – Will

14

Đối với trò chơi, tôi thực sự sẽ sử dụng quyền truy cập cấp thấp hơn vào đồ họa. LunarLander từ Google là một ví dụ tuyệt vời cho điều đó. Về cơ bản bạn cần phải làm hai việc:

  • thay vì sử dụng Xem SurfaceView
  • get handler từ SurfaceView
  • thay view.invalidate() với phương pháp tùy chỉnh repaint() mà sẽ chứa

    private void repaint() { 
        Canvas c = null; 
        try { 
        c = surfaceHolder.lockCanvas(); 
        paint(c); 
        } finally { 
        if (c != null) { 
         surfaceHolder.unlockCanvasAndPost(c); 
        } 
        } 
    } 
    

Phương pháp sơn sẽ chứa những gì bạn có trong Chế độ xem.Xuất hiện tại

+0

Tôi đã làm những gì bạn nói. Nó hoạt động ... loại. Cửa bây giờ hoạt hình nhưng bây giờ đồ họa bị trục trặc khi tôi cuộn quanh màn hình. Tôi có một gesturelistener trong lớp trò chơi của tôi mà vẽ lại màn hình khi người dùng cuộn bằng ngón tay của họ. Nó cho phép bạn cuộn quanh bản đồ. Nó sử dụng để vẽ tốt. Nhưng bây giờ tôi nhận được một nửa màn hình được vẽ và nửa còn lại không được cập nhật trong nửa giây trước khi nó tự sửa chữa. –

+2

Sử dụng các lớp xem khác nhau không giải quyết vấn đề này. Nó là cần thiết để hiểu không bao giờ EVER gọi ngủ trong chủ đề chính và sự vô hiệu hóa không kích hoạt vẽ ngay lập tức mà là "nhớ" các khu vực cần vẽ lại lần sau khi chuỗi giao diện người dùng có cơ hội làm như vậy. – Zordid

0

Tôi đã gặp phải sự cố tương tự trong đơn đăng ký của mình.

Trong trường hợp của tôi, tôi đang cố gắng gọi invalidate() từ phương thức [doInBackground()][1] của [AsyncTask][2].

Sự cố đã được giải quyết bằng cách di chuyển invalidate() đến [onProgressUpdate()][3] phương thức AsyncTask. I E.bạn không thể cập nhật giao diện người dùng từ phương thức doInBackground() của AsyncTask. Nó được đề cập trong tài liệu Android, nhưng nó rất dễ dàng để quên nó ... vì vậy, đừng quên kiểm tra nó.

Các vấn đề liên quan