@@ -46,6 +46,7 @@ void MotionBlocks::registerBlocks(IEngine *engine)
4646 engine->addCompileFunction (this , " motion_gotoxy" , &compileGoToXY);
4747 engine->addCompileFunction (this , " motion_goto" , &compileGoTo);
4848 engine->addCompileFunction (this , " motion_glidesecstoxy" , &compileGlideSecsToXY);
49+ engine->addCompileFunction (this , " motion_glideto" , &compileGlideTo);
4950}
5051
5152CompilerValue *MotionBlocks::compileMoveSteps (Compiler *compiler)
@@ -178,6 +179,73 @@ CompilerValue *MotionBlocks::compileGlideSecsToXY(Compiler *compiler)
178179 return nullptr ;
179180}
180181
182+ CompilerValue *MotionBlocks::compileGlideTo (Compiler *compiler)
183+ {
184+ Target *target = compiler->target ();
185+ CompilerValue *duration = compiler->addInput (" SECS" );
186+ CompilerValue *startX = target->isStage () ? compiler->addConstValue (0 ) : compiler->addTargetFunctionCall (" motion_xposition" , Compiler::StaticType::Number);
187+ CompilerValue *startY = target->isStage () ? compiler->addConstValue (0 ) : compiler->addTargetFunctionCall (" motion_yposition" , Compiler::StaticType::Number);
188+ CompilerValue *endX = target->isStage () ? compiler->addConstValue (0 ) : nullptr ;
189+ CompilerValue *endY = target->isStage () ? compiler->addConstValue (0 ) : nullptr ;
190+
191+ Input *input = compiler->input (" TO" );
192+ bool ifStatement = false ;
193+
194+ if (input->pointsToDropdownMenu ()) {
195+ std::string value = input->selectedMenuItem ();
196+
197+ if (value == " _mouse_" ) {
198+ if (!target->isStage ()) {
199+ endX = compiler->addFunctionCallWithCtx (" motion_get_mouse_x" , Compiler::StaticType::Number);
200+ endY = compiler->addFunctionCallWithCtx (" motion_get_mouse_y" , Compiler::StaticType::Number);
201+ }
202+ } else if (value == " _random_" ) {
203+ if (!target->isStage ()) {
204+ endX = compiler->addFunctionCallWithCtx (" motion_get_random_x" , Compiler::StaticType::Number);
205+ endY = compiler->addFunctionCallWithCtx (" motion_get_random_y" , Compiler::StaticType::Number);
206+ }
207+ } else {
208+ int index = compiler->engine ()->findTarget (value);
209+ Target *anotherTarget = compiler->engine ()->targetAt (index);
210+
211+ if (anotherTarget && !anotherTarget->isStage ()) {
212+ if (!target->isStage ()) {
213+ endX = compiler->addFunctionCallWithCtx (" motion_get_sprite_x_by_index" , Compiler::StaticType::Number, { Compiler::StaticType::Number }, { compiler->addConstValue (index) });
214+ endY = compiler->addFunctionCallWithCtx (" motion_get_sprite_y_by_index" , Compiler::StaticType::Number, { Compiler::StaticType::Number }, { compiler->addConstValue (index) });
215+ }
216+ } else
217+ return nullptr ;
218+ }
219+ } else {
220+ CompilerValue *to = compiler->addInput (input);
221+ CompilerValue *valid = compiler->addFunctionCallWithCtx (" motion_is_target_valid" , Compiler::StaticType::Bool, { Compiler::StaticType::String }, { to });
222+ ifStatement = true ;
223+ compiler->beginIfStatement (valid);
224+
225+ if (!target->isStage ()) {
226+ endX = compiler->addFunctionCallWithCtx (" motion_get_target_x" , Compiler::StaticType::Number, { Compiler::StaticType::String }, { to });
227+ endY = compiler->addFunctionCallWithCtx (" motion_get_target_y" , Compiler::StaticType::Number, { Compiler::StaticType::String }, { to });
228+ }
229+ }
230+
231+ assert (endX && endY);
232+ assert (!target->isStage () || (target->isStage () && endX->isConst () && endY->isConst ()));
233+
234+ compiler->addFunctionCallWithCtx (" motion_start_glide" , Compiler::StaticType::Void, { Compiler::StaticType::Number }, { duration });
235+ compiler->createYield ();
236+
237+ compiler->beginLoopCondition ();
238+ auto numType = Compiler::StaticType::Number;
239+ CompilerValue *elapsed = compiler->addFunctionCallWithCtx (" motion_glide" , Compiler::StaticType::Bool, { numType, numType, numType, numType, numType }, { duration, startX, startY, endX, endY });
240+ compiler->beginRepeatUntilLoop (elapsed);
241+ compiler->endLoop ();
242+
243+ if (ifStatement)
244+ compiler->endIf ();
245+
246+ return nullptr ;
247+ }
248+
181249extern " C" void motion_movesteps (Sprite *sprite, double steps)
182250{
183251 double dir = sprite->direction ();
@@ -344,6 +412,104 @@ extern "C" bool motion_glide(ExecutionContext *ctx, double duration, double star
344412 }
345413}
346414
415+ extern " C" double motion_get_mouse_x (ExecutionContext *ctx)
416+ {
417+ return ctx->engine ()->mouseX ();
418+ }
419+
420+ extern " C" double motion_get_mouse_y (ExecutionContext *ctx)
421+ {
422+ return ctx->engine ()->mouseY ();
423+ }
424+
425+ extern " C" double motion_get_random_x (ExecutionContext *ctx)
426+ {
427+ const int stageWidth = ctx->engine ()->stageWidth ();
428+ return ctx->rng ()->randintDouble (-stageWidth / 2.0 , stageWidth / 2.0 );
429+ }
430+
431+ extern " C" double motion_get_random_y (ExecutionContext *ctx)
432+ {
433+ const int stageHeight = ctx->engine ()->stageHeight ();
434+ return ctx->rng ()->randintDouble (-stageHeight / 2.0 , stageHeight / 2.0 );
435+ }
436+
437+ extern " C" double motion_get_sprite_x_by_index (ExecutionContext *ctx, double index)
438+ {
439+ assert (!ctx->engine ()->targetAt (index)->isStage ());
440+ Sprite *sprite = static_cast <Sprite *>(ctx->engine ()->targetAt (index));
441+ return sprite->x ();
442+ }
443+
444+ extern " C" double motion_get_sprite_y_by_index (ExecutionContext *ctx, double index)
445+ {
446+ assert (!ctx->engine ()->targetAt (index)->isStage ());
447+ Sprite *sprite = static_cast <Sprite *>(ctx->engine ()->targetAt (index));
448+ return sprite->y ();
449+ }
450+
451+ extern " C" double motion_get_target_x (ExecutionContext *ctx, const StringPtr *name)
452+ {
453+ static const StringPtr MOUSE_STR (" _mouse_" );
454+ static const StringPtr RANDOM_STR (" _random_" );
455+
456+ if (string_compare_case_sensitive (name, &MOUSE_STR) == 0 )
457+ return ctx->engine ()->mouseX ();
458+ else if (string_compare_case_sensitive (name, &RANDOM_STR) == 0 )
459+ return motion_get_random_x (ctx);
460+ else {
461+ // TODO: Use UTF-16 in engine
462+ std::string u8name = utf8::utf16to8 (std::u16string (name->data ));
463+ IEngine *engine = ctx->engine ();
464+ Target *target = engine->targetAt (engine->findTarget (u8name));
465+
466+ if (target && !target->isStage ()) {
467+ Sprite *sprite = static_cast <Sprite *>(target);
468+ return sprite->x ();
469+ } else
470+ return 0 ;
471+ }
472+ }
473+
474+ extern " C" double motion_get_target_y (ExecutionContext *ctx, const StringPtr *name)
475+ {
476+ static const StringPtr MOUSE_STR (" _mouse_" );
477+ static const StringPtr RANDOM_STR (" _random_" );
478+
479+ if (string_compare_case_sensitive (name, &MOUSE_STR) == 0 )
480+ return ctx->engine ()->mouseY ();
481+ else if (string_compare_case_sensitive (name, &RANDOM_STR) == 0 )
482+ return motion_get_random_y (ctx);
483+ else {
484+ // TODO: Use UTF-16 in engine
485+ std::string u8name = utf8::utf16to8 (std::u16string (name->data ));
486+ IEngine *engine = ctx->engine ();
487+ Target *target = engine->targetAt (engine->findTarget (u8name));
488+
489+ if (target && !target->isStage ()) {
490+ Sprite *sprite = static_cast <Sprite *>(target);
491+ return sprite->y ();
492+ } else
493+ return 0 ;
494+ }
495+ }
496+
497+ extern " C" bool motion_is_target_valid (ExecutionContext *ctx, const StringPtr *name)
498+ {
499+ static const StringPtr MOUSE_STR (" _mouse_" );
500+ static const StringPtr RANDOM_STR (" _random_" );
501+
502+ if (string_compare_case_sensitive (name, &MOUSE_STR) == 0 || string_compare_case_sensitive (name, &RANDOM_STR) == 0 )
503+ return true ;
504+ else {
505+ // TODO: Use UTF-16 in engine
506+ std::string u8name = utf8::utf16to8 (std::u16string (name->data ));
507+ IEngine *engine = ctx->engine ();
508+ Target *target = engine->targetAt (engine->findTarget (u8name));
509+ return (target && !target->isStage ());
510+ }
511+ }
512+
347513extern " C" double motion_xposition (Sprite *sprite)
348514{
349515 return sprite->x ();
0 commit comments