Как сказал Джимми, эллипс, вероятно, лучше подходит для этого движения. Вот несколько идей о том, как на самом деле реализовать это, с некоторыми подробностями для тех, кто заинтересован.
Принимая время
Для начала вам нужна переменная, чтобы отслеживать время в игровом мире. Вы можете реализовать это так, как вам нравится, но вот пример. Я буду использовать переменную с именем 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
у = грех (т)
Это хорошая функция, потому что значение 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