p5-phone 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +509 -0
  3. package/dist/p5-phone.js +1062 -0
  4. package/dist/p5-phone.min.js +10 -0
  5. package/examples/Phone Sensor Examples/microphone/01_mic_level/index.html +19 -0
  6. package/examples/Phone Sensor Examples/microphone/01_mic_level/sketch.js +117 -0
  7. package/examples/Phone Sensor Examples/movement/01_orientation_basic/index.html +28 -0
  8. package/examples/Phone Sensor Examples/movement/01_orientation_basic/sketch.js +123 -0
  9. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/index.html +28 -0
  10. package/examples/Phone Sensor Examples/movement/02_rotational_velocity/sketch.js +144 -0
  11. package/examples/Phone Sensor Examples/movement/03_acceleration/index.html +28 -0
  12. package/examples/Phone Sensor Examples/movement/03_acceleration/sketch.js +87 -0
  13. package/examples/Phone Sensor Examples/sound/01_dual_audio/index.html +31 -0
  14. package/examples/Phone Sensor Examples/sound/01_dual_audio/sketch.js +225 -0
  15. package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio1.mp3 +0 -0
  16. package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio2.mp3 +0 -0
  17. package/examples/Phone Sensor Examples/sound/02_volume_touches/index.html +31 -0
  18. package/examples/Phone Sensor Examples/sound/02_volume_touches/sketch.js +269 -0
  19. package/examples/Phone Sensor Examples/sound/02_volume_touches/tracks/audio1.mp3 +0 -0
  20. package/examples/Phone Sensor Examples/touch/01_touch_basic/index.html +28 -0
  21. package/examples/Phone Sensor Examples/touch/01_touch_basic/sketch.js +94 -0
  22. package/examples/Phone Sensor Examples/touch/02_touch_zones/index.html +28 -0
  23. package/examples/Phone Sensor Examples/touch/02_touch_zones/sketch.js +220 -0
  24. package/examples/Phone Sensor Examples/touch/03_touch_count/index.html +28 -0
  25. package/examples/Phone Sensor Examples/touch/03_touch_count/sketch.js +93 -0
  26. package/examples/Phone Sensor Examples/touch/04_touch_distance/index.html +28 -0
  27. package/examples/Phone Sensor Examples/touch/04_touch_distance/sketch.js +120 -0
  28. package/examples/Phone Sensor Examples/touch/05_touch_angle/index.html +28 -0
  29. package/examples/Phone Sensor Examples/touch/05_touch_angle/sketch.js +117 -0
  30. package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/index.html +19 -0
  31. package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/sketch.js +72 -0
  32. package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/index.html +18 -0
  33. package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/sketch.js +51 -0
  34. package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/index.html +18 -0
  35. package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/sketch.js +70 -0
  36. package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/index.html +18 -0
  37. package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/sketch.js +83 -0
  38. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/index.html +19 -0
  39. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/sketch.js +96 -0
  40. package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/tracks/audio1.mp3 +0 -0
  41. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/index.html +19 -0
  42. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/sketch.js +118 -0
  43. package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/tracks/audio1.mp3 +0 -0
  44. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/index.html +18 -0
  45. package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/sketch.js +58 -0
  46. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/index.html +18 -0
  47. package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/sketch.js +78 -0
  48. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/index.html +18 -0
  49. package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/sketch.js +64 -0
  50. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/index.html +18 -0
  51. package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/sketch.js +69 -0
  52. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/index.html +18 -0
  53. package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/sketch.js +85 -0
  54. package/examples/Phone and Gif/collision/README.md +31 -0
  55. Gif/collision/gifs/spaceSuit2.png +0 -0
  56. package/examples/Phone and Gif/collision/index.html +19 -0
  57. package/examples/Phone and Gif/collision/sketch.js +226 -0
  58. Gif/fetch/gifs/corgiswimflip.gif +0 -0
  59. package/examples/Phone and Gif/fetch/index.html +18 -0
  60. package/examples/Phone and Gif/fetch/sketch.js +139 -0
  61. Gif/fly/gifs/comparison.gif +0 -0
  62. package/examples/Phone and Gif/fly/index.html +18 -0
  63. package/examples/Phone and Gif/fly/sketch.js +103 -0
  64. Gif/roll/gifs/how-penciles-are-made.gif +0 -0
  65. package/examples/Phone and Gif/roll/index.html +18 -0
  66. package/examples/Phone and Gif/roll/sketch.js +121 -0
  67. package/examples/UXcompare/button-vs-movement/index.html +45 -0
  68. package/examples/UXcompare/button-vs-movement/sketch.js +355 -0
  69. package/examples/UXcompare/button-vs-orientation/index.html +25 -0
  70. package/examples/UXcompare/button-vs-orientation/sketch.js +317 -0
  71. package/examples/UXcompare/button-vs-shake/index.html +45 -0
  72. package/examples/UXcompare/button-vs-shake/sketch.js +320 -0
  73. package/examples/UXcompare/gyroscope-demo/index.html +78 -0
  74. package/examples/UXcompare/gyroscope-demo/sketch.js +166 -0
  75. package/examples/UXcompare/index.html +419 -0
  76. package/examples/UXcompare/microphone-demo/index.html +79 -0
  77. package/examples/UXcompare/microphone-demo/sketch.js +210 -0
  78. package/examples/UXcompare/slider-vs-angle/index.html +25 -0
  79. package/examples/UXcompare/slider-vs-angle/sketch.js +429 -0
  80. package/examples/UXcompare/slider-vs-distance/index.html +25 -0
  81. package/examples/UXcompare/slider-vs-distance/sketch.js +401 -0
  82. package/examples/UXcompare/slider-vs-microphone/index.html +26 -0
  83. package/examples/UXcompare/slider-vs-microphone/sketch.js +336 -0
  84. package/examples/UXcompare/slider-vs-touches/index.html +25 -0
  85. package/examples/UXcompare/slider-vs-touches/sketch.js +376 -0
  86. package/examples/UXcompare/sliders-vs-acceleration/index.html +25 -0
  87. package/examples/UXcompare/sliders-vs-acceleration/sketch.js +361 -0
  88. package/examples/UXcompare/sliders-vs-rotation/index.html +25 -0
  89. package/examples/UXcompare/sliders-vs-rotation/sketch.js +375 -0
  90. package/examples/blankTemplate/index.html +31 -0
  91. package/examples/blankTemplate/sketch.js +55 -0
  92. package/examples/homepage/index.html +506 -0
  93. package/package.json +73 -0
  94. package/src/p5-phone.js +1062 -0
  95. package/src/permissionMic.js +240 -0
  96. package/src/permissionsGesture.js +213 -0
  97. package/src/permissionsGyro.js +246 -0
