Làm cách nào để hạn chế di chuyển click'n'drag vào một khu vực?


11

Tôi xin lỗi vì tiêu đề hơi chung chung. Tôi thực sự không có nhiều manh mối về cách thực hiện những gì tôi đang cố gắng làm, điều này làm cho việc nghiên cứu một giải pháp khả thi trở nên khó khăn hơn.

Tôi đang cố gắng thực hiện một điểm đánh dấu đường dẫn (có thể có một tên phù hợp nhất cho nó, nhưng đây là cách tốt nhất tôi có thể nghĩ ra).

Ở phía trước của người chơi sẽ có một điểm đánh dấu đường dẫn, nó sẽ xác định cách người chơi sẽ di chuyển sau khi hoàn thành kế hoạch cho lượt của mình. Người chơi có thể nhấp và kéo điểm đánh dấu đến vị trí họ chọn, nhưng chỉ có thể di chuyển điểm đánh dấu trong một khu vực làm việc xác định (bit màu xám).

Sơ đồ đánh dấu đường dẫn

Vì vậy, bây giờ tôi bị mắc kẹt với hai vấn đề:

Trước hết, làm thế nào chính xác tôi nên xác định khu vực khả thi đó? Tôi có thể tưởng tượng có thể hai vectơ có người chơi làm điểm bắt đầu để tạo thành góc khả thi và có thể hai cung đó có thể đến từ các vòng tròn có trung tâm của người chơi, nhưng tôi chắc chắn không biết làm thế nào để đặt tất cả cùng với nhau.

Và thứ hai, sau khi tôi đã xác định khu vực có thể đặt điểm đánh dấu, làm cách nào tôi có thể thực thi rằng điểm đánh dấu chỉ nên ở trong khu vực đó? Ví dụ: nếu người chơi nhấp và kéo điểm đánh dấu xung quanh, nó có thể di chuyển tự do trong khu vực làm việc, nhưng không được rời khỏi ranh giới của khu vực. Vì vậy, ví dụ, nếu người chơi bắt đầu kéo điểm đánh dấu lên trên, nó sẽ di chuyển lên trên cho đến khi chạm vào điểm cuối của vùng làm việc (sơ đồ đầu tiên bên dưới), nhưng nếu sau đó, người chơi bắt đầu kéo sang một bên, điểm đánh dấu phải theo kéo trong khu vực (sơ đồ thứ hai bên dưới).

Sơ đồ đầu tiên: Di chuyển lên trên Sơ đồ thứ hai: Theo sau kéo

Tôi hy vọng điều này không quá khó hiểu. Cảm ơn các bạn.

Chỉnh sửa: Trong trường hợp điều này tạo ra sự khác biệt, tôi đang sử dụng C ++ với Marmalade SDK.


Tôi nghĩ thuật ngữ bạn đang tìm kiếm là "điểm tham chiếu" và bạn có thể xác định một cách toán học khu vực màu xám không? Giải pháp cho vấn đề của bạn có lẽ sẽ dễ dàng hơn rất nhiều nếu có.
John McDonald

Arent waypoint liên quan đến tìm đường và như vậy? Ngoài ra, về mặt toán học xác định vùng màu xám là một trong những vấn đề của tôi: PI nghĩ rằng tôi có thể tìm ra thứ gì đó giống như hình chữ nhật hoặc thậm chí là một hình tròn, nhưng hình dạng đó, với hai vòng cung cho hai bên và hai cạnh khác trên một góc ... Đó là một chút trên đầu của tôi.
Vexille

Bạn cũng cần chỉ định ngôn ngữ và / hoặc bộ công cụ nào bạn đang sử dụng, vì các giải pháp chủ yếu phụ thuộc vào nền tảng.
Raceimaztion

Có thật không? Tôi đã tìm ra một giải pháp algorhithmic hoặc thậm chí mã giả sẽ giúp ích. Tôi sẽ chỉnh sửa câu hỏi nào, chỉ trong trường hợp.
Vexille

