Định dạng tệp mở rộng tùy chỉnh cho bản đồ lát gạch 2d


8

Tôi đã triển khai phần lớn logic trò chơi của mình ngay bây giờ, nhưng vẫn tạo ra các bản đồ của mình với các vòng lặp khó chịu khi đang di chuyển để có thể làm việc với một cái gì đó. Bây giờ tôi muốn tiếp tục và thực hiện một số nghiên cứu về cách (un) tuần tự hóa dữ liệu này. (Tôi không tìm kiếm trình chỉnh sửa bản đồ - Tôi đang nói về chính tệp bản đồ)

Hiện tại tôi đang tìm kiếm các đề xuất và tài nguyên, cách triển khai định dạng tệp tùy chỉnh cho bản đồ của mình để cung cấp chức năng sau (dựa trên phương pháp MoSCoW):

  • Phải có
    • Khả năng mở rộng và tương thích ngược
    • Xử lý các lớp khác nhau
    • Siêu dữ liệu về việc một lát có vững chắc hay có thể được truyền qua
    • Tuần tự hóa đặc biệt của các thực thể / kích hoạt với các thuộc tính / siêu dữ liệu liên quan
  • Đã có thể
    • Một số loại bao gồm các ô để tránh có các tệp / ô phân tán

Tôi đang phát triển với C ++ (sử dụng SDL) và chỉ nhắm mục tiêu Windows. Bất kỳ trợ giúp hữu ích, mẹo, đề xuất, ... sẽ được đánh giá cao!


Kết quả của cuộc thảo luận dưới đây

Tôi đã thiết kế định dạng tệp bản đồ của mình trong vài giờ qua và đưa ra một bộ xương (hiện chỉ chứa các lớp - Tôi sẽ để phần còn lại cho mọi người thiết kế định dạng của riêng mình) mà tôi muốn chia sẻ với mọi người quan tâm - nếu bạn có cùng ý định bạn có thể có được một loại cảm hứng. Ảnh chụp màn hình kích thước đầy đủ có thể được tải xuống tại Imgur .

Định dạng tệp bản đồ Kore


2
XML là một định dạng tuyệt vời để bắt đầu, tương thích ngược, có thể mở rộng, bạn có thể thêm bất kỳ thông tin và siêu dữ liệu nào bạn muốn. Có nhiều hỗ trợ để đọc, soạn thảo và chỉnh sửa XML. Hỗ trợ tuần tự hóa đến và từ XML tồn tại cho mọi ngôn ngữ. Nhược điểm của nó là không gian khá hiệu quả, điều này có thể được cải thiện bằng cách sử dụng phiên bản nhị phân hoặc sử dụng nén zip trên chính tệp. Dù sao đi nữa, đây là điểm khởi đầu tốt để tạo các định dạng tệp của riêng bạn
Daniel Carlsson

@DanielCarlsson: Như đã đề cập trong câu trả lời được chấp nhận bên dưới, tôi sẽ sử dụng XML ngay từ đầu để có một cái gì đó hữu ích để gỡ lỗi và làm việc với. Sau này tôi sẽ chuyển sang một định dạng nhị phân tùy chỉnh. Tuy nhiên, được nâng cấp bởi vì XML là kết hợp tuyệt vời với libs RapidXML trong C ++.
Christian Ivicevic

Câu trả lời:


6

Cá nhân, tôi là một fan hâm mộ của các định dạng nhị phân với các phần (như Windows PE, đơn giản hơn nhiều). Chúng cũng dễ phân tích hơn (nhưng đó chỉ là ý kiến ​​của tôi .... Tôi đã làm việc với XML đủ để khiến tôi đau đầu, kiểm tra xem getEuityByName đã trả về một giá trị hay danh sách các giá trị ... ugh). Vì vậy, nếu tôi là bạn, tôi sẽ biến nó thành như thế này:

