Giống như Jimmy nói một hình elip có lẽ phù hợp hơn cho chuyển động này. Dưới đây là một số ý tưởng về cách thực sự triển khai nó với một chút chi tiết hơn cho những người quan tâm.
Mất thời gian
Để bắt đầu, bạn cần một biến để theo dõi thời gian trong thế giới trò chơi. Bạn có thể thực hiện nó theo bất kỳ cách nào bạn thích, nhưng đây là một ví dụ. Tôi sẽ sử dụng một biến được gọi là hours
thay đổi từ 0 đến 24 (mặc dù khi đạt đến 24, nó sẽ quay trở về 0).
Không giống như cuộc sống thực, tôi chỉ xem xét ngày đó bắt đầu từ 0 giờ và đêm bắt đầu lúc 12 giờ. Điều này sẽ làm cho một số tính toán dễ dàng hơn.
Tôi cũng sẽ xác định tốc độ thay đổi thời gian của trò chơi liên quan đến thời gian thực. Trong ví dụ này, cứ hai phút thời gian thực sẽ tương ứng với một giờ trong trò chơi.
float hours = 0.0f; // From 0 to 24 wrapping around
const float HoursPerSecond = 1f / 120f; // E.g. 2 minutes = 1 hour ingame
public void Update(float elapsed)
{
hours += elapsed * HoursPerSecond; // Advance clock
if(hours >= 24f) hours -= 24f; // Wrap around 24 hours
}
Cấu hình
Bây giờ trước khi thiết lập chuyển động của mặt trời, chúng ta cần chỉ định một vài tham số của nó. Cụ thể, tại giá trị X nào nó tăng lên từ đường chân trời và tại giá trị X nào nó rơi vào đường chân trời. Ngoài ra, những gì Y tương ứng với đường chân trời, và anh ta phải cao bao nhiêu trên đường đó.
float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;
Tính toán tọa độ của mặt trời
Bây giờ là lúc để tính toán vị trí của mặt trời trong một thời gian nhất định trong ngày. Thay vào đó, tôi sẽ sử dụng chức năng tham số tương tự được sử dụng bởi Jimmy nhưng với miền nằm trong khoảng [0..2PI] (để đưa mặt trời trở lại vị trí ban đầu khi bình minh):
x = (1-cos (t)) / 2
y = sin (t)
Đây là một chức năng tốt vì giá trị X thay đổi từ 0 đến 1 và sau đó trở lại 0 (chúng ta sẽ ánh xạ tới các giá trị X bắt đầu và kết thúc của mặt trời) và giá trị Y bắt đầu từ 0 và di chuyển lên 1 và quay lại về 0 lần nữa (sẽ là phần ngày của chúng ta ) và sau đó lặp lại chính xác điều tương tự ở phía tiêu cực trước khi quay trở lại vị trí ban đầu (sẽ là đêm của chúng ta mặc dù mặt trời sẽ không được vẽ vào thời điểm này).
Bước đầu tiên là nhân rộng số giờ từ phạm vi [0..24) sang phạm vi chức năng của chúng tôi là [0..2PI):
float t = (hours / 24f) * MathHelper.TwoPi; // Scale: [0..24) to [0..2PI)
Tiếp theo, chúng tôi áp dụng các hàm để lấy lại các giá trị trong khoảng từ 0 đến 1 Tôi đã nói ở trên:
float horizontal = (float)((1-Math.Cos(t)) / 2f); // Changes: 0 1 0
float vertical = (float)(Math.Sin(t)); // Changes: 0 1 0 -1 0
Và cuối cùng, chúng tôi mở rộng các giá trị đó bằng các tham số của mặt trời:
float sunX = startX + (endX - startX) * horizontal; // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical; // Up and down around horizonY