Có phải đó là một ý tưởng tồi đối với bản đồ trên mạng, vị trí chuột trên màn hình để phát hiện va chạm hoạt động bất kể độ phân giải?


16

Hãy xem xét một trò chơi có độ phân giải mặc định là 800x600. Các đối tượng có mặt nạ va chạm được đặt trong một thế giới trò chơi có kích thước 800x600. Mặt nạ va chạm có thể phát hiện khi chuột va chạm với chúng.

Bây giờ hãy xem xét chúng tôi mở rộng trò chơi lên tới 1024x768 (giả sử chúng tôi chia tỷ lệ đồ họa bằng cách đơn giản hiển thị mọi thứ thành một lớp và sau đó nhân rộng toàn bộ lớp lên cùng một lúc). Chúng tôi có hai tùy chọn để làm cho các va chạm với chuột hoạt động chính xác trong độ phân giải mới này:

A.) Mở rộng thế giới lên 1024x768 và mở rộng mặt nạ va chạm của mọi đối tượng tương ứng.

B.) "Ánh xạ" vị trí chuột vào thế giới ban đầu (800x600).

Theo "bản đồ", ý tôi chỉ đơn giản là thu nhỏ vị trí chuột vào thế giới 800x600 ban đầu. Vì vậy, ví dụ, nếu vị trí chuột trên màn hình là (1024, 768), thì vị trí chuột trên thế giới là (800, 600).

Bây giờ rõ ràng, tùy chọn B yêu cầu cách tính toán ít hơn và có lẽ ít bị lỗi hình học hơn, nhưng nó cũng cảm thấy hơi "hackish" đối với tôi, giống như có những hậu quả không lường trước được khi sử dụng phương pháp này sẽ là địa ngục để khắc phục sau này.

Tôi nên dùng phương pháp nào: A, B, hay cái gì khác?


2
Như được chỉ ra bởi Classic Thunder, tọa độ hiển thị không được giống với tọa độ thế giới hoặc tọa độ đối tượng. Thông thường, bạn muốn có các phép biến đổi (về cơ bản, như bạn nói về ánh xạ , nhưng thường được thực hiện với toán ma trận).
Dan

Câu trả lời:


38

Thông thường (ngay cả đối với các trò chơi 2d) có một hệ thống tọa độ riêng cho trò chơi không phụ thuộc vào độ phân giải, điều này thường được gọi là không gian thế giới. Điều này cho phép bạn mở rộng đến một độ phân giải tùy ý.

Cách dễ nhất để đạt được điều này là sử dụng Máy ảnh 2D, về cơ bản là ma trận xác định quá trình chuyển từ không gian thế giới (đơn vị tùy ý của bạn) sang không gian màn hình (các pixel trên màn hình). Điều này làm cho việc đối phó với toán học tầm thường.

Hãy xem phần bên dưới trong XNA 2d Camera Scrolling - tại sao sử dụng biến đổi ma trận?

Nó làm cho nó thực sự dễ dàng để chuyển đổi giữa các định nghĩa hệ tọa độ

Để đi từ màn hình đến không gian thế giới, chỉ cần sử dụng Vector2.Transform. Điều này thường được sử dụng để có được vị trí của chuột trên thế giới để chọn đối tượng.

Vector2.Transform(mouseLocation, Matrix.Invert(Camera.TransformMatrix));

Để đi từ thế giới đến không gian màn hình chỉ cần làm ngược lại.

Vector2.Transform(mouseLocation, Camera.TransformMatrix);

Không có nhược điểm nào khi sử dụng ma trận ngoài việc học hỏi một chút.


... Và thực tế, nói chung, phần cứng hiện đại được thiết kế cho các hoạt động ma trận thông qua các kiến ​​trúc véc tơ như SSE, NEON, v.v. Vì vậy, đây là lựa chọn thông minh - bạn sẽ tiết kiệm chu kỳ CPU qua các phương pháp không theo vectơ.
Kỹ sư

1
Từ chối trách nhiệm nhẹ: XNA đã bị microsoft ngừng cung cấp, nhưng Monogame sử dụng cùng API.
Pharap

1
Chắc chắn, thật thông minh khi sử dụng ma trận để dịch giữa hai hệ tọa độ. Nhưng làm thế nào mà trả lời câu hỏi? Bạn vẫn phải quyết định, nếu bạn muốn ánh xạ từ hệ thống A sang hệ thống B hoặc từ B đến A và hậu quả là gì, nếu có.
mastov

"Có phải đó là một ý tưởng tồi đối với bản đồ khu vực vị trí chuột trên màn hình để phát hiện va chạm hoạt động bất kể độ phân giải?" được trả lời bởi "thật thông minh khi sử dụng ma trận để dịch giữa hai hệ tọa độ" ...
ClassicThunder

Tôi cũng trả lời "Bạn vẫn phải quyết định, nếu bạn muốn ánh xạ từ hệ thống A sang hệ thống B hoặc từ B đến A và hậu quả là gì, nếu có bất kỳ." bằng cách nói rằng bạn nên sử dụng một tùy ý không gắn liền với độ phân giải và tỷ lệ từ nó. Vậy C -> A hoặc C -> B tùy thuộc vào việc A hoặc B là độ phân giải. Tất nhiên bạn có thể có C bằng độ phân giải cơ sở mà bạn thiết kế và chia tỷ lệ từ đó. Điểm là tất cả toán học xảy ra trong cùng một hệ tọa độ và bạn chỉ chia tỷ lệ cho kết xuất.
ClassicThunder

