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.
- package/LICENSE +21 -0
- package/README.md +509 -0
- package/dist/p5-phone.js +1062 -0
- package/dist/p5-phone.min.js +10 -0
- package/examples/Phone Sensor Examples/microphone/01_mic_level/index.html +19 -0
- package/examples/Phone Sensor Examples/microphone/01_mic_level/sketch.js +117 -0
- package/examples/Phone Sensor Examples/movement/01_orientation_basic/index.html +28 -0
- package/examples/Phone Sensor Examples/movement/01_orientation_basic/sketch.js +123 -0
- package/examples/Phone Sensor Examples/movement/02_rotational_velocity/index.html +28 -0
- package/examples/Phone Sensor Examples/movement/02_rotational_velocity/sketch.js +144 -0
- package/examples/Phone Sensor Examples/movement/03_acceleration/index.html +28 -0
- package/examples/Phone Sensor Examples/movement/03_acceleration/sketch.js +87 -0
- package/examples/Phone Sensor Examples/sound/01_dual_audio/index.html +31 -0
- package/examples/Phone Sensor Examples/sound/01_dual_audio/sketch.js +225 -0
- package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio1.mp3 +0 -0
- package/examples/Phone Sensor Examples/sound/01_dual_audio/tracks/audio2.mp3 +0 -0
- package/examples/Phone Sensor Examples/sound/02_volume_touches/index.html +31 -0
- package/examples/Phone Sensor Examples/sound/02_volume_touches/sketch.js +269 -0
- package/examples/Phone Sensor Examples/sound/02_volume_touches/tracks/audio1.mp3 +0 -0
- package/examples/Phone Sensor Examples/touch/01_touch_basic/index.html +28 -0
- package/examples/Phone Sensor Examples/touch/01_touch_basic/sketch.js +94 -0
- package/examples/Phone Sensor Examples/touch/02_touch_zones/index.html +28 -0
- package/examples/Phone Sensor Examples/touch/02_touch_zones/sketch.js +220 -0
- package/examples/Phone Sensor Examples/touch/03_touch_count/index.html +28 -0
- package/examples/Phone Sensor Examples/touch/03_touch_count/sketch.js +93 -0
- package/examples/Phone Sensor Examples/touch/04_touch_distance/index.html +28 -0
- package/examples/Phone Sensor Examples/touch/04_touch_distance/sketch.js +120 -0
- package/examples/Phone Sensor Examples/touch/05_touch_angle/index.html +28 -0
- package/examples/Phone Sensor Examples/touch/05_touch_angle/sketch.js +117 -0
- package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/index.html +19 -0
- package/examples/Phone Sensor Examples - Minimal/microphone/01_mic_level/sketch.js +72 -0
- package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/movement/01_orientation_basic/sketch.js +51 -0
- package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/movement/02_rotational_velocity/sketch.js +70 -0
- package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/movement/03_acceleration/sketch.js +83 -0
- package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/index.html +19 -0
- package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/sketch.js +96 -0
- package/examples/Phone Sensor Examples - Minimal/sound/01_sound_basic/tracks/audio1.mp3 +0 -0
- package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/index.html +19 -0
- package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/sketch.js +118 -0
- package/examples/Phone Sensor Examples - Minimal/sound/02_sound_amplitude/tracks/audio1.mp3 +0 -0
- package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/touch/01_touch_basic/sketch.js +58 -0
- package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/touch/02_touch_zones/sketch.js +78 -0
- package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/touch/03_touch_count/sketch.js +64 -0
- package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/touch/04_touch_distance/sketch.js +69 -0
- package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/index.html +18 -0
- package/examples/Phone Sensor Examples - Minimal/touch/05_touch_angle/sketch.js +85 -0
- package/examples/Phone and Gif/collision/README.md +31 -0
- Gif/collision/gifs/spaceSuit2.png +0 -0
- package/examples/Phone and Gif/collision/index.html +19 -0
- package/examples/Phone and Gif/collision/sketch.js +226 -0
- Gif/fetch/gifs/corgiswimflip.gif +0 -0
- package/examples/Phone and Gif/fetch/index.html +18 -0
- package/examples/Phone and Gif/fetch/sketch.js +139 -0
- Gif/fly/gifs/comparison.gif +0 -0
- package/examples/Phone and Gif/fly/index.html +18 -0
- package/examples/Phone and Gif/fly/sketch.js +103 -0
- Gif/roll/gifs/how-penciles-are-made.gif +0 -0
- package/examples/Phone and Gif/roll/index.html +18 -0
- package/examples/Phone and Gif/roll/sketch.js +121 -0
- package/examples/UXcompare/button-vs-movement/index.html +45 -0
- package/examples/UXcompare/button-vs-movement/sketch.js +355 -0
- package/examples/UXcompare/button-vs-orientation/index.html +25 -0
- package/examples/UXcompare/button-vs-orientation/sketch.js +317 -0
- package/examples/UXcompare/button-vs-shake/index.html +45 -0
- package/examples/UXcompare/button-vs-shake/sketch.js +320 -0
- package/examples/UXcompare/gyroscope-demo/index.html +78 -0
- package/examples/UXcompare/gyroscope-demo/sketch.js +166 -0
- package/examples/UXcompare/index.html +419 -0
- package/examples/UXcompare/microphone-demo/index.html +79 -0
- package/examples/UXcompare/microphone-demo/sketch.js +210 -0
- package/examples/UXcompare/slider-vs-angle/index.html +25 -0
- package/examples/UXcompare/slider-vs-angle/sketch.js +429 -0
- package/examples/UXcompare/slider-vs-distance/index.html +25 -0
- package/examples/UXcompare/slider-vs-distance/sketch.js +401 -0
- package/examples/UXcompare/slider-vs-microphone/index.html +26 -0
- package/examples/UXcompare/slider-vs-microphone/sketch.js +336 -0
- package/examples/UXcompare/slider-vs-touches/index.html +25 -0
- package/examples/UXcompare/slider-vs-touches/sketch.js +376 -0
- package/examples/UXcompare/sliders-vs-acceleration/index.html +25 -0
- package/examples/UXcompare/sliders-vs-acceleration/sketch.js +361 -0
- package/examples/UXcompare/sliders-vs-rotation/index.html +25 -0
- package/examples/UXcompare/sliders-vs-rotation/sketch.js +375 -0
- package/examples/blankTemplate/index.html +31 -0
- package/examples/blankTemplate/sketch.js +55 -0
- package/examples/homepage/index.html +506 -0
- package/package.json +73 -0
- package/src/p5-phone.js +1062 -0
- package/src/permissionMic.js +240 -0
- package/src/permissionsGesture.js +213 -0
- package/src/permissionsGyro.js +246 -0
|
@@ -0,0 +1,45 @@
|
|
|
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, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
6
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
7
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
8
|
+
<title>Button vs Shake Comparison</title>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
* {
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
-webkit-user-select: none;
|
|
16
|
+
user-select: none;
|
|
17
|
+
-webkit-tap-highlight-color: transparent;
|
|
18
|
+
-webkit-touch-callout: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
html, body {
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
position: fixed;
|
|
26
|
+
touch-action: none;
|
|
27
|
+
background: #000;
|
|
28
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
canvas {
|
|
32
|
+
display: block;
|
|
33
|
+
position: fixed;
|
|
34
|
+
left: 0;
|
|
35
|
+
top: 0;
|
|
36
|
+
}
|
|
37
|
+
</style>
|
|
38
|
+
|
|
39
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
|
|
40
|
+
<script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.min.js"></script>
|
|
41
|
+
</head>
|
|
42
|
+
<body>
|
|
43
|
+
<script src="sketch.js"></script>
|
|
44
|
+
</body>
|
|
45
|
+
</html>
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
// Button vs Shake Comparison
|
|
2
|
+
// Shows traditional button UI vs mobile device shake interaction
|
|
3
|
+
|
|
4
|
+
// Color states
|
|
5
|
+
let isBlueBackground = true; // true = blue, false = orange
|
|
6
|
+
let buttonColor1 = '#3498db'; // Blue
|
|
7
|
+
let buttonColor2 = '#e67e22'; // Orange
|
|
8
|
+
|
|
9
|
+
// Counters
|
|
10
|
+
let buttonClickCount = 0;
|
|
11
|
+
let shakeCount = 0;
|
|
12
|
+
|
|
13
|
+
// Button properties
|
|
14
|
+
let buttonWidth = 200;
|
|
15
|
+
let buttonHeight = 60;
|
|
16
|
+
let buttonX, buttonY;
|
|
17
|
+
|
|
18
|
+
// Slider properties
|
|
19
|
+
let sliderX, sliderY;
|
|
20
|
+
let sliderWidth = 200;
|
|
21
|
+
let sliderHeight = 20;
|
|
22
|
+
let sliderValue = 100; // Default shake threshold (higher = less sensitive)
|
|
23
|
+
let sliderMin = 30;
|
|
24
|
+
let sliderMax = 150;
|
|
25
|
+
let isDraggingSlider = false;
|
|
26
|
+
|
|
27
|
+
// Simple shake debounce
|
|
28
|
+
let lastShakeFrame = 0;
|
|
29
|
+
|
|
30
|
+
// Layout properties
|
|
31
|
+
let topSectionHeight;
|
|
32
|
+
let bottomSectionHeight;
|
|
33
|
+
let dividerY;
|
|
34
|
+
|
|
35
|
+
function setup() {
|
|
36
|
+
createCanvas(windowWidth, windowHeight);
|
|
37
|
+
|
|
38
|
+
// Enable gesture locking and motion sensors
|
|
39
|
+
lockGestures();
|
|
40
|
+
enableGyroTap('Tap to enable shake detection');
|
|
41
|
+
|
|
42
|
+
// Calculate layout for portrait orientation
|
|
43
|
+
topSectionHeight = height * 0.5;
|
|
44
|
+
bottomSectionHeight = height * 0.5;
|
|
45
|
+
dividerY = height * 0.5;
|
|
46
|
+
|
|
47
|
+
// Position button in top section
|
|
48
|
+
buttonX = width / 2 - buttonWidth / 2;
|
|
49
|
+
buttonY = topSectionHeight / 2 - buttonHeight / 2;
|
|
50
|
+
|
|
51
|
+
// Position slider in bottom section
|
|
52
|
+
sliderX = width / 2 - sliderWidth / 2;
|
|
53
|
+
sliderY = height - 120;
|
|
54
|
+
|
|
55
|
+
// Set initial shake threshold (higher value = less sensitive)
|
|
56
|
+
setShakeThreshold(sliderValue);
|
|
57
|
+
|
|
58
|
+
textAlign(CENTER, CENTER);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function draw() {
|
|
62
|
+
// Set background color based on current state
|
|
63
|
+
if (isBlueBackground) {
|
|
64
|
+
background(buttonColor1);
|
|
65
|
+
} else {
|
|
66
|
+
background(buttonColor2);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Draw divider line
|
|
70
|
+
stroke(255, 255, 255, 100);
|
|
71
|
+
strokeWeight(2);
|
|
72
|
+
line(0, dividerY, width, dividerY);
|
|
73
|
+
|
|
74
|
+
// Draw top section - Traditional Button UI
|
|
75
|
+
drawTopSection();
|
|
76
|
+
|
|
77
|
+
// Draw bottom section - Shake Interaction
|
|
78
|
+
drawBottomSection();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function drawTopSection() {
|
|
82
|
+
// Section title
|
|
83
|
+
fill(255);
|
|
84
|
+
textSize(24);
|
|
85
|
+
text('TRADITIONAL UI', width / 2, 40);
|
|
86
|
+
|
|
87
|
+
// Draw button
|
|
88
|
+
drawButton();
|
|
89
|
+
|
|
90
|
+
// Draw counter
|
|
91
|
+
textSize(20);
|
|
92
|
+
text('Button pressed: ' + buttonClickCount + ' times', width / 2, buttonY + buttonHeight + 40);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function drawBottomSection() {
|
|
96
|
+
// Section title
|
|
97
|
+
fill(255);
|
|
98
|
+
textSize(24);
|
|
99
|
+
text('MOBILE INTERACTION', width / 2, dividerY + 40);
|
|
100
|
+
|
|
101
|
+
// Instructions or shake indicator
|
|
102
|
+
textSize(18);
|
|
103
|
+
if (window.sensorsEnabled) {
|
|
104
|
+
text('Shake your device!', width / 2, dividerY + 80);
|
|
105
|
+
} else {
|
|
106
|
+
text('Enable motion sensors first', width / 2, dividerY + 80);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Draw shake visualization
|
|
110
|
+
if (window.sensorsEnabled) {
|
|
111
|
+
drawShakeIndicator();
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Draw shake threshold slider
|
|
115
|
+
drawSlider();
|
|
116
|
+
|
|
117
|
+
// Draw counter
|
|
118
|
+
textSize(20);
|
|
119
|
+
text('Device shaken: ' + shakeCount + ' times', width / 2, height - 30);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function drawButton() {
|
|
123
|
+
// Button shadow
|
|
124
|
+
fill(0, 0, 0, 50);
|
|
125
|
+
noStroke();
|
|
126
|
+
rect(buttonX + 3, buttonY + 3, buttonWidth, buttonHeight, 8);
|
|
127
|
+
|
|
128
|
+
// Button background
|
|
129
|
+
if (isBlueBackground) {
|
|
130
|
+
fill(255, 255, 255, 200);
|
|
131
|
+
} else {
|
|
132
|
+
fill(255, 255, 255, 200);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Check if button is being pressed
|
|
136
|
+
if (isButtonPressed()) {
|
|
137
|
+
fill(255, 255, 255, 255); // Brighter when pressed
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
rect(buttonX, buttonY, buttonWidth, buttonHeight, 8);
|
|
141
|
+
|
|
142
|
+
// Button text
|
|
143
|
+
fill(0);
|
|
144
|
+
textSize(18);
|
|
145
|
+
text('TOGGLE COLOR', width / 2, buttonY + buttonHeight / 2);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function drawShakeIndicator() {
|
|
149
|
+
// Simple shake visualization - concentric circles
|
|
150
|
+
let centerX = width / 2;
|
|
151
|
+
let centerY = dividerY + (bottomSectionHeight / 2) - 20;
|
|
152
|
+
|
|
153
|
+
// Get motion intensity for visualization
|
|
154
|
+
let motionIntensity = 0;
|
|
155
|
+
if (typeof accelerationX !== 'undefined') {
|
|
156
|
+
motionIntensity = abs(accelerationX) + abs(accelerationY) + abs(accelerationZ);
|
|
157
|
+
motionIntensity = constrain(motionIntensity, 0, 10);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Draw concentric circles that respond to motion
|
|
161
|
+
noFill();
|
|
162
|
+
stroke(255, 150);
|
|
163
|
+
strokeWeight(2);
|
|
164
|
+
|
|
165
|
+
for (let i = 1; i <= 3; i++) {
|
|
166
|
+
let radius = 30 + (i * 20) + (motionIntensity * 2);
|
|
167
|
+
circle(centerX, centerY, radius);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Center dot
|
|
171
|
+
fill(255);
|
|
172
|
+
noStroke();
|
|
173
|
+
circle(centerX, centerY, 10);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function drawSlider() {
|
|
177
|
+
// Slider label
|
|
178
|
+
fill(255);
|
|
179
|
+
textSize(16);
|
|
180
|
+
text('Shake Sensitivity: ' + sliderValue, width / 2, sliderY - 25);
|
|
181
|
+
|
|
182
|
+
// Slider track (background)
|
|
183
|
+
fill(255, 255, 255, 100);
|
|
184
|
+
noStroke();
|
|
185
|
+
rect(sliderX, sliderY, sliderWidth, sliderHeight, sliderHeight / 2);
|
|
186
|
+
|
|
187
|
+
// Calculate slider handle position
|
|
188
|
+
let handleX = map(sliderValue, sliderMin, sliderMax, sliderX, sliderX + sliderWidth - 20);
|
|
189
|
+
|
|
190
|
+
// Slider handle
|
|
191
|
+
fill(255);
|
|
192
|
+
if (isDraggingSlider) {
|
|
193
|
+
fill(255, 255, 0); // Yellow when dragging
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Handle shadow
|
|
197
|
+
fill(0, 0, 0, 50);
|
|
198
|
+
circle(handleX + 12, sliderY + sliderHeight / 2 + 2, 24);
|
|
199
|
+
|
|
200
|
+
// Handle
|
|
201
|
+
if (isDraggingSlider) {
|
|
202
|
+
fill(255, 255, 0);
|
|
203
|
+
} else {
|
|
204
|
+
fill(255);
|
|
205
|
+
}
|
|
206
|
+
circle(handleX + 10, sliderY + sliderHeight / 2, 24);
|
|
207
|
+
|
|
208
|
+
// Handle indicator
|
|
209
|
+
fill(0);
|
|
210
|
+
circle(handleX + 10, sliderY + sliderHeight / 2, 8);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function isButtonPressed() {
|
|
214
|
+
return mouseIsPressed &&
|
|
215
|
+
mouseX >= buttonX &&
|
|
216
|
+
mouseX <= buttonX + buttonWidth &&
|
|
217
|
+
mouseY >= buttonY &&
|
|
218
|
+
mouseY <= buttonY + buttonHeight;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function isSliderPressed() {
|
|
222
|
+
let handleX = map(sliderValue, sliderMin, sliderMax, sliderX, sliderX + sliderWidth - 20);
|
|
223
|
+
return mouseX >= handleX &&
|
|
224
|
+
mouseX <= handleX + 20 &&
|
|
225
|
+
mouseY >= sliderY - 10 &&
|
|
226
|
+
mouseY <= sliderY + sliderHeight + 10;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Handle button clicks
|
|
230
|
+
function mousePressed() {
|
|
231
|
+
// Check button press
|
|
232
|
+
if (mouseX >= buttonX &&
|
|
233
|
+
mouseX <= buttonX + buttonWidth &&
|
|
234
|
+
mouseY >= buttonY &&
|
|
235
|
+
mouseY <= buttonY + buttonHeight) {
|
|
236
|
+
|
|
237
|
+
// Toggle background color
|
|
238
|
+
isBlueBackground = !isBlueBackground;
|
|
239
|
+
|
|
240
|
+
// Increment counter
|
|
241
|
+
buttonClickCount++;
|
|
242
|
+
|
|
243
|
+
console.log('Button clicked! Count:', buttonClickCount);
|
|
244
|
+
|
|
245
|
+
return false; // Prevent default
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Check slider press
|
|
249
|
+
if (isSliderPressed()) {
|
|
250
|
+
isDraggingSlider = true;
|
|
251
|
+
updateSliderValue();
|
|
252
|
+
return false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function mouseDragged() {
|
|
257
|
+
if (isDraggingSlider) {
|
|
258
|
+
updateSliderValue();
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function mouseReleased() {
|
|
264
|
+
isDraggingSlider = false;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function updateSliderValue() {
|
|
268
|
+
// Calculate new slider value based on mouse position
|
|
269
|
+
let newValue = map(mouseX, sliderX, sliderX + sliderWidth, sliderMin, sliderMax);
|
|
270
|
+
newValue = constrain(newValue, sliderMin, sliderMax);
|
|
271
|
+
sliderValue = round(newValue);
|
|
272
|
+
|
|
273
|
+
// Update shake threshold
|
|
274
|
+
setShakeThreshold(sliderValue);
|
|
275
|
+
|
|
276
|
+
console.log('Shake threshold set to:', sliderValue);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Handle device shake (built-in p5.js function)
|
|
280
|
+
function deviceShaken() {
|
|
281
|
+
// Only respond if motion sensors are enabled
|
|
282
|
+
if (window.sensorsEnabled) {
|
|
283
|
+
// Simple debounce - ignore if shake happened in last 10 frames (about 1/6 second)
|
|
284
|
+
if (frameCount - lastShakeFrame > 10) {
|
|
285
|
+
// Toggle background color
|
|
286
|
+
isBlueBackground = !isBlueBackground;
|
|
287
|
+
|
|
288
|
+
// Increment counter
|
|
289
|
+
shakeCount++;
|
|
290
|
+
|
|
291
|
+
// Update last shake frame
|
|
292
|
+
lastShakeFrame = frameCount;
|
|
293
|
+
|
|
294
|
+
console.log('Device shaken! Count:', shakeCount);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Handle screen rotation
|
|
300
|
+
function windowResized() {
|
|
301
|
+
resizeCanvas(windowWidth, windowHeight);
|
|
302
|
+
|
|
303
|
+
// Recalculate layout
|
|
304
|
+
topSectionHeight = height * 0.5;
|
|
305
|
+
bottomSectionHeight = height * 0.5;
|
|
306
|
+
dividerY = height * 0.5;
|
|
307
|
+
|
|
308
|
+
// Reposition button
|
|
309
|
+
buttonX = width / 2 - buttonWidth / 2;
|
|
310
|
+
buttonY = topSectionHeight / 2 - buttonHeight / 2;
|
|
311
|
+
|
|
312
|
+
// Reposition slider
|
|
313
|
+
sliderX = width / 2 - sliderWidth / 2;
|
|
314
|
+
sliderY = height - 120;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Called when permissions are ready
|
|
318
|
+
function userSetupComplete() {
|
|
319
|
+
console.log('Motion sensors enabled! You can now shake the device.');
|
|
320
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
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, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
|
|
6
|
+
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
7
|
+
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
8
|
+
<title>Tilt Ball Game</title>
|
|
9
|
+
|
|
10
|
+
<style>
|
|
11
|
+
* {
|
|
12
|
+
margin: 0;
|
|
13
|
+
padding: 0;
|
|
14
|
+
box-sizing: border-box;
|
|
15
|
+
-webkit-user-select: none;
|
|
16
|
+
user-select: none;
|
|
17
|
+
-webkit-tap-highlight-color: transparent;
|
|
18
|
+
-webkit-touch-callout: none;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
html, body {
|
|
22
|
+
width: 100%;
|
|
23
|
+
height: 100%;
|
|
24
|
+
overflow: hidden;
|
|
25
|
+
position: fixed;
|
|
26
|
+
touch-action: none;
|
|
27
|
+
background: #000;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
canvas {
|
|
31
|
+
display: block;
|
|
32
|
+
position: fixed;
|
|
33
|
+
left: 0;
|
|
34
|
+
top: 0;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
#startButton {
|
|
38
|
+
position: fixed;
|
|
39
|
+
top: 50%;
|
|
40
|
+
left: 50%;
|
|
41
|
+
transform: translate(-50%, -50%);
|
|
42
|
+
padding: 40px 60px;
|
|
43
|
+
font-size: 24px;
|
|
44
|
+
font-weight: bold;
|
|
45
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
46
|
+
color: white;
|
|
47
|
+
border: none;
|
|
48
|
+
border-radius: 20px;
|
|
49
|
+
cursor: pointer;
|
|
50
|
+
z-index: 10000;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
#statusText {
|
|
54
|
+
position: fixed;
|
|
55
|
+
top: 60%;
|
|
56
|
+
left: 50%;
|
|
57
|
+
transform: translate(-50%, 0);
|
|
58
|
+
color: white;
|
|
59
|
+
font-family: Arial, sans-serif;
|
|
60
|
+
text-align: center;
|
|
61
|
+
z-index: 9999;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.hidden {
|
|
65
|
+
display: none;
|
|
66
|
+
}
|
|
67
|
+
</style>
|
|
68
|
+
|
|
69
|
+
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.min.js"></script>
|
|
70
|
+
<script src="https://cdn.jsdelivr.net/npm/mobile-p5-permissions@1.4.4/dist/p5.mobile-permissions.min.js"></script>
|
|
71
|
+
</head>
|
|
72
|
+
<body>
|
|
73
|
+
<button id="startButton">START GAME</button>
|
|
74
|
+
<div id="statusText" class="hidden">Requesting motion sensors...</div>
|
|
75
|
+
|
|
76
|
+
<script src="sketch.js"></script>
|
|
77
|
+
</body>
|
|
78
|
+
</html>
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// Tilt Ball Game
|
|
2
|
+
// Demonstrates gyroscope and accelerometer input
|
|
3
|
+
|
|
4
|
+
let ball;
|
|
5
|
+
let targets = [];
|
|
6
|
+
let score = 0;
|
|
7
|
+
let gameStarted = false;
|
|
8
|
+
|
|
9
|
+
function setup() {
|
|
10
|
+
createCanvas(windowWidth, windowHeight);
|
|
11
|
+
|
|
12
|
+
// Initialize ball
|
|
13
|
+
ball = {
|
|
14
|
+
x: width / 2,
|
|
15
|
+
y: height / 2,
|
|
16
|
+
vx: 0,
|
|
17
|
+
vy: 0,
|
|
18
|
+
size: 30
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Create initial targets
|
|
22
|
+
createTargets();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function draw() {
|
|
26
|
+
background(20, 30, 50);
|
|
27
|
+
|
|
28
|
+
if (window.sensorsEnabled) {
|
|
29
|
+
gameStarted = true;
|
|
30
|
+
updateGame();
|
|
31
|
+
} else {
|
|
32
|
+
showWaitingScreen();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function updateGame() {
|
|
37
|
+
// Apply tilt forces to ball
|
|
38
|
+
let tiltX = rotationY || 0;
|
|
39
|
+
let tiltY = rotationX || 0;
|
|
40
|
+
|
|
41
|
+
// Scale the tilt input
|
|
42
|
+
ball.vx += tiltX * 0.3;
|
|
43
|
+
ball.vy += tiltY * 0.3;
|
|
44
|
+
|
|
45
|
+
// Apply friction
|
|
46
|
+
ball.vx *= 0.95;
|
|
47
|
+
ball.vy *= 0.95;
|
|
48
|
+
|
|
49
|
+
// Update ball position
|
|
50
|
+
ball.x += ball.vx;
|
|
51
|
+
ball.y += ball.vy;
|
|
52
|
+
|
|
53
|
+
// Bounce off walls
|
|
54
|
+
if (ball.x < ball.size/2 || ball.x > width - ball.size/2) {
|
|
55
|
+
ball.vx *= -0.8;
|
|
56
|
+
ball.x = constrain(ball.x, ball.size/2, width - ball.size/2);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (ball.y < ball.size/2 || ball.y > height - ball.size/2) {
|
|
60
|
+
ball.vy *= -0.8;
|
|
61
|
+
ball.y = constrain(ball.y, ball.size/2, height - ball.size/2);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Draw targets
|
|
65
|
+
for (let i = targets.length - 1; i >= 0; i--) {
|
|
66
|
+
let target = targets[i];
|
|
67
|
+
|
|
68
|
+
// Animate target
|
|
69
|
+
target.pulse += 0.1;
|
|
70
|
+
let pulseSize = target.size + sin(target.pulse) * 5;
|
|
71
|
+
|
|
72
|
+
fill(target.color[0], target.color[1], target.color[2], 150);
|
|
73
|
+
circle(target.x, target.y, pulseSize);
|
|
74
|
+
|
|
75
|
+
// Check collision with ball
|
|
76
|
+
let distance = dist(ball.x, ball.y, target.x, target.y);
|
|
77
|
+
if (distance < (ball.size + target.size) / 2) {
|
|
78
|
+
// Target hit!
|
|
79
|
+
score++;
|
|
80
|
+
targets.splice(i, 1);
|
|
81
|
+
|
|
82
|
+
// Create new target
|
|
83
|
+
if (targets.length < 3) {
|
|
84
|
+
createTarget();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Draw ball
|
|
90
|
+
fill(255, 200, 100);
|
|
91
|
+
stroke(255, 255, 150);
|
|
92
|
+
strokeWeight(2);
|
|
93
|
+
circle(ball.x, ball.y, ball.size);
|
|
94
|
+
|
|
95
|
+
// Draw trail
|
|
96
|
+
fill(255, 200, 100, 50);
|
|
97
|
+
noStroke();
|
|
98
|
+
circle(ball.x - ball.vx * 2, ball.y - ball.vy * 2, ball.size * 0.8);
|
|
99
|
+
circle(ball.x - ball.vx * 4, ball.y - ball.vy * 4, ball.size * 0.6);
|
|
100
|
+
|
|
101
|
+
// Draw UI
|
|
102
|
+
drawUI();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function createTargets() {
|
|
106
|
+
targets = [];
|
|
107
|
+
for (let i = 0; i < 3; i++) {
|
|
108
|
+
createTarget();
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function createTarget() {
|
|
113
|
+
let target = {
|
|
114
|
+
x: random(50, width - 50),
|
|
115
|
+
y: random(50, height - 50),
|
|
116
|
+
size: random(40, 80),
|
|
117
|
+
color: [random(100, 255), random(100, 255), random(100, 255)],
|
|
118
|
+
pulse: random(TWO_PI)
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// Make sure target isn't too close to ball
|
|
122
|
+
while (dist(target.x, target.y, ball.x, ball.y) < 100) {
|
|
123
|
+
target.x = random(50, width - 50);
|
|
124
|
+
target.y = random(50, height - 50);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
targets.push(target);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function drawUI() {
|
|
131
|
+
// Score
|
|
132
|
+
fill(255);
|
|
133
|
+
textAlign(LEFT, TOP);
|
|
134
|
+
textSize(24);
|
|
135
|
+
text("Score: " + score, 20, 20);
|
|
136
|
+
|
|
137
|
+
// Instructions
|
|
138
|
+
textAlign(CENTER, BOTTOM);
|
|
139
|
+
textSize(14);
|
|
140
|
+
text("Tilt your device to move the ball", width/2, height - 20);
|
|
141
|
+
|
|
142
|
+
// Tilt indicator
|
|
143
|
+
if (window.sensorsEnabled) {
|
|
144
|
+
textAlign(RIGHT, TOP);
|
|
145
|
+
textSize(12);
|
|
146
|
+
text("Tilt X: " + (rotationY || 0).toFixed(1), width - 20, 20);
|
|
147
|
+
text("Tilt Y: " + (rotationX || 0).toFixed(1), width - 20, 40);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function showWaitingScreen() {
|
|
152
|
+
fill(255, 150);
|
|
153
|
+
textAlign(CENTER, CENTER);
|
|
154
|
+
textSize(24);
|
|
155
|
+
text("Waiting for motion sensors...", width/2, height/2);
|
|
156
|
+
textSize(16);
|
|
157
|
+
text("Make sure to allow permissions!", width/2, height/2 + 40);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function windowResized() {
|
|
161
|
+
resizeCanvas(windowWidth, windowHeight);
|
|
162
|
+
|
|
163
|
+
// Keep ball in bounds
|
|
164
|
+
ball.x = constrain(ball.x, ball.size/2, width - ball.size/2);
|
|
165
|
+
ball.y = constrain(ball.y, ball.size/2, height - ball.size/2);
|
|
166
|
+
}
|