".MMF\0" // magic value at the start, null-terminated string. stands for My Map Format :)
    char header_length // useful when parsing. char is a byte, of course, an unsigned one
    char version // version of the map file. (you don't really need ints here, because you probably won't be needing more than 255 versions for example, but you can also use them)
    char* map_name // null terminated string describing the name of the level/map
    char* author_name // if you are going to have a map editor for the general public, it would be nice to credit the person who made the map
    int width // it's probably wise to plan ahead and expect an int here when you're parsing the file
    int height
    ".layer\0" // we begin another subsection
        char header_length
        char type // type of the layer. for example, you can put 1 there if you want this to be a layer describing different tiles/block in a Terraria like game
        ".data\0" // yet another subsection. this will hold the data for the tiles
                  // in a hypothetical terraria 2d game, you would lay down tiles from
                  // the top-right corner (0,0) and then begin writing row after row
                  // write(1,0); write(2,0); write(3,0); ... then write(0,1); write(1,1);
                  // write(2,1); write(3,1); and so on..
            char t1 // tile at (0,0). for example, value 0 is empty, or passable tile
            char t2 // tile at (1,0). this might be a dirt block - value 1
            char t3 // tile at (2,0). a rock, perhaps? value 3
            (...)
            char tn // tile at (width-1, height-1) or the bottom-left tile
    ".layer\0" // another layer.
        char header_length    
        char type // let this on be of value 2, and let it describe portals.
                  // putting portals in a game makes it instantly 20% cooler
        ".data\0"
            char t1  // 0, no portal here at tile (0,0)
            char t2  // still nothing
            char t3  // nope, try again
            (...)
            char t47 // at some location, you made a red portal. let's put 1 here so we can read it in our engine
            (...)
            char t86 // looke here, another 1! you can exit here from location corresponding to t47
            (...)
            char t99 // value 2. hm, a green portal?
            (...)
            char tn  // bottom-left tile, at (width-1, height-1)
    ".layer\0" // another layer
        char header_length
        char type // value 3, player&enemies spawn points
        char something // you don't have to have header len fixed. you can add stuff later
                       // and because you were smart enough to put header length 
                       // older versions can know where the stuff of interest lays
                       // i.e. version one of the parser can read only the type of layer
                       // in version two, you add more meta-data  and the old parser
                       // just skips it, and goes straight to the .data section
            ".data\0"
                char t1  // zero
                char t2  // zero
                char t3  // zero
                (...)
                char t42 // a 1 - maybe the player spawn point. 5 tiles to the right
                         // there's a red portal
                (...)
                char t77 // a 2: some enemy spawn point
                (...)
                char tn  // last tile

,

Ưu điểm:

  • Trông thật hấp dẫn.
  • Làm cho bạn nghĩ rằng bạn biết một cái gì đó về lập trình, làm công cụ theo cách cũ.
  • Bạn có thể tự viết các cấp của mình trong trình soạn thảo hex:
  • Nói chung nhanh hơn INI và XML, cả từ quan điểm viết và đọc
  • Đó thực sự là một luồng dữ liệu byte dài. Không cần phải dành thời gian để làm cho nó trông đẹp, thụt vào (như những gì bạn muốn làm với XML).
  • Thật dễ dàng để thêm công cụ trong các tiêu đề. Nếu một phần dữ liệu xuất hiện ở dưới cùng của tiêu đề, các phiên bản cũ của trình phân tích cú pháp có thể được hướng dẫn để tránh nó và chuyển đến phần của tệp mà họ hiểu.

Nhược điểm:

  • Bạn phải chăm sóc tốt vị trí dữ liệu.
    • Các trường dữ liệu phải được đặt hàng.
    • Bạn phải biết kiểu của chúng trong trình phân tích cú pháp - như tôi đã nói, nó chỉ là một chuỗi byte dài.
    • Di chuyển dữ liệu theo một vị trí (ví dụ: bạn quên ghi loại lớp; trình phân tích cú pháp mong đợi một byte ở đó và nó tìm thấy giá trị của '.' - điều đó không tốt) làm rối tung toàn bộ mảng dữ liệu từ điểm đó trở đi.
  • Khó nhảy ngay vào - không có API, không có chức năng như getLayerWidth () - bạn phải tự thực hiện tất cả điều đó.
  • Có khả năng rất nhiều không gian lãng phí. Lấy lớp thứ ba chẳng hạn. Nó chắc chắn sẽ được đóng gói với rất nhiều số không. Điều này có thể được phá vỡ mặc dù nếu bạn sử dụng một số loại nén. Nhưng một lần nữa, điều đó lại gây rối với những thứ cấp thấp một lần nữa ...

