2016-10-02 2 views
0

Я просто написал фрагмент кода для обработки вращения объекта в сцене THREE.js. Однако проблема не является 3D-спецификой.JavaScript - алгоритм анимированного вращения

Я хочу, чтобы мой объект (это) поворачивался на 0,25 радиан по каждому вызову функции до тех пор, пока его вращение (this.clientRotation) не достигнет поворота, определенного в this.targetRotation. Код ниже - это содержимое функции update(), которая непрерывно вызывается в цикле рендеринга.

Я должен был проверить, находится ли абсолютная разница между текущим и целевым вращением выше количества оборотов для каждого вызова (0,25), чтобы избежать поворота назад и вперед, когда почти полностью достигнуто вращение цели.

Я должен был проверить, находится ли разность вращения (в радианах) выше 180 градусов, и в этом случае самый короткий поворот будет наоборот.

Я должен был проверить, остается ли обновленное вращение между -PI и + PI (0 и 360 градусов).

//Move only if we find a delta big enough between the target rotation and current rotation 
//Rotation goes from -PI to +PI 
this.rotationSpeed = 0.25; 

var absDiff = Math.abs(this.clientRotation - this.targetRotation); 
if(absDiff > this.rotationSpeed){ 

    if(absDiff < Math.PI){ 

    //Less than 180 degrees, turn towards the target 
    if(this.targetRotation > this.clientRotation) this.clientRotation += this.rotationSpeed; 
    if(this.targetRotation < this.clientRotation) this.clientRotation -= this.rotationSpeed; 
    } else { 

    //More than 180 degrees this way, so it is shorter to turn the other way 
    if(this.targetRotation > this.clientRotation) this.clientRotation -= this.rotationSpeed; 
    if(this.targetRotation < this.clientRotation) this.clientRotation += this.rotationSpeed; 
    } 

    //If rotation radians becomes more than a complete 360 turn, start again from 0 
//If it goes below 0, start again down from 360 
    if(this.clientRotation > Math.PI) this.clientRotation -= Math.PI*2; 
    if(this.clientRotation < -Math.PI) this.clientRotation += Math.PI*2; 
} 

Это работает, но кажется слишком сложным. Существует ли более оптимизированный способ достижения этого стандартного поведения вращения?

ответ

2

Код, приведенный ниже, функционально одинаковый, только используя тройники для конденсации логики. ИМО гораздо легче читать, но это полностью предпочтение.

this.rotationSpeed = 0.25; 
var absDiff = Math.abs(this.clientRotation - this.targetRotation); 
if(absDiff > this.rotationSpeed) { 
    var lessThan180 = absDiff < Math.PI; 
    if(this.targetRotation > this.clientRotation) { 
    this.clientRotation = (lessThan180) ? this.clientRotation + this.rotationSpeed : this.clientRotation - this.rotationSpeed; 
    } else if (this.targetRotation < this.clientRotation) { 
    this.clientRotation = (lessThan180) ? this.clientRotation - this.RotationSpeed : this.clientRotation + this.rotationSpeed; 
    } 
    this.clientRotation = (this.clientRotation > Math.PI) ? this.clientRotation - Math.PI*2 : this.clientRotation + Math.PI*2; 
} 

Ваш исходный код может показаться более сложным, но на самом деле я думаю, что вы проделали большую работу документирования кода через комментарии и делая код ясным и читаемым. Единственное, что я рекомендовал бы изменить, независимо от того, что (даже если вы не являетесь поклонником троянов), использует «if»/«else-if» вместо «if», затем другое «if» условное , Это связано с тем, что оба условия «если» будут выполняться независимо от того, что в случае «if»/«else-if», если условие «if» условно преуспевает, условие «else-if» не будет проверяться и пропущено , поэтому он более эффективен.

+0

Я тоже часто использую тройники, но в некоторых случаях я лично вижу код без них. Хорошая точка для else-ifs :) – Rayjax

Смежные вопросы