Thiết kế một động cơ dựa trên gạch linh hoạt


8

Tôi đang cố gắng tạo ra một công cụ trò chơi dựa trên gạch linh hoạt để tạo ra tất cả các loại trò chơi giải đố không có thời gian thực, giống như Bejeweled, Civilization, Sokoban, v.v.

Cách tiếp cận đầu tiên tôi có là có một mảng 2D các đối tượng Ngói, và sau đó có các lớp kế thừa từ Ngói đại diện cho các đối tượng trò chơi. Thật không may, theo cách đó, tôi không thể xếp nhiều yếu tố trò chơi hơn trên cùng một Ngói mà không có mảng 3D.

Sau đó, tôi đã làm một điều khác biệt: Tôi vẫn có mảng 2D của các đối tượng Ngói, nhưng mọi đối tượng Ngói đều chứa một Danh sách nơi tôi đặt và các thực thể khác nhau. Điều này hoạt động tốt cho đến 20 phút trước, khi tôi nhận ra rằng quá tốn kém để làm nhiều việc, hãy xem ví dụ này:

Tôi có một thực thể Tường. Mỗi bản cập nhật tôi phải kiểm tra 8 ô liền kề, sau đó kiểm tra tất cả các thực thể trong Danh sách của Ngói, kiểm tra xem có bất kỳ thực thể nào trong số đó là Tường không, sau đó cuối cùng vẽ đúng sprite. (Điều này được thực hiện để vẽ các bức tường cạnh nhau liền mạch)

Giải pháp duy nhất tôi thấy bây giờ là có một mảng 3D, với nhiều lớp, có thể phù hợp với mọi tình huống. Nhưng theo cách đó tôi không thể xếp chồng hai thực thể có chung một lớp trên cùng một ô. Bất cứ khi nào tôi muốn làm điều đó tôi phải tạo một lớp mới.

Có một giải pháp tốt hơn? Bạn sẽ làm gì?


Làm thế nào việc sử dụng một mảng 3D sẽ khắc phục vấn đề của bạn với tình huống kiểm tra tường đó. Nó sẽ không giống nhau chứ?
Michael Coleman

Tôi biết rằng Tường chỉ ở trên lớp số 1. Vì vậy, tôi chỉ có thể làm: Gạch [Wall.X - 1, Wall.Y, 1] là Tường?
Vee

Hơn bạn không thể kiểm tra yếu tố đầu tiên trong danh sách? Tôi không thấy làm thế nào một danh sách đặt ra một vấn đề.
Michael Coleman

Bức tường có thể là bất cứ nơi nào trong danh sách với cách tiếp cận thứ hai. Tôi cần phải lặp qua mọi Thực thể và kiểm tra xem đó có phải là một bức tường không.
Vee

4
Bạn đã thực sự có một vấn đề hiệu suất, hoặc bạn chỉ lo lắng rằng bạn sẽ? Bạn đã định hình nó chưa?
khoan hồng

Câu trả lời:


2

Bạn đã thực sự nhìn thấy vấn đề này, hoặc bạn vừa nghĩ ra nó? Bởi vì tôi không thấy cách lặp qua danh sách đối tượng có bất kỳ ảnh hưởng đáng chú ý nào đến hiệu suất. Bạn sẽ phải có hàng trăm đối tượng trên mỗi ô cho vấn đề này. Hầu hết các trò chơi tôi có thể nghĩ là có 10, ngọn.

Nếu bạn thực sự có vấn đề, ý tưởng tốt nhất là lưu trữ dữ liệu, không thay đổi biểu diễn. Trong ví dụ của bạn, cấu hình tường có thể không thay đổi mọi khung. Chỉ cần lưu trữ đúng loại sprite, không tính toán lại liên tục.

Nếu bạn muốn tạo ra một số trò chơi điên rồ có nhiều đối tượng và chúng thay đổi mọi lúc, bạn có thể tạo các lớp khác nhau với các ngữ nghĩa khác nhau. Ví dụ, lớp tường chỉ chứa các bức tường, không quá 1 trên mỗi ô và, giả sử, lớp trang trí chứa danh sách các đối tượng không bao giờ thay đổi.

Cuối cùng, nếu bạn muốn có kiến ​​trúc cực kỳ linh hoạt hỗ trợ lý tưởng cho mọi trò chơi có thể - may mắn khó khăn, không có điều đó.


2

Hai gợi ý. Trước tiên, bạn nên giải quyết sprite rằng mỗi ô sẽ được vẽ trong quá trình tải bản đồ / cấp độ ô của bạn. Nó phải đủ dễ dàng để vượt qua mảng 2D, một cấp độ của bạn được tải và quyết định rằng một bức tường chứng nhận cần phải là hình chữ L và một cái khác cần phải là một | hình dạng.

Thứ hai, tôi sẽ lưu trữ dữ liệu tĩnh liên quan đến ô ở một nơi khác với dữ liệu hoạt động. Vì vậy, một đối tượng ô vuông có thể có một danh sách các đối tượng đến và đi từ ô đó nhưng không cần phải duyệt qua phần này để xem, ví dụ: chúng ta chỉ muốn biết liệu ô có thể đi được hay không.

Mã psudo này ít nhiều là cách tôi đã tiếp cận một hệ thống dựa trên gạch.

Tile {
  Texture tex;
  //...other static data...
  List currentObjects;
}

Tile t = Tiles[x][y];

