Add 2 files
Browse files- index.html +209 -498
- prompts.txt +2 -1
index.html
CHANGED
|
@@ -2,536 +2,247 @@
|
|
| 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>Somatic
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
|
| 8 |
<style>
|
| 9 |
-
|
| 10 |
-
* {
|
| 11 |
-
-webkit-tap-highlight-color: transparent;
|
| 12 |
-
-webkit-touch-callout: none;
|
| 13 |
-
-webkit-user-select: none;
|
| 14 |
-
user-select: none;
|
| 15 |
-
}
|
| 16 |
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
border-radius: 15px;
|
| 21 |
-
color: #e2e8f0;
|
| 22 |
-
}
|
| 23 |
-
.neumorphic-dark-inset {
|
| 24 |
-
background-color: #2d3748;
|
| 25 |
-
box-shadow: inset 5px 5px 10px #1a202c, inset -5px -5px 10px #404958;
|
| 26 |
-
border-radius: 15px;
|
| 27 |
-
}
|
| 28 |
-
.neumorphic-button {
|
| 29 |
-
background-color: #2d3748;
|
| 30 |
-
box-shadow: 5px 5px 10px #1a202c, -5px -5px 10px #404958;
|
| 31 |
-
border-radius: 10px;
|
| 32 |
-
transition: all 0.2s ease;
|
| 33 |
}
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
.game-container {
|
| 38 |
-
position: relative;
|
| 39 |
-
width: 100%;
|
| 40 |
-
height: 60vh;
|
| 41 |
-
min-height: 300px;
|
| 42 |
-
overflow: hidden;
|
| 43 |
-
border-radius: 15px;
|
| 44 |
-
touch-action: none;
|
| 45 |
-
}
|
| 46 |
-
#gameCanvas {
|
| 47 |
-
background-color: #1a202c;
|
| 48 |
-
width: 100%;
|
| 49 |
-
height: 100%;
|
| 50 |
-
display: block;
|
| 51 |
}
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
border-radius: 50%;
|
| 58 |
-
box-shadow: 0 0 20px rgba(0, 0, 0, 0.2);
|
| 59 |
-
display: flex;
|
| 60 |
-
justify-content: center;
|
| 61 |
-
align-items: center;
|
| 62 |
-
z-index: 10;
|
| 63 |
-
touch-action: none;
|
| 64 |
}
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
background: #4a5568;
|
| 69 |
-
border-radius: 50%;
|
| 70 |
-
box-shadow: inset 3px 3px 5px rgba(0, 0, 0, 0.2);
|
| 71 |
}
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
background-color: #1a202c;
|
| 76 |
-
border-radius: 5px;
|
| 77 |
-
overflow: hidden;
|
| 78 |
}
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
transition:
|
| 83 |
}
|
| 84 |
-
|
| 85 |
-
|
| 86 |
-
|
| 87 |
-
top: 0;
|
| 88 |
-
left: 0;
|
| 89 |
-
right: 0;
|
| 90 |
-
bottom: 0;
|
| 91 |
-
background-color: rgba(0, 0, 0, 0.9);
|
| 92 |
-
color: white;
|
| 93 |
-
z-index: 100;
|
| 94 |
-
flex-direction: column;
|
| 95 |
-
justify-content: center;
|
| 96 |
-
align-items: center;
|
| 97 |
-
padding: 20px;
|
| 98 |
-
text-align: center;
|
| 99 |
}
|
| 100 |
-
|
| 101 |
-
|
| 102 |
-
|
| 103 |
-
|
| 104 |
-
}
|
| 105 |
-
.joystick-knob {
|
| 106 |
-
width: 35px;
|
| 107 |
-
height: 35px;
|
| 108 |
-
}
|
| 109 |
}
|
| 110 |
</style>
|
| 111 |
</head>
|
| 112 |
-
<body class="
|
| 113 |
-
<div class="
|
| 114 |
-
<
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
|
| 122 |
-
|
| 123 |
-
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
|
| 128 |
-
<div class="h-12 w-12 mr-4 flex items-center justify-center bg-purple-500 rounded-lg">
|
| 129 |
-
<svg xmlns="http://www.w3.org/2000/svg" class="h-8 w-8 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
| 130 |
-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
| 131 |
-
</svg>
|
| 132 |
</div>
|
| 133 |
-
<h1 class="text-2xl font-bold text-gray-200">Somatic Ghost Catcher</h1>
|
| 134 |
</div>
|
| 135 |
-
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
</div>
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 144 |
</div>
|
| 145 |
-
|
| 146 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 147 |
</div>
|
| 148 |
-
|
| 149 |
-
|
| 150 |
-
|
| 151 |
-
|
| 152 |
-
|
| 153 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 154 |
</div>
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
<div class="
|
| 160 |
-
<
|
| 161 |
-
|
| 162 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 163 |
</div>
|
| 164 |
-
|
| 165 |
-
|
| 166 |
-
|
| 167 |
-
|
| 168 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
</div>
|
| 170 |
</div>
|
| 171 |
</div>
|
| 172 |
</div>
|
| 173 |
-
|
| 174 |
-
<
|
| 175 |
-
|
| 176 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 177 |
</button>
|
| 178 |
</div>
|
| 179 |
</div>
|
| 180 |
|
| 181 |
<script>
|
| 182 |
-
//
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
|
| 205 |
-
|
| 206 |
-
|
| 207 |
-
|
| 208 |
-
|
| 209 |
-
|
| 210 |
-
// Initialize game
|
| 211 |
-
function initGame() {
|
| 212 |
-
canvas = document.getElementById('gameCanvas');
|
| 213 |
-
ctx = canvas.getContext('2d');
|
| 214 |
-
|
| 215 |
-
// Set canvas dimensions
|
| 216 |
-
resizeCanvas();
|
| 217 |
-
window.addEventListener('resize', resizeCanvas);
|
| 218 |
-
|
| 219 |
-
// Initialize positions
|
| 220 |
-
resetGame();
|
| 221 |
-
|
| 222 |
-
// Event listeners
|
| 223 |
-
startBtn.addEventListener('click', startGame);
|
| 224 |
-
|
| 225 |
-
// Joystick controls for desktop/touch
|
| 226 |
-
setupJoystick();
|
| 227 |
-
|
| 228 |
-
// Check for device orientation support
|
| 229 |
-
if (window.DeviceOrientationEvent) {
|
| 230 |
-
// iOS 13+ requires permission
|
| 231 |
-
if (typeof DeviceOrientationEvent.requestPermission === 'function') {
|
| 232 |
-
orientationWarning.style.display = 'flex';
|
| 233 |
-
requestPermissionBtn.addEventListener('click', requestOrientationPermission);
|
| 234 |
-
|
| 235 |
-
// Also allow clicking anywhere to request permission (iOS quirk)
|
| 236 |
-
document.addEventListener('click', requestOrientationPermission, { once: true });
|
| 237 |
-
} else {
|
| 238 |
-
// Other browsers that don't require permission
|
| 239 |
-
window.addEventListener('deviceorientation', handleOrientation);
|
| 240 |
-
hasPermission = true;
|
| 241 |
-
}
|
| 242 |
} else {
|
| 243 |
-
|
| 244 |
-
|
| 245 |
-
requestPermissionBtn.style.display = 'none';
|
| 246 |
-
orientationWarning.style.display = 'flex';
|
| 247 |
-
}
|
| 248 |
-
}
|
| 249 |
-
|
| 250 |
-
// Request permission for device orientation (iOS 13+)
|
| 251 |
-
async function requestOrientationPermission() {
|
| 252 |
-
try {
|
| 253 |
-
const permissionState = await DeviceOrientationEvent.requestPermission();
|
| 254 |
-
if (permissionState === 'granted') {
|
| 255 |
-
window.addEventListener('deviceorientation', handleOrientation);
|
| 256 |
-
hasPermission = true;
|
| 257 |
-
orientationWarning.style.display = 'none';
|
| 258 |
-
startGame();
|
| 259 |
-
} else {
|
| 260 |
-
orientationWarning.querySelector('p').textContent = 'Permission was denied. You can still play with the virtual joystick.';
|
| 261 |
-
requestPermissionBtn.style.display = 'none';
|
| 262 |
-
}
|
| 263 |
-
} catch (error) {
|
| 264 |
-
console.error('Error requesting permission:', error);
|
| 265 |
-
orientationWarning.querySelector('p').textContent = 'Error requesting permission. You can still play with the virtual joystick.';
|
| 266 |
-
requestPermissionBtn.style.display = 'none';
|
| 267 |
}
|
| 268 |
}
|
| 269 |
-
|
| 270 |
-
//
|
| 271 |
-
|
| 272 |
-
|
| 273 |
-
|
| 274 |
-
|
| 275 |
-
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
|
| 283 |
-
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
| 287 |
-
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
// Center player
|
| 291 |
-
player.x = canvas.width / 2;
|
| 292 |
-
player.y = canvas.height / 2;
|
| 293 |
-
|
| 294 |
-
// Place ghost randomly
|
| 295 |
-
placeGhost();
|
| 296 |
-
|
| 297 |
-
// Set initial ghost color
|
| 298 |
-
currentGhostColor = ghostColors[level - 1];
|
| 299 |
-
}
|
| 300 |
-
|
| 301 |
-
// Place ghost at random position
|
| 302 |
-
function placeGhost() {
|
| 303 |
-
const margin = 50;
|
| 304 |
-
ghost.x = margin + Math.random() * (canvas.width - 2 * margin);
|
| 305 |
-
ghost.y = margin + Math.random() * (canvas.height - 2 * margin);
|
| 306 |
-
|
| 307 |
-
// Random direction
|
| 308 |
-
const angle = Math.random() * Math.PI * 2;
|
| 309 |
-
ghost.dx = Math.cos(angle) * ghost.speed;
|
| 310 |
-
ghost.dy = Math.sin(angle) * ghost.speed;
|
| 311 |
-
|
| 312 |
-
currentGhostColor = ghostColors[level - 1];
|
| 313 |
-
}
|
| 314 |
-
|
| 315 |
-
// Start the game
|
| 316 |
-
function startGame() {
|
| 317 |
-
if (gameRunning) {
|
| 318 |
-
// If game is already running, reset it
|
| 319 |
-
cancelAnimationFrame(animationFrameId);
|
| 320 |
-
gameRunning = false;
|
| 321 |
-
resetGame();
|
| 322 |
-
}
|
| 323 |
-
|
| 324 |
-
gameRunning = true;
|
| 325 |
-
startBtn.textContent = 'Restart Game';
|
| 326 |
-
lastUpdateTime = performance.now();
|
| 327 |
-
|
| 328 |
-
// Start game loop
|
| 329 |
-
gameLoop();
|
| 330 |
-
}
|
| 331 |
-
|
| 332 |
-
// Game loop
|
| 333 |
-
function gameLoop(timestamp) {
|
| 334 |
-
if (!gameRunning) return;
|
| 335 |
-
|
| 336 |
-
animationFrameId = requestAnimationFrame(gameLoop);
|
| 337 |
-
|
| 338 |
-
// Calculate delta time for smooth movement
|
| 339 |
-
const deltaTime = timestamp - lastUpdateTime;
|
| 340 |
-
lastUpdateTime = timestamp;
|
| 341 |
-
|
| 342 |
-
// Clear canvas
|
| 343 |
-
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
| 344 |
-
|
| 345 |
-
// Update game state
|
| 346 |
-
updateGame(deltaTime);
|
| 347 |
-
|
| 348 |
-
// Draw game elements
|
| 349 |
-
drawGame();
|
| 350 |
-
}
|
| 351 |
-
|
| 352 |
-
// Update game state
|
| 353 |
-
function updateGame(deltaTime) {
|
| 354 |
-
// Normalize delta time to 60fps reference
|
| 355 |
-
const timeFactor = deltaTime / (1000 / 60);
|
| 356 |
-
|
| 357 |
-
// Move ghost
|
| 358 |
-
ghost.x += ghost.dx * timeFactor;
|
| 359 |
-
ghost.y += ghost.dy * timeFactor;
|
| 360 |
-
|
| 361 |
-
// Bounce ghost off walls
|
| 362 |
-
if (ghost.x < ghost.size / 2 || ghost.x > canvas.width - ghost.size / 2) {
|
| 363 |
-
ghost.dx *= -1;
|
| 364 |
-
}
|
| 365 |
-
if (ghost.y < ghost.size / 2 || ghost.y > canvas.height - ghost.size / 2) {
|
| 366 |
-
ghost.dy *= -1;
|
| 367 |
-
}
|
| 368 |
-
|
| 369 |
-
// Move player based on joystick or device tilt
|
| 370 |
-
const moveSpeed = 4 * timeFactor;
|
| 371 |
-
|
| 372 |
-
// Use joystick if active, otherwise use device tilt if permission granted
|
| 373 |
-
if (joystickActive) {
|
| 374 |
-
player.x += joystickVector.x * moveSpeed;
|
| 375 |
-
player.y += joystickVector.y * moveSpeed;
|
| 376 |
-
} else if (hasPermission) {
|
| 377 |
-
// Map device tilt to movement (gamma for x, beta for y)
|
| 378 |
-
const tiltX = deviceOrientation.gamma / 30; // Normalize
|
| 379 |
-
const tiltY = deviceOrientation.beta / 30; // Normalize
|
| 380 |
-
|
| 381 |
-
player.x += tiltX * moveSpeed;
|
| 382 |
-
player.y += tiltY * moveSpeed;
|
| 383 |
-
|
| 384 |
-
// Update tilt display
|
| 385 |
-
tiltInfo.textContent = `X: ${Math.round(deviceOrientation.gamma)}°\nY: ${Math.round(deviceOrientation.beta)}°`;
|
| 386 |
-
}
|
| 387 |
-
|
| 388 |
-
// Keep player within bounds
|
| 389 |
-
player.x = Math.max(player.size / 2, Math.min(canvas.width - player.size / 2, player.x));
|
| 390 |
-
player.y = Math.max(player.size / 2, Math.min(canvas.height - player.size / 2, player.y));
|
| 391 |
-
|
| 392 |
-
// Check collision with ghost
|
| 393 |
-
const dx = player.x - ghost.x;
|
| 394 |
-
const dy = player.y - ghost.y;
|
| 395 |
-
const distance = Math.sqrt(dx * dx + dy * dy);
|
| 396 |
-
|
| 397 |
-
// Update distance display
|
| 398 |
-
distanceInfo.textContent = `${Math.round(distance)} units`;
|
| 399 |
-
|
| 400 |
-
if (distance < (player.size + ghost.size) / 2) {
|
| 401 |
-
// Caught the ghost!
|
| 402 |
-
score += 10;
|
| 403 |
-
|
| 404 |
-
// Level up every 50 points
|
| 405 |
-
if (score % 50 === 0) {
|
| 406 |
-
level++;
|
| 407 |
-
ghost.speed += 0.5;
|
| 408 |
-
levelDisplay.textContent = level;
|
| 409 |
-
currentGhostColor = ghostColors[Math.min(level - 1, ghostColors.length - 1)];
|
| 410 |
-
}
|
| 411 |
-
|
| 412 |
-
updateUI();
|
| 413 |
-
placeGhost();
|
| 414 |
-
}
|
| 415 |
-
}
|
| 416 |
-
|
| 417 |
-
// Draw game elements
|
| 418 |
-
function drawGame() {
|
| 419 |
-
// Draw player
|
| 420 |
-
ctx.fillStyle = '#E2E8F0';
|
| 421 |
-
ctx.beginPath();
|
| 422 |
-
ctx.arc(player.x, player.y, player.size / 2, 0, Math.PI * 2);
|
| 423 |
-
ctx.fill();
|
| 424 |
-
|
| 425 |
-
// Draw ghost
|
| 426 |
-
ctx.fillStyle = currentGhostColor;
|
| 427 |
-
ctx.beginPath();
|
| 428 |
-
ctx.arc(ghost.x, ghost.y, ghost.size / 2, 0, Math.PI * 2);
|
| 429 |
-
ctx.fill();
|
| 430 |
-
|
| 431 |
-
// Draw glow around ghost
|
| 432 |
-
const gradient = ctx.createRadialGradient(
|
| 433 |
-
ghost.x, ghost.y, ghost.size / 2,
|
| 434 |
-
ghost.x, ghost.y, ghost.size
|
| 435 |
-
);
|
| 436 |
-
gradient.addColorStop(0, currentGhostColor);
|
| 437 |
-
gradient.addColorStop(1, 'transparent');
|
| 438 |
-
|
| 439 |
-
ctx.fillStyle = gradient;
|
| 440 |
-
ctx.beginPath();
|
| 441 |
-
ctx.arc(ghost.x, ghost.y, ghost.size, 0, Math.PI * 2);
|
| 442 |
-
ctx.fill();
|
| 443 |
-
}
|
| 444 |
-
|
| 445 |
-
// Update UI elements
|
| 446 |
-
function updateUI() {
|
| 447 |
-
scoreDisplay.textContent = `${score}%`;
|
| 448 |
-
progressBar.style.width = `${Math.min(score, 100)}%`;
|
| 449 |
-
}
|
| 450 |
-
|
| 451 |
-
// Handle device orientation
|
| 452 |
-
function handleOrientation(event) {
|
| 453 |
-
deviceOrientation.beta = event.beta; // Front-to-back tilt (y-axis)
|
| 454 |
-
deviceOrientation.gamma = event.gamma; // Left-to-right tilt (x-axis)
|
| 455 |
-
}
|
| 456 |
-
|
| 457 |
-
// Setup virtual joystick
|
| 458 |
-
function setupJoystick() {
|
| 459 |
-
let joystickStartX, joystickStartY;
|
| 460 |
-
let joystickCenterX, joystickCenterY;
|
| 461 |
-
|
| 462 |
-
joystick.addEventListener('touchstart', handleJoystickStart);
|
| 463 |
-
joystick.addEventListener('mousedown', handleJoystickStart);
|
| 464 |
-
|
| 465 |
-
document.addEventListener('touchmove', handleJoystickMove);
|
| 466 |
-
document.addEventListener('mousemove', handleJoystickMove);
|
| 467 |
-
|
| 468 |
-
document.addEventListener('touchend', handleJoystickEnd);
|
| 469 |
-
document.addEventListener('mouseup', handleJoystickEnd);
|
| 470 |
-
|
| 471 |
-
function handleJoystickStart(e) {
|
| 472 |
-
e.preventDefault();
|
| 473 |
-
joystickActive = true;
|
| 474 |
-
|
| 475 |
-
const rect = joystick.getBoundingClientRect();
|
| 476 |
-
joystickCenterX = rect.left + rect.width / 2;
|
| 477 |
-
joystickCenterY = rect.top + rect.height / 2;
|
| 478 |
-
|
| 479 |
-
if (e.type === 'mousedown') {
|
| 480 |
-
joystickStartX = e.clientX;
|
| 481 |
-
joystickStartY = e.clientY;
|
| 482 |
-
} else if (e.touches) {
|
| 483 |
-
joystickStartX = e.touches[0].clientX;
|
| 484 |
-
joystickStartY = e.touches[0].clientY;
|
| 485 |
-
}
|
| 486 |
-
}
|
| 487 |
-
|
| 488 |
-
function handleJoystickMove(e) {
|
| 489 |
-
if (!joystickActive) return;
|
| 490 |
-
e.preventDefault();
|
| 491 |
-
|
| 492 |
-
let clientX, clientY;
|
| 493 |
-
|
| 494 |
-
if (e.type === 'mousemove') {
|
| 495 |
-
clientX = e.clientX;
|
| 496 |
-
clientY = e.clientY;
|
| 497 |
-
} else if (e.touches) {
|
| 498 |
-
clientX = e.touches[0].clientX;
|
| 499 |
-
clientY = e.touches[0].clientY;
|
| 500 |
-
}
|
| 501 |
-
|
| 502 |
-
const dx = clientX - joystickStartX;
|
| 503 |
-
const dy = clientY - joystickStartY;
|
| 504 |
-
const distance = Math.sqrt(dx * dx + dy * dy);
|
| 505 |
-
const maxDistance = 40;
|
| 506 |
-
|
| 507 |
-
// Calculate joystick vector (normalized)
|
| 508 |
-
if (distance > maxDistance) {
|
| 509 |
-
joystickVector.x = dx / distance;
|
| 510 |
-
joystickVector.y = dy / distance;
|
| 511 |
-
} else {
|
| 512 |
-
joystickVector.x = dx / maxDistance;
|
| 513 |
-
joystickVector.y = dy / maxDistance;
|
| 514 |
-
}
|
| 515 |
-
|
| 516 |
-
// Move joystick knob
|
| 517 |
-
const knobX = Math.min(maxDistance, Math.max(-maxDistance, dx)) * 0.7;
|
| 518 |
-
const knobY = Math.min(maxDistance, Math.max(-maxDistance, dy)) * 0.7;
|
| 519 |
-
joystickKnob.style.transform = `translate(${knobX}px, ${knobY}px)`;
|
| 520 |
-
}
|
| 521 |
-
|
| 522 |
-
function handleJoystickEnd(e) {
|
| 523 |
-
if (!joystickActive) return;
|
| 524 |
-
e.preventDefault();
|
| 525 |
-
|
| 526 |
-
joystickActive = false;
|
| 527 |
-
joystickVector.x = 0;
|
| 528 |
-
joystickVector.y = 0;
|
| 529 |
-
joystickKnob.style.transform = 'translate(0, 0)';
|
| 530 |
-
}
|
| 531 |
-
}
|
| 532 |
-
|
| 533 |
-
// Initialize the game when DOM is loaded
|
| 534 |
-
document.addEventListener('DOMContentLoaded', initGame);
|
| 535 |
</script>
|
| 536 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=emolivera/artecno" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 537 |
</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>Somatic Learning App Concept</title>
|
| 7 |
<script src="https://cdn.tailwindcss.com"></script>
|
| 8 |
+
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
| 9 |
<style>
|
| 10 |
+
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 11 |
|
| 12 |
+
body {
|
| 13 |
+
font-family: 'Inter', sans-serif;
|
| 14 |
+
background-color: #f8f9fa;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
}
|
| 16 |
+
|
| 17 |
+
.sensor-feedback {
|
| 18 |
+
animation: pulse 2s infinite;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 19 |
}
|
| 20 |
+
|
| 21 |
+
@keyframes pulse {
|
| 22 |
+
0% { transform: scale(1); }
|
| 23 |
+
50% { transform: scale(1.05); }
|
| 24 |
+
100% { transform: scale(1); }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
}
|
| 26 |
+
|
| 27 |
+
.progress-ring {
|
| 28 |
+
transform: rotate(-90deg);
|
|
|
|
|
|
|
|
|
|
| 29 |
}
|
| 30 |
+
|
| 31 |
+
.progress-ring__circle {
|
| 32 |
+
transition: stroke-dashoffset 0.5s;
|
|
|
|
|
|
|
|
|
|
| 33 |
}
|
| 34 |
+
|
| 35 |
+
.microinteraction:hover {
|
| 36 |
+
transform: translateY(-2px);
|
| 37 |
+
transition: all 0.2s ease;
|
| 38 |
}
|
| 39 |
+
|
| 40 |
+
.haptic-feedback:active {
|
| 41 |
+
animation: haptic 0.3s;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
}
|
| 43 |
+
|
| 44 |
+
@keyframes haptic {
|
| 45 |
+
0% { transform: scale(1); }
|
| 46 |
+
50% { transform: scale(0.98); }
|
| 47 |
+
100% { transform: scale(1); }
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
| 49 |
</style>
|
| 50 |
</head>
|
| 51 |
+
<body class="min-h-screen flex items-center justify-center p-4">
|
| 52 |
+
<div class="w-full max-w-md mx-auto bg-white rounded-3xl shadow-xl overflow-hidden">
|
| 53 |
+
<!-- App Header -->
|
| 54 |
+
<div class="bg-indigo-600 text-white p-6">
|
| 55 |
+
<div class="flex justify-between items-center">
|
| 56 |
+
<div>
|
| 57 |
+
<h1 class="text-2xl font-bold">SomaLearn</h1>
|
| 58 |
+
<p class="text-indigo-100 text-sm">Body-aware learning</p>
|
| 59 |
+
</div>
|
| 60 |
+
<div class="flex space-x-3">
|
| 61 |
+
<button class="microinteraction w-10 h-10 rounded-full bg-indigo-500 flex items-center justify-center">
|
| 62 |
+
<i class="fas fa-user"></i>
|
| 63 |
+
</button>
|
| 64 |
+
<button class="microinteraction w-10 h-10 rounded-full bg-indigo-500 flex items-center justify-center">
|
| 65 |
+
<i class="fas fa-cog"></i>
|
| 66 |
+
</button>
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
</div>
|
|
|
|
| 68 |
</div>
|
| 69 |
+
</div>
|
| 70 |
+
|
| 71 |
+
<!-- Main Content -->
|
| 72 |
+
<div class="p-6">
|
| 73 |
+
<!-- Sensor Feedback Area -->
|
| 74 |
+
<div class="sensor-feedback mb-8 bg-indigo-50 rounded-2xl p-6 text-center">
|
| 75 |
+
<div class="relative w-40 h-40 mx-auto mb-4">
|
| 76 |
+
<svg class="progress-ring w-full h-full" viewBox="0 0 100 100">
|
| 77 |
+
<circle class="progress-ring__circle stroke-indigo-200" stroke-width="8" fill="transparent" r="40" cx="50" cy="50"/>
|
| 78 |
+
<circle class="progress-ring__circle stroke-indigo-600" stroke-width="8" fill="transparent" r="40" cx="50" cy="50" stroke-dasharray="251.2" stroke-dashoffset="125.6"/>
|
| 79 |
+
</svg>
|
| 80 |
+
<div class="absolute inset-0 flex flex-col items-center justify-center">
|
| 81 |
+
<i class="fas fa-hand-holding-heart text-3xl text-indigo-600 mb-2"></i>
|
| 82 |
+
<span class="text-sm font-medium text-indigo-800">Body Position</span>
|
| 83 |
+
<span class="text-xs text-indigo-500">75% optimal</span>
|
| 84 |
+
</div>
|
| 85 |
+
</div>
|
| 86 |
+
<p class="text-sm text-indigo-800">Adjust your posture to match the demonstration</p>
|
| 87 |
</div>
|
| 88 |
+
|
| 89 |
+
<!-- Microlearning Card -->
|
| 90 |
+
<div class="haptic-feedback bg-white rounded-xl shadow-md p-5 mb-6 border border-gray-100">
|
| 91 |
+
<div class="flex items-start mb-4">
|
| 92 |
+
<div class="bg-indigo-100 p-3 rounded-lg mr-4">
|
| 93 |
+
<i class="fas fa-running text-indigo-600"></i>
|
| 94 |
+
</div>
|
| 95 |
+
<div>
|
| 96 |
+
<h3 class="font-semibold text-gray-800">Posture Alignment</h3>
|
| 97 |
+
<p class="text-sm text-gray-600">Keep your spine neutral and shoulders relaxed</p>
|
| 98 |
+
</div>
|
| 99 |
+
</div>
|
| 100 |
+
<div class="flex justify-between items-center">
|
| 101 |
+
<div class="flex space-x-1">
|
| 102 |
+
<span class="text-xs px-2 py-1 bg-indigo-100 text-indigo-700 rounded-full">2 min</span>
|
| 103 |
+
<span class="text-xs px-2 py-1 bg-green-100 text-green-700 rounded-full">Beginner</span>
|
| 104 |
+
</div>
|
| 105 |
+
<button class="microinteraction px-4 py-2 bg-indigo-600 text-white rounded-lg text-sm font-medium">
|
| 106 |
+
Start Practice
|
| 107 |
+
</button>
|
| 108 |
+
</div>
|
| 109 |
</div>
|
| 110 |
+
|
| 111 |
+
<!-- Progress Section -->
|
| 112 |
+
<div class="mb-6">
|
| 113 |
+
<div class="flex justify-between items-center mb-2">
|
| 114 |
+
<h3 class="font-medium text-gray-800">Today's Progress</h3>
|
| 115 |
+
<span class="text-sm text-indigo-600">60% complete</span>
|
| 116 |
+
</div>
|
| 117 |
+
<div class="w-full bg-gray-200 rounded-full h-2.5">
|
| 118 |
+
<div class="bg-indigo-600 h-2.5 rounded-full" style="width: 60%"></div>
|
| 119 |
+
</div>
|
| 120 |
</div>
|
| 121 |
+
|
| 122 |
+
<!-- Quick Actions -->
|
| 123 |
+
<div class="grid grid-cols-4 gap-3 mb-6">
|
| 124 |
+
<button class="haptic-feedback microinteraction flex flex-col items-center justify-center p-3 bg-gray-50 rounded-xl">
|
| 125 |
+
<i class="fas fa-book text-indigo-600 mb-1"></i>
|
| 126 |
+
<span class="text-xs text-gray-700">Library</span>
|
| 127 |
+
</button>
|
| 128 |
+
<button class="haptic-feedback microinteraction flex flex-col items-center justify-center p-3 bg-gray-50 rounded-xl">
|
| 129 |
+
<i class="fas fa-chart-line text-indigo-600 mb-1"></i>
|
| 130 |
+
<span class="text-xs text-gray-700">Stats</span>
|
| 131 |
+
</button>
|
| 132 |
+
<button class="haptic-feedback microinteraction flex flex-col items-center justify-center p-3 bg-gray-50 rounded-xl">
|
| 133 |
+
<i class="fas fa-video text-indigo-600 mb-1"></i>
|
| 134 |
+
<span class="text-xs text-gray-700">Demo</span>
|
| 135 |
+
</button>
|
| 136 |
+
<button class="haptic-feedback microinteraction flex flex-col items-center justify-center p-3 bg-gray-50 rounded-xl">
|
| 137 |
+
<i class="fas fa-trophy text-indigo-600 mb-1"></i>
|
| 138 |
+
<span class="text-xs text-gray-700">Rewards</span>
|
| 139 |
+
</button>
|
| 140 |
</div>
|
| 141 |
+
|
| 142 |
+
<!-- Upcoming Exercises -->
|
| 143 |
+
<div>
|
| 144 |
+
<h3 class="font-medium text-gray-800 mb-3">Next Exercises</h3>
|
| 145 |
+
<div class="space-y-3">
|
| 146 |
+
<div class="haptic-feedback microinteraction flex items-center p-3 bg-gray-50 rounded-lg">
|
| 147 |
+
<div class="w-10 h-10 rounded-full bg-indigo-100 flex items-center justify-center mr-3">
|
| 148 |
+
<i class="fas fa-walking text-indigo-600"></i>
|
| 149 |
+
</div>
|
| 150 |
+
<div class="flex-1">
|
| 151 |
+
<h4 class="text-sm font-medium text-gray-800">Walking Meditation</h4>
|
| 152 |
+
<p class="text-xs text-gray-500">Mindful movement practice</p>
|
| 153 |
+
</div>
|
| 154 |
+
<i class="fas fa-chevron-right text-gray-400"></i>
|
| 155 |
</div>
|
| 156 |
+
<div class="haptic-feedback microinteraction flex items-center p-3 bg-gray-50 rounded-lg">
|
| 157 |
+
<div class="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center mr-3">
|
| 158 |
+
<i class="fas fa-lungs text-purple-600"></i>
|
| 159 |
+
</div>
|
| 160 |
+
<div class="flex-1">
|
| 161 |
+
<h4 class="text-sm font-medium text-gray-800">Breath Control</h4>
|
| 162 |
+
<p class="text-xs text-gray-500">Diaphragmatic breathing</p>
|
| 163 |
+
</div>
|
| 164 |
+
<i class="fas fa-chevron-right text-gray-400"></i>
|
| 165 |
</div>
|
| 166 |
</div>
|
| 167 |
</div>
|
| 168 |
</div>
|
| 169 |
+
|
| 170 |
+
<!-- Bottom Navigation -->
|
| 171 |
+
<div class="flex justify-around items-center p-4 bg-white border-t border-gray-200">
|
| 172 |
+
<button class="microinteraction flex flex-col items-center text-indigo-600">
|
| 173 |
+
<i class="fas fa-home"></i>
|
| 174 |
+
<span class="text-xs mt-1">Home</span>
|
| 175 |
+
</button>
|
| 176 |
+
<button class="microinteraction flex flex-col items-center text-gray-500">
|
| 177 |
+
<i class="fas fa-compass"></i>
|
| 178 |
+
<span class="text-xs mt-1">Explore</span>
|
| 179 |
+
</button>
|
| 180 |
+
<button class="microinteraction flex flex-col items-center text-gray-500">
|
| 181 |
+
<i class="fas fa-calendar-alt"></i>
|
| 182 |
+
<span class="text-xs mt-1">Schedule</span>
|
| 183 |
+
</button>
|
| 184 |
+
<button class="microinteraction flex flex-col items-center text-gray-500">
|
| 185 |
+
<i class="fas fa-inbox"></i>
|
| 186 |
+
<span class="text-xs mt-1">Inbox</span>
|
| 187 |
</button>
|
| 188 |
</div>
|
| 189 |
</div>
|
| 190 |
|
| 191 |
<script>
|
| 192 |
+
// Simulate sensor feedback
|
| 193 |
+
const sensorFeedback = document.querySelector('.sensor-feedback');
|
| 194 |
+
const progressCircle = document.querySelector('.progress-ring__circle');
|
| 195 |
+
|
| 196 |
+
// Random progress for demo purposes
|
| 197 |
+
function updateSensorFeedback() {
|
| 198 |
+
const randomProgress = Math.floor(Math.random() * 60) + 20;
|
| 199 |
+
const offset = 251.2 - (251.2 * randomProgress / 100);
|
| 200 |
+
progressCircle.style.strokeDashoffset = offset;
|
| 201 |
+
|
| 202 |
+
// Update text
|
| 203 |
+
const feedbackText = sensorFeedback.querySelector('p:last-child');
|
| 204 |
+
const feedbackOptions = [
|
| 205 |
+
"Great job! Maintain this position",
|
| 206 |
+
"Small adjustment needed in your shoulders",
|
| 207 |
+
"Focus on your breathing pattern",
|
| 208 |
+
"Relax your jaw muscles",
|
| 209 |
+
"Shift weight slightly to your left"
|
| 210 |
+
];
|
| 211 |
+
feedbackText.textContent = feedbackOptions[Math.floor(Math.random() * feedbackOptions.length)];
|
| 212 |
+
|
| 213 |
+
// Change color based on progress
|
| 214 |
+
if(randomProgress > 70) {
|
| 215 |
+
progressCircle.classList.remove('stroke-indigo-600');
|
| 216 |
+
progressCircle.classList.add('stroke-green-500');
|
| 217 |
+
} else if(randomProgress > 40) {
|
| 218 |
+
progressCircle.classList.remove('stroke-green-500', 'stroke-red-500');
|
| 219 |
+
progressCircle.classList.add('stroke-indigo-600');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 220 |
} else {
|
| 221 |
+
progressCircle.classList.remove('stroke-indigo-600');
|
| 222 |
+
progressCircle.classList.add('stroke-red-500');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
}
|
| 224 |
}
|
| 225 |
+
|
| 226 |
+
// Update every 3 seconds to simulate real-time feedback
|
| 227 |
+
setInterval(updateSensorFeedback, 3000);
|
| 228 |
+
|
| 229 |
+
// Add microinteractions to all buttons
|
| 230 |
+
document.querySelectorAll('.microinteraction').forEach(button => {
|
| 231 |
+
button.addEventListener('click', function() {
|
| 232 |
+
this.classList.add('active');
|
| 233 |
+
setTimeout(() => this.classList.remove('active'), 200);
|
| 234 |
+
});
|
| 235 |
+
});
|
| 236 |
+
|
| 237 |
+
// Haptic feedback simulation
|
| 238 |
+
document.querySelectorAll('.haptic-feedback').forEach(element => {
|
| 239 |
+
element.addEventListener('click', function() {
|
| 240 |
+
this.style.boxShadow = '0 0 0 3px rgba(99, 102, 241, 0.3)';
|
| 241 |
+
setTimeout(() => {
|
| 242 |
+
this.style.boxShadow = 'none';
|
| 243 |
+
}, 300);
|
| 244 |
+
});
|
| 245 |
+
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 246 |
</script>
|
| 247 |
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=emolivera/artecno" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
|
| 248 |
</html>
|
prompts.txt
CHANGED
|
@@ -1,3 +1,4 @@
|
|
| 1 |
device tilt not working, optimize for mobile
|
| 2 |
check why it doesnt start game
|
| 3 |
-
it doesnt work, browser blocks. sensor
|
|
|
|
|
|
| 1 |
device tilt not working, optimize for mobile
|
| 2 |
check why it doesnt start game
|
| 3 |
+
it doesnt work, browser blocks. sensor
|
| 4 |
+
Your role is that of a User Experience (UX) Design Consultant for a mobile app development project. The task at hand is to refine and enhance the concept of a testing app that utilizes microlearning and microinteraction principles. This involves designing a user-friendly interface, identifying key features, and suggesting ways to effectively incorporate microlearning and microinteraction. You should consider the app's target audience, its purpose, and how it can engage users in a testing environment. The initial concept to work with is "device geared somatic learning." Please provide detailed recommendations to improve this concept. Remember, your responses should be specific to UX design and app development.
|