Cách xử lý sự khác biệt giữa tọa độ màn hình 2D và tọa độ Descartes


23
  • Hầu hết các hệ tọa độ màn hình / bitmap 2D đều có trục Y dương hướng xuống (với gốc tọa độ ở góc trên bên trái).
  • Điều này trái ngược với cách mà hầu hết mọi người nghĩ về mặt hình học với trục Y dương hướng lên (với gốc tọa độ ở giữa).

Làm thế nào để hầu hết các trò chơi quản lý hai hệ tọa độ 2D khác nhau? Có hai loại tọa độ chính (màn hình so với Cartesian), nhưng có thể có nhiều không gian tọa độ khác nhau: không gian sprite, không gian thế giới, không gian xem, không gian màn hình, v.v ...

Lý lịch:

Ban đầu tôi đã làm cho tọa độ thế giới trong trò chơi của mình khớp với quy ước tọa độ màn hình 2D. Điều này làm cho nó rất tự nhiên khi sử dụng các thói quen vẽ đồ họa, nhưng các vấn đề tinh tế nảy sinh khi sử dụng các hàm lượng giác như atan2 (). Kết quả cho ăn tọa độ màn hình 2D atan2 () rất khó hiểu vì atan2 () giả định trục y dương hướng lên.

Vì vậy, tôi đã thay đổi tọa độ thế giới của mình để theo hệ tọa độ Cartesian cổ điển (với gốc ở phía dưới bên trái màn hình). Lý luận với atan2 () đơn giản hơn nhiều, nhưng bây giờ khó thực hiện các loại lý luận khác:

  • Nếu tôi nhấp vào màn hình ở đây, sprite bên dưới là gì?
  • Tôi đã nhấp vào sprite đó ở đâu?
  • Nếu một sprite được vẽ ở vị trí sai, những gì đã được tính toán không chính xác? Các tọa độ màn hình hay tọa độ thế giới?

Tôi nhận thấy việc chuyển đổi từ màn hình sang tọa độ Descartes chỉ đơn giản là thay đổi giá trị y theo -1 với một bản dịch tùy chọn của cả hai giá trị (x, y). Tôi quan tâm nhiều hơn đến các thực tiễn tốt nhất cho thiết kế trò chơi:

  • Có phải hầu hết các trò chơi chỉ gắn bó với quy ước phối hợp màn hình và thay đổi suy nghĩ về cách mọi thứ như atan2 () nên hoạt động?
  • Khi nào / làm thế nào để chuyển đổi hệ thống phối hợp được thực hiện? (Sử dụng ma trận, trừu tượng OOP, v.v.)
  • Là các vị trí sprite được lưu trữ như là trung tâm của sprite hoặc một trong các góc? Chiều cao / chiều rộng của sprite đi theo hướng "sai" dường như là một vấn đề phổ biến khi tôi vẽ chúng.

Mặc dù câu hỏi của tôi chủ yếu là về các trò chơi 2D, nhưng có vẻ như OpenGL sử dụng hệ thống tọa độ nơi trục Y hướng lên. OpenGL cuối cùng phải chiếu các tọa độ 3D đó lên hệ thống tọa độ màn hình 2D. Có lẽ một số hướng dẫn có thể được tìm thấy trong phương pháp của OpenGL ...

Câu trả lời:


8

Đã từng thử mọi cách có thể tưởng tượng được, tôi nhận thấy nếu đó hoàn toàn là một game 2D, chỉ cần sử dụng hệ thống vẽ màn hình, nó sẽ giúp cuộc sống của bạn dễ dàng hơn nhiều. Sin, Cos và atan2 cần được sử dụng hơi khác nhau, nhưng sự bất tiện này dễ dàng được bù đắp bởi sự đơn giản của việc biết đường lên, xuống, theo chiều kim đồng hồ và ngược chiều kim đồng hồ. Tôi cũng khuyên bạn nên làm việc bằng pixel thay vì mét cho các trò chơi 2D - việc nghĩ về khoảng cách trên màn hình sẽ dễ dàng hơn nhiều và khả năng bạn muốn thay đổi toàn bộ quy mô trò chơi của mình gần bằng không.

"Làm thế nào để hầu hết các trò chơi quản lý hai hệ tọa độ 2D khác nhau?"

  • hầu hết các trò chơi 2D tôi đã thấy nguồn để sử dụng hệ thống màn hình, nhưng mỗi thực thể nên biết không gian thế giới của nó, hãy để trình quản lý bản vẽ của bạn chuyển đổi vị trí này sang vị trí màn hình. Tại thời điểm này, bạn sẽ làm bất cứ điều gì chuyển đổi ma trận bạn cần.

"Các vị trí sprite được lưu trữ như là trung tâm của sprite hoặc một trong các góc?"

  • Nếu bạn làm việc từ trung tâm, nó sẽ giúp quay thẳng hơn, mặc dù bạn cũng muốn biết các góc.

