@@ -105,6 +105,7 @@ TEST_F(MotionBlocksTest, RegisterBlocks)
105105 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_gotoxy" , &MotionBlocks::compileGoToXY));
106106 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_goto" , &MotionBlocks::compileGoTo));
107107 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_glidesecstoxy" , &MotionBlocks::compileGlideSecsToXY));
108+ EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_glideto" , &MotionBlocks::compileGlideTo));
108109
109110 // Inputs
110111 EXPECT_CALL (m_engineMock, addInput (m_section.get (), " STEPS" , MotionBlocks::STEPS));
@@ -660,8 +661,8 @@ TEST_F(MotionBlocksTest, GlideSecsToXYImpl)
660661 static BlockFunc functions[] = { &MotionBlocks::startGlideSecsTo, &MotionBlocks::glideSecsTo };
661662 static Value constValues[] = { 2.5 , 95.2 , -175.9 };
662663
663- double startX = 100.32 ;
664- double startY = -50.12 ;
664+ static const double startX = 100.32 ;
665+ static const double startY = -50.12 ;
665666
666667 Sprite sprite;
667668 sprite.setX (startX);
@@ -716,3 +717,206 @@ TEST_F(MotionBlocksTest, GlideSecsToXYImpl)
716717
717718 MotionBlocks::clock = Clock::instance ().get ();
718719}
720+
721+ TEST_F (MotionBlocksTest, GlideTo)
722+ {
723+ Compiler compiler (&m_engineMock);
724+
725+ // glide (3.25) secs to (mouse-pointer)
726+ auto block1 = std::make_shared<Block>(" a" , " motion_glideto" );
727+ addValueInput (block1, " SECS" , MotionBlocks::SECS, 3.25 );
728+ addDropdownInput (block1, " TO" , MotionBlocks::TO, " _mouse_" );
729+
730+ // glide (2.5) secs to (random position)
731+ auto block2 = std::make_shared<Block>(" b" , " motion_glideto" );
732+ addValueInput (block2, " SECS" , MotionBlocks::SECS, 2.5 );
733+ addDropdownInput (block2, " TO" , MotionBlocks::TO, " _random_" );
734+
735+ // glide (5.01) secs to (Sprite2)
736+ auto block3 = std::make_shared<Block>(" c" , " motion_glideto" );
737+ addValueInput (block3, " SECS" , MotionBlocks::SECS, 3.25 );
738+ addDropdownInput (block3, " TO" , MotionBlocks::TO, " Sprite2" );
739+
740+ // glide (6.5) secs to (join "" "")
741+ auto joinBlock = std::make_shared<Block>(" e" , " operator_join" );
742+ joinBlock->setCompileFunction (&OperatorBlocks::compileJoin);
743+ auto block4 = std::make_shared<Block>(" d" , " motion_glideto" );
744+ addValueInput (block4, " SECS" , MotionBlocks::SECS, 6.5 );
745+ addDropdownInput (block4, " TO" , MotionBlocks::TO, " " , joinBlock);
746+
747+ compiler.init ();
748+
749+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::startGlideToMousePointer)).WillOnce (Return (0 ));
750+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::glideSecsTo)).WillOnce (Return (4 ));
751+ compiler.setBlock (block1);
752+ MotionBlocks::compileGlideTo (&compiler);
753+
754+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::startGlideToRandomPosition)).WillOnce (Return (1 ));
755+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::glideSecsTo)).WillOnce (Return (4 ));
756+ compiler.setBlock (block2);
757+ MotionBlocks::compileGlideTo (&compiler);
758+
759+ EXPECT_CALL (m_engineMock, findTarget (" Sprite2" )).WillOnce (Return (5 ));
760+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::startGlideToByIndex)).WillOnce (Return (2 ));
761+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::glideSecsTo)).WillOnce (Return (4 ));
762+ compiler.setBlock (block3);
763+ MotionBlocks::compileGlideTo (&compiler);
764+
765+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::startGlideTo)).WillOnce (Return (3 ));
766+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::glideSecsTo)).WillOnce (Return (4 ));
767+ compiler.setBlock (block4);
768+ MotionBlocks::compileGlideTo (&compiler);
769+
770+ compiler.end ();
771+
772+ ASSERT_EQ (
773+ compiler.bytecode (),
774+ std::vector<unsigned int >(
775+ { vm::OP_START,
776+ vm::OP_CONST,
777+ 0 ,
778+ vm::OP_EXEC,
779+ 0 ,
780+ vm::OP_EXEC,
781+ 4 ,
782+ vm::OP_CONST,
783+ 1 ,
784+ vm::OP_EXEC,
785+ 1 ,
786+ vm::OP_EXEC,
787+ 4 ,
788+ vm::OP_CONST,
789+ 2 ,
790+ vm::OP_CONST,
791+ 3 ,
792+ vm::OP_EXEC,
793+ 2 ,
794+ vm::OP_EXEC,
795+ 4 ,
796+ vm::OP_CONST,
797+ 4 ,
798+ vm::OP_NULL,
799+ vm::OP_NULL,
800+ vm::OP_STR_CONCAT,
801+ vm::OP_EXEC,
802+ 3 ,
803+ vm::OP_EXEC,
804+ 4 ,
805+ vm::OP_HALT }));
806+ ASSERT_EQ (compiler.constValues (), std::vector<Value>({ 3.25 , 2.5 , 3.25 , 5 , 6.5 }));
807+ }
808+
809+ TEST_F (MotionBlocksTest, GlideToImpl)
810+ {
811+ static unsigned int bytecode1[] = { vm::OP_START, vm::OP_CONST, 0 , vm::OP_CONST, 1 , vm::OP_EXEC, 0 , vm::OP_EXEC, 4 , vm::OP_HALT };
812+ static unsigned int bytecode2[] = { vm::OP_START, vm::OP_CONST, 0 , vm::OP_CONST, 2 , vm::OP_EXEC, 1 , vm::OP_EXEC, 4 , vm::OP_HALT };
813+ static unsigned int bytecode3[] = { vm::OP_START, vm::OP_CONST, 0 , vm::OP_EXEC, 2 , vm::OP_EXEC, 4 , vm::OP_HALT };
814+ static unsigned int bytecode4[] = { vm::OP_START, vm::OP_CONST, 0 , vm::OP_EXEC, 3 , vm::OP_EXEC, 4 , vm::OP_HALT };
815+ static unsigned int *scripts[] = { bytecode1, bytecode2, bytecode3, bytecode4 };
816+ static BlockFunc functions
817+ [] = { &MotionBlocks::startGlideTo, &MotionBlocks::startGlideToByIndex, &MotionBlocks::startGlideToMousePointer, &MotionBlocks::startGlideToRandomPosition, &MotionBlocks::glideSecsTo };
818+ static Value constValues[] = { 2.5 , " Sprite2" , 3 };
819+
820+ static const double startX = 100.32 ;
821+ static const double startY = -50.12 ;
822+ static const double endX = 95.2 ;
823+ static const double endY = -175.9 ;
824+
825+ Sprite sprite;
826+ Sprite anotherSprite;
827+ anotherSprite.setX (endX);
828+ anotherSprite.setY (endY);
829+
830+ VirtualMachine vm (&sprite, &m_engineMock, nullptr );
831+ vm.setFunctions (functions);
832+ vm.setConstValues (constValues);
833+
834+ ClockMock clock;
835+ RandomGeneratorMock rng;
836+ MotionBlocks::clock = &clock;
837+ MotionBlocks::rng = &rng;
838+ int i = 0 ;
839+
840+ for (auto script : scripts) {
841+ sprite.setX (startX);
842+ sprite.setY (startY);
843+
844+ switch (i) {
845+ case 0 :
846+ EXPECT_CALL (m_engineMock, findTarget (" Sprite2" )).WillOnce (Return (3 ));
847+ EXPECT_CALL (m_engineMock, targetAt (3 )).WillOnce (Return (&anotherSprite));
848+ break ;
849+
850+ case 1 :
851+ EXPECT_CALL (m_engineMock, targetAt (3 )).WillOnce (Return (&anotherSprite));
852+ break ;
853+
854+ case 2 :
855+ EXPECT_CALL (m_engineMock, mouseX ()).WillOnce (Return (endX));
856+ EXPECT_CALL (m_engineMock, mouseY ()).WillOnce (Return (endY));
857+ break ;
858+ case 3 :
859+ EXPECT_CALL (rng, randint (-240 , 240 )).WillOnce (Return (std::round (endX)));
860+ EXPECT_CALL (rng, randint (-180 , 180 )).WillOnce (Return (std::round (endY)));
861+ default :
862+ break ;
863+ }
864+
865+ vm.setBytecode (script);
866+ std::chrono::steady_clock::time_point startTime (std::chrono::milliseconds (1000 ));
867+ EXPECT_CALL (clock, currentSteadyTime ()).Times (2 ).WillRepeatedly (Return (startTime));
868+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (1 );
869+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (1 );
870+ vm.run ();
871+
872+ ASSERT_EQ (vm.registerCount (), 0 );
873+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) != MotionBlocks::m_timeMap.cend ());
874+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) != MotionBlocks::m_glideMap.cend ());
875+ ASSERT_FALSE (vm.atEnd ());
876+ ASSERT_EQ (sprite.x (), startX);
877+ ASSERT_EQ (sprite.y (), startY);
878+
879+ std::chrono::steady_clock::time_point time1 (std::chrono::milliseconds (3456 ));
880+ EXPECT_CALL (clock, currentSteadyTime ()).WillOnce (Return (time1));
881+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (1 );
882+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (1 );
883+ vm.run ();
884+
885+ ASSERT_EQ (vm.registerCount (), 0 );
886+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) != MotionBlocks::m_timeMap.cend ());
887+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) != MotionBlocks::m_glideMap.cend ());
888+ ASSERT_FALSE (vm.atEnd ());
889+
890+ if (i == 3 ) {
891+ ASSERT_EQ (std::round (sprite.x () * 100 ) / 100 , 95.09 );
892+ ASSERT_EQ (std::round (sprite.y () * 100 ) / 100 , -173.78 );
893+ } else {
894+ ASSERT_EQ (std::round (sprite.x () * 100 ) / 100 , 95.29 );
895+ ASSERT_EQ (std::round (sprite.y () * 100 ) / 100 , -173.69 );
896+ }
897+
898+ std::chrono::steady_clock::time_point time2 (std::chrono::milliseconds (3500 ));
899+ EXPECT_CALL (clock, currentSteadyTime ()).WillOnce (Return (time2));
900+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (0 );
901+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (0 );
902+ vm.run ();
903+
904+ ASSERT_EQ (vm.registerCount (), 0 );
905+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) == MotionBlocks::m_timeMap.cend ());
906+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) == MotionBlocks::m_glideMap.cend ());
907+ ASSERT_TRUE (vm.atEnd ());
908+
909+ if (i == 3 ) {
910+ ASSERT_EQ (sprite.x (), std::round (endX));
911+ ASSERT_EQ (sprite.y (), std::round (endY));
912+ } else {
913+ ASSERT_EQ (std::round (sprite.x () * 100 ) / 100 , endX);
914+ ASSERT_EQ (std::round (sprite.y () * 100 ) / 100 , endY);
915+ }
916+
917+ i++;
918+ }
919+
920+ MotionBlocks::clock = Clock::instance ().get ();
921+ MotionBlocks::rng = RandomGenerator::instance ().get ();
922+ }
0 commit comments