Phát hiện va chạm làm chậm màn hình vẽ


8

Gần đây tôi đã theo đuổi phát triển trò chơi như một sở thích và quyết định rằng để tìm hiểu về phát triển trò chơi trong và ngoài, tôi nên tạo ra một trò chơi và tự thể hiện mọi thứ (không sử dụng công cụ trò chơi). Điều này đã được chứng minh khá phức tạp, tuy nhiên tôi đang có những tiến bộ lớn. Tuy nhiên, tôi đã gặp phải một vấn đề mà tôi nghĩ có thể liên quan đến cách điện thoại Android kết xuất đồ họa của họ và sẽ cần một số giải thích rõ ràng về vấn đề này.

Vấn đề

Trò chơi của tôi chứa một loạt các quả bóng trong một khẩu pháo; Khi người dùng nhấn vào màn hình, khẩu pháo sẽ phóng các quả bóng và động cơ (mà tôi đang thực hiện) xử lý các bản cập nhật cho thông tin vị trí và phát hiện va chạm từ đó. Bây giờ, trước khi tôi thực hiện phát hiện va chạm, trò chơi của tôi đã chạy rất mượt mà và nhạy bén, tuy nhiên khi tôi bảo động cơ chỉ rút hạt nếu nó nằm trong giới hạn và "bật" nó ra khỏi tường, thì có vẻ như là động cơ vòng lặp bây giờ mất một khoảng thời gian dài hơn đáng kể để chạy.

Điều này sẽ ổn, nếu không phải vì độ trễ mà nó đang cung cấp cho trải nghiệm người dùng. Ví dụ, khi màn hình được chạm vào bây giờ , phải mất ~ 2 giây để quả bóng được hiển thị là di chuyển xung quanh màn hình và đôi khi nó hoàn toàn không xuất hiện . Trước đây, phản ứng là tức thời.

Hơn nữa, khi tôi nhận xét phần phát hiện va chạm trong động cơ vật lý của mình, nó sẽ tiếp tục hành vi phản ứng thông thường của nó.

Những gì tôi nghĩ là gây ra hành vi này

Lưu ý: Tôi đã đọc lại giả định này (xem 'Thông tin gỡ lỗi' bên dưới)

Tôi nghĩ rằng vì tôi không có bộ giới hạn khung được triển khai cho trò chơi của mình và nó được hiển thị nhanh như phần cứng sẽ cho phép, nên nó đang vẽ rất nhiều khung hình cũ (trong một số bộ đệm, có thể?) Cho màn hình nó đang bận vẽ trong khi cần cập nhật vật lý. Mặc dù việc gỡ lỗi của tôi cho đến nay vẫn chưa chỉ ra rằng đây là trường hợp, tôi dường như không thể đi đến bất kỳ kết luận nào khác.

Một số mã

Lưu ý rằng mã này sẽ khá khó hiểu để không biết mọi thứ làm gì. Tôi chỉ đơn giản bao gồm nó trong trường hợp bất kỳ ai đặc biệt về việc có một số mã để làm việc với. Các biến được làm rõ bên dưới đoạn trích.

Vật lýEngine.updateBeadP vị trí (float) :

