Trước hết, tôi biết chính xác những gì vấn đề bản vẽ của tôi là, và tôi có những ý tưởng khác nhau về cách tiếp cận giải quyết nó. Tôi ở đây để tìm ra cách điều chỉnh khung hình nào được vẽ để "ảo giác" đẳng cự được duy trì.
Tôi đang viết một trò chơi 2D, mắt chim diễn ra trong không gian. Tôi đang cố gắng sử dụng đồ họa isometric trong một thế giới nơi Up là North, không xoay quanh thế giới trò chơi như trong các game isometric truyền thống (hãy nhớ rằng, trò chơi diễn ra trong không gian, không có địa hình). Dưới đây là một ví dụ về sprite mà tôi đang cố gắng sử dụng: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64.png Xoay 64 lần về trục dọc của chính nó với góc nhìn 35 độ (aka, iso). Hình ảnh đã được tạo ra, vì vậy điều này có thể được thay đổi.
Để cho rõ ràng, tôi đã ra lệnh rằng Bắc (Lên) là 0 độ, và Đông (Phải) là 90.
Vấn đề của tôi là sprite của tôi không phải lúc nào cũng trông như nó phải đối mặt với nơi mà các trò chơi nghĩ đó là do sự khác biệt trong những chiếc máy bay 3D được sử dụng. Không chắc chắn liệu tôi có sử dụng thuật ngữ chính xác hay không, nhưng tàu vũ trụ của tôi đã được quay trên một mặt phẳng và mặt phẳng khung nhìn đang mong đợi mọi thứ sẽ được quay trên mặt phẳng của chính nó. Đây là một mô tả của vấn đề:
http://cell.stat-life.com/images/stories/AsteroidOutpost/ProjectionIssue.png Ở bên trái, tôi có chế độ xem bên, bên phải tôi có chế độ xem từ trên xuống. Trên cùng, tôi có chế độ xem tàu không gian / sprite của thế giới. Ở phía dưới, tôi có những gì ma ngoại hình giống như khi nó được vẽ lên màn ảnh.
Ở phía trên bên phải là một phiên bản đơn giản về cách tàu vũ trụ của tôi được xoay (thậm chí phân tách độ giữa mỗi khung). Ở phía dưới bên phải là góc mà sprite trông giống như nó đối diện khi một góc cụ thể được vẽ trên màn hình. Vấn đề là rõ ràng nhất ở khoảng 45 độ. Dưới đây là hình ảnh được phủ lên một dòng "mặt phẳng màn hình" được chỉ theo hướng mà con tàu phải đối mặt: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLine.png Đường màu đỏ phải luôn luôn được chỉ theo cùng một hướng với con tàu, nhưng như bạn có thể thấy, vấn đề chiếu đang gây ra vấn đề. Tôi hy vọng tôi đang mô tả vấn đề đủ tốt.
EDIT: Đường màu đỏ được quay trên mặt phẳng màn hình, trong khi tàu không gian được quay trên "mặt phẳng tàu", do đó có sự khác biệt lớn giữa góc tàu và góc màn hình khi được vẽ. EDIT KẾT THÚC
Trông có vẻ khá kỳ quặc khi con tàu này đang bắn một tia laser vào một mục tiêu bị lệch sang một bên, khi nó nên bắn thẳng về phía trước.
Vì vậy, ... các giải pháp mà tôi đã đưa ra là:
- Ngừng cố gắng giả mạo một quan điểm đẳng cự, đi lớn hoặc về nhà. Xoay thế giới của tôi rồi. (PS: điều này sẽ khắc phục vấn đề của tôi, phải không?)
- Thay đổi bảng sprite của tôi (bằng cách nào đó) để có các khung đại diện cho "góc màn hình" mà mô hình sẽ được xem tại. Vì vậy, khi tôi yêu cầu một hình ảnh 45 độ, nó thực sự sẽ trông giống như nó quay mặt 45 độ trên màn hình.
- Thay đổi hệ thống kết xuất sprite của tôi để lấy một khung khác từ bảng sprite (bằng cách nào đó), biết rằng lấy khung "bình thường" sẽ trông buồn cười. Vì vậy, thay vì lấy khung 45 độ, nó sẽ lấy ... khung 33 độ (chỉ đoán) để nó trông chính xác với người dùng.
- Chỉ cần sử dụng 3D! Nó dễ hơn nhiều
Đối với một: Giải pháp nào bạn muốn giới thiệu? Tôi đang nghiêng về phía 2, mặc dù tôi biết điều đó là sai. Hãy nhớ rằng tôi có toàn quyền truy cập vào công cụ tạo sprite. Phương pháp 3 sẽ là lựa chọn thứ hai của tôi. Cả hai phương pháp này chỉ đơn giản yêu cầu tôi áp dụng một số phép toán cho (các) góc để có kết quả mong muốn. Btw, tôi đã thêm số 4 vào đó như một trò đùa, tôi không muốn chuyển sang 3D.
Đối với hai: Sử dụng phương pháp 2 hoặc 3, tôi sẽ điều chỉnh góc đầu vào hoặc đầu ra như thế nào? Tôi không giỏi lắm với các phép chiếu 3D và ma trận 3D (huống chi là ma trận 2D) và bất kỳ phép toán nào khác có thể được sử dụng để đạt được kết quả mong muốn của tôi.
Suy nghĩ thành tiếng ở đây: nếu tôi lấy một vectơ đơn vị hướng về phía mà tôi muốn con tàu nhìn (trên mặt phẳng màn hình), sau đó chiếu nó lên mặt phẳng tàu, sau đó tìm ra góc giữa đường chiếu đó và mặt phẳng của máy bay phía bắc là, tôi nên có góc của đồ họa tàu mà tôi muốn hiển thị. Đúng? (giải pháp cho số 3?) Người đàn ông ... Tôi không thể làm việc đó.
BIÊN TẬP:
Tôi biết vấn đề khó hình dung bằng hình ảnh tĩnh, vì vậy tôi đã tuân thủ Sprite Library Visual Tester của tôi để hiển thị vấn đề: http://cell.stat-life.com/doads/SpriteLibVisualTest.zip Nó yêu cầu XNA 4.0 Ứng dụng này là chỉ cần xoay sprite và vẽ một đường thẳng từ điểm chính giữa của nó ra ngoài theo góc mà trò chơi nghĩ rằng con tàu sẽ phải đối mặt.
EDIT ngày 8 tháng 9
Tiếp tục từ đoạn "nghĩ lớn" của tôi: Thay vì sử dụng phép chiếu (vì nó có vẻ khó) Tôi nghĩ rằng tôi có thể lấy một vectơ đơn vị hướng về phía bắc (0x, 1y, 0z), sử dụng ma trận để xoay nó theo góc sprite thực sự phải đối mặt, sau đó xoay nó một lần nữa từ "mặt phẳng xem" ra ngoài "mặt phẳng sprite" quanh trục X, sau đó ... làm phẳng? vectơ (về cơ bản chiếu nó) trở lại mặt phẳng xem bằng cách chỉ sử dụng X và Y (bỏ qua Z). Sau đó, sử dụng vectơ phẳng mới đó, tôi có thể xác định góc của nó và sử dụng nó để ... một cái gì đó. Tôi sẽ suy nghĩ nhiều hơn sau.
EDIT ngày 8 tháng 9 (2)
Tôi đã thử làm theo ý tưởng của tôi từ trên cao với một số thành công, yay! Vì vậy, ... để có được một đường màu đỏ trông giống như nó đang đi thẳng ra khỏi tàu vũ trụ của tôi (chỉ nhằm mục đích thử nghiệm), tôi đã làm như sau:
Vector3 vect = new Vector3(0, 1, 0);
vect = Vector3.Transform(vect, Matrix.CreateRotationZ(rotation));
vect = Vector3.Transform(vect, Matrix.CreateRotationY((float)((Math.PI / 2) - MathHelper.ToRadians(AngleFromHorizon))));
Vector2 flattenedVect = new Vector2(vect.X, vect.Y);
float adjustedRotation = (float)(getAngle(flattenedVect.X, flattenedVect.Y));
Trong trường hợp rotation
là góc màn hình và adjustedRotation
bây giờ là góc màn hình trên máy bay sprite. Tôi không biết tại sao tôi cần xoay Y thay vì X, nhưng có lẽ đó là điều cần làm với 3D mà tôi không biết.
Vì vậy, bây giờ tôi có thêm một phần thông tin, nhưng làm cách nào để sử dụng thông tin này để chọn một khung phù hợp hơn? Có lẽ thay vì quay từ mặt phẳng khung nhìn vào mặt phẳng sprite, sau đó chiếu lại, tôi nên thử làm theo cách khác. Đây là sprite của tôi với một dòng màu đỏ được điều chỉnh, nhưng điều tôi thực sự muốn làm là điều chỉnh mô hình, chứ không phải dòng: http://cell.stat-life.com/images/stories/AsteroidOutpost/Spaceship64RedLineCorrected.png
EDIT ngày 9 tháng 9
CHÚC MỪNG! Nó đã được sửa! Tôi sẽ mô tả những gì tôi đã làm để sửa nó:
Tôi đã làm theo lời khuyên của eBusiness và "squished" bởi hệ thống tọa độ thế giới (hoặc kéo dài ...?). Đây thực chất là giải pháp số 1, mặc dù tôi có ấn tượng rằng tôi sẽ phải xoay hệ tọa độ thế giới của mình liên quan đến hệ thống tọa độ màn hình. Không đúng! Lên vẫn là + y và Quyền vẫn là + x. Tôi đã sửa đổi các phương thức WorldToScreen và ScreenToWorld của mình để chuyển đổi chính xác giữa thế giới và tọa độ màn hình. Các phương thức này có thể không tối ưu, nhưng đây là hai phương thức duy nhất trong cơ sở mã của tôi phải thay đổi.
public Vector2 ScreenToWorld(float x, float y)
{
float deltaX = x - (size.Width / 2f);
float deltaY = y - (size.Height / 2f);
deltaX = deltaX * scaleFactor / (float)Math.Sqrt(3);
deltaY = deltaY * scaleFactor;
return new Vector2(focusWorldPoint.X + deltaX, focusWorldPoint.Y + deltaY);
}
public Vector2 WorldToScreen(float x, float y)
{
float deltaX = x - focusWorldPoint.X;
float deltaY = y - focusWorldPoint.Y;
deltaX = deltaX / scaleFactor * (float)Math.Sqrt(3);
deltaY = deltaY / scaleFactor;
return new Vector2(size.Width / 2f + deltaX, size.Height / 2f + deltaY);
}
Điều đó là vậy đó! Thay đổi hai phương thức đó ảnh hưởng đến mọi thứ khác: những gì tôi đang nhìn, nơi các đối tượng được vẽ, nơi tôi đang nhấp, mọi thứ. Tàu vũ trụ của tôi bây giờ nhìn thẳng vào mục tiêu nó đang bắn, và mọi thứ rơi đúng vị trí. Tôi sẽ thử nghiệm với phép chiếu chính tả, xem liệu nó có khiến mọi thứ dường như 'thật' hơn không.