Điều này giả định rằng có các ô tĩnh trong trò chơi của bạn nhưng đó là một giả định khá tốt trong nhiều trò chơi dựa trên gạch mà bạn đang xử lý các bức tường và những thứ tương tự.


1

Bạn đã nói:

Tôi đã có một mảng 2D các đối tượng Ngói, và sau đó có các lớp kế thừa từ Ngói đại diện cho các đối tượng trò chơi. Thật không may, theo cách đó, tôi không thể xếp nhiều yếu tố trò chơi hơn trên cùng một Ngói mà không có mảng 3D.

Sau đó, tôi đã làm một điều khác biệt: Tôi vẫn có mảng 2D của các đối tượng Ngói, nhưng mọi đối tượng Ngói đều chứa một Danh sách nơi tôi đặt và các thực thể khác nhau. Điều này hoạt động tốt cho đến 20 phút trước, khi tôi nhận ra rằng quá tốn kém để làm nhiều việc

Đây chính xác là tình huống mà bạn muốn giải quyết bằng cách sử dụng mẫu MVC (bộ điều khiển chế độ xem mô hình) để tách mô hình của bạn khỏi chế độ xem của bạn. MVC làm cho vấn đề này hai phần:

  • Làm thế nào để mô hình một chồng gạch
  • Làm thế nào để hiển thị một chồng gạch

Thay vì có một mảng 2D hoặc một mảng 2D của danh sách các ô, mô hình của bạn sẽ lưu trữ một mảng 2D của các đối tượng trò chơi. Sau đó, mảng 2D của các lớp xếp của bạn sẽ xem xét các đối tượng trò chơi tương ứng và quyết định cách hiển thị chúng.

Thay vì có một đối tượng Ngói duy nhất hiển thị một đối tượng trò chơi, bạn có thể có một đối tượng Ngói duy nhất hiển thị một cái gì đó trông giống như một chồng các đối tượng. Điều này sẽ hiệu quả hơn và sẽ phân tách rõ ràng logic mã lõi của bạn và giao diện của nó.

Cũng giống như những bức tường. Logic rất tầm thường, nhưng kết xuất phức tạp hơn.


3
Tôi không thấy MVC (vốn không phổ biến trong các trò chơi từ trải nghiệm của tôi) sẽ giúp ích như thế nào ở đây. Nếu bất cứ điều gì, nó sẽ làm cho nó tồi tệ hơn: bạn sẽ kết thúc với một số dư thừa giữa mô hình và chế độ xem phải được giữ đồng bộ.
khoan hồng

1
Vâng, khi bạn gặp vấn đề, chỉ cần sử dụng <buzzword>. Bây giờ bạn có hai vấn đề.
Nevermind

1
np, tôi tuôn ra nhiều chi tiết hơn.
tro999

OK tôi lấy lại downvote của tôi. Stil, tôi không nghĩ rằng MVC là hữu ích ở đây. Hầu hết thời gian, đối tượng khác nhau bởi logic, không (chỉ) bởi biểu diễn đồ họa.
Nevermind

Không thể làm hài lòng tất cả mọi người, tôi đoán vậy. Đối với tôi, MVC ngay lập tức nhảy ra như một phần của giải pháp cho một phần của vấn đề. Nhưng tôi đồng ý rằng tôi không cung cấp giải pháp hoàn chỉnh cho tất cả các vấn đề - điều đó sẽ cần một bài tiểu luận!
tro999

0

Tôi đồng ý với @Omnion. Sử dụng cách tiếp cận danh sách, nhưng giữ cho nó được sắp xếp nếu hiệu suất là một vấn đề. Đó là nói sử dụng một cách tiếp cận lai. Sử dụng danh sách làm thứ nguyên thứ ba của bạn, nhưng chỉ xác định 5 mục đầu tiên là một loại cụ thể và bất kỳ thứ gì sau đó là loại mực riêng hoặc loại không yêu cầu kiểm tra nhiều lần trên mỗi khung.


0

Bạn nên "không bao giờ" tạo các lớp riêng biệt cho những thứ như gạch. Bạn nên tạo một cấu trúc từ byte, quần short và ints đề cập đến loại gạch và các đối tượng trên nó. Hiệu suất ints khôn ngoan là tốt nhất để đi cùng hoặc thậm chí dài trên các hệ thống 64 bit. Nhưng nếu bạn muốn lưu bản đồ của mình, bạn nên đi bằng byte hoặc quần short bất cứ nơi nào bạn có thể, đặc biệt là đối với các bản đồ khổng lồ.

Trong các trò chơi của mình, tôi có một lớp bản đồ chỉ có các trường như: byte brickType; 256 loại địa hình khác nhau là đủ cho trò chơi này. Mất 1 byte. ushort brickObject; 65.536 đối tượng khác nhau là rất nhiều để đi với. Mất 2 byte, v.v.

Nếu tôi lấy ví dụ ở trên, mỗi ô chỉ mất 3 byte trong bộ nhớ. Vì vậy, 10000x10000 sẽ có bộ nhớ 300mb và không phải là vấn đề. Bất cứ khi nào bạn cần tìm kiếm thứ gì đó bạn xác định nơi bạn muốn tìm trên bản đồ và những gì bạn đang tìm kiếm và lặp lại các mảng cho phù hợp.

Nếu bạn có những thứ năng động trên khắp bản đồ, hãy tự hỏi xem người chơi có thực sự nhận thấy những thứ đó nằm ngoài tầm nhìn của nó không.

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.