private void updateBeadPositions(float delta){

    //Update all of the beads currently on the board.
    beads = control.getBoard().getValues();

    temp_x = 0.0f;
    temp_y = 0.0f;

    //For each row...
    for(Bead[] row : beads){

        //For each bead...
        for(Bead bead : row){

            //If this bead exists...
            if(bead != null){

                temp_y = (float) (bead.getYCoordinate() * bead.getYVelocity() * delta);

                //If the coordinates are within the bounds of the game
                if(outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    bead.setYCoordinate(temp_y);
                }
            }
        }
    }

    //If the cannon Bead has been set...
    if(control.getCannon().getReleased() != null){

        //Update the cannon bead
        if(control.getCannon().getReleased().getXVelocity() == PhysicsEngine.VELOCITY_STATIC && control.getCannon().getReleased().getYVelocity() == PhysicsEngine.VELOCITY_STATIC){

            control.getCannon().getReleased().setXCoordinate(control.getCannon().getX());
            control.getCannon().getReleased().setYCoordinate(control.getCannon().getY() - Cannon.PIVOT_Y_OFFSET);
        }
        else{

            temp_x = control.getCannon().getReleased().getXCoordinate() + (control.getCannon().getReleased().getXVelocity() * delta);
            temp_y = control.getCannon().getReleased().getYCoordinate() + (control.getCannon().getReleased().getYVelocity() * delta);

            //TODO: Commented out collision checkers!

            //If the horizontal coordinates are within the bounds of the game
            if(!outwithHorizontalBounds(temp_x, control.getBoard())){

                //If the vertical coordinates are within the bounds of game
                if(!outwithVerticalBounds(temp_y, control.getBoard())){

                    //Set the X coordinate equal to the distance * the time differential (delta).       
                    control.getCannon().getReleased().setXCoordinate(temp_x);

                    //Set the X coordinate equal to the distance * the time differential (delta).
                    control.getCannon().getReleased().setYCoordinate(temp_y);
                }
                //Otherwise...
                else{

                    //Bounds off the wall in the y direction
                    control.getCannon().getReleased().setYVelocity(-1.0f * control.getCannon().getReleased().getYVelocity());
                }
            }
            //Otherwise...
            else{

                //Bounce off the wall in the x direction (flip the x velocity)
                control.getCannon().getReleased().setXVelocity(-1.0f * control.getCannon().getReleased().getXVelocity());
            }
        }
    }
}

Ở đây, các biến được định nghĩa là:

  • controllà một tài liệu tham khảo cho bộ điều khiển trò chơi của tôi. Nó gói phần lớn mã trò chơi.

  • beads là một tham chiếu đến mảng 2D có chứa các hạt trên bảng hiện tại (không bao gồm các hạt đang di chuyển)

  • delta là chênh lệch thời gian giữa các cuộc gọi trước với động cơ vật lý và cuộc gọi hiện tại

Xem các ý kiến ​​trong mã cho bất kỳ giải thích khác.

Vật lýEngine.outwithHTHERBound (float, Board) :

private boolean outwithHorizontalBounds(float x, Board board){

    //If the horizontal values are within the bounds...
    if(x > (board.getRight() - bead_radius)){

        return true;
    }

    if(x < (board.getLeft() + bead_radius)){

        return true;
    }

    //Otherwise, it is not.
    return false;
}

Phương pháp outwithVerticalBounds(float, Board)này có chức năng tương đương, nhưng theo hướng y.


Câu hỏi của tôi

Điều gì về phát hiện va chạm sẽ khiến kết xuất màn hình bị ức chế mạnh mẽ như vậy? Tôi biết đó là một hoạt động rất chuyên sâu, nhưng việc gỡ lỗi của tôi đã cho thấy rằng các bản cập nhật vật lý đang hoàn thành cùng lúc với các bản vẽ.

Thông tin gỡ lỗi

Cập nhật lần cuối: 29 tháng 1 năm 2013 4:27 PM EST

Dưới đây là tổng hợp các thông tin gỡ lỗi mà tôi đã thu được cho đến nay. Tôi sẽ cập nhật điều này khi thời gian tiến triển:

  • Các update()phương pháp trong động cơ của tôi, mất, trung bình, chỉ .018 msđể thực thi. Thông thường, độ trễ nhảy lên 0.020 ms, khi tôi chạm vào màn hình để nhả hạt.

  • Sau khi so sánh thời gian bốc thăm và cập nhật trò chơi, có vẻ như tôi đã đúng: chúng xảy ra đồng thời . Vì vậy, đây không thể là vấn đề, phải không?

  • Các FPScủa trò chơi là khoảng 87, nó gai ngẫu nhiên (vào cuối thấp) 60 FPS, tuy nhiên tăng vọt này là không liên quan đến việc phát hành của hạt. Không có FPSnhược điểm để làm điều này. Điều này có ý nghĩa vì phần duy nhất làm tăng độ phức tạp của nó sau khi hạt được phát hành là update()cuộc gọi, việc vẽ vẫn diễn ra nhanh nhất có thể.

  • Sau khi thử nghiệm thêm, rõ ràng đây không phải là trường hợp màn hình bị tụt lại phía sau vật lý. Tôi đã thử nghiệm điều này với một cờ boolean đơn giản trong đó nền màn hình sẽ chuyển sang màu trắng khi tôi chạm vào nó và điều này xảy ra ngay lập tức . Vì vậy, phải có một số nguyên nhân khác cho hạt không vẽ. Tôi sẽ cập nhật sớm.

