Для отрисовки используется p5js, но это можно повторить на любом языке и любой граф. библиотеке (не движком).
Если двигать объект без фикс. временного шага и интерполяции - он чёткий, а с фикс. и интерполяцией - мыльный, если убрать интерполяцию - ещё и дёрганый по понятным причинам.
- Комменты оставил.
Песочница:
editor.p5js.org, вставьте пример слева и запустите кнопкой или
ctrl + enter.
const step = 1 / 60; // Шаг физики
let acc = 0; // Аккумулятор
let pos1; // Верхний прямоугольник
let lastPos1; // Последняя позиция верхнего прямоугольника
let pos2; // Нижний прямоугольник
// Функция вызывается один раз (init)
function setup() {
createCanvas(windowWidth, windowHeight); // Создаём канвас
frameRate(144); // Устанавливаем кол-во кадров / сек
// Инициализируем позиции прямоугольников
pos1 = createVector(0, height/2 - 100);
pos2 = createVector(0, height/2);
}
// Функция вызывается каждый кадр
function draw() {
background(220); // Заливаем фон
acc += deltaTime / 1000; // Увеличиваем аккумулятор
lastPos1 = pos1; // Сохраняем последнюю позицию верхнего прямоугольника
while(acc >= step) { // Пока аккумулятор больше шага физики
pos1.x += 100 * step; // Двигаем верхний прямоугольник вправо
acc -= step; // Уменьшаем аккумулятор
}
pos2.x += 100 * (deltaTime / 1000); // Двигаем нижний прямоугольник вправо
const alpha = acc / step; // Коэффициент интерполяции
// Интерполяция позиции
const interpPos = p5.Vector.lerp(lastPos1, pos1, alpha);
// Верхний прямоугольник (двигает: физики)
rect(interpPos.x, interpPos.y, 200, 50);
// Нижний прямоугольник (двигает: рендер)
rect(pos2.x, pos2.y, 200, 50);
}