Ошибка многомерной интерполяции в GML

все. Я использую Game Maker, программу с синтаксисом, несколько похожим на Python (за исключением пробелов), для реализации интерполяции между несколькими значениями данных, как описано здесь. Представьте себе диаграмму рассеяния с x = 0 в начале координат и x = 100 в конце с одинаковым интервалом между каждым значением данных. Позиции x постоянны, но позиции y могут иметь любое значение. Если бы между каждой точкой данных были соединены линии, то в идеале скрипт смог бы найти y для данной x-позиции. Вот моя оригинальная реализация:

// This is executed once.

nums = 3; // the number of values to interpolate between
t = 0; // the position along the "scatterplot" of values

// Values may be decimals with any sign.  There should be values >= nums.
ind[0] = 100;
ind[1] = 0;
ind[2] = 100;

//This is executed each step.

intervals = 100 / (nums - 1);
index = round(percent / intervals);
if percent != 0 {newpercent=  (intervals / (percent - index)) / 100;}
else {newpercent = 0;}
newval = ind[index] * (1 - newpercent) + ind[index + 1] * newpercent;

Это должно было использовать lerp() после определения того, какие две точки окружают заданную позицию x, чтобы вернуть интерполяцию между их двумя значениями, но это не так, поэтому мой вопрос:
Что пошло не так и как я могу это исправить? Заранее спасибо.

Изменить: вот готовый и рабочий код:

// This is executed once.

nums = 3; // the number of values to interpolate between
t = 0; // the position along the "scatterplot" of values

// Values may be decimals with any sign.  There should be values >= nums.
ind[0] = 100;
ind[1] = 0;
ind[2] = 100;

// This is executed each step; setting the result to 'alpha'.

if (nums > 1) {
    if (t != 1) {
        _temp1 = 1 / (nums - 1);
        _temp2 = floor(t / _temp1);
        _temp3 = (t - (_temp1 * _temp2)) * (nums - 1);
        alpha = ind[_temp2] + _temp3 * (ind[_temp2 + 1] - ind[_temp2]);
    }
    else {
        alpha = ind[nums - 1];
    }
}

person Community    schedule 29.08.2013    source источник
comment
Я не знаком с Game Maker, но не удивлюсь, если в нем уже есть функционал для линейной интерполяции (часто называемый lerp).   -  person Simon    schedule 30.08.2013
comment
Я знал, что эта функция называется lerp(), и я проверил википедию и адаптировал ее версию для Game Maker, так как она ограничена. Язык Game Maker по умолчанию по синтаксису близок к Python, так что вы можете использовать его в качестве справочного материала. На самом деле вы можете написать код на Python, потому что я все равно могу его передать (если так удобнее).   -  person    schedule 31.08.2013


Ответы (1)


То, что вы хотите сделать, это интерполировать значение свойства вашей игры (громкость звука, уровень опасности, сила тяжести и т. д.). Давайте назовем переменную, которую вы хотите вычислить, y по мере изменения некоторых других свойств (таких как время, x-позиция и т. д.) назовите это t.

У нас есть n точки, где мы знаем значение y. Назовем каждую из этих точек p0, p1 ... pn-1, где каждое число — это index этой точки. Назовем значения в этих точках y0, y1 ... yn-1. Итак, для любого заданного значения t мы хотим сделать следующее:

Сначала находим две точки, ближайшие к t. Поскольку все точки равномерно распределены, мы знаем, что значение t для данной точки равно t = index/(n-1), и, переупорядочив это уравнение, мы можем получить «индекс» любого заданного t, как это index = t*(n-1). Когда t не находится точно в том же положении, что и одна из наших точек, это будет число между значениями индекса двух ближайших точек pk и pk1. Таким образом, pk = floor(index) дает вам индекс, предшествующий вашему t, а pk1 = pk + 1 является следующей точкой.

Затем мы должны выяснить, насколько близко t к каждой из этих двух точек (значение между 0 и 1), так как это определяет, какое влияние значение каждой точки получит при интерполяции. Назовем это измерение alpha. Затем alpha = (t - pk)/(pk1 - pk).

Наконец, если pk и pk1 имеют значения yk и yk1, вы получите интерполированное значение y следующим образом.

y = (1-alpha)*yk + alpha*yk1;
person Simon    schedule 29.08.2013
comment
Эта формула по-прежнему неверна. Это также то же самое, что и мой расчет, с той лишь небольшой разницей, что он менее эффективен (с большим количеством определенных переменных и разделенных формул, чтобы снизить скорость обработки моей эквивалентной формулы). Выход по-прежнему ошибочен; было бы неплохо, если бы вы сначала протестировали код. - person ; 30.08.2013
comment
Эти две формулы не совпадают. Первое отличие состоит в том, что пол отличается от раунда (я не знаю gml, но я был бы удивлен, если бы это было не так). Второе отличие заключается в том, как мы вычисляем alpha/newpercent. Что касается вашего комментария относительно эффективности; это не предназначено для кода, а скорее для объяснения линейной интерполяции, адаптированной к вашему конкретному случаю. Если вы поместите это в код, вы можете сделать это за то же количество шагов, и, вероятно, это будет более эффективно, поскольку будет меньше делений (деления медленные). - person Simon; 30.08.2013
comment
Не работает использование round() или floor(), потому что они округляются до ближайшего целого числа (это был остаток кода, когда я использовал проценты от 0 до 100). Теперь нам нужно округлить до ближайших сотых: round(number * 100) / 100 - person ; 31.08.2013