-
Notifications
You must be signed in to change notification settings - Fork 165
Add Links & Barcodes and Joystick #475
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
76921d6
links-and-barcodes.js
moosanaeempc-lgtm 441baba
delete me.txt
moosanaeempc-lgtm 43b3823
Add files via upload
moosanaeempc-lgtm 3d63a75
delete me.txt
moosanaeempc-lgtm 286d1ee
extensions.js
moosanaeempc-lgtm ceacc01
Update extensions.js
moosanaeempc-lgtm 5bfa6a9
Update links-and-barcodes.js
moosanaeempc-lgtm 2bba9d5
Update extensions.js
moosanaeempc-lgtm 7c42de1
Rename links-&-barcodes.png to links-and-barcodes.png
moosanaeempc-lgtm 9b9cc26
Update extensions.js
moosanaeempc-lgtm b58d4e1
Update links-and-barcodes.js
moosanaeempc-lgtm f83f70e
Update extensions.js
moosanaeempc-lgtm f7fe6da
Update links-and-barcodes.js
moosanaeempc-lgtm 8dc6a89
Update links-and-barcodes.js
moosanaeempc-lgtm 6839b5a
Update extensions.js
moosanaeempc-lgtm 276d6ed
Update links-and-barcodes.js
moosanaeempc-lgtm 32c2727
Update links-and-barcodes.js
moosanaeempc-lgtm 381de1b
Update extensions.js
moosanaeempc-lgtm 8a2ab44
Update links-and-barcodes.js
moosanaeempc-lgtm 44f0552
Update links-and-barcodes.js
moosanaeempc-lgtm 9566be0
Update links-and-barcodes.js
moosanaeempc-lgtm cb87ee9
Update links-and-barcodes.js
moosanaeempc-lgtm fb24a5a
Update links-and-barcodes.js
moosanaeempc-lgtm 584daba
Update links-and-barcodes.js
moosanaeempc-lgtm 38f41ce
Update links-and-barcodes.js
moosanaeempc-lgtm 581bf2b
Update links-and-barcodes.js
moosanaeempc-lgtm d704a62
Update links-and-barcodes.js
moosanaeempc-lgtm 65b1eba
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm 591c9f5
Create delete me
moosanaeempc-lgtm c4d4c08
Add files via upload
moosanaeempc-lgtm b6c66bd
Delete static/images/codemaster/delete me
moosanaeempc-lgtm 64a0c03
Create delete me
moosanaeempc-lgtm 407ac87
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm d94c029
Add files via upload
moosanaeempc-lgtm 619c56d
Delete static/images/codemaster/links-and-barcodes.png
moosanaeempc-lgtm cf8b24a
Add files via upload
moosanaeempc-lgtm f9ae104
Delete static/images/codemaster/delete me
moosanaeempc-lgtm 6ae6872
Merge branch 'main' into main
moosanaeempc-lgtm ed59bd3
Update extensions.js
moosanaeempc-lgtm 301a91b
Create joystick.js
moosanaeempc-lgtm eb57e09
Add files via upload
moosanaeempc-lgtm 6d82a14
Delete static/images/codemaster/Joystick.png
moosanaeempc-lgtm 21a3098
Add files via upload
moosanaeempc-lgtm 4363e94
Update extensions.js
moosanaeempc-lgtm 169d80c
Update joystick.js
moosanaeempc-lgtm c151332
Update joystick.js
moosanaeempc-lgtm 6093802
Delete static/images/codemaster/joystick.png
moosanaeempc-lgtm 26f1395
Add files via upload
moosanaeempc-lgtm a32d3a9
Delete static/images/codemaster/joystick.png
moosanaeempc-lgtm a73f2d0
Add files via upload
moosanaeempc-lgtm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,227 @@ | ||
| (function(Scratch) { | ||
| 'use strict'; | ||
|
|
||
| class StageJoystick { | ||
| constructor() { | ||
| this.container = null; | ||
| this.base = null; | ||
| this.stick = null; | ||
| this.xMove = 0; | ||
| this.yMove = 0; | ||
| this.isVisible = false; | ||
| this.scratchX = -100; | ||
| this.scratchY = -100; | ||
| this.scratchSize = 100; | ||
| this.baseAlpha = 0; | ||
| this.stickAlpha = 0; | ||
|
|
||
| this._injectJoystick(); | ||
|
|
||
| // Safety check: Wait for the Scratch VM to be fully loaded | ||
| if (Scratch.vm && Scratch.vm.runtime) { | ||
| this._setupListeners(Scratch.vm.runtime); | ||
| } else { | ||
| const checkVM = setInterval(() => { | ||
| if (Scratch.vm && Scratch.vm.runtime) { | ||
| this._setupListeners(Scratch.vm.runtime); | ||
| clearInterval(checkVM); | ||
| } | ||
| }, 100); | ||
| } | ||
| } | ||
|
|
||
| getInfo() { | ||
| return { | ||
| id: 'codemasterJoystick', | ||
| name: 'Joystick', | ||
| isUnsandboxed: true, // Required to touch the Stage HTML | ||
| color1: '#3366ff', | ||
| blocks: [ | ||
| { opcode: 'showJoystick', blockType: Scratch.BlockType.COMMAND, text: 'show joystick' }, | ||
| { opcode: 'hideJoystick', blockType: Scratch.BlockType.COMMAND, text: 'hide joystick' }, | ||
| { | ||
| opcode: 'setPos', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick x [X] y [Y]', | ||
| arguments: { | ||
| X: { type: Scratch.ArgumentType.NUMBER, defaultValue: -100 }, | ||
| Y: { type: Scratch.ArgumentType.NUMBER, defaultValue: -100 } | ||
| } | ||
| }, | ||
| { | ||
| opcode: 'setSize', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick size to [SIZE]', | ||
| arguments: { | ||
| SIZE: { type: Scratch.ArgumentType.NUMBER, defaultValue: 100 } | ||
| } | ||
| }, | ||
| { | ||
| opcode: 'setBaseColor', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick base color to [COLOR]', | ||
| arguments: { | ||
| COLOR: { type: Scratch.ArgumentType.COLOR, defaultValue: '#888888' } | ||
| } | ||
| }, | ||
| { | ||
| opcode: 'setBaseOpacity', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick base transparency level to [OPACITY]', | ||
| arguments: { | ||
| OPACITY: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 } | ||
| } | ||
| }, | ||
| { | ||
| opcode: 'setStickColor', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick stick color to [COLOR]', | ||
| arguments: { | ||
| COLOR: { type: Scratch.ArgumentType.COLOR, defaultValue: '#ffffff' } | ||
| } | ||
| }, | ||
| { | ||
| opcode: 'setStickOpacity', | ||
| blockType: Scratch.BlockType.COMMAND, | ||
| text: 'set joystick stick transparency level to [OPACITY]', | ||
| arguments: { | ||
| OPACITY: { type: Scratch.ArgumentType.NUMBER, defaultValue: 0 } | ||
| } | ||
| }, | ||
| { opcode: 'getX', blockType: Scratch.BlockType.REPORTER, text: 'joystick x movement' }, | ||
| { opcode: 'getY', blockType: Scratch.BlockType.REPORTER, text: 'joystick y movement' } | ||
| ] | ||
| }; | ||
| } | ||
|
|
||
| _setupListeners(runtime) { | ||
| runtime.on('PROJECT_START', () => this.hideJoystick()); | ||
| runtime.on('PROJECT_STOP_ALL', () => this.hideJoystick()); | ||
|
|
||
| const updateLoop = () => { | ||
| this._updateVisuals(); | ||
| requestAnimationFrame(updateLoop); | ||
| }; | ||
| requestAnimationFrame(updateLoop); | ||
| } | ||
|
|
||
| _updateVisuals() { | ||
| if (!this.container) return; | ||
| const stageWrapper = document.querySelector('[class*="stage_stage-wrapper"]') || | ||
| document.querySelector('[class*="stage_stage-canvas-overlay"]'); | ||
| const isGuiOverlay = !!document.querySelector('[class*="modal_modal-overlay"]'); | ||
|
|
||
| if (!stageWrapper || isGuiOverlay || !this.isVisible) { | ||
| this.container.style.display = 'none'; | ||
| return; | ||
| } | ||
|
|
||
| if (this.container.parentElement !== stageWrapper) { | ||
| stageWrapper.appendChild(this.container); | ||
| } | ||
|
|
||
| const rect = stageWrapper.getBoundingClientRect(); | ||
| if (rect.width === 0 || rect.height === 0) return; | ||
|
|
||
| const scale = rect.width / 480; | ||
| const halfSize = this.scratchSize / 2; | ||
| const clampedX = Math.max(-240 + halfSize, Math.min(240 - halfSize, this.scratchX)); | ||
| const clampedY = Math.max(-180 + halfSize, Math.min(180 - halfSize, this.scratchY)); | ||
|
|
||
| const percentX = ((clampedX + 240) / 480) * 100; | ||
| const percentY = ((180 - clampedY) / 360) * 100; | ||
|
|
||
| const pixelSize = this.scratchSize * scale; | ||
| this.container.style.display = 'block'; | ||
|
|
||
| Object.assign(this.container.style, { | ||
| position: 'absolute', | ||
| width: `${pixelSize}px`, | ||
| height: `${pixelSize}px`, | ||
| left: `calc(${percentX}% - ${pixelSize / 2}px)`, | ||
| top: `calc(${percentY}% - ${pixelSize / 2}px)`, | ||
| zIndex: '1000' | ||
| }); | ||
|
|
||
| if (this.base) this.base.style.opacity = 1 - this.baseAlpha; | ||
| if (this.stick) this.stick.style.opacity = 1 - this.stickAlpha; | ||
| } | ||
|
|
||
| _injectJoystick() { | ||
| this.container = document.createElement('div'); | ||
| this.container.style.touchAction = 'none'; | ||
|
|
||
| this.base = document.createElement('div'); | ||
| Object.assign(this.base.style, { | ||
| width: '100%', height: '100%', borderRadius: '50%', | ||
| backgroundColor: '#888888', position: 'absolute', | ||
| boxSizing: 'border-box', border: '2px solid rgba(0,0,0,0.1)', | ||
| top: '0', left: '0' | ||
| }); | ||
|
|
||
| this.stick = document.createElement('div'); | ||
| Object.assign(this.stick.style, { | ||
| width: '40%', height: '40%', borderRadius: '50%', | ||
| backgroundColor: '#ffffff', position: 'absolute', | ||
| top: '30%', left: '30%', pointerEvents: 'none', | ||
| boxShadow: '0 2px 4px rgba(0,0,0,0.3)', | ||
| zIndex: '1001' | ||
| }); | ||
|
|
||
| this.container.appendChild(this.base); | ||
| this.container.appendChild(this.stick); | ||
|
|
||
| const handleMove = (e) => { | ||
| const bRect = this.base.getBoundingClientRect(); | ||
| const cX = bRect.left + bRect.width / 2; | ||
| const cY = bRect.top + bRect.height / 2; | ||
| const clientX = e.touches ? e.touches[0].clientX : e.clientX; | ||
| const clientY = e.touches ? e.touches[0].clientY : e.clientY; | ||
|
|
||
| let dx = clientX - cX; | ||
| let dy = clientY - cY; | ||
| const maxDist = bRect.width / 2; | ||
| const dist = Math.sqrt(dx * dx + dy * dy); | ||
|
|
||
| if (dist > maxDist) { | ||
| dx *= maxDist / dist; | ||
| dy *= maxDist / dist; | ||
| } | ||
|
|
||
| this.stick.style.transform = `translate(${dx}px, ${dy}px)`; | ||
| this.xMove = (dx / maxDist) * 100; | ||
| this.yMove = (dy / maxDist) * -100; | ||
| }; | ||
|
|
||
| this.container.addEventListener('pointerdown', (e) => { | ||
| this.container.setPointerCapture(e.pointerId); | ||
| const onMove = (me) => handleMove(me); | ||
| const onUp = () => { | ||
| window.removeEventListener('pointermove', onMove); | ||
| window.removeEventListener('pointerup', onUp); | ||
| this.stick.style.transform = 'translate(0,0)'; | ||
| this.xMove = 0; | ||
| this.yMove = 0; | ||
| }; | ||
| window.addEventListener('pointermove', onMove); | ||
| window.addEventListener('pointerup', onUp); | ||
| }); | ||
| } | ||
|
|
||
| showJoystick() { this.isVisible = true; } | ||
| hideJoystick() { this.isVisible = false; } | ||
| setPos(args) { | ||
| this.scratchX = Number(args.X); | ||
| this.scratchY = Number(args.Y); | ||
| } | ||
| setSize(args) { this.scratchSize = Number(args.SIZE); } | ||
| setBaseColor(args) { if(this.base) this.base.style.backgroundColor = args.COLOR; } | ||
| setStickColor(args) { if(this.stick) this.stick.style.backgroundColor = args.COLOR; } | ||
| setBaseOpacity(args) { this.baseAlpha = Math.max(0, Math.min(100, Number(args.OPACITY))) / 100; } | ||
| setStickOpacity(args) { this.stickAlpha = Math.max(0, Math.min(100, Number(args.OPACITY))) / 100; } | ||
| getX() { return Math.round(this.xMove); } | ||
| getY() { return Math.round(this.yMove); } | ||
| } | ||
|
|
||
| Scratch.extensions.register(new StageJoystick()); | ||
| })(Scratch); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.