From 005a022c74b9bb5f39a7549ee65cb62b6a62c370 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 17:51:00 +0900 Subject: [PATCH 01/12] feat: add "tilted any direction" event block for MicroBit More MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new gesture option "TILTED" that triggers when any of the tilt events (TILT_UP, TILT_DOWN, TILT_LEFT, TILT_RIGHT) occur. This matches the microbit extension's "(どれかの向き▼)に傾いたとき" behavior. Implementation details: - Add TILTED menu item to GESTURES_MENU - Add state tracking variables for tilt events - Add TILTED handling in whenGesture method with gap detection logic - Add Japanese translations for the new menu item Refs smalruby/smalruby3-develop#20 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/extensions/microbitMore/index.js | 88 +++++++++++++++++++ src/extensions/microbitMore/translations.json | 2 + 2 files changed, 90 insertions(+) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index cfca31a3ed..080777d6b6 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -1614,6 +1614,14 @@ class MbitMoreBlocks { }), value: 'MOVED' }, + { + text: formatMessage({ + id: 'mbitMore.gesturesMenu.tilted', + default: 'tilted any', + description: 'label for tilted any direction gesture in gesture picker for microbit more extension' + }), + value: 'TILTED' + }, { text: formatMessage({ id: 'mbitMore.gesturesMenu.tiltUp', @@ -2167,6 +2175,24 @@ class MbitMoreBlocks { */ this.isWaitingForGap = false; + /** + * The last time the "tilted" event was fired. + * @type {number} + */ + this.lastTiltedEventTime = null; + + /** + * The last time any tilt event was detected. + * @type {number} + */ + this.lastTiltOccurredTime = null; + + /** + * Whether the extension is waiting for a gap in tilting before firing again. + * @type {boolean} + */ + this.isWaitingForTiltGap = false; + /** * The timer of updateLastGestureEvent. * @type {number} @@ -2947,6 +2973,68 @@ class MbitMoreBlocks { return shouldFire; } + if (gestureName === 'TILTED') { + const now = Date.now(); + const stepTime = this.runtime.currentStepTime; + const gapThreshold = stepTime * 5; // 5フレームの空白 + const timeoutThreshold = stepTime * 30; // 30フレームで強制発火 + + // Only check tilt-related gestures + const tiltGestures = [ + MbitMoreGestureName.TILT_UP, + MbitMoreGestureName.TILT_DOWN, + MbitMoreGestureName.TILT_LEFT, + MbitMoreGestureName.TILT_RIGHT + ]; + + const changedTiltGestures = []; + tiltGestures.forEach(name => { + const timestamp = this._peripheral.gestureEvents[name]; + if (typeof timestamp !== 'undefined') { + if (this.prevGestureEvents[name]) { + if (timestamp !== this.prevGestureEvents[name]) { + changedTiltGestures.push(name); + } + } else { + changedTiltGestures.push(name); + } + } + }); + + const eventDetected = changedTiltGestures.length > 0; + if (eventDetected) { + this.lastTiltOccurredTime = now; + } + + // 静止判定(隙間ができたか) + const timeSinceLastOccurred = this.lastTiltOccurredTime === null ? + Infinity : (now - this.lastTiltOccurredTime); + if (timeSinceLastOccurred >= gapThreshold) { + this.isWaitingForTiltGap = false; + } + + let shouldFire = false; + + if (eventDetected) { + if (this.isWaitingForTiltGap) { + // 傾き続けている場合の強制発火判定 + const timeSinceLastFired = this.lastTiltedEventTime === null ? + Infinity : (now - this.lastTiltedEventTime); + if (timeSinceLastFired >= timeoutThreshold) { + shouldFire = true; + } + } else { + shouldFire = true; + } + } + + if (shouldFire) { + this.lastTiltedEventTime = now; + this.isWaitingForTiltGap = true; + } + + return shouldFire; + } const lastTimestamp = this._peripheral.getGestureEventTimestamp(gestureName); if (lastTimestamp === null) return false; diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index c8cf67e1b3..90626ddad9 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -121,6 +121,7 @@ "mbitMore.gesturesMenu.g8": "8Gかかった", "mbitMore.gesturesMenu.shake": "ゆさぶられた", "mbitMore.gesturesMenu.moved": "動いた", + "mbitMore.gesturesMenu.tilted": "どれかの向きに傾いた", "mbitMore.displayMatrix": "[MATRIX] を表示する", "mbitMore.display": "[TEXT] を表示する", "mbitMore.displayText": "文字 [TEXT] を [DELAY] ミリ秒間隔で流す", @@ -211,6 +212,7 @@ "mbitMore.gesturesMenu.g8": "8Gかかった", "mbitMore.gesturesMenu.shake": "ゆさぶられた", "mbitMore.gesturesMenu.moved": "うごいた", + "mbitMore.gesturesMenu.tilted": "どれかのむきにかたむいた", "mbitMore.displayMatrix": "[MATRIX] をひょうじする", "mbitMore.display": "[TEXT] をひょうじする", "mbitMore.displayText": "もじ [TEXT] を [DELAY] ミリびょうかんかくでながす", From 8a7e785a780c3490a3eebea965b7458052d69f99 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 17:58:17 +0900 Subject: [PATCH 02/12] feat: add isTilted boolean block for MicroBit More MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a new boolean block "[DIRECTION] に傾いた" that detects tilt state: Implementation: - Added TILT_DIRECTION_MENU with options: ANY, UP, DOWN, LEFT, RIGHT - Added isTilted method that returns true if tilted within 5 frames - Uses gesture event timestamps for tilt detection - Matches microbit extension pattern for user migration Japanese translations: - Block: "[DIRECTION] に傾いた" / "[DIRECTION] にかたむいた" - Menu items: どれかの向き, 上, 下, 左, 右 Related to: smalruby/smalruby3-develop#20 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/extensions/microbitMore/index.js | 101 ++++++++++++++++++ src/extensions/microbitMore/translations.json | 12 +++ 2 files changed, 113 insertions(+) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 080777d6b6..043e5e3346 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -1713,6 +1713,53 @@ class MbitMoreBlocks { ]; } + /** + * @return {array} - text and values for each tilt direction menu element + */ + get TILT_DIRECTION_MENU () { + return [ + { + text: formatMessage({ + id: 'mbitMore.tiltDirectionMenu.any', + default: 'any', + description: 'label for any direction element in tilt direction picker for Microbit More extension' + }), + value: 'ANY' + }, + { + text: formatMessage({ + id: 'mbitMore.tiltDirectionMenu.up', + default: 'up', + description: 'label for up element in tilt direction picker for Microbit More extension' + }), + value: MbitMoreGestureName.TILT_UP + }, + { + text: formatMessage({ + id: 'mbitMore.tiltDirectionMenu.down', + default: 'down', + description: 'label for down element in tilt direction picker for Microbit More extension' + }), + value: MbitMoreGestureName.TILT_DOWN + }, + { + text: formatMessage({ + id: 'mbitMore.tiltDirectionMenu.left', + default: 'left', + description: 'label for left element in tilt direction picker for Microbit More extension' + }), + value: MbitMoreGestureName.TILT_LEFT + }, + { + text: formatMessage({ + id: 'mbitMore.tiltDirectionMenu.right', + default: 'right', + description: 'label for right element in tilt direction picker for Microbit More extension' + }), + value: MbitMoreGestureName.TILT_RIGHT + } + ]; + } /** * @return {array} - text and values for each buttons menu element @@ -2332,6 +2379,22 @@ class MbitMoreBlocks { } } }, + { + opcode: 'isTilted', + text: formatMessage({ + id: 'mbitMore.isTilted', + default: 'tilted [DIRECTION] ?', + description: 'whether the micro:bit is tilted in a direction' + }), + blockType: BlockType.BOOLEAN, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + menu: 'tiltDirectionMenu', + defaultValue: 'ANY' + } + } + }, '---', { opcode: 'displayMatrix', @@ -2767,6 +2830,10 @@ class MbitMoreBlocks { acceptReporters: false, items: this.GESTURES_MENU }, + tiltDirectionMenu: { + acceptReporters: false, + items: this.TILT_DIRECTION_MENU + }, analogInPins: { acceptReporters: false, items: this.ANALOG_IN_PINS_MENU @@ -3042,6 +3109,40 @@ class MbitMoreBlocks { return lastTimestamp !== this.prevGestureEvents[gestureName]; } + /** + * Test whether the micro:bit is tilted in a direction. + * @param {object} args - the block's arguments. + * @param {string} args.DIRECTION - the direction to check. + * @return {boolean} - true if tilted within the time window. + */ + isTilted (args) { + const direction = args.DIRECTION; + const now = Date.now(); + const stepTime = this.runtime.currentStepTime; + const timeWindow = stepTime * 5; // 5フレームの期間 + + const tiltGestures = direction === 'ANY' ? + [ + MbitMoreGestureName.TILT_UP, + MbitMoreGestureName.TILT_DOWN, + MbitMoreGestureName.TILT_LEFT, + MbitMoreGestureName.TILT_RIGHT + ] : + [direction]; + + for (const gestureName of tiltGestures) { + const timestamp = this._peripheral.getGestureEventTimestamp(gestureName); + if (timestamp !== null) { + const timeSinceEvent = now - timestamp; + if (timeSinceEvent <= timeWindow) { + return true; + } + } + } + + return false; + } + /** * Display pixcel pattern on the 5x5 LED matrix with brightness and write mode. * @param {object} args - the block's arguments. diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index 90626ddad9..cf7e1311c9 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -122,6 +122,12 @@ "mbitMore.gesturesMenu.shake": "ゆさぶられた", "mbitMore.gesturesMenu.moved": "動いた", "mbitMore.gesturesMenu.tilted": "どれかの向きに傾いた", + "mbitMore.isTilted": "[DIRECTION] に傾いた", + "mbitMore.tiltDirectionMenu.any": "どれかの向き", + "mbitMore.tiltDirectionMenu.up": "上", + "mbitMore.tiltDirectionMenu.down": "下", + "mbitMore.tiltDirectionMenu.left": "左", + "mbitMore.tiltDirectionMenu.right": "右", "mbitMore.displayMatrix": "[MATRIX] を表示する", "mbitMore.display": "[TEXT] を表示する", "mbitMore.displayText": "文字 [TEXT] を [DELAY] ミリ秒間隔で流す", @@ -213,6 +219,12 @@ "mbitMore.gesturesMenu.shake": "ゆさぶられた", "mbitMore.gesturesMenu.moved": "うごいた", "mbitMore.gesturesMenu.tilted": "どれかのむきにかたむいた", + "mbitMore.isTilted": "[DIRECTION] にかたむいた", + "mbitMore.tiltDirectionMenu.any": "どれかのむき", + "mbitMore.tiltDirectionMenu.up": "うえ", + "mbitMore.tiltDirectionMenu.down": "した", + "mbitMore.tiltDirectionMenu.left": "ひだり", + "mbitMore.tiltDirectionMenu.right": "みぎ", "mbitMore.displayMatrix": "[MATRIX] をひょうじする", "mbitMore.display": "[TEXT] をひょうじする", "mbitMore.displayText": "もじ [TEXT] を [DELAY] ミリびょうかんかくでながす", From a422ede3ec0aa211b58fdd423f5aafc2039704b4 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 18:03:55 +0900 Subject: [PATCH 03/12] feat: add getTiltAngle reporter block for MicroBit More MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added a new reporter block "[DIRECTION] 方向の傾き" that returns tilt angle: Implementation: - Added TILT_ANGLE_DIRECTION_MENU with options: FRONT, BACK, LEFT, RIGHT - Added getTiltAngle method using pitch/roll values: - FRONT → pitch (forward tilt angle) - BACK → -pitch (backward tilt angle) - LEFT → roll (left tilt angle) - RIGHT → -roll (right tilt angle) - Matches microbit extension pattern for user migration Japanese translations: - Block: "[DIRECTION] 方向の傾き" / "[DIRECTION] ほうこうのかたむき" - Menu items: 前, 後ろ, 左, 右 / まえ, うしろ, ひだり, みぎ Related to: smalruby/smalruby3-develop#20 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- src/extensions/microbitMore/index.js | 85 +++++++++++++++++++ src/extensions/microbitMore/translations.json | 10 +++ 2 files changed, 95 insertions(+) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 043e5e3346..cdef88519b 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -1761,6 +1761,46 @@ class MbitMoreBlocks { ]; } + /** + * @return {array} - text and values for each tilt angle direction menu element + */ + get TILT_ANGLE_DIRECTION_MENU () { + return [ + { + text: formatMessage({ + id: 'mbitMore.tiltAngleDirectionMenu.front', + default: 'front', + description: 'label for front element in tilt angle direction picker for Microbit More extension' + }), + value: 'FRONT' + }, + { + text: formatMessage({ + id: 'mbitMore.tiltAngleDirectionMenu.back', + default: 'back', + description: 'label for back element in tilt angle direction picker for Microbit More extension' + }), + value: 'BACK' + }, + { + text: formatMessage({ + id: 'mbitMore.tiltAngleDirectionMenu.left', + default: 'left', + description: 'label for left element in tilt angle direction picker for Microbit More extension' + }), + value: 'LEFT' + }, + { + text: formatMessage({ + id: 'mbitMore.tiltAngleDirectionMenu.right', + default: 'right', + description: 'label for right element in tilt angle direction picker for Microbit More extension' + }), + value: 'RIGHT' + } + ]; + } + /** * @return {array} - text and values for each buttons menu element */ @@ -2395,6 +2435,22 @@ class MbitMoreBlocks { } } }, + { + opcode: 'getTiltAngle', + text: formatMessage({ + id: 'mbitMore.getTiltAngle', + default: 'tilt angle [DIRECTION]', + description: 'get the tilt angle in a direction' + }), + blockType: BlockType.REPORTER, + arguments: { + DIRECTION: { + type: ArgumentType.STRING, + menu: 'tiltAngleDirectionMenu', + defaultValue: 'FRONT' + } + } + }, '---', { opcode: 'displayMatrix', @@ -2834,6 +2890,10 @@ class MbitMoreBlocks { acceptReporters: false, items: this.TILT_DIRECTION_MENU }, + tiltAngleDirectionMenu: { + acceptReporters: false, + items: this.TILT_ANGLE_DIRECTION_MENU + }, analogInPins: { acceptReporters: false, items: this.ANALOG_IN_PINS_MENU @@ -3143,6 +3203,31 @@ class MbitMoreBlocks { return false; } + /** + * Get the tilt angle in a direction. + * @param {object} args - the block's arguments. + * @param {string} args.DIRECTION - the direction to check (FRONT, BACK, LEFT, RIGHT). + * @return {number} - the tilt angle in degrees. + */ + getTiltAngle (args) { + const direction = args.DIRECTION; + const pitch = this._peripheral.readPitch(); + const roll = this._peripheral.readRoll(); + + switch (direction) { + case 'FRONT': + return pitch; + case 'BACK': + return -pitch; + case 'LEFT': + return roll; + case 'RIGHT': + return -roll; + default: + return 0; + } + } + /** * Display pixcel pattern on the 5x5 LED matrix with brightness and write mode. * @param {object} args - the block's arguments. diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index cf7e1311c9..f9458c061a 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -128,6 +128,11 @@ "mbitMore.tiltDirectionMenu.down": "下", "mbitMore.tiltDirectionMenu.left": "左", "mbitMore.tiltDirectionMenu.right": "右", + "mbitMore.getTiltAngle": "[DIRECTION] 方向の傾き", + "mbitMore.tiltAngleDirectionMenu.front": "前", + "mbitMore.tiltAngleDirectionMenu.back": "後ろ", + "mbitMore.tiltAngleDirectionMenu.left": "左", + "mbitMore.tiltAngleDirectionMenu.right": "右", "mbitMore.displayMatrix": "[MATRIX] を表示する", "mbitMore.display": "[TEXT] を表示する", "mbitMore.displayText": "文字 [TEXT] を [DELAY] ミリ秒間隔で流す", @@ -225,6 +230,11 @@ "mbitMore.tiltDirectionMenu.down": "した", "mbitMore.tiltDirectionMenu.left": "ひだり", "mbitMore.tiltDirectionMenu.right": "みぎ", + "mbitMore.getTiltAngle": "[DIRECTION] ほうこうのかたむき", + "mbitMore.tiltAngleDirectionMenu.front": "まえ", + "mbitMore.tiltAngleDirectionMenu.back": "うしろ", + "mbitMore.tiltAngleDirectionMenu.left": "ひだり", + "mbitMore.tiltAngleDirectionMenu.right": "みぎ", "mbitMore.displayMatrix": "[MATRIX] をひょうじする", "mbitMore.display": "[TEXT] をひょうじする", "mbitMore.displayText": "もじ [TEXT] を [DELAY] ミリびょうかんかくでながす", From 477c2227fe50162b016761de516b662e597cfd26 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 22:02:54 +0900 Subject: [PATCH 04/12] fix: invert signs of pitch and roll to match expected coordinate system - FRONT vertical now returns -90 as expected by user - Nose-up is now positive for pitch, matching description - Clockwise tilt is now positive for roll, matching description - Corrected inverted behavior in getTiltAngle, getPitch, and getRoll blocks Issue #20 --- src/extensions/microbitMore/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index cdef88519b..8c0a2efec7 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -961,8 +961,8 @@ class MbitMore { const data = base64ToUint8Array(result.message); const dataView = new DataView(data.buffer, 0); // Accelerometer - this.pitch = Math.round(dataView.getInt16(0, true) * 180 / Math.PI / 1000); - this.roll = Math.round(dataView.getInt16(2, true) * 180 / Math.PI / 1000); + this.pitch = -Math.round(dataView.getInt16(0, true) * 180 / Math.PI / 1000); + this.roll = -Math.round(dataView.getInt16(2, true) * 180 / Math.PI / 1000); this.acceleration.x = 1000 * dataView.getInt16(4, true) / G; this.acceleration.y = 1000 * dataView.getInt16(6, true) / G; this.acceleration.z = 1000 * dataView.getInt16(8, true) / G; From 437b49c541c082dbbf7cea17b8dda8f0b3b2ca69 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 22:11:14 +0900 Subject: [PATCH 05/12] fix: align isTilted and getTiltAngle with standard micro:bit extension logic - Modified getTiltAngle to return positive values when tilted in the specified direction - Re-implemented isTilted to use tilt angle value (>= 15 degrees) instead of gesture events - This matches the behavior of the standard micro:bit extension and fixes user-reported issues Issue #20 --- src/extensions/microbitMore/index.js | 47 +++++++++++----------------- 1 file changed, 19 insertions(+), 28 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 8c0a2efec7..edde9098e2 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -3176,31 +3176,22 @@ class MbitMoreBlocks { * @return {boolean} - true if tilted within the time window. */ isTilted (args) { - const direction = args.DIRECTION; - const now = Date.now(); - const stepTime = this.runtime.currentStepTime; - const timeWindow = stepTime * 5; // 5フレームの期間 - - const tiltGestures = direction === 'ANY' ? - [ - MbitMoreGestureName.TILT_UP, - MbitMoreGestureName.TILT_DOWN, - MbitMoreGestureName.TILT_LEFT, - MbitMoreGestureName.TILT_RIGHT - ] : - [direction]; - - for (const gestureName of tiltGestures) { - const timestamp = this._peripheral.getGestureEventTimestamp(gestureName); - if (timestamp !== null) { - const timeSinceEvent = now - timestamp; - if (timeSinceEvent <= timeWindow) { - return true; - } - } + if (args.DIRECTION === 'ANY') { + return ( + this.getTiltAngle({DIRECTION: 'FRONT'}) >= 15 || + this.getTiltAngle({DIRECTION: 'BACK'}) >= 15 || + this.getTiltAngle({DIRECTION: 'LEFT'}) >= 15 || + this.getTiltAngle({DIRECTION: 'RIGHT'}) >= 15 + ); } - - return false; + const directionMap = { + [MbitMoreGestureName.TILT_UP]: 'FRONT', + [MbitMoreGestureName.TILT_DOWN]: 'BACK', + [MbitMoreGestureName.TILT_LEFT]: 'LEFT', + [MbitMoreGestureName.TILT_RIGHT]: 'RIGHT' + }; + const direction = directionMap[args.DIRECTION]; + return this.getTiltAngle({DIRECTION: direction}) >= 15; } /** @@ -3216,13 +3207,13 @@ class MbitMoreBlocks { switch (direction) { case 'FRONT': - return pitch; - case 'BACK': return -pitch; + case 'BACK': + return pitch; case 'LEFT': - return roll; - case 'RIGHT': return -roll; + case 'RIGHT': + return roll; default: return 0; } From 7d62de725a164709787762869cb798204ccf3aa2 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 22:16:04 +0900 Subject: [PATCH 06/12] style: rename tilt up/down to front/back in labels and ja translations - Updated tiltDirectionMenu and GESTURES_MENU labels (English and Japanese) - Changed 'up' to 'front' and 'down' to 'back' to match physical orientation - Fixed 'titl' typo in English default strings Issue #20 --- src/extensions/microbitMore/index.js | 20 +++++++++---------- src/extensions/microbitMore/translations.json | 16 +++++++-------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index edde9098e2..352845e0b5 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -1625,23 +1625,23 @@ class MbitMoreBlocks { { text: formatMessage({ id: 'mbitMore.gesturesMenu.tiltUp', - default: 'titl up', - description: 'label for tilt up gesture in gesture picker for microbit more extension' + default: 'tilt front', + description: 'label for tilt front gesture in gesture picker for microbit more extension' }), value: MbitMoreGestureName.TILT_UP }, { text: formatMessage({ id: 'mbitMore.gesturesMenu.tiltDown', - default: 'titl down', - description: 'label for tilt down gesture in gesture picker for microbit more extension' + default: 'tilt back', + description: 'label for tilt back gesture in gesture picker for microbit more extension' }), value: MbitMoreGestureName.TILT_DOWN }, { text: formatMessage({ id: 'mbitMore.gesturesMenu.tiltLeft', - default: 'titl left', + default: 'tilt left', description: 'label for tilt left gesture in gesture picker for microbit more extension' }), value: MbitMoreGestureName.TILT_LEFT @@ -1649,7 +1649,7 @@ class MbitMoreBlocks { { text: formatMessage({ id: 'mbitMore.gesturesMenu.tiltRight', - default: 'titl right', + default: 'tilt right', description: 'label for tilt right gesture in gesture picker for microbit more extension' }), value: MbitMoreGestureName.TILT_RIGHT @@ -1729,16 +1729,16 @@ class MbitMoreBlocks { { text: formatMessage({ id: 'mbitMore.tiltDirectionMenu.up', - default: 'up', - description: 'label for up element in tilt direction picker for Microbit More extension' + default: 'front', + description: 'label for front element in tilt direction picker for Microbit More extension' }), value: MbitMoreGestureName.TILT_UP }, { text: formatMessage({ id: 'mbitMore.tiltDirectionMenu.down', - default: 'down', - description: 'label for down element in tilt direction picker for Microbit More extension' + default: 'back', + description: 'label for back element in tilt direction picker for Microbit More extension' }), value: MbitMoreGestureName.TILT_DOWN }, diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index f9458c061a..d350cd4d1c 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -109,8 +109,8 @@ "mbitMore.touchEventMenu.longTapped": "ロングタップされた", "mbitMore.touchEventMenu.doubleTapped": "ダブルタップされた", "mbitMore.whenGesture": "[GESTURE] とき", - "mbitMore.gesturesMenu.tiltUp": "上へ傾いた", - "mbitMore.gesturesMenu.tiltDown": "下へ傾いた", + "mbitMore.gesturesMenu.tiltUp": "前へ傾いた", + "mbitMore.gesturesMenu.tiltDown": "後ろへ傾いた", "mbitMore.gesturesMenu.tiltLeft": "左へ傾いた", "mbitMore.gesturesMenu.tiltRight": "右へ傾いた", "mbitMore.gesturesMenu.faceUp": "表になった", @@ -124,8 +124,8 @@ "mbitMore.gesturesMenu.tilted": "どれかの向きに傾いた", "mbitMore.isTilted": "[DIRECTION] に傾いた", "mbitMore.tiltDirectionMenu.any": "どれかの向き", - "mbitMore.tiltDirectionMenu.up": "上", - "mbitMore.tiltDirectionMenu.down": "下", + "mbitMore.tiltDirectionMenu.up": "前", + "mbitMore.tiltDirectionMenu.down": "後ろ", "mbitMore.tiltDirectionMenu.left": "左", "mbitMore.tiltDirectionMenu.right": "右", "mbitMore.getTiltAngle": "[DIRECTION] 方向の傾き", @@ -211,8 +211,8 @@ "mbitMore.touchEventMenu.longTapped": "ロングタップされた", "mbitMore.touchEventMenu.doubleTapped": "ダブルタップされた", "mbitMore.whenGesture": "[GESTURE] とき", - "mbitMore.gesturesMenu.tiltUp": "うえへかたむいた", - "mbitMore.gesturesMenu.tiltDown": "したへかたむいた", + "mbitMore.gesturesMenu.tiltUp": "まえへかたむいた", + "mbitMore.gesturesMenu.tiltDown": "うしろへかたむいた", "mbitMore.gesturesMenu.tiltLeft": "ひだりへかたむいた", "mbitMore.gesturesMenu.tiltRight": "みぎへかたむいた", "mbitMore.gesturesMenu.faceUp": "おもてになった", @@ -226,8 +226,8 @@ "mbitMore.gesturesMenu.tilted": "どれかのむきにかたむいた", "mbitMore.isTilted": "[DIRECTION] にかたむいた", "mbitMore.tiltDirectionMenu.any": "どれかのむき", - "mbitMore.tiltDirectionMenu.up": "うえ", - "mbitMore.tiltDirectionMenu.down": "した", + "mbitMore.tiltDirectionMenu.up": "まえ", + "mbitMore.tiltDirectionMenu.down": "うしろ", "mbitMore.tiltDirectionMenu.left": "ひだり", "mbitMore.tiltDirectionMenu.right": "みぎ", "mbitMore.getTiltAngle": "[DIRECTION] ほうこうのかたむき", From a2bbe829ad5370b6c138513e0225bb415a509796 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 22:19:13 +0900 Subject: [PATCH 07/12] Revert "fix: invert signs of pitch and roll to match expected coordinate system" This reverts commit 477c2227fe50162b016761de516b662e597cfd26. --- src/extensions/microbitMore/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 352845e0b5..9fbed61b3e 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -961,8 +961,8 @@ class MbitMore { const data = base64ToUint8Array(result.message); const dataView = new DataView(data.buffer, 0); // Accelerometer - this.pitch = -Math.round(dataView.getInt16(0, true) * 180 / Math.PI / 1000); - this.roll = -Math.round(dataView.getInt16(2, true) * 180 / Math.PI / 1000); + this.pitch = Math.round(dataView.getInt16(0, true) * 180 / Math.PI / 1000); + this.roll = Math.round(dataView.getInt16(2, true) * 180 / Math.PI / 1000); this.acceleration.x = 1000 * dataView.getInt16(4, true) / G; this.acceleration.y = 1000 * dataView.getInt16(6, true) / G; this.acceleration.z = 1000 * dataView.getInt16(8, true) / G; From 36bb8f078a305bc245031c80ff2cb4258b011322 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Fri, 16 Jan 2026 22:43:27 +0900 Subject: [PATCH 08/12] fix: swap tilt front/back gesture mapping and update ja translations MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Swapped MbitMoreGestureID mapping for 1 and 2 to correct inverted tilt front/back detection - Updated Japanese (ja/ja-Hira) translations for tilt gestures from 'へ傾いた' to 'に傾いた' - Confirmed 'TILTED' (any) gesture correctly filters only tilt directions Issue #20 --- src/extensions/microbitMore/index.js | 4 ++-- src/extensions/microbitMore/translations.json | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 9fbed61b3e..4e043fce96 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -273,8 +273,8 @@ const MbitMoreGestureName = */ const MbitMoreGestureID = { - 1: 'TILT_UP', - 2: 'TILT_DOWN', + 1: 'TILT_DOWN', + 2: 'TILT_UP', 3: 'TILT_LEFT', 4: 'TILT_RIGHT', 5: 'FACE_UP', diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index d350cd4d1c..9cce91a22c 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -109,10 +109,10 @@ "mbitMore.touchEventMenu.longTapped": "ロングタップされた", "mbitMore.touchEventMenu.doubleTapped": "ダブルタップされた", "mbitMore.whenGesture": "[GESTURE] とき", - "mbitMore.gesturesMenu.tiltUp": "前へ傾いた", - "mbitMore.gesturesMenu.tiltDown": "後ろへ傾いた", - "mbitMore.gesturesMenu.tiltLeft": "左へ傾いた", - "mbitMore.gesturesMenu.tiltRight": "右へ傾いた", + "mbitMore.gesturesMenu.tiltUp": "前に傾いた", + "mbitMore.gesturesMenu.tiltDown": "後ろに傾いた", + "mbitMore.gesturesMenu.tiltLeft": "左に傾いた", + "mbitMore.gesturesMenu.tiltRight": "右に傾いた", "mbitMore.gesturesMenu.faceUp": "表になった", "mbitMore.gesturesMenu.faceDown": "裏になった", "mbitMore.gesturesMenu.freefall": "落ちた", @@ -211,10 +211,10 @@ "mbitMore.touchEventMenu.longTapped": "ロングタップされた", "mbitMore.touchEventMenu.doubleTapped": "ダブルタップされた", "mbitMore.whenGesture": "[GESTURE] とき", - "mbitMore.gesturesMenu.tiltUp": "まえへかたむいた", - "mbitMore.gesturesMenu.tiltDown": "うしろへかたむいた", - "mbitMore.gesturesMenu.tiltLeft": "ひだりへかたむいた", - "mbitMore.gesturesMenu.tiltRight": "みぎへかたむいた", + "mbitMore.gesturesMenu.tiltUp": "まえにかたむいた", + "mbitMore.gesturesMenu.tiltDown": "うしろにかたむいた", + "mbitMore.gesturesMenu.tiltLeft": "ひだりにかたむいた", + "mbitMore.gesturesMenu.tiltRight": "みぎにかたむいた", "mbitMore.gesturesMenu.faceUp": "おもてになった", "mbitMore.gesturesMenu.faceDown": "うらになった", "mbitMore.gesturesMenu.freefall": "おちた", From 64ff452808ee0b3e5f9a9bd20119be848d77a401 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Sat, 17 Jan 2026 00:09:53 +0900 Subject: [PATCH 09/12] feat: add whenPinConnected block to MicroBit More - Implemented whenPinConnected hat block (Standard micro:bit compatibility) - Reuses whenTouchEvent logic with fixed 'DOWN' (touched) event - Added touchPinIDMenu restricting pins to 0, 1, and 2 - Added translations for the new block in ja, ja-Hira, and de Issue #20 --- src/extensions/microbitMore/index.js | 55 ++++++++++++++++++- src/extensions/microbitMore/translations.json | 3 + 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 4e043fce96..7cc521e00c 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -1910,6 +1910,26 @@ class MbitMoreBlocks { ]; } + /** + * @return {array} - Menu items for touch pin selector (P0, P1, P2). + */ + get TOUCH_PIN_ID_MENU () { + return [ + { + text: '0', + value: MbitMoreButtonName.P0 + }, + { + text: '1', + value: MbitMoreButtonName.P1 + }, + { + text: '2', + value: MbitMoreButtonName.P2 + } + ]; + } + /** * @return {array} - Menu items for touch event selector. */ @@ -2365,6 +2385,22 @@ class MbitMoreBlocks { } } }, + { + opcode: 'whenPinConnected', + text: formatMessage({ + id: 'mbitMore.whenPinConnected', + default: 'when pin [PIN] connected', + description: 'when the selected touch pin on the micro:bit is connected' + }), + blockType: BlockType.HAT, + arguments: { + PIN: { + type: ArgumentType.STRING, + menu: 'touchPinIDMenu', + defaultValue: '0' + } + } + }, { opcode: 'whenTouchEvent', text: formatMessage({ @@ -2878,6 +2914,10 @@ class MbitMoreBlocks { acceptReporters: false, items: this.TOUCH_ID_MENU }, + touchPinIDMenu: { + acceptReporters: false, + items: this.TOUCH_PIN_ID_MENU + }, touchEventMenu: { acceptReporters: false, items: this.TOUCH_EVENT_MENU @@ -2985,13 +3025,22 @@ class MbitMoreBlocks { /** - * Test whether the touch event raised at the pin. + * Test whether the pin is connected (touched). * @param {object} args - the block's arguments. - * @param {string} args.NAME - name of the pin to catch. - * @param {string} args.EVENT - event to catch. + * @param {string} args.PIN - name of the pin. * @param {object} util - utility object provided by the runtime. * @return {boolean|Promise|undefined} - true if the event raised or promise that or undefinde if yield. */ + whenPinConnected (args, util) { + return this.whenTouchEvent({ + NAME: args.PIN, + EVENT: MbitMoreButtonEventName.DOWN + }, util); + } + + /** + * Test whether the touch-pin event raised. + whenTouchEvent (args, util) { const buttonName = args.NAME; if (buttonName === MbitMoreButtonName.LOGO) { diff --git a/src/extensions/microbitMore/translations.json b/src/extensions/microbitMore/translations.json index 9cce91a22c..7af1ce123f 100644 --- a/src/extensions/microbitMore/translations.json +++ b/src/extensions/microbitMore/translations.json @@ -2,6 +2,7 @@ "de": { "mbitMore.name": "MicroBit More", "mbitMore.whenButtonEvent": "Wenn Taste [NAME] [EVENT] ist", + "mbitMore.whenPinConnected": "Wenn Pin [PIN] verbunden wird", "mbitMore.buttonIDMenu.a": "A", "mbitMore.buttonIDMenu.b": "B", "mbitMore.buttonEventMenu.down": "unten", @@ -90,6 +91,7 @@ "ja": { "mbitMore.name": "MicroBit More", "mbitMore.whenButtonEvent": "ボタン [NAME] が [EVENT] とき", + "mbitMore.whenPinConnected": "ピン [PIN] がつながったとき", "mbitMore.buttonIDMenu.a": "A", "mbitMore.buttonIDMenu.b": "B", "mbitMore.buttonEventMenu.down": "押された", @@ -192,6 +194,7 @@ "ja-Hira": { "mbitMore.name": "MicroBit More", "mbitMore.whenButtonEvent": "[NAME] ボタンが [EVENT] とき", + "mbitMore.whenPinConnected": "ピン [PIN] がつながったとき", "mbitMore.buttonIDMenu.a": "A", "mbitMore.buttonIDMenu.b": "B", "mbitMore.buttonEventMenu.down": "おされた", From 2c35991c3e858cc9c09c5539ccd6a390a01adedc Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Sat, 17 Jan 2026 00:16:14 +0900 Subject: [PATCH 10/12] fix: restore whenTouchEvent method signature - Fixed broken JSDoc comment that caused whenTouchEvent to be incorrectly parsed - Resolves 'this.whenTouchEvent is not a function' error Issue #20 --- src/extensions/microbitMore/index.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index 7cc521e00c..b1f3cec089 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -3040,7 +3040,12 @@ class MbitMoreBlocks { /** * Test whether the touch-pin event raised. - + * @param {object} args - the block's arguments. + * @param {string} args.NAME - name of the pin to catch. + * @param {string} args.EVENT - event to catch. + * @param {object} util - utility object provided by the runtime. + * @return {boolean|Promise|undefined} - true if the event raised or promise that or undefinde if yield. + */ whenTouchEvent (args, util) { const buttonName = args.NAME; if (buttonName === MbitMoreButtonName.LOGO) { From 0bd71266572babdff614709786212c749349b321 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Sat, 17 Jan 2026 02:30:39 +0900 Subject: [PATCH 11/12] chore: fix order --- src/extensions/microbitMore/index.js | 170 ++++++++++++++------------- 1 file changed, 87 insertions(+), 83 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index b1f3cec089..ae3d49dac6 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -2331,23 +2331,6 @@ class MbitMoreBlocks { blockIconURI: blockIconURI, showStatusButton: true, blocks: [ - { - opcode: 'whenConnectionChanged', - text: formatMessage({ - id: 'mbitMore.whenConnectionChanged', - default: 'when micro:bit [STATE]', - description: 'when a micro:bit connection state changed' - }), - blockType: BlockType.HAT, - arguments: { - STATE: { - type: ArgumentType.STRING, - menu: 'connectionStateMenu', - defaultValue: 'connected' - } - } - }, - '---', { opcode: 'whenButtonEvent', text: formatMessage({ @@ -2385,76 +2368,64 @@ class MbitMoreBlocks { } } }, + '---', { - opcode: 'whenPinConnected', + opcode: 'whenGesture', text: formatMessage({ - id: 'mbitMore.whenPinConnected', - default: 'when pin [PIN] connected', - description: 'when the selected touch pin on the micro:bit is connected' + id: 'mbitMore.whenGesture', + default: 'when [GESTURE]', + description: 'when the selected gesture is detected by the micro:bit' }), blockType: BlockType.HAT, arguments: { - PIN: { + GESTURE: { type: ArgumentType.STRING, - menu: 'touchPinIDMenu', - defaultValue: '0' + menu: 'gestures', + defaultValue: 'MOVED' } } }, + '---', { - opcode: 'whenTouchEvent', + opcode: 'displayMatrix', text: formatMessage({ - id: 'mbitMore.whenTouchEvent', - default: 'when pin [NAME] is [EVENT]', - description: 'when the selected touch pin on the micro:bit is touched' + id: 'mbitMore.displayMatrix', + default: 'display pattern [MATRIX] ', + description: 'display a pattern on the micro:bit display' }), - blockType: BlockType.HAT, + blockType: BlockType.COMMAND, arguments: { - NAME: { - type: ArgumentType.STRING, - menu: 'touchIDMenu', - defaultValue: MbitMoreButtonName.LOGO - }, - EVENT: { - type: ArgumentType.STRING, - menu: 'touchEventMenu', - defaultValue: MbitMoreButtonEventName.DOWN + MATRIX: { + type: ArgumentType.MATRIX, + defaultValue: '0101010101100010101000100' } } }, { - opcode: 'isPinTouched', + opcode: 'display', text: formatMessage({ - id: 'mbitMore.isPinTouched', - default: 'pin [NAME] is touched?', - description: 'is the selected pin is touched?' + id: 'mbitMore.display', + default: 'display [TEXT]', + description: 'display text on the micro:bit display' }), - blockType: BlockType.BOOLEAN, + blockType: BlockType.COMMAND, arguments: { - NAME: { + TEXT: { type: ArgumentType.STRING, - menu: 'touchIDMenu', - defaultValue: MbitMoreButtonName.LOGO + defaultValue: 'Hello!' } } }, - '---', { - opcode: 'whenGesture', + opcode: 'displayClear', text: formatMessage({ - id: 'mbitMore.whenGesture', - default: 'when [GESTURE]', - description: 'when the selected gesture is detected by the micro:bit' + id: 'mbitMore.clearDisplay', + default: 'clear display', + description: 'display nothing on the micro:bit display' }), - blockType: BlockType.HAT, - arguments: { - GESTURE: { - type: ArgumentType.STRING, - menu: 'gestures', - defaultValue: 'MOVED' - } - } + blockType: BlockType.COMMAND }, + '---', { opcode: 'isTilted', text: formatMessage({ @@ -2489,35 +2460,77 @@ class MbitMoreBlocks { }, '---', { - opcode: 'displayMatrix', + opcode: 'whenPinConnected', text: formatMessage({ - id: 'mbitMore.displayMatrix', - default: 'display pattern [MATRIX] ', - description: 'display a pattern on the micro:bit display' + id: 'mbitMore.whenPinConnected', + default: 'when pin [PIN] connected', + description: 'when the selected touch pin on the micro:bit is connected' }), - blockType: BlockType.COMMAND, + blockType: BlockType.HAT, arguments: { - MATRIX: { - type: ArgumentType.MATRIX, - defaultValue: '0101010101100010101000100' + PIN: { + type: ArgumentType.STRING, + menu: 'touchPinIDMenu', + defaultValue: '0' } } }, + '---', { - opcode: 'display', + opcode: 'whenConnectionChanged', text: formatMessage({ - id: 'mbitMore.display', - default: 'display [TEXT]', - description: 'display text on the micro:bit display' + id: 'mbitMore.whenConnectionChanged', + default: 'when micro:bit [STATE]', + description: 'when a micro:bit connection state changed' }), - blockType: BlockType.COMMAND, + blockType: BlockType.HAT, arguments: { - TEXT: { + STATE: { type: ArgumentType.STRING, - defaultValue: 'Hello!' + menu: 'connectionStateMenu', + defaultValue: 'connected' } } }, + '---', + { + opcode: 'whenTouchEvent', + text: formatMessage({ + id: 'mbitMore.whenTouchEvent', + default: 'when pin [NAME] is [EVENT]', + description: 'when the selected touch pin on the micro:bit is touched' + }), + blockType: BlockType.HAT, + arguments: { + NAME: { + type: ArgumentType.STRING, + menu: 'touchIDMenu', + defaultValue: MbitMoreButtonName.LOGO + }, + EVENT: { + type: ArgumentType.STRING, + menu: 'touchEventMenu', + defaultValue: MbitMoreButtonEventName.DOWN + } + } + }, + { + opcode: 'isPinTouched', + text: formatMessage({ + id: 'mbitMore.isPinTouched', + default: 'pin [NAME] is touched?', + description: 'is the selected pin is touched?' + }), + blockType: BlockType.BOOLEAN, + arguments: { + NAME: { + type: ArgumentType.STRING, + menu: 'touchIDMenu', + defaultValue: MbitMoreButtonName.LOGO + } + } + }, + '---', { opcode: 'displayText', text: formatMessage({ @@ -2537,15 +2550,6 @@ class MbitMoreBlocks { } } }, - { - opcode: 'displayClear', - text: formatMessage({ - id: 'mbitMore.clearDisplay', - default: 'clear display', - description: 'display nothing on the micro:bit display' - }), - blockType: BlockType.COMMAND - }, '---', { opcode: 'getLightLevel', From 516d26138cd50e28502e8678120e5b5360ca3f30 Mon Sep 17 00:00:00 2001 From: Kouji Takao Date: Sat, 17 Jan 2026 02:39:54 +0900 Subject: [PATCH 12/12] feat: simplify TILTED gesture logic - Remove gap and timeout thresholds for TILTED gesture - Make TILTED gesture a simple proxy for TILT_UP, TILT_DOWN, TILT_LEFT, and TILT_RIGHT events - Remove unused tilt tracking properties from constructor Co-Authored-By: Gemini --- src/extensions/microbitMore/index.js | 76 ++-------------------------- 1 file changed, 5 insertions(+), 71 deletions(-) diff --git a/src/extensions/microbitMore/index.js b/src/extensions/microbitMore/index.js index ae3d49dac6..cbd6dec3da 100644 --- a/src/extensions/microbitMore/index.js +++ b/src/extensions/microbitMore/index.js @@ -2282,24 +2282,6 @@ class MbitMoreBlocks { */ this.isWaitingForGap = false; - /** - * The last time the "tilted" event was fired. - * @type {number} - */ - this.lastTiltedEventTime = null; - - /** - * The last time any tilt event was detected. - * @type {number} - */ - this.lastTiltOccurredTime = null; - - /** - * Whether the extension is waiting for a gap in tilting before firing again. - * @type {boolean} - */ - this.isWaitingForTiltGap = false; - /** * The timer of updateLastGestureEvent. * @type {number} @@ -3159,66 +3141,18 @@ class MbitMoreBlocks { return shouldFire; } if (gestureName === 'TILTED') { - const now = Date.now(); - const stepTime = this.runtime.currentStepTime; - const gapThreshold = stepTime * 5; // 5フレームの空白 - const timeoutThreshold = stepTime * 30; // 30フレームで強制発火 - - // Only check tilt-related gestures const tiltGestures = [ MbitMoreGestureName.TILT_UP, MbitMoreGestureName.TILT_DOWN, MbitMoreGestureName.TILT_LEFT, MbitMoreGestureName.TILT_RIGHT ]; - - const changedTiltGestures = []; - tiltGestures.forEach(name => { - const timestamp = this._peripheral.gestureEvents[name]; - if (typeof timestamp !== 'undefined') { - if (this.prevGestureEvents[name]) { - if (timestamp !== this.prevGestureEvents[name]) { - changedTiltGestures.push(name); - } - } else { - changedTiltGestures.push(name); - } - } + return tiltGestures.some(name => { + const lastTimestamp = this._peripheral.getGestureEventTimestamp(name); + if (lastTimestamp === null) return false; + if (!this.prevGestureEvents[name]) return true; + return lastTimestamp !== this.prevGestureEvents[name]; }); - - const eventDetected = changedTiltGestures.length > 0; - if (eventDetected) { - this.lastTiltOccurredTime = now; - } - - // 静止判定(隙間ができたか) - const timeSinceLastOccurred = this.lastTiltOccurredTime === null ? - Infinity : (now - this.lastTiltOccurredTime); - if (timeSinceLastOccurred >= gapThreshold) { - this.isWaitingForTiltGap = false; - } - - let shouldFire = false; - - if (eventDetected) { - if (this.isWaitingForTiltGap) { - // 傾き続けている場合の強制発火判定 - const timeSinceLastFired = this.lastTiltedEventTime === null ? - Infinity : (now - this.lastTiltedEventTime); - if (timeSinceLastFired >= timeoutThreshold) { - shouldFire = true; - } - } else { - shouldFire = true; - } - } - - if (shouldFire) { - this.lastTiltedEventTime = now; - this.isWaitingForTiltGap = true; - } - - return shouldFire; } const lastTimestamp = this._peripheral.getGestureEventTimestamp(gestureName);