LCOV - code coverage report
Current view: top level - xenolith/renderer/basic2d - XL2dActionAcceleratedMove.cc (source / functions) Hit Total Coverage
Test: coverage.info Lines: 34 356 9.6 %
Date: 2024-05-12 00:16:13 Functions: 6 23 26.1 %

          Line data    Source code
       1             : /**
       2             :  Copyright (c) 2023 Stappler LLC <admin@stappler.dev>
       3             : 
       4             :  Permission is hereby granted, free of charge, to any person obtaining a copy
       5             :  of this software and associated documentation files (the "Software"), to deal
       6             :  in the Software without restriction, including without limitation the rights
       7             :  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
       8             :  copies of the Software, and to permit persons to whom the Software is
       9             :  furnished to do so, subject to the following conditions:
      10             : 
      11             :  The above copyright notice and this permission notice shall be included in
      12             :  all copies or substantial portions of the Software.
      13             : 
      14             :  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      15             :  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      16             :  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      17             :  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      18             :  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      19             :  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
      20             :  THE SOFTWARE.
      21             :  **/
      22             : 
      23             : #include "XL2dActionAcceleratedMove.h"
      24             : #include "XLNode.h"
      25             : 
      26             : #define XL_ACCELERATED_LOG(...)
      27             : //#define XL_ACCELERATED_LOG(...) stappler::log::format("ActionAcceleratedMove", __VA_ARGS__)
      28             : 
      29             : namespace STAPPLER_VERSIONIZED stappler::xenolith::basic2d {
      30             : 
      31           0 : Rc<ActionInterval> ActionAcceleratedMove::createBounce(float acceleration, Vec2 from, Vec2 to, Vec2 velocity,
      32             :                 float bounceAcceleration, Function<void(Node *)> &&callback) {
      33           0 :         Vec2 diff = to - from;
      34           0 :         float distance = diff.length();
      35             : 
      36           0 :         if (std::fabs(distance) < std::numeric_limits<float>::epsilon()) {
      37           0 :                 return Rc<DelayTime>::create(0.0f);
      38             :         }
      39             : 
      40           0 :     Vec2 normal = diff.getNormalized();
      41           0 :         normal.normalize();
      42             : 
      43           0 :     Vec2 velProject = velocity.project(normal);
      44             : 
      45             :     float startSpeed;
      46           0 :     if (std::fabs(normal.getAngle(velProject)) < M_PI_2) {
      47           0 :         startSpeed = velProject.length();
      48             :     } else {
      49           0 :         startSpeed = -velProject.length();
      50             :     }
      51             : 
      52           0 :     return ActionAcceleratedMove::createBounce(acceleration, from, to, startSpeed, bounceAcceleration, move(callback));
      53             : }
      54             : 
      55           0 : Rc<ActionInterval> ActionAcceleratedMove::createBounce(float acceleration, Vec2 from, Vec2 to, float velocity,
      56             :                 float bounceAcceleration, Function<void(Node *)> &&callback) {
      57           0 :         Vec2 diff = to - from;
      58           0 :         float distance = diff.length();
      59             : 
      60           0 :         if (std::fabs(distance) < std::numeric_limits<float>::epsilon()) {
      61           0 :                 return Rc<DelayTime>::create(0.0f);
      62             :         }
      63             : 
      64           0 :     Vec2 normal = diff.getNormalized();
      65           0 :         normal.normalize();
      66             : 
      67           0 :     float startSpeed = velocity;
      68             : 
      69           0 :         if (startSpeed == 0) {
      70           0 :                 float duration = std::sqrt(distance / acceleration);
      71             : 
      72           0 :                 auto a = ActionAcceleratedMove::createWithDuration(duration, normal, from, startSpeed, acceleration);
      73           0 :                 auto b = ActionAcceleratedMove::createWithDuration(duration, normal, a->getEndPosition(), a->getEndVelocity(), -acceleration);
      74             : 
      75           0 :                 a->setCallback(Function<void(Node *)>(callback));
      76           0 :                 b->setCallback(move(callback));
      77             : 
      78           0 :                 return Rc<Sequence>::create(a, b);
      79           0 :         } else {
      80           0 :                 float t = startSpeed / acceleration;
      81           0 :                 float result = (startSpeed * t) - (acceleration * t * t * 0.5);
      82             : 
      83           0 :                 if (startSpeed > 0 && distance > result) {
      84           0 :                         float pseudoDistance = distance + acceleration * t * t * 0.5;
      85           0 :                         float pseudoDuration = std::sqrt(pseudoDistance / acceleration);
      86             : 
      87           0 :                         auto a = ActionAcceleratedMove::createAccelerationTo(normal, from, startSpeed, acceleration * pseudoDuration, acceleration);
      88           0 :                         auto b = ActionAcceleratedMove::createWithDuration(pseudoDuration, normal, a->getEndPosition(), a->getEndVelocity(), -acceleration);
      89             : 
      90           0 :                         a->setCallback(Function<void(Node *)>(callback));
      91           0 :                         b->setCallback(move(callback));
      92             : 
      93           0 :                         return Rc<Sequence>::create(a, b);
      94           0 :                 } else if (startSpeed > 0 && distance <= result) {
      95           0 :                         if (bounceAcceleration == 0) {
      96           0 :                                 acceleration = -acceleration;
      97           0 :                                 float pseudoDistance = distance - result; // < 0
      98           0 :                                 float pseudoDuration = std::sqrt(pseudoDistance / acceleration); // > 0
      99             : 
     100           0 :                                 auto a = ActionAcceleratedMove::createAccelerationTo(normal, from, startSpeed, acceleration * pseudoDuration, acceleration);
     101           0 :                                 auto b = ActionAcceleratedMove::createWithDuration(pseudoDuration, normal, a->getEndPosition(), a->getEndVelocity(), -acceleration);
     102             : 
     103           0 :                                 a->setCallback(Function<void(Node *)>(callback));
     104           0 :                                 b->setCallback(move(callback));
     105             : 
     106           0 :                                 return Rc<Sequence>::create(a, b);
     107           0 :                         } else {
     108           0 :                                 auto a0 = ActionAcceleratedMove::createAccelerationTo(from, to, startSpeed, -acceleration);
     109           0 :                                 auto a1 = ActionAcceleratedMove::createDecceleration(normal, a0->getEndPosition(), a0->getEndVelocity(), bounceAcceleration);
     110             : 
     111           0 :                                 Vec2 tmpFrom = a1->getEndPosition();
     112           0 :                                 diff = to - tmpFrom;
     113           0 :                                 distance = diff.length();
     114           0 :                             normal = diff.getNormalized();
     115           0 :                                 float duration = std::sqrt(distance / acceleration);
     116             : 
     117           0 :                                 auto a = ActionAcceleratedMove::createWithDuration(duration, normal, tmpFrom, 0, acceleration);
     118           0 :                                 auto b = ActionAcceleratedMove::createWithDuration(duration, normal, a->getEndPosition(), a->getEndVelocity(), -acceleration);
     119             : 
     120           0 :                                 a0->setCallback(Function<void(Node *)>(callback));
     121           0 :                                 a1->setCallback(Function<void(Node *)>(callback));
     122           0 :                                 a->setCallback(Function<void(Node *)>(callback));
     123           0 :                                 b->setCallback(move(callback));
     124             : 
     125           0 :                                 return Rc<Sequence>::create(a0, a1, a, b);
     126           0 :                         }
     127             :                 } else {
     128           0 :                         float pseudoDistance = 0;
     129             : 
     130           0 :                         if (bounceAcceleration) {
     131           0 :                                 t = startSpeed / bounceAcceleration;
     132           0 :                                 pseudoDistance = distance + std::fabs((startSpeed * t) - bounceAcceleration * t * t * 0.5);
     133             :                         } else {
     134           0 :                                 pseudoDistance = distance + std::fabs((startSpeed * t) - acceleration * t * t * 0.5);
     135             :                         }
     136             : 
     137           0 :                         float pseudoDuration = std::sqrt(pseudoDistance / acceleration);
     138             : 
     139           0 :                         Rc<ActionAcceleratedMove> a1;
     140           0 :                         Rc<ActionAcceleratedMove> a2;
     141           0 :                         if (bounceAcceleration) {
     142           0 :                                 a1 = ActionAcceleratedMove::createDecceleration(-normal, from, -startSpeed, bounceAcceleration);
     143           0 :                                 a2 = ActionAcceleratedMove::createAccelerationTo(normal, a1->getEndPosition(), 0, acceleration * pseudoDuration, acceleration);
     144             :                         } else {
     145           0 :                                 a2 = ActionAcceleratedMove::createAccelerationTo(normal, from, startSpeed, acceleration * pseudoDuration, acceleration);
     146             :                         }
     147             : 
     148           0 :                         auto b = ActionAcceleratedMove::createDecceleration(normal, a2->getEndPosition(), a2->getEndVelocity(), acceleration);
     149             : 
     150           0 :                         if (a1) {
     151           0 :                                 a2->setCallback(Function<void(Node *)>(callback));
     152           0 :                                 b->setCallback(Function<void(Node *)>(callback));
     153           0 :                                 a1->setCallback(move(callback));
     154           0 :                                 return Rc<Sequence>::create(a1, a2, b);
     155             :                         } else {
     156           0 :                                 a2->setCallback(Function<void(Node *)>(callback));
     157           0 :                                 b->setCallback(move(callback));
     158           0 :                                 return Rc<Sequence>::create(a2, b);
     159             :                         }
     160           0 :                 }
     161             :         }
     162             : }
     163             : 
     164           0 : Rc<ActionInterval> ActionAcceleratedMove::createFreeBounce(float acceleration, Vec2 from, Vec2 to, Vec2 velocity,
     165             :                 float bounceAcceleration, Function<void(Node *)> &&callback) {
     166             : 
     167           0 :         Vec2 diff = to - from;
     168           0 :         float distance = diff.length();
     169           0 :         Vec2 normal = diff.getNormalized();
     170           0 :         Vec2 velProject = velocity.project(normal);
     171             : 
     172             :     float startSpeed;
     173           0 :     if (std::fabs(normal.getAngle(velProject)) < M_PI_2) {
     174           0 :         startSpeed = velProject.length();
     175             :     } else {
     176           0 :         startSpeed = -velProject.length();
     177             :     }
     178             : 
     179           0 :     if (startSpeed < 0) {
     180           0 :         return createBounce(acceleration, from, to, velocity, bounceAcceleration, move(callback));
     181             :     } else {
     182           0 :         float duration = startSpeed / acceleration;
     183           0 :         float deccelerationPath = startSpeed * duration - acceleration * duration * duration * 0.5;
     184           0 :         if (deccelerationPath < distance) {
     185           0 :                 auto a = createWithDuration(duration, normal, from, startSpeed, -acceleration);
     186           0 :                         a->setCallback(move(callback));
     187           0 :                         return a;
     188           0 :         } else {
     189           0 :                 return createBounce(acceleration, from, to, velocity, bounceAcceleration, move(callback));
     190             :         }
     191             :     }
     192             : }
     193             : 
     194           0 : Rc<ActionInterval> ActionAcceleratedMove::createWithBounds(float acceleration, Vec2 from, Vec2 velocity,
     195             :                 const Rect &bounds, Function<void(Node *)> &&callback) {
     196           0 :         Vec2 normal = velocity.getNormalized();
     197             : 
     198           0 :         float angle = normal.getAngle();
     199             : 
     200             :         float start, end, pos, v, t, dist;
     201           0 :         Vec2 x, y, z, a, b, i;
     202             : 
     203           0 :         if (bounds.size.width == 0 && bounds.size.height == 0) {
     204           0 :                 return nullptr;
     205             :         }
     206             : 
     207           0 :         if (bounds.size.width == 0) {
     208           0 :                 start = bounds.origin.y;
     209           0 :                 end = bounds.origin.y + bounds.size.height;
     210           0 :                 pos = from.y;
     211             : 
     212           0 :                 v = velocity.y;
     213           0 :                 t = std::fabs(v) / std::fabs(acceleration);
     214           0 :                 dist = std::fabs(v) * t - std::fabs(acceleration) * t * t * 0.5;
     215             : 
     216           0 :                 if (velocity.y > 0) {
     217           0 :                         if (std::fabs(pos - end) < std::numeric_limits<float>::epsilon()) {
     218           0 :                                 return Rc<DelayTime>::create(0.0f);
     219           0 :                         } else if (pos + dist < end) {
     220           0 :                                 return createDecceleration(Vec2(0, 1), from, velocity.y, -acceleration, move(callback));
     221             :                         } else {
     222           0 :                                 return createAccelerationTo(from, Vec2(from.x, end), v, -acceleration, move(callback));
     223             :                         }
     224             :                 } else {
     225           0 :                         if (std::fabs(pos - start) < std::numeric_limits<float>::epsilon()) {
     226           0 :                                 return Rc<DelayTime>::create(0.0f);
     227           0 :                         } else if (pos - dist > start) {
     228           0 :                                 return createDecceleration(Vec2(0, -1), from, velocity.y, -acceleration, move(callback));
     229             :                         } else {
     230           0 :                                 return createAccelerationTo(from, Vec2(from.x, start), std::fabs(v), -acceleration, move(callback));
     231             :                         }
     232             :                 }
     233             :         }
     234             : 
     235           0 :         if (bounds.size.height == 0) {
     236           0 :                 start = bounds.origin.x;
     237           0 :                 end = bounds.origin.x + bounds.size.width;
     238           0 :                 pos = from.x;
     239             : 
     240           0 :                 v = std::fabs(velocity.x);
     241           0 :                 t = v / std::fabs(acceleration);
     242           0 :                 dist = v * t - std::fabs(acceleration) * t * t * 0.5;
     243             : 
     244           0 :                 if (velocity.x > 0) {
     245           0 :                         if (std::fabs(pos - end) < std::numeric_limits<float>::epsilon()) {
     246           0 :                                 return Rc<DelayTime>::create(0.0f);
     247           0 :                         } else if (pos + dist < end) {
     248           0 :                                 return createDecceleration(Vec2(1, 0), from, v, -acceleration, move(callback));
     249             :                         } else {
     250           0 :                                 return createAccelerationTo(from, Vec2(end, from.y), v, -acceleration, move(callback));
     251             :                         }
     252             :                 } else {
     253           0 :                         if (std::fabs(pos - start) < std::numeric_limits<float>::epsilon()) {
     254           0 :                                 return nullptr;
     255           0 :                         } else if (pos - dist > start) {
     256           0 :                                 return createDecceleration(Vec2(-1, 0), from, v, -acceleration, move(callback));
     257             :                         } else {
     258           0 :                                 return createAccelerationTo(from, Vec2(start, from.y), v, -acceleration, move(callback));
     259             :                         }
     260             :                 }
     261             :         }
     262             : 
     263           0 :         if (angle < -M_PI_2) {
     264           0 :                 x = Vec2(bounds.getMinX(), bounds.getMaxY());
     265           0 :                 y = Vec2(bounds.getMinX(), bounds.getMinY());
     266           0 :                 z = Vec2(bounds.getMaxX(), bounds.getMinY());
     267             : 
     268           0 :                 a = (normal.x == 0)?from:Vec2::getIntersectPoint(from, from + normal, x, y);
     269           0 :                 b = (normal.y == 0)?from:Vec2::getIntersectPoint(from, from + normal, y, z);
     270           0 :         } else if (angle < 0) {
     271           0 :                 x = Vec2(bounds.getMinX(), bounds.getMinY());
     272           0 :                 y = Vec2(bounds.getMaxX(), bounds.getMinY());
     273           0 :                 z = Vec2(bounds.getMaxX(), bounds.getMaxY());
     274             : 
     275           0 :                 a = (normal.x == 0)?from:Vec2::getIntersectPoint(from, from + normal, x, y);
     276           0 :                 b = (normal.y == 0)?from:Vec2::getIntersectPoint(from, from + normal, y, z);
     277           0 :         } else if (angle < M_PI_2) {
     278           0 :                 x = Vec2(bounds.getMaxX(), bounds.getMinY());
     279           0 :                 y = Vec2(bounds.getMaxX(), bounds.getMaxY());
     280           0 :                 z = Vec2(bounds.getMinX(), bounds.getMaxY());
     281             : 
     282           0 :                 a = (normal.y == 0)?from:Vec2::getIntersectPoint(from, from + normal, x, y);
     283           0 :                 b = (normal.x == 0)?from:Vec2::getIntersectPoint(from, from + normal, y, z);
     284             :         } else {
     285           0 :                 x = Vec2(bounds.getMaxX(), bounds.getMaxY());
     286           0 :                 y = Vec2(bounds.getMinX(), bounds.getMaxY());
     287           0 :                 z = Vec2(bounds.getMinX(), bounds.getMinY());
     288             : 
     289           0 :                 a = (normal.y == 0)?from:Vec2::getIntersectPoint(from, from + normal, x, y);
     290           0 :                 b = (normal.x == 0)?from:Vec2::getIntersectPoint(from, from + normal, y, z);
     291             :         }
     292             : 
     293           0 :         float a_len = from.distance(a);
     294           0 :         float b_len = from.distance(b);
     295             :         float i_len, s_len;
     296             : 
     297           0 :         if (a_len < b_len) {
     298           0 :                 i = a; i_len = a_len; s_len = b_len;
     299             :         } else {
     300           0 :                 i = b; i_len = b_len; s_len = a_len;
     301             :         }
     302             : 
     303           0 :         v = velocity.length();
     304           0 :         t = v / acceleration;
     305           0 :         float path = v * t - acceleration * t * t * 0.5;
     306             : 
     307           0 :         if (path < i_len) {
     308           0 :                 return createDecceleration(normal, from, v, acceleration, move(callback));
     309             :         } else {
     310           0 :                 auto a1 = createAccelerationTo(from, i, v, -acceleration);
     311             : 
     312           0 :                 if (s_len > 0) {
     313           0 :                         a1->setCallback(Function<void(Node *)>(callback));
     314           0 :                         Vec2 diff = y - i;
     315           0 :                         if (diff.length() < std::numeric_limits<float>::epsilon()) {
     316           0 :                                 return a1;
     317             :                         }
     318           0 :                         Vec2 newNormal = diff.getNormalized();
     319             : 
     320           0 :                         i_len = diff.length();
     321             : 
     322           0 :                         acceleration = (normal * acceleration).project(newNormal).length();
     323           0 :                         if (acceleration == 0.0f) {
     324           0 :                                 return a1;
     325             :                         }
     326           0 :                         v = (normal * a1->getEndVelocity()).project(newNormal).length();
     327           0 :                         t = v / acceleration;
     328           0 :                         path = v * t - acceleration * t * t * 0.5;
     329             : 
     330           0 :                         if (path < i_len) {
     331           0 :                                 auto a2 = createDecceleration(newNormal, i, v, acceleration);
     332           0 :                                 a2->setCallback(move(callback));
     333           0 :                                 return Rc<Sequence>::create(a1, a2);
     334           0 :                         } else {
     335           0 :                                 auto a2 = createAccelerationTo(i, y, v, -acceleration);
     336           0 :                                 a2->setCallback(move(callback));
     337           0 :                                 return Rc<Sequence>::create(a1, a2);
     338           0 :                         }
     339             :                 } else {
     340           0 :                         if (a1) {
     341           0 :                                 a1->setCallback(move(callback));
     342             :                         }
     343           0 :                         return a1;
     344             :                 }
     345           0 :         }
     346             : }
     347             : 
     348          14 : Vec2 ActionAcceleratedMove::computeEndPoint() {
     349          14 :         return _startPoint + (_normalPoint * ((_startVelocity * _accDuration) + (_acceleration * _accDuration * _accDuration * 0.5)));
     350             : }
     351             : 
     352           0 : Vec2 ActionAcceleratedMove::computeNormalPoint() {
     353           0 :         return (_endPoint - _startPoint).getNormalized();
     354             : }
     355             : 
     356           0 : float ActionAcceleratedMove::computeEndVelocity() {
     357           0 :         return _startVelocity + _acceleration * _accDuration;
     358             : }
     359             : 
     360          14 : Rc<ActionAcceleratedMove> ActionAcceleratedMove::createDecceleration(Vec2 normal, Vec2 startPoint, float startVelocity,
     361             :                 float acceleration, Function<void(Node *)> &&callback) {
     362          14 :         auto pRet = Rc<ActionAcceleratedMove>::alloc();
     363          14 :         if (pRet->initDecceleration(normal, startPoint, startVelocity, acceleration, move(callback))) {
     364          14 :                 return pRet;
     365             :         }
     366           0 :         return nullptr;
     367          14 : }
     368             : 
     369           0 : Rc<ActionAcceleratedMove> ActionAcceleratedMove::createDecceleration(Vec2 startPoint, Vec2 endPoint,
     370             :                 float acceleration, Function<void(Node *)> &&callback) {
     371           0 :         auto pRet = Rc<ActionAcceleratedMove>::alloc();
     372           0 :         if (pRet->initDecceleration(startPoint, endPoint, acceleration, move(callback))) {
     373           0 :                 return pRet;
     374             :         }
     375           0 :         return nullptr;
     376           0 : }
     377             : 
     378           0 : Rc<ActionAcceleratedMove> ActionAcceleratedMove::createAccelerationTo(Vec2 normal, Vec2 startPoint, float startVelocity, float endVelocity,
     379             :                 float acceleration, Function<void(Node *)> &&callback) {
     380           0 :         auto pRet = Rc<ActionAcceleratedMove>::alloc();
     381           0 :         if (pRet->initAccelerationTo(normal, startPoint, startVelocity, endVelocity, acceleration, move(callback))) {
     382           0 :                 return pRet;
     383             :         }
     384           0 :         return nullptr;
     385           0 : }
     386             : 
     387           0 : Rc<ActionAcceleratedMove> ActionAcceleratedMove::createAccelerationTo(Vec2 startPoint, Vec2 endPoint, float startVelocity,
     388             :                 float acceleration, Function<void(Node *)> &&callback) {
     389           0 :         auto pRet = Rc<ActionAcceleratedMove>::alloc();
     390           0 :         if (pRet->initAccelerationTo(startPoint, endPoint, startVelocity, acceleration, move(callback))) {
     391           0 :                 return pRet;
     392             :         }
     393           0 :         return nullptr;
     394           0 : }
     395             : 
     396           0 : Rc<ActionAcceleratedMove> ActionAcceleratedMove::createWithDuration(float duration, Vec2 normal, Vec2 startPoint, float startVelocity,
     397             :                 float acceleration, Function<void(Node *)> &&callback) {
     398           0 :         auto pRet = Rc<ActionAcceleratedMove>::alloc();
     399           0 :         if (pRet->initWithDuration(duration, normal, startPoint, startVelocity, acceleration, move(callback))) {
     400           0 :                 return pRet;
     401             :         }
     402           0 :         return nullptr;
     403           0 : }
     404             : 
     405          14 : bool ActionAcceleratedMove::initDecceleration(Vec2 normal, Vec2 startPoint, float startVelocity,
     406             :                 float acceleration, Function<void(Node *)> &&callback) {
     407          14 :         acceleration = std::fabs(acceleration);
     408          14 :         startVelocity = std::fabs(startVelocity);
     409          14 :         if (startVelocity < 0 || acceleration < 0) {
     410             :                 XL_ACCELERATED_LOG("Deceleration failed: velocity:%f acceleration:%f", startVelocity, acceleration);
     411           0 :                 return false;
     412             :         }
     413             : 
     414          14 :         _accDuration = startVelocity / acceleration;
     415             : 
     416          14 :         if (!ActionInterval::init(_accDuration)) {
     417           0 :                 return false;
     418             :         }
     419             : 
     420          14 :         _acceleration = -acceleration;
     421          14 :         _startVelocity = startVelocity;
     422          14 :         _endVelocity = 0;
     423             : 
     424          14 :         _normalPoint = normal;
     425          14 :         _startPoint = startPoint;
     426             : 
     427          14 :         _endPoint = computeEndPoint();
     428             : 
     429             :         XL_ACCELERATED_LOG("%s %d Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     430             :                         __FUNCTION__, __LINE__,
     431             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     432             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     433             : 
     434          14 :         if (isnan(_endPoint.x) || isnan(_endPoint.y) || isnan(_accDuration)) {
     435             :                 XL_ACCELERATED_LOG("Failed!");
     436           0 :                 return false;
     437             :         }
     438             : 
     439          14 :         _callback = move(callback);
     440          14 :         return true;
     441             : }
     442             : 
     443           0 : bool ActionAcceleratedMove::initDecceleration(Vec2 startPoint, Vec2 endPoint, float acceleration, Function<void(Node *)> &&callback) {
     444           0 :         float distance = startPoint.distance(endPoint);
     445           0 :         acceleration = std::fabs(acceleration);
     446             : 
     447           0 :         if (std::fabs(distance) < std::numeric_limits<float>::epsilon()) {
     448           0 :                 _accDuration = 0.0f;
     449             :         } else {
     450           0 :                 _accDuration = std::sqrt((distance * 2.0f) / acceleration);
     451             :         }
     452             : 
     453           0 :         if (!ActionInterval::init(_accDuration)) {
     454           0 :                 return false;
     455             :         }
     456             : 
     457           0 :         _acceleration = -acceleration;
     458           0 :         _startVelocity = _accDuration * acceleration;
     459           0 :         _endVelocity = 0;
     460             : 
     461           0 :         _startPoint = startPoint;
     462           0 :         _endPoint = endPoint;
     463           0 :         _normalPoint = computeNormalPoint();
     464             : 
     465             :         XL_ACCELERATED_LOG("%s %d Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     466             :                         __FUNCTION__, __LINE__,
     467             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     468             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     469             : 
     470           0 :         if (isnan(_endPoint.x) || isnan(_endPoint.y) || isnan(_accDuration)) {
     471             :                 XL_ACCELERATED_LOG("Failed!");
     472           0 :                 return false;
     473             :         }
     474             : 
     475           0 :         _callback = move(callback);
     476           0 :         return true;
     477             : }
     478             : 
     479           0 : bool ActionAcceleratedMove::initAccelerationTo(Vec2 normal, Vec2 startPoint, float startVelocity, float endVelocity,
     480             :                 float acceleration, Function<void(Node *)> &&callback) {
     481             : 
     482           0 :         _accDuration = (endVelocity - startVelocity) / acceleration;
     483             : 
     484           0 :         if (_accDuration < 0) {
     485             :                 XL_ACCELERATED_LOG("AccelerationTo failed: velocity:(%f:%f) acceleration:%f", startVelocity, endVelocity, acceleration);
     486           0 :                 return false;
     487             :         }
     488             : 
     489           0 :         if (!ActionInterval::init(_accDuration)) {
     490           0 :                 return false;
     491             :         }
     492             : 
     493           0 :         _acceleration = acceleration;
     494           0 :         _startVelocity = startVelocity;
     495           0 :         _endVelocity = endVelocity;
     496             : 
     497           0 :         _normalPoint = normal;
     498           0 :         _startPoint = startPoint;
     499             : 
     500           0 :         _endPoint = computeEndPoint();
     501             : 
     502             :         XL_ACCELERATED_LOG("%s %d Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     503             :                         __FUNCTION__, __LINE__,
     504             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     505             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     506             : 
     507           0 :         if (isnan(_endPoint.x) || isnan(_endPoint.y) || isnan(_accDuration)) {
     508             :                 XL_ACCELERATED_LOG("Failed!");
     509           0 :                 return false;
     510             :         }
     511             : 
     512           0 :         _callback = move(callback);
     513           0 :         return true;
     514             : }
     515             : 
     516           0 : bool ActionAcceleratedMove::initAccelerationTo(Vec2 startPoint, Vec2 endPoint, float startVelocity,
     517             :                 float acceleration, Function<void(Node *)> &&callback) {
     518             : 
     519           0 :         float distance = - endPoint.distance(startPoint);
     520           0 :         float d = startVelocity * startVelocity - 2 * acceleration * distance;
     521             : 
     522           0 :         if (std::fabs(distance) < std::numeric_limits<float>::epsilon()) {
     523             :                 XL_ACCELERATED_LOG("zero distance");
     524             :         }
     525             : 
     526           0 :         if (d < 0) {
     527             :                 XL_ACCELERATED_LOG("AccelerationTo failed: acceleration:%f velocity:%f D:%f", acceleration, startVelocity, d);
     528           0 :                 return false;
     529             :         }
     530             : 
     531           0 :         float t1 = (-startVelocity + std::sqrt(d)) / acceleration;
     532           0 :         float t2 = (-startVelocity - std::sqrt(d)) / acceleration;
     533             : 
     534           0 :         if (distance != 0.0f) {
     535           0 :                 _accDuration = t1 < 0 ? t2 : (t2 < 0 ? t1 : std::min(t1, t2));
     536           0 :                 if (isnan(_accDuration)) {
     537           0 :                         _accDuration = 0.0f;
     538             :                 }
     539             :         } else {
     540           0 :                 _accDuration = 0.0f;
     541             :         }
     542             : 
     543           0 :         if (_accDuration < 0) {
     544           0 :                 if (d < 0) {
     545             :                         XL_ACCELERATED_LOG("AccelerationTo failed: acceleration:%f velocity:%f duration:%f", acceleration, startVelocity, _accDuration);
     546           0 :                         return false;
     547             :                 }
     548             :         }
     549             : 
     550           0 :         if (!ActionInterval::init(_accDuration)) {
     551           0 :                 return false;
     552             :         }
     553             : 
     554           0 :         _startPoint = startPoint;
     555           0 :         _endPoint = endPoint;
     556           0 :         _normalPoint = computeNormalPoint();
     557             : 
     558           0 :         _acceleration = acceleration;
     559           0 :         _startVelocity = startVelocity;
     560           0 :         _endVelocity = computeEndVelocity();
     561             : 
     562             :         XL_ACCELERATED_LOG("%s %d Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     563             :                         __FUNCTION__, __LINE__,
     564             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     565             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     566             : 
     567           0 :         if (isnan(_endPoint.x) || isnan(_endPoint.y) || isnan(_accDuration)) {
     568             :                 XL_ACCELERATED_LOG("Failed!");
     569           0 :                 return false;
     570             :         }
     571             : 
     572           0 :         _callback = move(callback);
     573           0 :         return true;
     574             : }
     575             : 
     576           0 : bool ActionAcceleratedMove::initWithDuration(float duration, Vec2 normal, Vec2 startPoint, float startVelocity,
     577             :                 float acceleration, Function<void(Node *)> &&callback) {
     578             : 
     579           0 :         _accDuration = duration;
     580             : 
     581           0 :         if (!ActionInterval::init(_accDuration)) {
     582           0 :                 return false;
     583             :         }
     584             : 
     585           0 :         _normalPoint = normal;
     586           0 :         _startPoint = startPoint;
     587             : 
     588           0 :         _acceleration = acceleration;
     589           0 :         _startVelocity = startVelocity;
     590             : 
     591           0 :         _endVelocity = computeEndVelocity();
     592           0 :         _endPoint = computeEndPoint();
     593             : 
     594             :         XL_ACCELERATED_LOG("%s %d Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     595             :                         __FUNCTION__, __LINE__,
     596             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     597             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     598             : 
     599           0 :         if (isnan(_endPoint.x) || isnan(_endPoint.y) || isnan(_accDuration)) {
     600             :                 XL_ACCELERATED_LOG("Failed!");
     601           0 :                 return false;
     602             :         }
     603             : 
     604           0 :         _callback = move(callback);
     605           0 :         return true;
     606             : }
     607             : 
     608           0 : float ActionAcceleratedMove::getDuration() const {
     609           0 :         return _accDuration;
     610             : }
     611             : 
     612         338 : Vec2 ActionAcceleratedMove::getPosition(float timePercent) const {
     613         338 :         float t = timePercent * _accDuration;
     614         338 :         return _startPoint + _normalPoint * ((_startVelocity * t) + (_acceleration * t * t * 0.5));
     615             : }
     616             : 
     617           0 : float ActionAcceleratedMove::getCurrentVelocity() const {
     618           0 :         return _startVelocity + _acceleration * _elapsed;
     619             : }
     620             : 
     621          14 : void ActionAcceleratedMove::startWithTarget(Node *target) {
     622          14 :         ActionInterval::startWithTarget(target);
     623             :         XL_ACCELERATED_LOG("Acceleration:%f velocity:%f->%f duration:%f position:(%f %f)->(%f %f)",
     624             :                         _acceleration, _startVelocity, _endVelocity, _accDuration,
     625             :                         _startPoint.x, _startPoint.y, _endPoint.x, _endPoint.y);
     626          14 : }
     627             : 
     628         338 : void ActionAcceleratedMove::update(float t) {
     629         338 :     if (_target) {
     630         338 :         Vec2 pos = getPosition(t);
     631         338 :         _target->setPosition(pos);
     632         338 :                 if (_callback) {
     633           0 :                         _callback(_target);
     634             :                 }
     635             :     }
     636         338 : }
     637             : 
     638           0 : void ActionAcceleratedMove::setCallback(Function<void(Node *)> &&callback) {
     639           0 :         _callback = move(callback);
     640           0 : }
     641             : 
     642             : }

Generated by: LCOV version 1.14