Xác định hình dạng trong tọa độ cực (góc tối đa từ góc ký tự và khoảng cách tối thiểu / tối đa từ ký tự). Sau đó, chỉ cập nhật điểm tham chiếu đến vị trí của chuột nếu chuột nằm trong các ranh giới đó. Nếu nó vượt quá bất kỳ extreem nào, hãy gắn nó với giá trị extreem nhất có thể. Bắt đầu cập nhật khi nhấp vào bên trong khu vực và dừng lại khi thả chuột.
ClassicThunder

Câu trả lời:


8

Bạn có thể xác định vùng khả thi như vùng trong câu hỏi của mình bằng ba giá trị:

float innerRadius;
float outerRadius;
float maxAngle;

Các giá trị này sẽ được dựa trên một điểm trung tâm có thể hoặc không thể là vị trí của người chơi. Hình dạng của khu vực khả thi phụ thuộc vào nơi bạn đặt điểm này.

nhập mô tả hình ảnh ở đây

Trong ví dụ trên, vị trí trung tâm nằm ở một khoảng cách nhất định (giả sử 50 đơn vị) phía sau người chơi. Điều này có thể dễ dàng được tính như sau:

float offset = -50;
Vector2 centerPosition = playerPosition + offset * playerForward;

Để giới hạn vị trí của điểm đánh dấu vào vùng khả thi đó, trước tiên hãy di chuyển điểm đánh dấu như bình thường. Sau đó xác nhận khoảng cách giữa điểm trung tâm và điểm đánh dấu:

Vector2 direction = markerPosition - centerPosition;
float distance = direction.Length();
direction.Normalize();
markerPosition = centerPosition + direction * clamp(distance, innerRadius, outerRadius);

Cuối cùng, xác nhận góc của điểm đánh dấu đến phạm vi được chỉ định. Tôi sẽ sử dụng mã giả cho cái này:

- Find angle between vector C->M and vector playerForward
- If abs(angle) <= maxAngle Then do nothing
- Else If angle > 0 Then rotate M around C by maxAngle-angle
- Else If angle < 0 Then rotate M around C by -maxAngle-angle

Nhìn xung quanh về cách xoay một điểm xung quanh điểm khác. Nó có thể được thực hiện bằng lượng giác hoặc ma trận biến đổi.

Bạn cũng có thể muốn tính đến kích thước của điểm đánh dấu và làm cho bán kính và góc nhỏ hơn một chút để bù lại.

Chỉnh sửa: Trên suy nghĩ thứ hai, nó có thể trông tự nhiên hơn nếu bạn xác nhận góc đầu tiên, sau đó là khoảng cách, vì vậy hãy thử cả hai phương án!


Giải pháp tuyệt vời! Tôi đã bắt gặp một cái gì đó liên quan đến hai vòng tròn và một hình tam giác, nhưng solutiong của bạn đơn giản hóa điều đó. Về xác thực góc, tôi đã nghĩ ra một cái gì đó dọc theo đường có một vectơ chuẩn hóa đứng ở maxAngle (và một cái khác ở -maxAngle) từ playerForward, có thể nhân với độ dài của C-> M trong trường hợp đó là giới hạn , góc khôn ngoan. Tôi cho rằng giải pháp xoay M quanh C của bạn sẽ ít tốn kém hơn, đúng không?
Vexille

@Vexille Chà, xoay vòng bao gồm một cosvà một sinhoạt động, vì vậy tôi không chắc chắn. Nhưng để tính hai vectơ đó bạn cũng cần xoay chúng, mặc dù bạn chỉ cần làm điều đó khi vectơ chuyển tiếp thay đổi. Dù sao cũng không quan trọng lắm, hãy chọn cái bạn thích thực hiện.
David Gouveia

10

Tôi đã suy nghĩ làm thế nào vấn đề có thể được giải quyết nếu hình dạng không đều, và người ta không thể định nghĩa nó theo toán học. Cảnh báo: đây là một giải pháp bẩn, không dành cho người yếu tim.

1. Lấy khu vực của bạn:

nhập mô tả hình ảnh ở đây

2. Và chuyển đổi nó thành một bitmap đơn sắc:

