Движение объекта в 2D: физика, формула и векторное управление

    Разработка игр и симуляторов на Canvas JavaScript требует понимания базовой физики движения. Когда у вас есть объект (космический корабль, спрайт) в прямоугольной системе координат с позицией x и y, а также управление через WASD, ключевой вопрос - как правильно изменять координаты, чтобы движение было реалистичным. В этой статье мы разберём формулы перемещения, учёт ускорения и скорости, а также работу с векторами направления и вращения.

    Основная формула движения с ускорением

    Для движения объекта с постоянным ускорением и ограничением по скорости используйте классическую кинематическую модель. Каждый кадр (tick) обновляйте скорость и позицию:

    • Скорость: velocity += acceleration * direction * deltaTime
    • Позиция: position += velocity * deltaTime

    Где direction - нормализованный вектор направления (единичной длины), полученный из нажатых клавиш. Например, при нажатии W вектор (0, -1), при D (1, 0). Ускорение и скорость - скалярные величины, которые вы ограничиваете максимальным значением. В коде это выглядит так:

    // Псевдокод обновления каждый кадр
    let accel = 0.5; // ускорение
    let maxSpeed = 10;
    let friction = 0.98; // трение для остановки
    
    // Обновление скорости
    if (isMoving) {
        speed += accel * dt;
        if (speed > maxSpeed) speed = maxSpeed;
    } else {
        speed *= friction;
    }
    
    // Обновление позиции
    x += dirX * speed * dt;
    y += dirY * speed * dt;

    Учёт вращения и вектора направления носа

    Если объект может вращаться, у вас появляются два вектора: вектор текущего движения (куда объект фактически летит) и вектор направления носа (куда смотрит объект). Их не нужно складывать - вместо этого используйте скалярное произведение (dot product) для определения, ускоряться или тормозить:

    • Dot product > 0: нос и движение сонаправлены - ускоряем.
    • Dot product < 0: нос и движение противоположны - тормозим (или разворачиваем).

    Формула: dot = (moveDir.x * noseDir.x + moveDir.y * noseDir.y). Если значение положительное, тяга двигателя добавляется к скорости; если отрицательное - скорость уменьшается.

    Пример реализации поворота и тяги

    // Вектор движения (нормализованный)
    let moveDir = {x: Math.cos(angle), y: Math.sin(angle)};
    
    // Вектор текущей скорости (нормализованный)
    let velDir = {x: vx / speed, y: vy / speed};
    
    // Скалярное произведение
    let dot = moveDir.x * velDir.x + moveDir.y * velDir.y;
    
    if (dot > 0) {
        // Ускоряемся
        speed += thrust * dt;
    } else {
        // Тормозим
        speed -= brake * dt;
    }
    
    // Обновляем позицию
    x += vx * dt;
    y += vy * dt;

    Формула точки на окружности для поворота

    Чтобы повернуть объект на заданный угол, используйте формулу точки на окружности. Если центр объекта (x0, y0), а нос находится на расстоянии r от центра, новые координаты носа после поворота на угол θ:

    newX = x0 + r * Math.cos(θ);
    newY = y0 + r * Math.sin(θ);

    Это пригодится для визуализации направления или для прицеливания.

    Практические советы для Canvas JS

    • Всегда нормализуйте векторы направления, чтобы скорость не зависела от количества одновременно нажатых клавиш.
    • Используйте deltaTime для независимости от частоты кадров (FPS).
    • Ограничивайте скорость через Math.min(speed, maxSpeed).
    • Для плавного торможения применяйте трение: speed *= 0.98 каждый кадр.

    Эти формулы и подходы - база для любой 2D-игры с управлением WASD. Если вы забыли старый код, просто восстановите логику по этим принципам: вектор направления, ускорение, ограничение скорости и скалярное произведение для поворота.

    Часто задаваемые вопросы