Lưu trữ các bức tường nằm giữa gạch


8

Tôi đang viết công cụ isometric trong c ++. Tôi quyết định thực hiện một cách tiếp cận thực tế hơn và làm cho các bức tường chiếm không gian giữa hai viên gạch chứ không phải toàn bộ một viên gạch, như trong hình bên dưới (giống như trong The Sims).

đồ họa khái niệm về những gì tôi muốn đạt được

Vấn đề của tôi là tôi không biết làm thế nào để lưu trữ dữ liệu liên quan đến bản đồ ô vuông trong một cái gì đó không phải là lưới. Trong tình huống này, tôi đoán tôi sẽ cần làm cho nó trở nên thân thiện với A *, do đó sẽ có các nút và cạnh giữa các ô không được chia cho các bức tường. Đây là một hình ảnh khác cho thấy những gì tôi muốn đạt được:

Vì vậy, đây là câu hỏi:

Tôi nên như thế nào:

  • lưu trữ toàn bộ bản đồ, cả gạch và tường
  • tối ưu hóa nó để kết xuất
  • sử dụng nó cho A * và các thuật toán khác khá đơn giản để thực hiện trên một lưới đơn giản nhưng bây giờ sử dụng các bức tường (các cạnh) để xác định khả năng hiển thị, va chạm, v.v.?

Bạn có cần phải có thể xem nó từ các góc độ khác nhau? Nếu vậy, bạn sẽ muốn áp dụng các kết cấu khác nhau cho các mặt đối diện của cùng một bức tường? Hình nền màu hồng ở một bên, bên kia màu xanh?
jzx

Tôi sẽ cần khả năng xoay bản đồ và sử dụng các loại sơn và vật liệu khác nhau trên cả hai mặt của bức tường. Bây giờ tôi nghĩ rằng phần trên cùng của bức tường cũng nên hiển thị vật liệu bên trong bức tường (ví dụ: bê tông, gạch, gỗ)
Tchayen

Câu trả lời:


7

Tôi bắt đầu với các hệ tọa độ - tọa độ cho các vị trí lưới là (x, y) nhưng như Krom đã đề cập trong một câu trả lời khác, đối với các bức tường có thể có tới hai bức tường cho mỗi vị trí lưới. Điều đó dẫn đến một hệ tọa độ thứ hai, cho các cạnh giữa các ô . Trong bài viết này tôi đã sử dụng Tây và Nam để các cạnh có thể là (x, y, West) hoặc (x, y, South), nhưng bạn có thể chọn hai miễn là bạn nhất quán.

Tọa độ cạnh cho lưới ô vuông

Hai hệ tọa độ (gạch lưới và cạnh) có liên quan. Bạn sẽ muốn hỏi: bốn cạnh bao quanh một gạch?

Cạnh xung quanh một lát

Đối với tìm đường, A * muốn biết gạch nào là hàng xóm (B) của gạch hiện tại (A). Thay vì trả lại tất cả bốn gạch liền kề, bạn có thể kiểm tra bốn cạnh. Bạn chỉ bao gồm gạch B là hàng xóm nếu không có tường giữa A và B.

Thay vì lưu trữ hai bức tường cho mỗi ô, như Krom gợi ý, tôi thường giữ các bức tường trong một cấu trúc dữ liệu riêng biệt: một bộ tọa độ cạnh. Khi A * muốn biết B có phải là hàng xóm của A hay không, tôi sẽ kiểm tra xem cạnh đó có nằm trong tập hợp không. Nếu có, thì tôi không trả lại B.

Bạn có thể không cần điều này cho A *, nhưng đối với những thứ khác, bạn có thể muốn biết cho bất kỳ cạnh nào, hai ô được kết nối với nó:

Gạch bao quanh một cạnh

Xem phần Thuật toán của Phần cứng trên trang của Trang để biết các tính toán cho hai thao tác này.

Cũng lưu ý: đối với một số loại bản đồ, bạn thực sự sẽ muốn lưu trữ bốn cạnh trên mỗi ô lưới, để bạn có thể hỗ trợ di chuyển một chiều.