Thông tin bổ sung

Dưới đây là một số thông tin bổ sung sẽ giúp bạn hiểu hoàn cảnh của tôi:

  • Tôi đang thử nghiệm điều này trên Google Nexus 7.

  • Có khá nhiều hạt trên bản đồ đang được cập nhật cùng một lúc (khoảng 30), nhưng chỉ một trong số chúng đang di chuyển.

  • Thông thường, sau khi hạt bắt đầu di chuyển (sau độ trễ ban đầu và nếu nó thực sự rút ra), sẽ tiếp tục di chuyển một cách rất trơn tru.

  • Điều quan trọng cần lưu ý là tôi có các thành phần UI khác trên màn hình cập nhật theo sự kiện chạm. Chẳng hạn, chuỗi hạt được nạp trong khẩu pháo trở thành chuỗi hạt mới khi màn hình được chạm vào (biểu thị rằng nó đã được giải phóng), nhưng hạt di động đơn giản là không được rút ra.


Nghĩ rằng việc gỡ lỗi của bạn cho thấy các cập nhật vật lý nội tuyến với các bản vẽ có thể không chính xác? Bạn đã thực hiện bất kỳ hồ sơ khác với mã này?
MichaelHouse

Tôi đã thực hiện một số gỡ lỗi mở rộng bằng cách sử dụng kết quả đầu ra cho bàn điều khiển (LogCat), tuy nhiên không có gì phức tạp hơn điều này. Nó có thể là trường hợp các tuyên bố gỡ lỗi của tôi là không chính xác, tôi sẽ xem xét chúng ngay bây giờ.
Squagem

Điều thú vị nữa là nếu FPS (Khung hình trên giây) thay đổi khi thêm trường hợp giới hạn hoặc vấn đề không liên quan đến tốc độ chương trình chạy.
Qqwy

Tôi đã chỉnh sửa câu hỏi của mình để trả lời những điểm bạn đã nêu ra.
Squagem

Câu trả lời:


8

Thành thật mà nói, tôi khá xấu hổ khi công bố giải pháp cho vấn đề của mình khi tôi dành nhiều giờ để tìm kiếm nó, và nó rất đơn giản và có thể tránh được một cách dễ dàng với một chút sơ suất thay cho tôi. Về mặt sáng sủa, cuối cùng tôi đã tìm thấy một vài đoạn mã khác mà bây giờ tôi có thể tối ưu hóa để có hiệu suất cao hơn nữa!

Giải pháp

Khẩu pháo đang phóng hạt nằm dưới ranh giới dưới của khu vực có thể chơi của tôi.

Điều này là sai lệch vì ranh giới dưới của khu vực chơi của tôi cao hơn một chút so với đáy màn hình thực của điện thoại. Vì vậy, về cơ bản, động cơ vật lý đã nảy nó trở lại và thứ tư hơi quá (vô hình với sự kiểm tra của con người) trong khoảng 5 giây trước khi nó được hiển thị trên màn hình.

Tôi đã di chuyển khẩu pháo cao hơn 50 pixel và nó hoạt động như dự định bây giờ.


Cảm ơn tất cả các bạn đã giúp đỡ! Tôi sẽ không đến đây mà không có gợi ý chu đáo của bạn.


3
+1 cho câu hỏi được định dạng tốt và +1 để tự trả lời câu hỏi
RoughPlace

Rất tiếc, quên câu hỏi này! Cảm ơn mọi người :)
Squagem
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.