55#include < scratchcpp/sprite.h>
66#include < enginemock.h>
77#include < randomgeneratormock.h>
8+ #include < clockmock.h>
89
910#include " ../common.h"
1011#include " blocks/motionblocks.h"
1112#include " blocks/operatorblocks.h"
1213#include " engine/internal/engine.h"
1314#include " engine/internal/randomgenerator.h"
15+ #include " engine/internal/clock.h"
1416
1517using namespace libscratchcpp ;
1618
@@ -102,6 +104,7 @@ TEST_F(MotionBlocksTest, RegisterBlocks)
102104 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_pointtowards" , &MotionBlocks::compilePointTowards));
103105 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_gotoxy" , &MotionBlocks::compileGoToXY));
104106 EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_goto" , &MotionBlocks::compileGoTo));
107+ EXPECT_CALL (m_engineMock, addCompileFunction (m_section.get (), " motion_glidesecstoxy" , &MotionBlocks::compileGlideSecsToXY));
105108
106109 // Inputs
107110 EXPECT_CALL (m_engineMock, addInput (m_section.get (), " STEPS" , MotionBlocks::STEPS));
@@ -111,6 +114,7 @@ TEST_F(MotionBlocksTest, RegisterBlocks)
111114 EXPECT_CALL (m_engineMock, addInput (m_section.get (), " X" , MotionBlocks::X));
112115 EXPECT_CALL (m_engineMock, addInput (m_section.get (), " Y" , MotionBlocks::Y));
113116 EXPECT_CALL (m_engineMock, addInput (m_section.get (), " TO" , MotionBlocks::TO));
117+ EXPECT_CALL (m_engineMock, addInput (m_section.get (), " SECS" , MotionBlocks::SECS));
114118
115119 m_section->registerBlocks (&m_engineMock);
116120}
@@ -627,3 +631,88 @@ TEST_F(MotionBlocksTest, GoToImpl)
627631
628632 MotionBlocks::rng = RandomGenerator::instance ().get ();
629633}
634+
635+ TEST_F (MotionBlocksTest, GlideSecsToXY)
636+ {
637+ Compiler compiler (&m_engineMock);
638+
639+ // glide (2.5) secs to x: (95.2) y: (-175.9)
640+ auto block = std::make_shared<Block>(" a" , " motion_gotoxy" );
641+ addValueInput (block, " SECS" , MotionBlocks::SECS, 2.5 );
642+ addValueInput (block, " X" , MotionBlocks::X, 95.2 );
643+ addValueInput (block, " Y" , MotionBlocks::Y, -175.9 );
644+
645+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::startGlideSecsTo)).WillOnce (Return (0 ));
646+ EXPECT_CALL (m_engineMock, functionIndex (&MotionBlocks::glideSecsTo)).WillOnce (Return (1 ));
647+
648+ compiler.init ();
649+ compiler.setBlock (block);
650+ MotionBlocks::compileGlideSecsToXY (&compiler);
651+ compiler.end ();
652+
653+ ASSERT_EQ (compiler.bytecode (), std::vector<unsigned int >({ vm::OP_START, vm::OP_CONST, 0 , vm::OP_CONST, 1 , vm::OP_CONST, 2 , vm::OP_EXEC, 0 , vm::OP_EXEC, 1 , vm::OP_HALT }));
654+ ASSERT_EQ (compiler.constValues (), std::vector<Value>({ 2.5 , 95.2 , -175.9 }));
655+ }
656+
657+ TEST_F (MotionBlocksTest, GlideSecsToXYImpl)
658+ {
659+ static unsigned int bytecode[] = { vm::OP_START, vm::OP_CONST, 0 , vm::OP_CONST, 1 , vm::OP_CONST, 2 , vm::OP_EXEC, 0 , vm::OP_EXEC, 1 , vm::OP_HALT };
660+ static BlockFunc functions[] = { &MotionBlocks::startGlideSecsTo, &MotionBlocks::glideSecsTo };
661+ static Value constValues[] = { 2.5 , 95.2 , -175.9 };
662+
663+ double startX = 100.32 ;
664+ double startY = -50.12 ;
665+
666+ Sprite sprite;
667+ sprite.setX (startX);
668+ sprite.setY (startY);
669+
670+ VirtualMachine vm (&sprite, &m_engineMock, nullptr );
671+ vm.setBytecode (bytecode);
672+ vm.setFunctions (functions);
673+ vm.setConstValues (constValues);
674+
675+ ClockMock clock;
676+ MotionBlocks::clock = &clock;
677+
678+ std::chrono::steady_clock::time_point startTime (std::chrono::milliseconds (1000 ));
679+ EXPECT_CALL (clock, currentSteadyTime ()).Times (2 ).WillRepeatedly (Return (startTime));
680+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (1 );
681+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (1 );
682+ vm.run ();
683+
684+ ASSERT_EQ (vm.registerCount (), 0 );
685+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) != MotionBlocks::m_timeMap.cend ());
686+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) != MotionBlocks::m_glideMap.cend ());
687+ ASSERT_FALSE (vm.atEnd ());
688+ ASSERT_EQ (sprite.x (), startX);
689+ ASSERT_EQ (sprite.y (), startY);
690+
691+ std::chrono::steady_clock::time_point time1 (std::chrono::milliseconds (3456 ));
692+ EXPECT_CALL (clock, currentSteadyTime ()).WillOnce (Return (time1));
693+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (1 );
694+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (1 );
695+ vm.run ();
696+
697+ ASSERT_EQ (vm.registerCount (), 0 );
698+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) != MotionBlocks::m_timeMap.cend ());
699+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) != MotionBlocks::m_glideMap.cend ());
700+ ASSERT_FALSE (vm.atEnd ());
701+ ASSERT_EQ (std::round (sprite.x () * 100 ) / 100 , 95.29 );
702+ ASSERT_EQ (std::round (sprite.y () * 100 ) / 100 , -173.69 );
703+
704+ std::chrono::steady_clock::time_point time2 (std::chrono::milliseconds (3500 ));
705+ EXPECT_CALL (clock, currentSteadyTime ()).WillOnce (Return (time2));
706+ EXPECT_CALL (m_engineMock, lockFrame ()).Times (0 );
707+ EXPECT_CALL (m_engineMock, breakFrame ()).Times (0 );
708+ vm.run ();
709+
710+ ASSERT_EQ (vm.registerCount (), 0 );
711+ ASSERT_TRUE (MotionBlocks::m_timeMap.find (&vm) == MotionBlocks::m_timeMap.cend ());
712+ ASSERT_TRUE (MotionBlocks::m_glideMap.find (&vm) == MotionBlocks::m_glideMap.cend ());
713+ ASSERT_TRUE (vm.atEnd ());
714+ ASSERT_EQ (std::round (sprite.x () * 100 ) / 100 , 95.2 );
715+ ASSERT_EQ (std::round (sprite.y () * 100 ) / 100 , -175.9 );
716+
717+ MotionBlocks::clock = Clock::instance ().get ();
718+ }
0 commit comments