В PaperJS вращение фигуры вокруг точки не работает должным образом

Я пытаюсь воссоздать игру Asteroids. Это пример кода для конструктора объекта Ship (я использую функцию конструктора, а не литерал объекта, потому что this не работает должным образом при ссылке на переменные в литерале):

function Ship(pos) {
    var position = pos ? pos : view.center;
    var segments = [
            new Point(position) + new Point(0, -7.5), // Front of ship
            new Point(position) + new Point(-5, 7.5), // Back left
            new Point(position) + new Point(0, 3.5), // Rear exhaust indentation
            new Point(position) + new Point(5, 7.5) // Back right
        ]
    this.shipPath = new Path.Line({
        segments: segments,
        closed: true,
        strokeColor: '#eee',
        strokeWidth: 2
    });
    this.velocity = new Point(0, -1);
    this.steering = new Point(0, -1);
    this.rot = function(ang) {
        this.steering.angle += ang;
        this.shipPath.rotate(ang, this.shipPath.position);
    }
    this.drive = function() {
        this.shipPath.position += this.velocity;
    }
}

var ship = new Ship();

var path = new Path({
    strokeColor: '#ddd',
    strokeWidth: 1
});

function onFrame(event) {
    path.add(ship.shipPath.position);
    ship.drive();
}

Я не упомянул обработчики клавиш, которые управляют кораблем, но в основном они вызывают функцию this.rot() под разными углами в зависимости от того, была ли нажата правая или левая кнопка.

По сути, моя проблема заключается в том, что, согласно этому, при управлении кораблем корабль должен вращаться вокруг своей shipPath.position, что оставляет эту точку движущейся по прямой линии, когда корабль вращается вокруг нее. Вместо этого это происходит:

введите здесь описание изображения

Кудрявая часть path связана с тем, что я непрерывно управлял кораблем в течение нескольких секунд. Почему это происходит? Если корабль вращается вокруг своего position, почему положение должно колебаться в сторону, когда корабль вращается?

Вот ссылка на то, как это работает на моем собственном веб-сайте: http://aronadler.com/asteroid/ Я бы с удовольствием поместил это на jsbin или codepen, но, несмотря на многочасовую работу, я так и не смог заставить paperscript работать в javascript.

Вот набросок. Поскольку по какой-то причине Sketch не позволяет обнаруживать клавиши со стрелками, я задал ему автоматическое постоянное вращение. Эффект тот же.


person Aron    schedule 30.12.2015    source источник
comment
jsbin был бы полезен   -  person Bek    schedule 30.12.2015
comment
Я согласен, но пытаться заставить paperjs работать в обычной области javascript - это кошмар. Потерпите меня.   -  person Aron    schedule 30.12.2015
comment
Я всегда использую бумагу в чистом режиме JavaScript — его намного проще отлаживать и он на самом деле быстрее, а paper-core.js также меньше, чем paper-full.js — он не включает анализатор JavaScript. paperjs.org/tutorials/getting-started/using-javascript-directly   -  person bmacnaughton    schedule 30.12.2015
comment
Я смотрел на эту страницу некоторое время. Я пытаюсь внедрить paperscript в глобальную область, выполнив window.onload = function() { paper.install(window); paper.setup('canvas'); // code }, но это дает мне сообщение об ошибке Uncaught TypeError: Cannot use 'in' operator to search for 'point' in { x: 0, y: 0 }{ x: 0, y: -7.5 }   -  person Aron    schedule 30.12.2015
comment
Просто добавил ссылку на скетч.   -  person Aron    schedule 30.12.2015
comment
Ничего страшного. Я не делаю именно то, что показывает учебник на самом деле. Я просто загружаю paper-core.js, а затем делаю paper.setup('canvas'). Что я теряю, так это возможность использовать + (и другие операторы) в точках; Я должен сделать point1.add(point2) и т. д. И я должен ссылаться на все бумажные функции и конструкторы с префиксом paper, поэтому paper.Path.Line и т. д.   -  person bmacnaughton    schedule 30.12.2015


Ответы (1)


Причина этого в том, что path.bounds.center не является центром треугольника. Центром вращения по умолчанию является path.bounds.center. See набросок. Красные точки — это bounds.center, зеленые прямоугольники — это прямоугольник границ.

Вы хотите вращаться вокруг центра треугольника (технически центроида), который можно рассчитать, найдя точку 2/3 пути от вершины до середины противоположной стороны.

Вот некоторый код для вычисления центроида вашего треугольника:

function centroid(triangle) {
    var segments = triangle.segments;
    var vertex = segments[0].point;
    var opposite = segments[1].point - (segments[1].point - segments[2].point) / 2;
    var c = vertex + (opposite - vertex) * 2/3;
    return c;
}

And an updated эскиз, показывающий, как центр не перемещается относительно вашего треугольника при его вращении при вычислении центроида.

And I've updated your sketch to use the centroid rather than position. Теперь он движется прямолинейно.

person bmacnaughton    schedule 30.12.2015
comment
Хорошо, я понимаю, но это не решает мою проблему, потому что я явно говорю ему вращаться вокруг определенной точки. Поэтому независимо от того, какова его естественная точка вращения, я говорю ему вращаться вокруг определенной точки, а именно ship.shipPath.position, так как же возможно, что вращение смещает положение этой самой точки? - person Aron; 30.12.2015
comment
Потому что эта точка не является центром треугольника. Посмотрите на эскиз в моем ответе - вращение треугольника меняет положение центра. Вам не нужна центральная позиция, потому что это не центр треугольника (на самом деле, когда вы вращаете треугольник, размер прямоугольника границ также изменяется). Я добавлю небольшой код для вычисления центроида треугольника. Если вы повернетесь вокруг этого положения, это сработает. - person bmacnaughton; 30.12.2015
comment
Аааа, да, хорошо, я понимаю. Спасибо @bmacnaughton!! И спасибо, что уже поместили это в мой код :) - person Aron; 30.12.2015