"Có lẽ một số hướng dẫn có thể được tìm thấy trong phương pháp của OpenGL ..."

  • Động cơ 3D là một trường hợp hoàn toàn khác. Vì họ có máy ảnh thực sự, vị trí màn hình có thể rất khác với vị trí thế giới. Đối với trò chơi từ trên xuống, bạn sẽ làm việc theo trục X và Z, thay vì X và Y cho một thứ.

1

Tôi có thể quá đơn giản hóa mọi thứ ở đây, nhưng thiên hướng của tôi sẽ là có bất kỳ hệ thống con 2D / UI nào xử lý nghiêm ngặt những gì bạn gọi là tọa độ "màn hình". Bạn sẽ có hai ma trận: ScreenToCartesianTransform và CartesianToScreenTransform. Khi nhận được các sự kiện nhập chuột, tọa độ chuột sẽ được chuyển đổi bằng CartesianToScreenTransform trước khi được chuyển đến trình quản lý đầu vào của hệ thống 2D / UI. Từ đó, hệ thống UI sẽ thực hiện kiểm tra lần truy cập bằng hệ thống tọa độ màn hình và xử lý (hoặc không xử lý) sự kiện tương ứng. Nếu sự kiện nhập chuột không được xử lý bởi 2D / UI, nó có thể được chuyển sang hệ thống 3D (nếu có) bằng cách sử dụng tọa độ ban đầu, chưa được xử lý.

Vì hệ thống 2D / UI sẽ chỉ xử lý tọa độ "màn hình", nên hình học của nó sẽ cần được chuyển đổi qua ScreenToCartesianTransform trước khi được xử lý bởi công cụ kết xuất.


Trên thực tế, tùy thuộc vào bộ công cụ nào bạn đang sử dụng, các sự kiện nhập chuột có thể đã ở tọa độ màn hình. Trong trường hợp đó, bạn sẽ không chuyển đổi chúng cho hệ thống 2D / UI, nhưng bạn sẽ làm cho hệ thống 3D (nếu có).
Mike Strobel

0

Tôi thích sử dụng cây hiển thị như trong Flash. Tôi sẽ có một nút gốc (chế độ xem trò chơi) chứa một đứa trẻ cho thế giới (nút thế giới) và một nút trên cùng cho HUD. Bên trong nút thế giới sẽ là các nút cho các đối tượng trong thế giới trò chơi.

Tôi sau đó chỉ đơn giản là chuyển đổi nút thế giới. Cùng với dịch thuật (lia máy ảnh) và chia tỷ lệ (thu phóng camera) tôi cũng áp dụng hai phép biến đổi khác:

  • Thang đo -1 y để lật hệ tọa độ.
  • Một tỷ lệ để chuyển đổi đơn vị thế giới (mét) sang đơn vị màn hình (pixel)

Sau đó, tôi sử dụng tọa độ y-up / world trong mã vẽ đối tượng trò chơi và tọa độ y-down / màn hình trong mã vẽ HUD, cả hai đều cảm thấy rất tự nhiên.

Để trả lời các câu hỏi như "tôi đang nhấp vào đối tượng nào" Tôi sử dụng các phương thức nút hiển thị để chuyển đổi tọa độ giữa các hệ tọa độ (chẳng hạn như globalToLocalvà nghịch đảo của nó trong Flash).

Nhân tiện, atankhông thực sự hoạt động khác nhau khi y xuống, bạn chỉ cần nghĩ mọi góc độ là đi theo chiều kim đồng hồ thay vì ngược chiều kim đồng hồ.


0

OpenGL, giống như DirectX, có trục X và Z dọc theo mặt phẳng ngang và Y hướng lên trên.
Tôi chưa bao giờ có bất kỳ vấn đề nào với tọa độ màn hình và tôi nghĩ cách đơn giản nhất là xử lý nó như thế nào: nếu một cái gì đó, chẳng hạn như atan2, không thích nó, thì hãy thay đổi các tham số được cung cấp.

Nếu bạn đang sử dụng tọa độ tương đối hoặc cục bộ, chẳng hạn như biểu đồ cảnh, thì một hàm đơn giản như ToGlobalCoords () là tốt. Trong thực tế, nếu bạn muốn tìm hiểu thêm về định vị không gian, đồ thị cảnh và localToGlobal, trích xuất miễn phí từ Game Engine Architecture là về điều đó.

Sprites được vẽ từ góc trên cùng bên trái hoặc (0,0) gốc. Lý do tại sao là do nguồn gốc trên cùng bên trái của cửa sổ.

Có vẻ hơi ngớ ngẩn khi thay đổi hệ thống tọa độ cửa sổ, và sẽ khiến những thứ như đầu vào, đóng vai trò lớn hơn trong hầu hết các trò chơi so với trig, khó khăn hơn đáng kể. Nó cũng khiến bạn xa lánh các tiêu chuẩn và bất kỳ người dùng mã nào của bạn.

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.