Chỉ hiển thị những gì trên màn hình


6

Tôi khá mới mẻ với thế giới này, vì vậy hãy chịu đựng tôi.

Tôi có một mạng lưới các khối trong trò chơi 2d từ trên xuống được viết bằng Slick. Cách tốt nhất để nghĩ về nó là thế giới Pokemon.

Ngay bây giờ, tôi đang hiển thị tất cả các khối trên một bản đồ cụ thể, cho dù chúng có ở trên màn hình hay không.

Có cách nào tốt hơn để làm điều này? Suy nghĩ của tôi có lẽ là cố gắng tạo ra một hình ảnh từ những gì tôi sẽ kết xuất và lấy phần phù hợp với màn hình để kết xuất. Tôi không biết làm thế nào để làm điều này, nhưng tôi muốn hỏi ý kiến ​​các chuyên gia trước khi tôi nghiên cứu về nó. Cảm ơn! ;)

BIÊN TẬP

Chỉ cần nghĩ rằng tôi sẽ thêm rằng Slick có cách xử lý việc cắt trong các trường hợp chuyên biệt cũng như chế độ xem của màn hình. Xem trang Wiki để biết thêm.


1
Có, bạn chỉ nên hiển thị những gì trên màn hình. Có lẽ cũng có một bộ đệm nhỏ ở bên ngoài để bạn không bị rung hình dọc theo cạnh nếu người chơi di chuyển nhanh. Tôi không biết nếu java / slick cung cấp một cách xây dựng để làm điều này mặc dù. Tôi sẽ tưởng tượng họ làm.

Câu trả lời:


11

Một cách để làm điều này là kiểm tra hộp giới hạn của khối so với hộp giới hạn của chế độ xem hiện tại (cộng thêm một chút cho an toàn).

Nếu khối tương tác với chế độ xem (hoàn toàn bên trong hoặc được cắt bớt) thì hãy vẽ nó. Nếu nó không - tức là hoàn toàn bên ngoài thì đừng vẽ.

Kiểm tra này có thể được thực hiện khá nhanh chóng - đặc biệt là trong 2D. Bạn không cần phải biết bao nhiêu khối có thể nhìn thấy - chỉ là một phần của nó có khả năng hiển thị.

Nếu tọa độ X tối đa của khối nhỏ hơn tọa độ X tối thiểu của chế độ xem hoặc tọa độ X tối thiểu của khối lớn hơn tọa độ X tối đa của chế độ xem thì khối này chắc chắn là vô hình. Thử nghiệm tương tự có thể được thực hiện trên tọa độ Y.

Như Joe chỉ ra là nhận xét khung / thư viện bạn đang sử dụng có thể có chức năng này được tích hợp.


2

Làm một cái gì đó như thế này:

if (renderX >= 0 && renderY >= 0
    && renderX <= container.getWidth() && renderY <= container.getWidth()) {
    //Render
}

Nó sẽ phải được tùy chỉnh cho từng đối tượng vì mỗi đối tượng có kích thước khác nhau. Tôi kết xuất từng nhóm thành phần riêng biệt. Nếu bạn đang sử dụng TiLeD, đây là một đoạn mã hay mà tôi đã tạo:

TiledMap map = mapComp.getMap();

    //Render positions as integers
    int renderX = (int) renderPos.getX();
    int renderY = (int) renderPos.getY();

    //Render offset for map
    int xRenderOffset = renderX % 32;
    int yRenderOffset = renderY % 32;

    //Get the first tile to be rendered
    int firstTileX = (int) -renderX / 32;
    int firstTileY = (int) -renderY / 32;

    //Render tiles only if their indices are greater than 0
    if (firstTileX < 0) {
        xRenderOffset += Math.abs(firstTileX) * 32;
        firstTileX = 0;
    }

    if (firstTileY < 0) {
        yRenderOffset += Math.abs(firstTileY) * 32;
        firstTileY = 0;
    }

    //Get the last tile to be rendered
    int lastTileX = firstTileX + (client.getContainer().getWidth() / 32) + 1;
    int lastTileY = firstTileY + (client.getContainer().getHeight() / 32) + 2;

    //Verify that the last tile is valid
    if (lastTileX > 127) {
        lastTileX = 127;
    }

    if (lastTileY > 127) {
        lastTileY = 127;
    }

    //Check if the map will be visible on the screen
    if (lastTileX >= 0 && lastTileY >= 0) {
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 0, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 1, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 2, true);
        map.render(xRenderOffset, yRenderOffset, firstTileX, firstTileY, lastTileX, lastTileY, 3, true);
    }

32 là chiều rộng ô của bạn và 127 là kích thước bản đồ của bạn - 1.


Một chút mã đẹp, nhưng tôi sẽ không dùng TiLeD trên cái này. Tôi đã quyết định tung ra cách xử lý bản đồ của riêng mình mà tôi đang tận hưởng khá tốt. Nó dựa trên việc triển khai tệp văn bản của bộ khởi động Platformer do Microsoft đưa ra. +1. :)
Andy

1

Nếu các khối của bạn có kích thước đồng đều (như trường hợp trong các trò chơi Pokemon cổ điển) và được lưu trữ trong mảng 2d, thì có lẽ cách tốt nhất để làm điều này là chỉ thực hiện các vòng lặp, đại loại như sau:

int startX = playerX - halfWidth;
int startY = playerY - halfHeight;

for( int x = startX , maxX = playerX + halfWidth; x < maxX; ++x )
{
    for( int y = startY , maxY = playerY + halfHeight; y < maxY; ++y )
    {
        DrawBlock( x - startX, y - startY, tiles[x][y] );
    }
}

trong đó HalfWidth và HalfHeight bằng một nửa chiều rộng và chiều cao của màn hình. Điều này sẽ cắt các cuộc gọi đến DrawBlock xuống chỉ những cuộc gọi hiển thị. Nếu bạn đang cuộn quanh lưới, thì bạn có thể vẽ một ô bổ sung theo từng hướng và thêm các giá trị bù hoạt hình của bạn vào các tham số DrawBlock nếu cần.

Cần phải đề cập rằng phương pháp này là bổ sung cho phương pháp cắt mà bạn đã liên kết đến trong chỉnh sửa của mình. Sử dụng phương pháp tôi đã trình bày ở đây, cắt sẽ hữu ích nếu các khối của bạn không chiếm toàn bộ màn hình (ví dụ: có một đường viền xung quanh chúng cho Giao diện người dùng), để ngăn các khối bổ sung được vẽ cho mục đích hoạt hình từ được rút ra trên các yếu tố khác. Trong trường hợp này, bạn sẽ đặt vùng cắt của mình chính xác là không gian nơi bạn muốn hiển thị lưới của mình và sau đó chỉ vẽ các khối tối thiểu cần thiết.


đề nghị tốt! Dường như Slick xử lý những điều này một cách duyên dáng trong nền, do đó, việc thêm mã của riêng tôi để xử lý việc cắt xén là không cần thiết.
Andy
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.