diff --git a/src/compiler/astgen.js b/src/compiler/astgen.js index d92e1569..71116981 100644 --- a/src/compiler/astgen.js +++ b/src/compiler/astgen.js @@ -578,6 +578,11 @@ class ScriptTreeGenerator { kind: 'constant', value: block.fields.DISTANCETOMENU.value }; + case 'sensing_distanceto': + return { + kind: 'sensing.distance', + target: this.descendInput(block, 'DISTANCETOMENU') + }; case 'sensing_keyoptions': return { kind: 'constant', diff --git a/src/compiler/compat-blocks.js b/src/compiler/compat-blocks.js index 313f703a..e553719b 100644 --- a/src/compiler/compat-blocks.js +++ b/src/compiler/compat-blocks.js @@ -49,7 +49,6 @@ const inputs = [ 'music_getTempo', 'sensing_answer', 'sensing_current', - 'sensing_distanceto', 'sensing_loud', 'sensing_loudness', 'sensing_of', diff --git a/src/compiler/execute.js b/src/compiler/execute.js index 39192319..49161ad6 100644 --- a/src/compiler/execute.js +++ b/src/compiler/execute.js @@ -289,7 +289,7 @@ const randomFloat = (low, high) => { * Perform an IO query * @param {string} device The name of the device to query * @param {string} func The function of the device to query - * @param {*} args The arguments to pass to the device + * @param {*} [args] The arguments to pass to the device * @returns {*} The value returned by the IO device */ const ioQuery = (device, func, args) => { @@ -329,6 +329,31 @@ const daysSince2000 = () => { return mSecsSinceStart / (24 * 60 * 60 * 1000); }; +/** + * Determine distance to a sprite or point. + * @param {string} menu The name of the sprite or location to find. + * @returns {number} Distance to the point, or 10000 if it cannot be calculated. + */ +const distance = menu => { + if (thread.target.isStage) return 10000; + + let targetX = 0; + let targetY = 0; + if (menu === '_mouse_') { + targetX = ioQuery('mouse', 'getScratchX'); + targetY = ioQuery('mouse', 'getScratchY'); + } else { + const distTarget = thread.target.runtime.getSpriteTargetByName(menu); + if (!distTarget) return 10000; + targetX = distTarget.x; + targetY = distTarget.y; + } + + const dx = thread.target.x - targetX; + const dy = thread.target.y - targetY; + return Math.sqrt((dx * dx) + (dy * dy)); +}; + /** * Convert a Scratch list index to a JavaScript list index. * "all" is not considered as a list index. diff --git a/src/compiler/jsgen.js b/src/compiler/jsgen.js index 90dbde93..a43248fc 100644 --- a/src/compiler/jsgen.js +++ b/src/compiler/jsgen.js @@ -466,6 +466,9 @@ class JSGenerator { return new TypedInput(`target.colorIsTouchingColor(colorToList(${this.descendInput(node.target).asUnknown()}), colorToList(${this.descendInput(node.mask).asUnknown()}))`, TYPE_BOOLEAN); case 'sensing.daysSince2000': return new TypedInput('daysSince2000()', TYPE_NUMBER); + case 'sensing.distance': + // TODO: on stages, this can be computed at compile time + return new TypedInput(`distance(${this.descendInput(node.target).asString()})`, TYPE_NUMBER); case 'sensing.touching': return new TypedInput(`target.isTouchingObject(${this.descendInput(node.object).asUnknown()})`, TYPE_BOOLEAN); case 'sensing.touchingColor':