@@ -0,0 +1,10 @@
1
+ /*!
2
+ * p5-phone v1.4.4
3
+ * Simplified mobile hardware access for p5.js - handle sensors, microphone, touch, and browser gestures with ease
4
+ * https://github.com/DigitalFuturesOCADU/p5-phone
5
+ *
6
+ * Copyright (c) 2025 Nick Puckett
7
+ * Released under the MIT License
8
+ * https://opensource.org/licenses/MIT
9
+ */
10
+ window._originalConsoleError=console.error,window._originalConsoleWarn=console.warn,window._debugErrorHandlersSet||(window._debugErrorHandlersSet=!0,window._earlyErrors=window._earlyErrors||[],window.addEventListener("error",function(e){const n=`${e.error?.message||e.message||"Unknown error"} (${e.filename?e.filename.split("/").pop():"unknown file"}:${e.lineno||"unknown line"})`;console.error("🚨 Error caught:",n),e.error?.stack&&console.error("Stack:",e.error.stack),window._earlyErrors.push({type:"error",message:"JavaScript Error: "+n,stack:e.error?.stack}),!1===window.SHOW_DEBUG||window._debugVisible||"function"==typeof showDebug&&showDebug(),window._debugVisible&&"function"==typeof debugError&&(debugError("JavaScript Error:",n),e.error?.stack&&debugError("Stack trace:",e.error.stack))}),window.addEventListener("unhandledrejection",function(e){const n=e.reason?.message||e.reason||"Unknown promise rejection";console.error("🚨 Promise rejection caught:",n),window._earlyErrors.push({type:"error",message:"Unhandled Promise Rejection: "+n}),window._debugVisible&&"function"==typeof debugError&&debugError("Unhandled Promise Rejection:",n)})),window.sensorsEnabled=!1,window.micEnabled=!1,window.soundEnabled=!1,window.gesturesLocked=!1;let _permissionsInitialized=!1,_micInstance=null;function lockGestures(){window.gesturesLocked||(console.log("🔒 Locking mobile gestures..."),_initializeGestureBlocking(),_initializeP5TouchOverrides(),window.gesturesLocked=!0,console.log("✅ Mobile gestures locked"))}function enableGyroButton(e="ENABLE MOTION SENSORS",n="Requesting motion sensors..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via button")})}function enableGyroTap(e="Tap screen to enable motion sensors"){_createTapToEnable(e,async()=>{await _requestMotionPermissions(),console.log("✅ Gyroscope enabled via tap")})}function enableMicButton(e="ENABLE MICROPHONE",n="Requesting microphone access..."){_createPermissionButton(e,n,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via button")})}function enableMicTap(e="Tap screen to enable microphone"){_createTapToEnable(e,async()=>{await _requestMicrophonePermissions(),console.log("✅ Microphone enabled via tap")})}function enableSoundButton(e="ENABLE SOUND",n="Enabling audio..."){_createPermissionButton(e,n,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via button")})}function enableSoundTap(e="Tap screen to enable sound"){_createTapToEnable(e,async()=>{await _requestSoundOutput(),console.log("✅ Sound output enabled via tap")})}function enableAllButton(e="ENABLE MOTION & MICROPHONE",n="Requesting permissions..."){_createPermissionButton(e,n,async()=>{await _requestMotionPermissions(),await _requestMicrophonePermissions(),console.log("✅ Motion sensors and microphone enabled via button")})}function enableAllTap(e="Tap screen to enable motion sensors & microphone"){_createTapToEnable(e,async()=>{await _requestMotionPermissions(),await _requestMicrophonePermissions(),console.log("✅ Motion sensors and microphone enabled via tap")})}async function _requestMotionPermissions(){try{if("undefined"!=typeof DeviceOrientationEvent&&"function"==typeof DeviceOrientationEvent.requestPermission){const e=await DeviceOrientationEvent.requestPermission();if(console.log("Orientation permission:",e),"undefined"!=typeof DeviceMotionEvent&&"function"==typeof DeviceMotionEvent.requestPermission){const e=await DeviceMotionEvent.requestPermission();console.log("Motion permission:",e)}}window.sensorsEnabled=!0,_notifySketchReady()}catch(e){console.error("Motion sensor permission error:",e),_debugVisible&&debugError("Motion sensor permission error:",e),window.sensorsEnabled=!0,_notifySketchReady()}}async function _requestMicrophonePermissions(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),"undefined"!=typeof mic&&mic&&mic.start?(mic.start(),_micInstance=mic,window.micEnabled=!0):console.warn("No microphone object found. Create one with: mic = new p5.AudioIn();"),_notifySketchReady()}catch(e){console.error("Microphone permission error:",e),_debugVisible&&debugError("Microphone permission error:",e),_notifySketchReady()}}async function _requestSoundOutput(){try{"undefined"!=typeof userStartAudio&&await userStartAudio(),window.soundEnabled=!0,_notifySketchReady()}catch(e){console.error("Sound output error:",e),_debugVisible&&debugError("Sound output error:",e),window.soundEnabled=!0,_notifySketchReady()}}function _notifySketchReady(){"function"==typeof userSetupComplete&&userSetupComplete(),window.dispatchEvent(new CustomEvent("permissionsReady",{detail:{sensors:window.sensorsEnabled,microphone:window.micEnabled,sound:window.soundEnabled,gestures:window.gesturesLocked}}))}function _createPermissionButton(e,n,o){_removeExistingUI();const t=document.createElement("button");t.id="permissionButton",t.textContent=e,t.style.cssText="\n position: fixed;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n padding: 20px 40px;\n font-size: 18px;\n font-weight: bold;\n background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);\n color: white;\n border: none;\n border-radius: 12px;\n cursor: pointer;\n z-index: 999999;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n box-shadow: 0 4px 15px rgba(0,0,0,0.2);\n transition: transform 0.2s ease;\n touch-action: manipulation;\n ";const i=document.createElement("div");i.id="permissionStatus",i.textContent=n,i.style.cssText="\n position: fixed;\n top: 60%;\n left: 50%;\n transform: translate(-50%, 0);\n color: white;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n z-index: 999998;\n display: none;\n ",t.addEventListener("mouseenter",()=>{t.style.transform="translate(-50%, -50%) scale(1.05)"}),t.addEventListener("mouseleave",()=>{t.style.transform="translate(-50%, -50%) scale(1)"});const r=async()=>{t.parentNode&&(t.style.display="none",i.style.display="block",await o(),i.style.display="none",_removeExistingUI())};t.addEventListener("click",r),t.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),r()}),t.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),r()}),document.body.appendChild(t),document.body.appendChild(i)}function _createTapToEnable(e,n){_removeExistingUI();const o=document.createElement("div");o.id="tapOverlay",o.style.cssText="\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background: rgba(0, 0, 0, 0.8);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 999999;\n cursor: pointer;\n touch-action: manipulation;\n ";const t=document.createElement("div");t.textContent=e,t.style.cssText="\n color: white;\n font-size: 24px;\n font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;\n text-align: center;\n padding: 40px;\n border: 2px solid rgba(255, 255, 255, 0.3);\n border-radius: 12px;\n background: rgba(255, 255, 255, 0.1);\n backdrop-filter: blur(10px);\n ",o.appendChild(t);const i=async()=>{o.parentNode&&(t.textContent="Enabling...",await n(),o.parentNode&&document.body.removeChild(o))};o.addEventListener("click",i),o.addEventListener("touchend",function(e){e.preventDefault(),e.stopPropagation(),i()}),o.addEventListener("pointerup",function(e){e.preventDefault(),e.stopPropagation(),i()}),document.body.appendChild(o)}function _removeExistingUI(){const e=document.getElementById("permissionButton"),n=document.getElementById("permissionStatus"),o=document.getElementById("tapOverlay");e&&e.remove(),n&&n.remove(),o&&o.remove()}function _initializeGestureBlocking(){window.history.pushState(null,"",window.location.href),window.onpopstate=function(){window.history.pushState(null,"",window.location.href)},window.addEventListener("beforeunload",function(e){e.preventDefault(),e.returnValue=""}),_initializeEdgeSwipePrevention(),_initializeOtherGesturePrevention()}function _initializeEdgeSwipePrevention(){let e=0,n=0;document.addEventListener("touchstart",function(o){o.touches&&o.touches.length>0&&(e=o.touches[0].clientX,n=o.touches[0].clientY,(e<20||e>window.innerWidth-20)&&o.preventDefault())},{passive:!1,capture:!0}),document.addEventListener("touchmove",function(o){if(!o.touches||0===o.touches.length)return;let t=o.touches[0].clientX,i=o.touches[0].clientY,r=t-e,s=i-n;(e<20&&r>0||e>window.innerWidth-20&&r<0)&&(o.preventDefault(),o.stopPropagation()),0===window.pageYOffset&&s>0&&o.preventDefault(),!o.target||"CANVAS"!==o.target.tagName||document.getElementById("tapOverlay")||document.getElementById("permissionButton")||o.preventDefault()},{passive:!1,capture:!0})}function _initializeOtherGesturePrevention(){document.addEventListener("gesturestart",function(e){e.preventDefault()}),document.addEventListener("gesturechange",function(e){e.preventDefault()}),document.addEventListener("gestureend",function(e){e.preventDefault()});let e=0;document.addEventListener("touchend",function(n){if(n.target&&("tapOverlay"===n.target.id||n.target.closest("#tapOverlay")||"permissionButton"===n.target.id||"permissionStatus"===n.target.id||n.target.closest("#permissionButton")||n.target.closest("#permissionStatus")))return;const o=Date.now();o-e<=300&&n.preventDefault(),e=o},!1),window.oncontextmenu=function(e){return e.preventDefault(),e.stopPropagation(),!1}}function _initializeP5TouchOverrides(){setTimeout(()=>{if(window._setupDone)_overrideP5Touch();else{const e=setInterval(()=>{window._setupDone&&(_overrideP5Touch(),clearInterval(e))},100)}},100)}function _overrideP5Touch(){const e=window.touchStarted||function(){},n=window.touchMoved||function(){},o=window.touchEnded||function(){},t=window.mousePressed||function(){},i=window.mouseDragged||function(){},r=window.mouseReleased||function(){};window.touchStarted=function(n){return e(n),!1},window.touchMoved=function(e){return n(e),!1},window.touchEnded=function(e){return o(e),!1},window.mousePressed=function(e){return t(e),!1},window.mouseDragged=function(e){return i(e),!1},window.mouseReleased=function(e){return r(e),!1}}document.addEventListener("DOMContentLoaded",function(){const e=document.getElementById("startButton"),n=document.getElementById("statusText");e&&n&&(console.warn("⚠️ Legacy HTML elements detected. Consider using the new API functions instead."),e.addEventListener("click",async()=>{e.classList.add("hidden"),n.classList.remove("hidden"),n.textContent="Requesting permissions...",await _requestMotionPermissions(),await _requestMicrophonePermissions(),n.classList.add("hidden")}),lockGestures())});let _debugPanel=null,_debugVisible=!1,_debugMessages=[];const MAX_DEBUG_MESSAGES=20;function showDebug(){_createDebugPanel(),_debugPanel.style.display="block",_debugVisible=!0,window._debugVisible=!0,_setupConsoleOverrides(),_displayEarlyErrors()}function hideDebug(){_debugPanel&&(_debugPanel.style.display="none",_debugVisible=!1)}function toggleDebug(){_debugVisible?hideDebug():showDebug()}function debug(...e){console.log(...e);_addDebugMessage(e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" "),"log")}function debugError(...e){(window._originalConsoleError||console.error).apply(console,e);_addDebugMessage(`❌ ERROR: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"error")}function debugWarn(...e){(window._originalConsoleWarn||console.warn).apply(console,e);_addDebugMessage(`⚠️ WARNING: ${e.map(e=>{if("object"==typeof e&&null!==e)try{return JSON.stringify(e,null,2)}catch(n){return String(e)}return String(e)}).join(" ")}`,"warning")}function _addDebugMessage(e,n="log"){const o={text:`[${(new Date).toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit",fractionalSecondDigits:3})}] ${e}`,type:n};_debugMessages.push(o),_debugMessages.length>20&&_debugMessages.shift(),_debugPanel&&_updateDebugDisplay()}function _setupConsoleOverrides(){window._consoleOverrideSet||(window._consoleOverrideSet=!0,window._originalConsoleError=console.error,window._originalConsoleWarn=console.warn,console.error=function(...e){window._originalConsoleError.apply(console,e),_debugVisible&&debugError(...e)},console.warn=function(...e){window._originalConsoleWarn.apply(console,e),_debugVisible&&debugWarn(...e)})}function _displayEarlyErrors(){window._earlyErrors&&window._earlyErrors.length>0&&(debugError(`🚨 Found ${window._earlyErrors.length} early error(s):`),window._earlyErrors.forEach(e=>{debugError(e.message),e.stack&&debugError("Stack trace:",e.stack)}),window._earlyErrors=[])}function _createDebugPanel(){if(_debugPanel)return;_debugPanel=document.createElement("div"),_debugPanel.id="mobile-debug-panel",_debugPanel.innerHTML='\n <div id="mobile-debug-header">\n <span>Debug</span>\n <button id="mobile-debug-close">×</button>\n </div>\n <div id="mobile-debug-content"></div>\n ';const e=document.createElement("style");e.textContent="\n #mobile-debug-panel {\n position: fixed;\n top: 20px;\n right: 20px;\n width: 350px;\n max-width: calc(100vw - 40px);\n max-height: 400px;\n background: rgba(0, 0, 0, 0.9);\n color: #ffffff;\n font-family: 'Courier New', monospace;\n font-size: 12px;\n border-radius: 8px;\n box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);\n z-index: 10000;\n display: none;\n }\n \n #mobile-debug-header {\n background: rgba(255, 255, 255, 0.1);\n padding: 8px 12px;\n border-bottom: 1px solid rgba(255, 255, 255, 0.2);\n display: flex;\n justify-content: space-between;\n align-items: center;\n border-radius: 8px 8px 0 0;\n }\n \n #mobile-debug-header span {\n font-weight: bold;\n font-size: 13px;\n }\n \n #mobile-debug-close {\n background: none;\n border: none;\n color: #ffffff;\n font-size: 18px;\n cursor: pointer;\n padding: 0;\n width: 20px;\n height: 20px;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n \n #mobile-debug-close:hover {\n background: rgba(255, 255, 255, 0.1);\n border-radius: 4px;\n }\n \n #mobile-debug-content {\n padding: 12px;\n max-height: 340px;\n overflow-y: auto;\n word-wrap: break-word;\n line-height: 1.4;\n }\n \n .debug-message {\n margin-bottom: 4px;\n white-space: pre-wrap;\n }\n \n .debug-message.error {\n color: #ff6b6b;\n background: rgba(255, 107, 107, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ff6b6b;\n }\n \n .debug-message.warning {\n color: #ffd93d;\n background: rgba(255, 217, 61, 0.1);\n padding: 4px;\n border-radius: 3px;\n border-left: 3px solid #ffd93d;\n }\n \n .debug-timestamp {\n color: #888;\n font-size: 10px;\n }\n \n @media (max-width: 480px) {\n #mobile-debug-panel {\n width: calc(100vw - 20px);\n right: 10px;\n top: 10px;\n }\n }\n ",document.head.appendChild(e),document.body.appendChild(_debugPanel),document.getElementById("mobile-debug-close").onclick=hideDebug,_updateDebugDisplay()}function _updateDebugDisplay(){if(!_debugPanel)return;const e=document.getElementById("mobile-debug-content");e&&(e.innerHTML=_debugMessages.map(e=>"string"==typeof e?`<div class="debug-message">${e}</div>`:`<div class="debug-message ${e.type}">${e.text}</div>`).join(""),e.scrollTop=e.scrollHeight)}debug.clear=function(){_debugMessages=[],_debugPanel&&_updateDebugDisplay(),console.clear()},window.debug=debug,window.debugError=debugError,window.debugWarn=debugWarn,window.showDebug=showDebug,window.hideDebug=hideDebug,window.toggleDebug=toggleDebug,window.lockGestures=lockGestures,window.enableGyroTap=enableGyroTap,window.enableGyroButton=enableGyroButton,window.enableMicTap=enableMicTap,window.enableMicButton=enableMicButton,window.enableSoundTap=enableSoundTap,window.enableSoundButton=enableSoundButton,window.enableAllTap=enableAllTap,window.enableAllButton=enableAllButton,"undefined"!=typeof p5&&p5.prototype&&(p5.prototype.lockGestures=lockGestures,p5.prototype.enableGyroTap=enableGyroTap,p5.prototype.enableGyroButton=enableGyroButton,p5.prototype.enableMicTap=enableMicTap,p5.prototype.enableMicButton=enableMicButton,p5.prototype.enableSoundTap=enableSoundTap,p5.prototype.enableSoundButton=enableSoundButton,p5.prototype.enableAllTap=enableAllTap,p5.prototype.enableAllButton=enableAllButton,p5.prototype.showDebug=showDebug,p5.prototype.hideDebug=hideDebug,p5.prototype.toggleDebug=toggleDebug,p5.prototype.debug=debug,p5.prototype.debugError=debugError,p5.prototype.debugWarn=debugWarn,console.log("✅ Mobile p5.js Permissions: p5.prototype functions registered"));
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>P5.js Mobile - Microphone Level</title>
5
+ <script src="https://cdn.jsdelivr.net/npm/p5@1.11.0/lib/p5.min.js"></script>
6
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.0/addons/p5.sound.min.js"></script>
7
+ <script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.min.js"></script>
8
+ <style>
9
+ body {
10
+ margin: 0;
11
+ padding: 0;
12
+ overflow: hidden;
13
+ }
14
+ </style>
15
+ </head>
16
+ <body>
17
+ <script src="sketch.js"></script>
18
+ </body>
19
+ </html>
@@ -0,0 +1,117 @@
1
+ // Microphone level example
2
+ // Demonstrates reading microphone input level with visual feedback
3
+ // Shows text display and full-width bar graph with threshold detection
4
+
5
+ // Global variables - easy to adjust for different use cases
6
+ let mic;
7
+ let micLevel = 0;
8
+ let micMultiplier = 5; // Multiplier to amplify mic sensitivity
9
+ let threshold = 0.3; // Threshold for background color change (0.0 - 1.0)
10
+ let backgroundColor;
11
+ let backgroundColorQuiet;
12
+ let backgroundColorLoud;
13
+
14
+ function setup()
15
+ {
16
+ createCanvas(windowWidth, windowHeight);
17
+
18
+ // Set up colors
19
+ backgroundColorQuiet = color(50, 50, 50); // Dark gray when quiet
20
+ backgroundColorLoud = color(255, 100, 50); // Orange when loud
21
+ backgroundColor = backgroundColorQuiet;
22
+
23
+ // Create microphone input (global variable for library to use)
24
+ mic = new p5.AudioIn();
25
+
26
+ textAlign(CENTER, CENTER);
27
+ textSize(16);
28
+
29
+ // lock Gesturs
30
+ lockGestures();
31
+
32
+ // Request permission for microphone on iOS
33
+ enableMicTap();
34
+ }
35
+
36
+ function draw()
37
+ {
38
+ background(backgroundColor);
39
+
40
+ // Check if microphone is available
41
+ if (window.micEnabled)
42
+ {
43
+ // Get current microphone level (0.0 to 1.0) and apply multiplier
44
+ micLevel = mic.getLevel() * micMultiplier;
45
+
46
+ // Check if level exceeds threshold and change background
47
+ if (micLevel > threshold)
48
+ {
49
+ backgroundColor = backgroundColorLoud;
50
+ }
51
+ else
52
+ {
53
+ backgroundColor = backgroundColorQuiet;
54
+ }
55
+
56
+ // Display microphone level as text
57
+ fill(255);
58
+ text("Microphone Level", width/2, height/6);
59
+
60
+ // Display numeric value with more precision
61
+ text("Level: " + nf(micLevel, 1, 3), width/2, height/6 + 40);
62
+
63
+ // Display threshold value
64
+ fill(150);
65
+ text("Threshold: " + nf(threshold, 1, 2), width/2, height/6 + 70);
66
+
67
+ // Calculate bar height based on mic level
68
+ let barHeight = map(micLevel, 0, 1, 0, height);
69
+
70
+ // Draw full-width bar graph from bottom
71
+ fill(100, 200, 255);
72
+ noStroke();
73
+ rect(0, height - barHeight, width, barHeight);
74
+
75
+ // Draw threshold line
76
+ let thresholdY = height - map(threshold, 0, 1, 0, height);
77
+ stroke(255, 200, 0);
78
+ strokeWeight(2);
79
+ line(0, thresholdY, width, thresholdY);
80
+
81
+ // Label the threshold line
82
+ fill(255, 200, 0);
83
+ noStroke();
84
+ text("Threshold", width/2, thresholdY - 15);
85
+
86
+ // Instructions
87
+ fill(255);
88
+ text("Make noise or speak to see the level change", width/2, height - 60);
89
+ text("When level exceeds threshold, background changes color", width/2, height - 30);
90
+ }
91
+ else
92
+ {
93
+ // Microphone not available or permission not granted
94
+ fill(255, 100, 100);
95
+ text("Microphone not available", width/2, height/2);
96
+ text("On iOS: Tap to request microphone permission", width/2, height/2 + 30);
97
+ text("Check device compatibility", width/2, height/2 + 60);
98
+ }
99
+ }
100
+
101
+ // ==============================================
102
+ // TOUCH EVENT FUNCTIONS
103
+ // ==============================================
104
+
105
+ // This function runs when a new touch begins
106
+ function touchStarted()
107
+ {
108
+ // Touch positions will be updated in draw() function
109
+ return false;
110
+ }
111
+
112
+ // This function runs when a touch ends
113
+ function touchEnded()
114
+ {
115
+ // Touch positions will be updated in draw() function
116
+ return false;
117
+ }
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Basic Orientation - Mobile p5.js</title>
7
+
8
+ <!-- Basic CSS to remove browser defaults and align canvas -->
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow: hidden;
14
+ }
15
+ </style>
16
+
17
+ <!-- Load p5.js library -->
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.js"></script>
19
+
20
+ <!-- Load the mobile p5.js permissions library -->
21
+ <script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.js"></script>
22
+
23
+ </head>
24
+ <body>
25
+ <!-- Load the p5.js sketch -->
26
+ <script src="sketch.js"></script>
27
+ </body>
28
+ </html>
@@ -0,0 +1,123 @@
1
+ // ==============================================
2
+ // BASIC ORIENTATION EXAMPLE
3
+ // ==============================================
4
+ // This example shows the device orientation
5
+ // values for x, y, and z rotation
6
+ //
7
+ // CONCEPTS COVERED:
8
+ // - Device orientation detection
9
+ // - Motion sensor permissions with enableGyroTap
10
+ // - rotationX, rotationY, rotationZ values
11
+ // - Simple display of sensor data
12
+ // - Global variables for sensor values
13
+ // ==============================================
14
+
15
+ // Variables to store orientation data
16
+ let orientationX = 0; // Rotation around X axis (front/back tilt)
17
+ let orientationY = 0; // Rotation around Y axis (left/right tilt)
18
+ let orientationZ = 0; // Rotation around Z axis (device rotation)
19
+
20
+ // ==============================================
21
+ // SETUP FUNCTION - Runs once when page loads
22
+ // ==============================================
23
+ function setup()
24
+ {
25
+ // Create a canvas that fills the entire screen
26
+ createCanvas(windowWidth, windowHeight);
27
+
28
+ // Set to show in Degrees
29
+ angleMode(DEGREES);
30
+
31
+ // Lock mobile gestures to prevent scrolling, zooming, etc.
32
+ lockGestures();
33
+
34
+ // Show debug panel to see what's happening
35
+ //showDebug();
36
+
37
+ // Try button instead of tap (more reliable)
38
+ enableGyroTap('ENABLE MOTION SENSORS', 'Requesting motion sensors...');
39
+
40
+ // Set text properties
41
+ textAlign(CENTER, CENTER);
42
+ textSize(32);
43
+
44
+
45
+ }
46
+
47
+ // ==============================================
48
+ // DRAW FUNCTION - Runs continuously
49
+ // ==============================================
50
+ function draw()
51
+ {
52
+ // Clear the screen
53
+ background(240, 240, 240);
54
+
55
+
56
+
57
+ // Check if sensors are working
58
+ if (window.sensorsEnabled)
59
+ {
60
+ background(200, 255, 200); // Light green when sensors active
61
+
62
+ // Update orientation values from device sensors ONLY when enabled
63
+ orientationX = rotationX;
64
+ orientationY = rotationY;
65
+ orientationZ = rotationZ;
66
+
67
+ // NOTE: You can use constrain() to keep values within a specific range
68
+ // Example: orientationX = constrain(rotationX, -90, 90);
69
+ // This would limit the X rotation to between -90 and 90 degrees
70
+ // Useful for mapping sensor values to specific ranges for animations or controls
71
+ // Learn more: https://p5js.org/reference/p5/constrain/
72
+
73
+ debug('angles',orientationX,orientationY,orientationZ);
74
+
75
+ // Display orientation values
76
+ fill(50, 50, 50); // Dark text
77
+ textAlign(CENTER, CENTER);
78
+
79
+ // Show current orientation values
80
+ textSize(24);
81
+ text("Device Orientation", width/2, height/2 - 100);
82
+
83
+ textSize(20);
84
+ text("X (Tilt Forward/Back): " + orientationX.toFixed(1) + "°", width/2, height/2 - 40);
85
+ text("Y (Tilt Left/Right): " + orientationY.toFixed(1) + "°", width/2, height/2);
86
+ text("Z (Rotation): " + orientationZ.toFixed(1) + "°", width/2, height/2 + 40);
87
+
88
+ // Instructions
89
+ textSize(16);
90
+ fill(100, 100, 100);
91
+ text("Tilt and rotate your device!", width/2, height/2 + 100);
92
+ }
93
+ else
94
+ {
95
+ // Instructions to enable sensors
96
+ fill(50, 50, 50); // Dark text
97
+ textAlign(CENTER, CENTER);
98
+ textSize(28);
99
+ fill(150, 50, 50); // Red text
100
+ text("Motion Sensors Disabled", width/2, height/2 - 40);
101
+
102
+ textSize(20);
103
+ fill(100, 100, 100);
104
+ text("Tap the screen to enable\\nmotion sensors", width/2, height/2 + 20);
105
+ }
106
+ }
107
+
108
+ // ==============================================
109
+ // TOUCH EVENT FUNCTIONS
110
+ // ==============================================
111
+ // Note: Touch events are handled by enableGyroTap for permissions
112
+
113
+ function touchStarted()
114
+ {
115
+ // Permission handling is done by enableGyroTap
116
+ return false;
117
+ }
118
+
119
+ function touchEnded()
120
+ {
121
+ return false;
122
+ }
123
+
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Rotational Velocity - Mobile p5.js</title>
7
+
8
+ <!-- Basic CSS to remove browser defaults and align canvas -->
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow: hidden;
14
+ }
15
+ </style>
16
+
17
+ <!-- Load p5.js library -->
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.js"></script>
19
+
20
+ <!-- Load the mobile p5.js permissions library -->
21
+ <script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.js"></script>
22
+
23
+ </head>
24
+ <body>
25
+ <!-- Load the p5.js sketch -->
26
+ <script src="sketch.js"></script>
27
+ </body>
28
+ </html>
@@ -0,0 +1,144 @@
1
+ // ==============================================
2
+ // ROTATIONAL VELOCITY EXAMPLE
3
+ // ==============================================
4
+ // This example shows the rotational velocity
5
+ // by comparing current rotation with previous rotation
6
+ //
7
+ // CONCEPTS COVERED:
8
+ // - Device rotational velocity detection
9
+ // - Motion sensor permissions with enableGyroTap
10
+ // - rotationX, rotationY, rotationZ values
11
+ // - pRotationX, pRotationY, pRotationZ (previous frame values)
12
+ // - Calculating velocity as change over time
13
+ // - Global variables for velocity values
14
+ // ==============================================
15
+
16
+ // Variables to store current rotation data
17
+ let orientationX = 0; // Current rotation around X axis (front/back tilt)
18
+ let orientationY = 0; // Current rotation around Y axis (left/right tilt)
19
+ let orientationZ = 0; // Current rotation around Z axis (device rotation)
20
+
21
+ // Variables to store rotational velocity
22
+ let velocityX = 0; // Change in X rotation per frame
23
+ let velocityY = 0; // Change in Y rotation per frame
24
+ let velocityZ = 0; // Change in Z rotation per frame
25
+
26
+ // ==============================================
27
+ // SETUP FUNCTION - Runs once when page loads
28
+ // ==============================================
29
+ function setup()
30
+ {
31
+ // Create a canvas that fills the entire screen
32
+ createCanvas(windowWidth, windowHeight);
33
+
34
+ // Lock mobile gestures to prevent scrolling, zooming, etc.
35
+ lockGestures();
36
+
37
+ // Enable motion sensors with tap-to-start
38
+ enableGyroTap('Tap screen to enable motion sensors');
39
+
40
+ // Set text properties
41
+ textAlign(CENTER, CENTER);
42
+ textSize(32);
43
+ }
44
+
45
+ // ==============================================
46
+ // DRAW FUNCTION - Runs continuously
47
+ // ==============================================
48
+ function draw()
49
+ {
50
+ // Clear the screen
51
+ background(240, 240, 240);
52
+
53
+ // Check if sensors are working
54
+ if (window.sensorsEnabled)
55
+ {
56
+ background(200, 255, 200); // Light green when sensors active
57
+
58
+ // Update orientation values from device sensors ONLY when enabled
59
+ orientationX = rotationX;
60
+ orientationY = rotationY;
61
+ orientationZ = rotationZ;
62
+
63
+ // Calculate rotational velocity (change from previous frame)
64
+ // p5.js provides pRotationX, pRotationY, pRotationZ for previous frame values
65
+ velocityX = orientationX - pRotationX;
66
+ velocityY = orientationY - pRotationY;
67
+ velocityZ = orientationZ - pRotationZ;
68
+
69
+ // NOTE: You can use constrain() to keep velocity values within a specific range
70
+ // Example: velocityX = constrain(velocityX, -10, 10);
71
+ // This would limit the X velocity to between -10 and 10 degrees per frame
72
+ // Useful for creating smooth animations or preventing extreme values
73
+ // Learn more: https://p5js.org/reference/p5/constrain/
74
+
75
+ // Display current orientation values
76
+ fill(50, 50, 50); // Dark text
77
+ textAlign(CENTER, CENTER);
78
+
79
+ // Show current orientation title
80
+ textSize(24);
81
+ text("Device Rotational Velocity", width/2, height/2 - 140);
82
+
83
+ // Show current rotation values
84
+ textSize(18);
85
+ fill(80, 80, 80);
86
+ text("Current Rotation:", width/2, height/2 - 100);
87
+
88
+ textSize(16);
89
+ text("X: " + orientationX.toFixed(1) + "°", width/2, height/2 - 80);
90
+ text("Y: " + orientationY.toFixed(1) + "°", width/2, height/2 - 60);
91
+ text("Z: " + orientationZ.toFixed(1) + "°", width/2, height/2 - 40);
92
+
93
+ // Show velocity values (change per frame)
94
+ textSize(18);
95
+ fill(150, 50, 50); // Red text for velocity
96
+ text("Rotational Velocity (°/frame):", width/2, height/2);
97
+
98
+ textSize(16);
99
+ text("X Velocity: " + velocityX.toFixed(2) + "°/frame", width/2, height/2 + 20);
100
+ text("Y Velocity: " + velocityY.toFixed(2) + "°/frame", width/2, height/2 + 40);
101
+ text("Z Velocity: " + velocityZ.toFixed(2) + "°/frame", width/2, height/2 + 60);
102
+
103
+ // Show velocity magnitude (total rotational speed)
104
+ let totalVelocity = sqrt(velocityX * velocityX + velocityY * velocityY + velocityZ * velocityZ);
105
+ textSize(18);
106
+ fill(50, 100, 150); // Blue text for total
107
+ text("Total Velocity: " + totalVelocity.toFixed(2) + "°/frame", width/2, height/2 + 90);
108
+
109
+ // Instructions
110
+ textSize(14);
111
+ fill(100, 100, 100);
112
+ text("Rotate your device quickly to see velocity changes!", width/2, height/2 + 130);
113
+ }
114
+ else
115
+ {
116
+ // Instructions to enable sensors
117
+ fill(50, 50, 50); // Dark text
118
+ textAlign(CENTER, CENTER);
119
+ textSize(28);
120
+ fill(150, 50, 50); // Red text
121
+ text("Motion Sensors Disabled", width/2, height/2 - 40);
122
+
123
+ textSize(20);
124
+ fill(100, 100, 100);
125
+ text("Tap the screen to enable\\nmotion sensors", width/2, height/2 + 20);
126
+ }
127
+ }
128
+
129
+ // ==============================================
130
+ // TOUCH EVENT FUNCTIONS
131
+ // ==============================================
132
+ // Note: Touch events are handled by enableGyroTap for permissions
133
+
134
+ function touchStarted()
135
+ {
136
+ // Permission handling is done by enableGyroTap
137
+ return false;
138
+ }
139
+
140
+ function touchEnded()
141
+ {
142
+ return false;
143
+ }
144
+
@@ -0,0 +1,28 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Basic Velocity - Mobile p5.js</title>
7
+
8
+ <!-- Basic CSS to remove browser defaults and align canvas -->
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow: hidden;
14
+ }
15
+ </style>
16
+
17
+ <!-- Load p5.js library -->
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.js"></script>
19
+
20
+ <!-- Load the mobile p5.js permissions library -->
21
+ <script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.js"></script>
22
+
23
+ </head>
24
+ <body>
25
+ <!-- Load the p5.js sketch -->
26
+ <script src="sketch.js"></script>
27
+ </body>
28
+ </html>
@@ -0,0 +1,87 @@
1
+ // Device acceleration example
2
+ // Demonstrates reading accelerationX, Y, Z values from device motion sensors
3
+ // Acceleration is measured in m/s² (meters per second squared)
4
+
5
+ let backgroundColor;
6
+
7
+ function setup()
8
+ {
9
+ createCanvas(windowWidth, windowHeight);
10
+ backgroundColor = color(50, 50, 50);
11
+ textAlign(CENTER, CENTER);
12
+ textSize(16);
13
+
14
+ // Request permission for motion sensors on iOS
15
+ enableGyroTap();
16
+ }
17
+
18
+ function draw()
19
+ {
20
+ background(backgroundColor);
21
+
22
+ // Check if motion sensors are available
23
+ if (window.sensorsEnabled)
24
+ {
25
+ // Display current acceleration values
26
+ fill(255);
27
+ text("Device Acceleration", width/2, height/6);
28
+
29
+ // Display individual acceleration values
30
+ text("X: " + nf(accelerationX, 1, 2) + " m/s²", width/2, height/6 + 40);
31
+ text("Y: " + nf(accelerationY, 1, 2) + " m/s²", width/2, height/6 + 70);
32
+ text("Z: " + nf(accelerationZ, 1, 2) + " m/s²", width/2, height/6 + 100);
33
+
34
+ // Calculate total acceleration magnitude using 3D distance formula
35
+ let totalAcceleration = sqrt(accelerationX * accelerationX +
36
+ accelerationY * accelerationY +
37
+ accelerationZ * accelerationZ);
38
+
39
+ text("Total: " + nf(totalAcceleration, 1, 2) + " m/s²", width/2, height/6 + 140);
40
+
41
+ // Visual representation using bars
42
+ fill(255, 100, 100); // Red for X
43
+ rect(width/2 - 120, height/2, map(abs(accelerationX), 0, 20, 0, 100), 20);
44
+
45
+ fill(100, 255, 100); // Green for Y
46
+ rect(width/2 - 120, height/2 + 30, map(abs(accelerationY), 0, 20, 0, 100), 20);
47
+
48
+ fill(100, 100, 255); // Blue for Z
49
+ rect(width/2 - 120, height/2 + 60, map(abs(accelerationZ), 0, 20, 0, 100), 20);
50
+
51
+ // Labels for the bars
52
+ fill(255);
53
+ text("X", width/2 - 140, height/2 + 10);
54
+ text("Y", width/2 - 140, height/2 + 40);
55
+ text("Z", width/2 - 140, height/2 + 70);
56
+
57
+ // Instructions
58
+ text("Move your device to see acceleration changes", width/2, height - 60);
59
+ text("Shake, tilt, or move the device in different directions", width/2, height - 30);
60
+ }
61
+ else
62
+ {
63
+ // Motion sensors not available or permission not granted
64
+ fill(255, 100, 100);
65
+ text("Motion sensors not available", width/2, height/2);
66
+ text("On iOS: Tap to request motion permission", width/2, height/2 + 30);
67
+ text("Check device compatibility", width/2, height/2 + 60);
68
+ }
69
+ }
70
+
71
+ // ==============================================
72
+ // TOUCH EVENT FUNCTIONS
73
+ // ==============================================
74
+
75
+ // This function runs when a new touch begins
76
+ function touchStarted()
77
+ {
78
+ // Touch positions will be updated in draw() function
79
+ return false;
80
+ }
81
+
82
+ // This function runs when a touch ends
83
+ function touchEnded()
84
+ {
85
+ // Touch positions will be updated in draw() function
86
+ return false;
87
+ }
@@ -0,0 +1,31 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Dual Audio Playback - Mobile p5.js</title>
7
+
8
+ <!-- Basic CSS to remove browser defaults and align canvas -->
9
+ <style>
10
+ body {
11
+ margin: 0;
12
+ padding: 0;
13
+ overflow: hidden;
14
+ }
15
+ </style>
16
+
17
+ <!-- Load p5.js library -->
18
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/p5.min.js"></script>
19
+
20
+ <!-- Load p5.sound library for audio -->
21
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.11.10/addons/p5.sound.min.js"></script>
22
+
23
+ <!-- Load the mobile p5.js permissions library -->
24
+ <script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.min.js"></script>
25
+
26
+ </head>
27
+ <body>
28
+ <!-- Load the p5.js sketch -->
29
+ <script src="sketch.js"></script>
30
+ </body>
31
+ </html>