Nhưng điều tốt nhất trong cách tiếp cận này theo ý kiến ​​của tôi là - bạn có thể tự làm tất cả. Rất nhiều thử và sai, nhưng cuối cùng, bạn đã học được rất nhiều.


Bạn chỉ đang lưu ... giả sử ID cho các ô xếp, nhưng còn siêu dữ liệu của chúng thì sao? Làm thế nào tôi nên lưu liệu gạch có thể vượt qua hay không? Điều gì về các kích hoạt và thậm chí có thể gọi các kịch bản / mã / hàm gọi liên quan đến chúng?
Christian Ivicevic

@ChristianIvicevic: Có một số cách để làm điều đó:
Vladimir Mitrovic

@ChristianIvicevic: 1. Đóng gói siêu dữ liệu trong một byte đơn. Bạn chỉ có tám gạch có thể? Tuyệt vời, tiết kiệm năm bit còn lại cho một cái gì đó khác. Trong trường hợp của bạn, bạn đã hỏi về gạch có thể vượt qua. Bạn có thể có bit đầu tiên (bit thứ 0) lưu trữ thông tin đó. Một chút thao tác bit :) sẽ thực hiện thủ thuật ( codepad.org/Q6zfTV44 ). 2. Sử dụng các lớp cho điều đó. Có một lớp với một loại duy nhất và làm cho nó chứa đầy các số 0 và một, các lớp cho các ô có thể vượt qua và các số 0 cho các ô không thể vượt qua. 3. Sử dụng nhiều hơn một byte cho mỗi ô. Một byte cho giá trị, cái kia cho siêu dữ liệu.
Vladimir Mitrovic

@ChristianIvicevic: Đối với tập lệnh, tôi cho rằng bạn đã triển khai trình phân tích cú pháp tập lệnh hoạt động. Bạn có thể thêm một phần vào tệp bản đồ của mình và đặt chúng ở đó: pastebin.com/yUKncz19 HOẶC Bạn có thể đặt chúng vào một tệp riêng và lưu tên tệp trong phần ".scripts". Sau đó, bạn chuẩn bị một phần ".layer" khác mô tả gạch nào phát ra tập lệnh nào: pastebin.com/BgPCR2xQ
Vladimir Mitrovic

Khá nhiều ví dụ - HÀNG ĐẦU! Bây giờ tôi sẽ sử dụng XML để tạo một số mức cơ bản để gỡ lỗi / làm việc và cuối cùng tôi sẽ chuyển sang định dạng nhị phân như bạn đã mô tả cho mapfile thô giữ dữ liệu và đóng gói tệp này bằng cả hai ô (png, v.v.) và scriptfile (s) thành một zip để mọi thứ được cấu trúc theo cách tốt hơn. Nó sẽ tùy thuộc vào việc viết mã, mà thực sự đọc dữ liệu nhị phân như vậy - nhưng đó là một chủ đề khác trong câu chuyện của tôi ... cảm ơn!
Christian Ivicevic

9

Bạn có thể sử dụng định dạng bản đồ TMX được sử dụng bởi trình chỉnh sửa Tiled (cũng như một số trình chỉnh sửa bản đồ khác).

Ngay cả khi bạn không sử dụng Tiled mình, định dạng TMX hỗ trợ tất cả các chức năng bạn đã đề cập và nó có một số trình tải / phân tích cú pháp hiện có cho nhiều ngôn ngữ. Cũng rất dễ hiểu định dạng và mở rộng nó cho trò chơi của riêng bạn.


Tôi sẽ có khái niệm XML hiện tại của mình dựa trên một chút về định dạng bản đồ TMX và sau đó đọc tất cả các tệp bằng RapidXML - sau này tôi sẽ chuyển sang một số định dạng tệp nhị phân tùy chỉnh.
Christian Ivicevic
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.