Xử lý đầu vào trong thiết kế dựa trên thành phần


12

Tôi biết câu hỏi này đã được hỏi nhiều lần, nhưng tôi vẫn không chắc cách triển khai xử lý đầu vào trong một công cụ dựa trên thành phần.

Thiết kế dựa trên thành phần mà tôi đã sử dụng dựa trên loạt blog của T = Machine và trên Artemis trong đó Thực thể chỉ là id.

Có ba ý tưởng chính tôi có trong việc thực hiện xử lý đầu vào:

  1. Thành phần đầu vào sẽ tổ chức các sự kiện mà nó quan tâm. Hệ thống đầu vào sẽ dịch các sự kiện phím và chuột sang các sự kiện trò chơi và lặp qua các thực thể với thành phần đầu vào và nếu chúng quan tâm đến sự kiện đó, hệ thống đầu vào sẽ thực hiện một hành động thích hợp. Hành động này sẽ được mã hóa cứng cho hệ thống đầu vào.
  2. Không có thành phần đầu vào. Bạn sẽ đăng ký các thực thể với các sự kiện cụ thể cho hệ thống đầu vào. Sau đó, hệ thống đầu vào sẽ gửi tin nhắn (với id thực thể và loại sự kiện) đến các hệ thống khác để chúng có thể thực hiện hành động thích hợp. Hoặc như trong trường hợp đầu tiên, các hành động sẽ được mã hóa cứng cho hệ thống đầu vào.
  3. Tương tự như phương thức đầu tiên, nhưng thay vì mã hóa cứng hành động cho hệ thống đầu vào, thành phần sẽ chứa bản đồ các sự kiện đến các hàm (tức là std::map<std::function>) sẽ được hệ thống đầu vào gọi. Điều này có thêm hiệu ứng của việc có thể kết hợp cùng một sự kiện với các hành động khác nhau.

Bạn có muốn giới thiệu bất kỳ phương pháp nào ở trên không hoặc bạn có đề xuất nào giúp tôi triển khai hệ thống xử lý đầu vào linh hoạt không? Ngoài ra, tôi chưa quen với đa luồng nhưng bất kỳ đề xuất nào có thể thân thiện với luồng thực hiện cũng được hoan nghênh.

Lưu ý: Một yêu cầu được thêm vào Tôi muốn triển khai thực hiện là tôi có thể chuyển cùng một đầu vào cho nhiều thực thể, ví dụ như di chuyển một thực thể máy ảnh và trình phát cùng một lúc.


2
Thông thường (khi camera theo dõi trình phát), bạn không muốn nhận đầu vào trong camera, thay vào đó bạn làm cho camera kiểm tra vị trí của trình phát và theo dõi nó.
Luke B.

1
Nó không thực sự quan trọng về mặt khái niệm nếu máy ảnh theo dõi người chơi hoặc "chính nó". Tuy nhiên, tôi không chắc cách đề xuất của bạn sẽ được thực hiện trong thiết kế dựa trên thành phần mà không vi phạm các nguyên tắc thiết kế.
Grieverlove

1
@Luke B.: Sau khi suy nghĩ kỹ, tôi thấy rằng bạn cũng có thể biến máy ảnh thành một lớp riêng biệt, lấy một con trỏ đến một thực thể để theo dõi.
Grieverlove

Câu trả lời:


8

Tôi nghĩ rằng, giống như câu trả lời của tôi về các vật liệu trong một hệ thống thành phần , bạn đang gặp phải một vấn đề trong đó bạn đang cố gắng chuyển mọi thứ thành một "thành phần". Bạn không cần phải làm điều này và làm như vậy có lẽ bạn đang tạo ra một giao diện thực sự cồng kềnh bằng cách cố gắng lắp một loạt các chốt vuông vào các lỗ tròn.

Có vẻ như bạn đã có một hệ thống xử lý việc thu thập đầu vào từ trình phát. Tôi đã chọn cách tiếp cận sau đó chuyển đầu vào đó thành hành động ("tiến lên" hoặc "di chuyển ngược") hoặc các sự kiện và gửi chúng cho các bên quan tâm. Trước đây, tôi không cho phép các thành phần tự đăng ký cho các sự kiện này, thích một cách tiếp cận trong đó hệ thống cấp cao hơn đã chọn rõ ràng "thực thể được kiểm soát". Nhưng nó có thể hoạt động theo cách khác nếu bạn thích, đặc biệt là nếu bạn sẽ sử dụng lại cùng một thông điệp để thực hiện các hành động không được kích thích trực tiếp bằng đầu vào.

Mặc dù vậy, tôi không nhất thiết phải đề xuất thực hiện hành vi theo dõi máy ảnh bằng cách để cả thực thể máy ảnh và thực thể người chơi phản hồi với thông báo "di chuyển về phía trước" (et cetera). Điều này tạo ra một kết nối cực kỳ cứng nhắc giữa hai đối tượng có thể sẽ không mang lại cảm giác tốt cho người chơi và nó cũng khiến cho việc xử lý những thứ như máy quay quanh người chơi khi người chơi quay sang trái hoặc phải: trả lời "xoay trái" bằng cách giả sử nó được trượt cho người chơi, nhưng điều đó có nghĩa là nó không thể phản hồi chính xác nếu nó không bị chặn ... trừ khi bạn đưa ra khái niệm đó như một số trạng thái bạn có thể kiểm tra. Và nếu bạn sẽ làm điều đó, bạn cũng có thể thực hiện một hệ thống phù hợp để trượt hai vật thể cùng nhau, hoàn thành với các điều chỉnh độ co giãn thích hợp, v.v.