nhập mô tả hình ảnh ở đây và đặt tên là scale_0

3. Sao chép bitmap và giảm tỷ lệ xuống 50%:

nhập mô tả hình ảnh ở đây và đặt tên theo tỷ lệ_1

4. Và cứ thế, cho đến khi có một bitmap nhỏ hơn 4 pixel chiều rộng / chiều cao:

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây tỷ lệ: 2, 3, 4, 5, 6

5. Bây giờ chúng ta có khu vực của mình dưới dạng bitmap đơn sắc có độ phân giải khác nhau: nhập mô tả hình ảnh ở đây

6. Lấy hình ảnh cuối cùng (ở đây "scale_6") và lặp lại qua tất cả các pixel của nó.

  • dịch tọa độ của từng pixel thành tọa độ màn hình: x = Math.pow ( 2, scale_level ); trong đó scale_level là số chúng tôi đã thêm sau "scale_". Chúng ta cũng có thể gọi nó là cấp bốn cây, mặc dù chúng ta không thực sự làm việc với cây bốn. Làm tương tự với y.
  • kiểm tra xem pixel tại bản dịch x & y có màu đen không. Nếu không, thì nó không phải là một phần của hình dạng, và bạn chỉ nêncontinue bước tiếp theo của vòng lặp
  • kiểm tra xem pixel có gần với con trỏ chuột hơn pixel đã kiểm tra trước đó không - nếu có, lưu tọa độ của pixel - sử dụng tọa độ trước khi dịch, đó là tọa độ bên trong bitmap.
  • ở cuối vòng lặp, nhân các tọa độ này với 2: x *= 2; y*=2;để dịch chúng sang tọa độ trong hình ảnh tiếp theo (tỷ lệ trước đó)

7. Chụp ảnh trước đó (ở đây "scale_5"), nhưng không lặp qua tất cả các pixel; bắt đầu tại x = yet_x và kết thúc bằng x = yet_x + 2, tương tự với y. Đó là, vì bây giờ bạn sẽ chỉ lặp qua 4 pixel cho mỗi cấp độ! Phần còn lại là như trong p. 6.

8. Chụp ảnh đầu tiên (lớn nhất = ảnh có độ phân giải lớn nhất), lặp lại qua 4 pixel và cuối cùng bạn có pixel gần nhất với con trỏ chuột:

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

9. Tuy nhiên, tôi đang coi "M" là một điểm ở đây. Nếu bạn muốn nó là một vòng tròn hoàn toàn vừa vặn, trước tiên bạn cần phải co lại (thu nhỏ) hình dạng theo circle.radiuspixel.

Tôi nghĩ rằng tôi đã thêm rằng thuật toán này sẽ chỉ hoạt động nếu bạn sẽ không sử dụng hình ảnh đơn sắc mà là màu xám và coi một pixel là "đầy đủ" nếu nó không phải là màu trắng và là "trống rỗng" nếu nó chính xác là màu trắng ... HOẶC nếu bạn thay đổi kích thước thuật toán thay đổi mỗi nhóm 4 pixel thành 1 pixel đen mỗi lần khi ít nhất một trong 4 pixel này không có màu trắng.


2
+1 cho câu trả lời cho các hình dạng khó (nếu không nói là không thể) diễn đạt bằng toán học.
Cypher

Wow, rất thú vị. +1 cũng vậy: D
Vexille

Tôi đã thực hiện nó trong dự án thực tế, và tôi phải nói rằng một số vấn đề nổi lên. Về cơ bản, bạn cần lập một danh sách các ô lưới, trong đó bạn lấy ô lưới gần nhất có tênclosest và kiểm tra khoảng cách đến điểm xa nhất trong closest- hãy đặt tên cho khoảng cách furthest_dist. Bây giờ bạn cần xóa khỏi danh sách tất cả các ô có điểm gần nhất của chúng hơn mức furthest_distvà đi sâu hơn. Vì vậy, thay vì một cái gì đó như thế này: i.imgur.com/4UuFo.png Đó là một cái gì đó như thế này: i.imgur.com/dyTT3.png
Markus von Broady
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.