Skip to content

Commit f0fa83f

Browse files
committed
Implement motion_glideto block
1 parent 3fe0fe6 commit f0fa83f

File tree

3 files changed

+825
-0
lines changed

3 files changed

+825
-0
lines changed

src/blocks/motionblocks.cpp

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

5152
CompilerValue *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+
181249
extern "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+
347513
extern "C" double motion_xposition(Sprite *sprite)
348514
{
349515
return sprite->x();

src/blocks/motionblocks.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class MotionBlocks : public IExtension
2525
static CompilerValue *compileGoToXY(Compiler *compiler);
2626
static CompilerValue *compileGoTo(Compiler *compiler);
2727
static CompilerValue *compileGlideSecsToXY(Compiler *compiler);
28+
static CompilerValue *compileGlideTo(Compiler *compiler);
2829
};
2930

3031
} // namespace libscratchcpp

0 commit comments

Comments
 (0)