2

Một tùy chọn khác sẽ là: Trên mỗi sự kiện di chuyển chuột đầu vào, di chuyển con trỏ chuột trong trò chơi theo số pixel trò chơi tương ứng với số pixel trong sự kiện chuột. Điều này xuất hiện một cách tự nhiên đối với các trò chơi 3D khóa con trỏ chuột thật vào trung tâm và xoay hướng ngắm bằng một lượng tương ứng với chuyển động của chuột đầu vào, nhưng bạn có thể làm điều đó theo cách tương tự bằng cách di chuyển một sprite đại diện cho con trỏ chuột trong trò chơi.

Bạn rõ ràng phải bỏ qua bất kỳ sự kiện di chuyển chuột đầu vào nào gây ra bởi việc vênh nó vào trung tâm và nếu trò chơi của bạn có bất kỳ độ trễ đầu vào nào thì sự không phản hồi của con trỏ sẽ là khía cạnh chói tai và đáng chú ý nhất.

Một phần, giải pháp bạn sử dụng phụ thuộc vào mức độ quan trọng của vị trí chuột đối với trò chơi. Nếu đây là RTS và người chơi chỉ cần nhấp để chọn đơn vị, bạn có thể chỉ cần đi với bất kỳ A hoặc B nào của bạn dễ dàng hơn. Nếu đó là một game bắn súng từ trên xuống và chuột trực tiếp điều khiển chuyển động của nhân vật, thì có lẽ bạn sẽ muốn một giải pháp chuyên sâu hơn, giới hạn mức độ biến đổi trong cách nhân vật có thể di chuyển dựa trên không chỉ độ phân giải mà cả những thứ như chuyển động của chuột tốc độ. Nếu chuột điều khiển hướng nhắm mục tiêu thay vào đó, thì bạn sẽ muốn một giải pháp khác, v.v.


0

Câu trả lời của ClassicThunder là đúng, nhưng tôi muốn cung cấp một ví dụ về một phương tiện thay thế / đơn giản hơn để đạt được hiệu quả mong muốn. Đây là một giải pháp đơn giản hơn để tạo mẫu nhanh, trong trường hợp bạn không truy cập vào thư viện đầy đủ tính năng hoặc cho các trường hợp bạn không có quyền truy cập vào GPU (ví dụ: trong các hệ thống nhúng).

Để thực hiện ánh xạ đã nói, bạn có thể sử dụng hàm sau (giả sử nó được định nghĩa trong lớp tĩnh Helper):

static float Map(float value, float fromLow, float fromHigh, float toLow, float toHigh)
{
    return ((value - fromLow) / (fromHigh - fromLow) * (toHigh - toLow)) + toLow;
}

(Bạn đã không chỉ định một ngôn ngữ, nhưng tôi thấy bạn có một số kiến ​​thức về C #, vì vậy ví dụ của tôi là trong C #.)

Sau đó, bạn có thể sử dụng chức năng này như vậy:

float mouseXInWorld = Helper.Map(Mouse.X, 0, Screen.Width - 1, camera.Bounds.X, camera.Bounds.X + camera.Bounds.Width - 1);
float mouseYInWorld = Helper.Map(Mouse.Y, 0, Screen.Height - 1, camera.Bounds.Y, camera.Bounds.Y + camera.Bounds.Height - 1);

Ở đâu camera.Bounds một hình chữ nhật đại diện cho khu vực của thế giới mà máy ảnh có thể nhìn thấy (tức là khu vực được chiếu lên màn hình).

Nếu bạn có một Vectorhoặc một Pointlớp, bạn có thể đơn giản hóa quá trình này hơn nữa bằng cách tạo một tương đương 2D của chức năng bản đồ, như vậy:

static Vector Map(Vector value, Rectangle fromArea, Rectangle toArea)
{
    Vector result = new Vector();
    result.X = Map(value.X, fromArea.X, fromArea.X + fromArea.Width - 1, toArea.X, toArea.X + toArea.Width - 1);
    result.Y = Map(value.Y, fromArea.Y, fromArea.Y + fromArea.Height - 1, toArea.Y, toArea.Y + toArea.Height - 1);
    return result;
}

Điều này sẽ làm cho mã ánh xạ của bạn trở thành một lớp lót đơn giản:

Vector mousePosInWorld = Map(Mouse.Pos, Screen.Bounds, camera.Bounds);

-1

Tùy chọn (C): thay đổi độ phân giải màn hình trở lại 800x600.

Ngay cả khi bạn không làm điều này, hãy coi nó như một thử nghiệm suy nghĩ. Trong trường hợp đó, trách nhiệm của màn hình là thay đổi kích thước đồ họa để phù hợp với kích thước vật lý của nó và sau đó là trách nhiệm của hệ điều hành để cung cấp cho bạn các sự kiện con trỏ ở độ phân giải 800x600.

Tôi nghĩ tất cả phụ thuộc vào việc đồ họa của bạn là bitmap hay vector. Nếu chúng là bitmap và bạn đang kết xuất thành bộ đệm 800x600, thì có, việc sắp xếp lại chuột vào không gian màn hình và bỏ qua độ phân giải màn hình thực sẽ dễ dàng hơn nhiều. Tuy nhiên, nhược điểm lớn của việc này là việc nâng cấp có thể trông xấu, đặc biệt nếu bạn đang làm đồ họa theo phong cách "8 bit".

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.