Як сказав Джиммі, еліпс, мабуть, краще підходить для цього руху. Ось кілька ідей щодо того, як насправді реалізувати його, трохи детальніше для зацікавлених.
Займаючи час
Для початку вам потрібна змінна, щоб слідкувати за часом у ігровому світі. Ви можете реалізовувати його будь-яким способом, але вам приклад. Я буду використовувати змінну, яка називається hours
, від 0 до 24 (хоча коли вона досягає 24, вона повертається до 0).
На відміну від реального життя, я просто вважаю, що день починається з 0 годин, а ніч починається з 12 годин. Це полегшить деякі розрахунки.
Я також визначу швидкість, з якою змінюється час гри в залежності від реального часу. У цьому прикладі кожні дві хвилини реального часу відповідають одній годині гри.
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
}
Конфігурація
Тепер перед встановленням руху нашого сонця нам потрібно вказати кілька його параметрів. Зокрема, за якого значення X воно піднімається з горизонту, і за якого значення X воно потрапляє в горизонт. Крім того, що Y відповідає горизонту, і наскільки високий він повинен піднятися над цією лінією.
float startX = 0;
float endX = 1000;
float horizonY = worldHeight/2;
float amplitudeY = 200;
Обчислення координат Сонця
Тепер настав час порахувати положення нашого сонця за заданий час доби. Я буду використовувати ту саму параметричну функцію, яку використовував Джиммі, але з доменним діапазоном від [0..2PI] (щоб повернути Сонце у вихідне положення до світанку):
x = (1-cos (t)) / 2
y = sin (t)
Це хороша функція, тому що значення X змінюється від 0 до 1, а потім знову до 0 (що ми будемо відображати до початку та кінця значення нашого сонця X), а значення Y починається з 0 і рухається до 1 і назад до 0 знову (що було б нашою порцією дня ), а потім повторює абсолютно те саме з негативної сторони, перш ніж повернутися в початкове положення (яке було б нашою ніччю, хоча сонце не буде затягнуте в цій точці).
Перший крок - масштабування годин із діапазону [0..24) до діапазону нашої функції, який становить [0..2PI):
float t = (hours / 24f) * MathHelper.TwoPi; // Scale: [0..24) to [0..2PI)
Далі ми застосовуємо функції для повернення значень між 0 і 1, про які я говорив вище:
float horizontal = (float)((1-Math.Cos(t)) / 2f); // Changes: 0 1 0
float vertical = (float)(Math.Sin(t)); // Changes: 0 1 0 -1 0
І нарешті ми масштабуємо ці значення за допомогою параметрів сонця:
float sunX = startX + (endX - startX) * horizontal; // From startX to endX and back
float sunY = horizonY + amplitydeY * vertical; // Up and down around horizonY