4

Trong mỗi ô bạn có thể lưu trữ các bức tường nó có ở phía Bắc và Đông. Bằng cách đó, mỗi ô chỉ cần lưu trữ thêm 2 booleans (hoặc ints, nếu bạn muốn lưu trữ loại tường). Nhược điểm là gạch dọc theo rìa Nam và Tây không thể có tường ở Nam và Tây trừ khi bạn thêm một hàng gạch ẩn sẽ có chúng.


2

Trong mỗi ô, nó có thể lưu trữ hàng xóm (hoặc kết nối) mà nó có quyền truy cập. Có lẽ là một bitmap. Các bức tường là nơi hai gạch liền kề không được kết nối. Điều này rất thân thiện với A *.

Cách tiếp cận thứ hai là lưu trữ kết nối của gạch dưới dạng liệt kê. Ví dụ: một ô mở hoàn toàn là 0, một ô có tường ở phía bắc và phần còn lại mở là 1, một ô có tường ở phía nam và phần còn lại mở là 2, và cứ thế cho đến khi bạn bao quát tất cả các kết hợp có thể.


Tôi không nghĩ nhận xét của bạn "thân thiện với A *" thực sự áp dụng, vì nó giả sử giao diện ("gạch nào liền kề?") Phải phù hợp với việc triển khai ("hàng xóm cửa hàng gạch"). Cả hai có thể khác nhau, ví dụ nếu bạn sử dụng cấu trúc dữ liệu riêng cho các bức tường như amitp gợi ý.
congusbongus

1

Hy vọng rằng C # này phù hợp với bạn - c ++ của tôi rất hoen rỉ:

abstract class MapFeature
{
    public void Draw();
    public bool IsWall();
}
enum Direction
{
    North, South, East, West
}
class Wall : MapFeature
{
    public bool IsWall() { return true; }
    public Tile Front, Back; // Tiles on either side of the wall, otherwise null.

    #region Implementation of MapFeature

    public void Draw()
    {
        // Wall specific drawing code...
    }

    #endregion
}
class Tile : MapFeature
{
    public bool IsWall() { return false; }

    public MapFeature North, South, East, West; // Tiles/Walls on each side, otherwise null

    public bool CanGo(Direction direction)
    {
        switch (direction)
        {
            case Direction.North:
                return !North.IsWall();
            case Direction.South:
                return !South.IsWall();
            case Direction.East:
                return !East.IsWall();
            case Direction.West:
                return !West.IsWall();
            default:
                throw new ArgumentOutOfRangeException("direction");
        }
    }

    #region Implementation of MapFeature

    public void Draw()
    {
        // Tile specific drawing code...
    }

    #endregion
}

Bạn có thể thêm thông tin dành riêng cho tường vào lớp Tường, thông tin cụ thể của Ngói cho lớp Ngói và điều chỉnh thêm các điều kiện trong phương thức "CanGo". Ví dụ, khi một bức tường thực sự là một cánh cửa bị khóa - giả sử, một lớp Cửa.

Để vẽ cái này, bạn sẽ bắt đầu với một số ô tùy ý - giả sử ô ở giữa vị trí máy ảnh hiện tại. Sau đó di chuyển về phía bên trái và bên trái của máy ảnh theo kích thước của gạch. Sau đó thực hiện một lần di chuyển ngang đầu tiên của các nút IMapFeature, vẽ từng bức tường / gạch theo thứ tự gặp phải.

A * sẽ hoạt động trên cấu trúc này, mặc dù bạn rõ ràng sẽ cần một số sửa đổi để xử lý một cái gì đó như cửa bị khóa.

Nếu bạn muốn, bạn cũng có thể duy trì một chỉ số không gian của các ô, bao gồm cả các bức tường, để tìm ra các ô nằm trong giới hạn camera.

Bạn vẫn chỉ cần chọn một ô bắt đầu và khoảng cách để di chuyển ngang dựa trên kích thước ô.

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.