@@ -43,6 +43,7 @@ void MotionBlocks::registerBlocks(IEngine *engine)
4343 engine->addCompileFunction (this , " motion_pointindirection" , &compilePointInDirection);
4444 engine->addCompileFunction (this , " motion_pointtowards" , &compilePointTowards);
4545 engine->addCompileFunction (this , " motion_gotoxy" , &compileGoToXY);
46+ engine->addCompileFunction (this , " motion_goto" , &compileGoTo);
4647}
4748
4849CompilerValue *MotionBlocks::compileMoveSteps (Compiler *compiler)
@@ -125,6 +126,35 @@ CompilerValue *MotionBlocks::compileGoToXY(Compiler *compiler)
125126 return nullptr ;
126127}
127128
129+ CompilerValue *MotionBlocks::compileGoTo (Compiler *compiler)
130+ {
131+ if (compiler->target ()->isStage ())
132+ return nullptr ;
133+
134+ Input *input = compiler->input (" TO" );
135+
136+ if (input->pointsToDropdownMenu ()) {
137+ std::string value = input->selectedMenuItem ();
138+
139+ if (value == " _mouse_" )
140+ compiler->addTargetFunctionCall (" motion_go_to_mouse" );
141+ else if (value == " _random_" )
142+ compiler->addFunctionCallWithCtx (" motion_go_to_random_pos" );
143+ else {
144+ int index = compiler->engine ()->findTarget (value);
145+ Target *anotherTarget = compiler->engine ()->targetAt (index);
146+
147+ if (anotherTarget && !anotherTarget->isStage ())
148+ compiler->addTargetFunctionCall (" motion_go_to_target_by_index" , Compiler::StaticType::Void, { Compiler::StaticType::Number }, { compiler->addConstValue (index) });
149+ }
150+ } else {
151+ CompilerValue *to = compiler->addInput (input);
152+ compiler->addFunctionCallWithCtx (" motion_goto" , Compiler::StaticType::Void, { Compiler::StaticType::String }, { to });
153+ }
154+
155+ return nullptr ;
156+ }
157+
128158extern " C" void motion_movesteps (Sprite *sprite, double steps)
129159{
130160 double dir = sprite->direction ();
@@ -213,3 +243,49 @@ extern "C" void motion_gotoxy(Sprite *sprite, double x, double y)
213243{
214244 sprite->setPosition (x, y);
215245}
246+
247+ extern " C" void motion_go_to_mouse (Sprite *sprite)
248+ {
249+ IEngine *engine = sprite->engine ();
250+ sprite->setPosition (engine->mouseX (), engine->mouseY ());
251+ }
252+
253+ extern " C" void motion_go_to_random_pos (ExecutionContext *ctx)
254+ {
255+ Sprite *sprite = static_cast <Sprite *>(ctx->thread ()->target ());
256+ IEngine *engine = ctx->engine ();
257+ const int stageWidth = engine->stageWidth ();
258+ const int stageHeight = engine->stageHeight ();
259+ IRandomGenerator *rng = ctx->rng ();
260+ sprite->setPosition (rng->randintDouble (-stageWidth / 2.0 , stageWidth / 2.0 ), rng->randintDouble (-stageHeight / 2.0 , stageHeight / 2.0 ));
261+ }
262+
263+ extern " C" void motion_go_to_target_by_index (Sprite *sprite, double index)
264+ {
265+ Sprite *anotherSprite = static_cast <Sprite *>(sprite->engine ()->targetAt (index));
266+ sprite->setPosition (anotherSprite->x (), anotherSprite->y ());
267+ }
268+
269+ extern " C" void motion_goto (ExecutionContext *ctx, const StringPtr *towards)
270+ {
271+ static const StringPtr MOUSE_STR (" _mouse_" );
272+ static const StringPtr RANDOM_STR (" _random_" );
273+
274+ Sprite *sprite = static_cast <Sprite *>(ctx->thread ()->target ());
275+
276+ if (string_compare_case_sensitive (towards, &MOUSE_STR) == 0 )
277+ motion_go_to_mouse (sprite);
278+ else if (string_compare_case_sensitive (towards, &RANDOM_STR) == 0 )
279+ motion_go_to_random_pos (ctx);
280+ else {
281+ // TODO: Use UTF-16 in engine
282+ std::string u8name = utf8::utf16to8 (std::u16string (towards->data ));
283+ IEngine *engine = ctx->engine ();
284+ Target *anotherTarget = engine->targetAt (engine->findTarget (u8name));
285+
286+ if (anotherTarget && !anotherTarget->isStage ()) {
287+ Sprite *anotherSprite = static_cast <Sprite *>(anotherTarget);
288+ sprite->setPosition (anotherSprite->x (), anotherSprite->y ());
289+ }
290+ }
291+ }
0 commit comments