Về đa luồng, tôi thực sự không thấy cần phải sử dụng nó ở đây vì nó có thể gây ra nhiều phức tạp hơn giá trị của nó và bạn đang xử lý một vấn đề nối tiếp vốn có nên bạn chỉ cần liên quan đến nhiều luồng đồng bộ nguyên thủy.


Tôi nghĩ câu hỏi của mình một số suy nghĩ và chuẩn bị tự trả lời nó. Tôi cũng đi đến kết luận rằng tôi nên tốt hơn trong việc tách rời việc xử lý đầu vào từ hệ thống EC để thật tuyệt khi thấy một xác nhận về điều này. Làm thế nào tôi nghĩ làm điều này là bằng cách sử dụng tín hiệu và khả năng liên kết một số thực thể với một loại sự kiện. Tôi cũng quyết định tách rời máy ảnh, mặc dù điều này không thực sự cần thiết và có nó như một thực thể sẽ khả thi như nhau. Tôi nghĩ khi vẫn còn là một người mới với EC, bạn thực sự phải nghĩ những lợi ích của việc biến thứ gì đó thành một thành phần hoặc thực thể.
Grieverlove

4

Kinh nghiệm của tôi có thể bị sai lệch nhưng trong các dự án đa nền tảng, các thiết bị đầu vào không được tiếp xúc trực tiếp với hệ thống thực thể.

Các thiết bị đầu vào được xử lý bởi một hệ thống cấp thấp hơn nhận các sự kiện từ các phím, nút, trục, chuột, bề mặt cảm ứng, gia tốc kế ...

Những sự kiện này sau đó được gửi qua một lớp các trình tạo ý định phụ thuộc bối cảnh.

Mỗi trình tạo đăng ký thay đổi sate từ các thành phần, thực thể và hệ thống có liên quan đến chức năng của nó.

Các trình tạo này sau đó gửi tin nhắn / ý định để định tuyến đến hệ thống ý định nơi các thực thể có một thành phần hoặc trực tiếp đến đúng thành phần.

Bằng cách này, bạn có thể chỉ cần dựa vào "luôn luôn" có cùng một đầu vào, ví dụ JUMP_INTENT (1), JUMP_INTENT (0), AIM_INTENT (1) ...

Và "tất cả" công việc đầu vào phụ thuộc nền tảng bẩn vẫn nằm ngoài hệ thống thực thể của bạn.


Liên quan đến máy ảnh nếu bạn muốn di chuyển nó xung quanh trình phát, nó có thể đăng ký thành phần mục đích riêng của nó và lắng nghe ý định bạn sẽ gửi.

Mặt khác, nếu theo sau người chơi, nó không bao giờ nên nghe đầu vào dành cho người chơi. Nó nên lắng nghe những thay đổi trạng thái do người chơi phát ra (ENTITY_MOVED (biến đổi)) ... và di chuyển tương ứng. Nếu bạn sử dụng hệ thống vật lý, bạn thậm chí có thể gắn máy ảnh vào máy nghe nhạc bằng một trong các khớp khác nhau.


Coyote, cảm ơn câu trả lời của bạn. Tôi cũng đã đọc bài viết khác của bạn ở đây . Mối quan tâm lớn nhất của tôi không phải là làm thế nào để trừu tượng hóa đầu vào. Tôi đã có một cấu trúc cấp thấp hơn để xử lý các phím bấm và như vậy, và thêm một cấp độ gián tiếp sẽ không khó khăn. Vấn đề của tôi là trong việc xử lý các sự kiện được tạo ra, ví dụ như hệ thống ý định của bạn. Nếu tôi hiểu chính xác, bạn không có thành phần đầu vào nào trong phương thức của bạn. Làm thế nào để bạn biết thực thể nào cần đầu vào và làm thế nào để bạn xử lý nó? Bạn có thể cho một số ví dụ cụ thể hơn?
Grieverlove

2

InputComponent mang lại lợi ích gì? Chắc chắn đó là đặc quyền của lệnh đầu vào để quyết định những thực thể mà nó đang thực hiện một hành động trên. Ví dụ kinh điển là làm cho người chơi nhảy. Thay vì có InputComponent trên mọi thực thể nghe các sự kiện "Nhảy", tại sao không có lệnh nhảy tra cứu thực thể được đánh dấu "trình phát" và tự thực hiện logic cần thiết?

Action jump = () =>
{
    entities["player"].Transform.Velocity.Y += 5;
};

Một ví dụ khác, từ OP:

Action moveRight = () =>
{
    foreach (var entity in entities.Tagged("player", "camera"))
        entity.Transform.Position.X += 5;
};
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.