LukasBe commited on
Commit
6b10b93
·
verified ·
1 Parent(s): 39c16ad

Add 3 files

Browse files
Files changed (3) hide show
  1. README.md +6 -4
  2. index.html +690 -19
  3. prompts.txt +2 -0
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Game 4 Rhytm Chef
3
- emoji: 🚀
4
- colorFrom: yellow
5
  colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: game-4-rhytm-chef
3
+ emoji: 🐳
4
+ colorFrom: blue
5
  colorTo: yellow
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,690 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Rhythm Chef: Beat Bites Deluxe</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ @keyframes moveDown {
10
+ 0% { transform: translateY(-100px); }
11
+ 100% { transform: translateY(calc(100vh - 200px)); }
12
+ }
13
+
14
+ .cue {
15
+ animation: moveDown var(--duration) linear forwards;
16
+ transition: all 0.1s ease;
17
+ }
18
+
19
+ .hit-effect {
20
+ animation: scaleFade 0.5s ease-out forwards;
21
+ }
22
+
23
+ @keyframes scaleFade {
24
+ 0% { transform: scale(0.8); opacity: 1; }
25
+ 100% { transform: scale(1.5); opacity: 0; }
26
+ }
27
+
28
+ .feedback-text {
29
+ animation: fadeUp 1s ease-out forwards;
30
+ }
31
+
32
+ @keyframes fadeUp {
33
+ 0% { transform: translateY(0) scale(1); opacity: 1; }
34
+ 100% { transform: translateY(-50px) scale(1.2); opacity: 0; }
35
+ }
36
+
37
+ .combo-text {
38
+ animation: pulse 0.5s ease infinite alternate;
39
+ }
40
+
41
+ @keyframes pulse {
42
+ 0% { transform: scale(1); }
43
+ 100% { transform: scale(1.1); }
44
+ }
45
+
46
+ #gameArea {
47
+ touch-action: manipulation;
48
+ background: radial-gradient(circle at center, #1a202c 0%, #111827 100%);
49
+ }
50
+
51
+ .kitchen-counter {
52
+ background: linear-gradient(to bottom, #8B5A2B 0%, #A67C52 100%);
53
+ box-shadow: 0 -10px 20px rgba(0,0,0,0.3);
54
+ }
55
+
56
+ .particle {
57
+ position: absolute;
58
+ pointer-events: none;
59
+ will-change: transform, opacity;
60
+ }
61
+
62
+ .glow {
63
+ filter: drop-shadow(0 0 8px currentColor);
64
+ }
65
+
66
+ .score-glow {
67
+ text-shadow: 0 0 10px rgba(255, 215, 0, 0.7);
68
+ }
69
+
70
+ .perfect-hit {
71
+ animation: perfectGlow 0.5s ease-out forwards;
72
+ }
73
+
74
+ @keyframes perfectGlow {
75
+ 0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); }
76
+ 50% { box-shadow: 0 0 30px 15px rgba(255, 255, 255, 0.7); }
77
+ 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
78
+ }
79
+ </style>
80
+ </head>
81
+ <body class="bg-gray-900 text-white font-sans overflow-hidden">
82
+ <!-- Start Screen -->
83
+ <div id="startScreen" class="fixed inset-0 flex flex-col items-center justify-center bg-gradient-to-br from-gray-900 to-gray-800 z-10 transition-opacity duration-500">
84
+ <div class="text-center mb-12">
85
+ <h1 class="text-7xl font-bold mb-4 text-yellow-400 glow">🍳 RHYTHM CHEF</h1>
86
+ <h2 class="text-4xl mb-6 text-yellow-300 glow">Beat Bites Deluxe</h2>
87
+ <div class="text-xl text-gray-300 max-w-md mx-auto">
88
+ Tap the ingredients in rhythm to cook up perfect dishes!
89
+ </div>
90
+ </div>
91
+ <button id="startButton" class="bg-gradient-to-r from-yellow-500 to-yellow-600 hover:from-yellow-400 hover:to-yellow-500 text-4xl text-gray-900 font-bold py-5 px-16 rounded-full transition-all transform hover:scale-105 shadow-lg glow">
92
+ START COOKING
93
+ </button>
94
+ <div class="absolute bottom-8 text-gray-400 text-sm">
95
+ Tap the beat when ingredients reach the counter
96
+ </div>
97
+ </div>
98
+
99
+ <!-- Game Screen -->
100
+ <div id="gameScreen" class="fixed inset-0 hidden flex flex-col">
101
+ <!-- Score Display -->
102
+ <div class="flex justify-between px-8 pt-6">
103
+ <div class="text-4xl font-bold score-glow">
104
+ 🏆 <span id="score">0</span>
105
+ </div>
106
+ <div id="comboContainer" class="text-4xl font-bold combo-text hidden">
107
+ 🔥 <span id="combo">0</span>x
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Game Area -->
112
+ <div id="gameArea" class="flex-1 relative overflow-hidden">
113
+ <!-- Floating particles background -->
114
+ <div id="particles"></div>
115
+
116
+ <!-- Target Zone (Kitchen Counter) -->
117
+ <div id="targetZone" class="kitchen-counter absolute left-0 right-0 h-24 rounded-t-3xl flex items-center justify-center" style="bottom: 20%;">
118
+ <div class="w-full h-1 bg-yellow-300 bg-opacity-50 rounded-full mx-8"></div>
119
+ </div>
120
+
121
+ <!-- Feedback Text -->
122
+ <div id="feedbackText" class="absolute left-1/2 transform -translate-x-1/2 text-6xl font-bold text-center opacity-0" style="bottom: 30%;"></div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- End Screen -->
127
+ <div id="endScreen" class="fixed inset-0 hidden flex flex-col items-center justify-center bg-gray-900 bg-opacity-95 z-20">
128
+ <div class="text-center">
129
+ <h2 class="text-6xl font-bold mb-8 text-yellow-400 glow">DISH COMPLETE! 🎉</h2>
130
+ <div class="text-5xl mb-8">Final Score: <span id="finalScore" class="text-yellow-300">0</span></div>
131
+ <div id="finalDish" class="text-9xl mb-12">🍲</div>
132
+ <div class="text-2xl mb-8">Max Combo: <span id="maxCombo" class="text-yellow-300">0</span>x</div>
133
+ <button id="restartButton" class="bg-gradient-to-r from-yellow-500 to-yellow-600 hover:from-yellow-400 hover:to-yellow-500 text-4xl text-gray-900 font-bold py-5 px-16 rounded-full transition-all transform hover:scale-105 shadow-lg glow">
134
+ COOK AGAIN
135
+ </button>
136
+ </div>
137
+ </div>
138
+
139
+ <script>
140
+ // Game state
141
+ const gameState = {
142
+ score: 0,
143
+ combo: 0,
144
+ maxCombo: 0,
145
+ isPlaying: false,
146
+ bpm: 128,
147
+ cueSpeed: 2, // seconds to reach target
148
+ perfectWindow: 80, // ms
149
+ goodWindow: 160, // ms,
150
+ ingredients: ['🍅', '🧀', '🍄', '🥩', '🥬', '🍞', '🥚', '🦐', '🌽', '🧅'],
151
+ dishes: ['🍕', '🍔', '🍣', '🥘', '🍛', '🍜', '🌮', '🥗', '🍲', '🍝'],
152
+ sequence: [
153
+ { beat: 1, type: 'tap' },
154
+ { beat: 2, type: 'tap' },
155
+ { beat: 3, type: 'tap' },
156
+ { beat: 4, type: 'tap' },
157
+ { beat: 5.5, type: 'tap' },
158
+ { beat: 6.5, type: 'tap' },
159
+ { beat: 7, type: 'tap' },
160
+ { beat: 8, type: 'tap' },
161
+ { beat: 9, type: 'tap' },
162
+ { beat: 10, type: 'tap' },
163
+ { beat: 11.5, type: 'tap' },
164
+ { beat: 12.5, type: 'tap' },
165
+ { beat: 13, type: 'tap' },
166
+ { beat: 14, type: 'tap' },
167
+ { beat: 15, type: 'tap' },
168
+ { beat: 16, type: 'tap' }
169
+ ],
170
+ activeCues: [],
171
+ sequenceStartTime: 0,
172
+ currentSequenceIndex: 0,
173
+ audioContext: null,
174
+ metronomeInterval: null,
175
+ backgroundParticles: []
176
+ };
177
+
178
+ // DOM elements
179
+ const startScreen = document.getElementById('startScreen');
180
+ const gameScreen = document.getElementById('gameScreen');
181
+ const endScreen = document.getElementById('endScreen');
182
+ const startButton = document.getElementById('startButton');
183
+ const restartButton = document.getElementById('restartButton');
184
+ const gameArea = document.getElementById('gameArea');
185
+ const targetZone = document.getElementById('targetZone');
186
+ const feedbackText = document.getElementById('feedbackText');
187
+ const scoreDisplay = document.getElementById('score');
188
+ const comboDisplay = document.getElementById('combo');
189
+ const comboContainer = document.getElementById('comboContainer');
190
+ const finalScoreDisplay = document.getElementById('finalScore');
191
+ const maxComboDisplay = document.getElementById('maxCombo');
192
+ const finalDishDisplay = document.getElementById('finalDish');
193
+ const particlesContainer = document.getElementById('particles');
194
+
195
+ // Initialize audio context
196
+ function initAudio() {
197
+ try {
198
+ gameState.audioContext = new (window.AudioContext || window.webkitAudioContext)();
199
+ } catch (e) {
200
+ console.warn('Web Audio API not supported');
201
+ }
202
+ }
203
+
204
+ // Play a sound
205
+ function playSound(frequency, duration, type = 'sine') {
206
+ if (!gameState.audioContext) return;
207
+
208
+ const oscillator = gameState.audioContext.createOscillator();
209
+ const gainNode = gameState.audioContext.createGain();
210
+
211
+ oscillator.connect(gainNode);
212
+ gainNode.connect(gameState.audioContext.destination);
213
+
214
+ oscillator.type = type;
215
+ oscillator.frequency.value = frequency;
216
+ gainNode.gain.value = 0.1;
217
+
218
+ oscillator.start();
219
+ oscillator.stop(gameState.audioContext.currentTime + duration);
220
+ }
221
+
222
+ // Create background particles
223
+ function createParticles() {
224
+ // Clear existing particles
225
+ particlesContainer.innerHTML = '';
226
+ gameState.backgroundParticles = [];
227
+
228
+ // Create new particles
229
+ for (let i = 0; i < 30; i++) {
230
+ createParticle(true);
231
+ }
232
+ }
233
+
234
+ function createParticle(isBackground = false) {
235
+ const particle = document.createElement('div');
236
+ particle.className = 'particle';
237
+
238
+ // Random properties
239
+ const size = Math.random() * 6 + 2;
240
+ const x = Math.random() * 100;
241
+ const y = Math.random() * 100;
242
+ const duration = Math.random() * 20 + 10;
243
+ const delay = Math.random() * 5;
244
+ const opacity = Math.random() * 0.3 + 0.1;
245
+ const color = `hsl(${Math.random() * 60 + 20}, 70%, 60%)`;
246
+
247
+ particle.style.width = `${size}px`;
248
+ particle.style.height = `${size}px`;
249
+ particle.style.left = `${x}%`;
250
+ particle.style.top = `${y}%`;
251
+ particle.style.backgroundColor = color;
252
+ particle.style.borderRadius = '50%';
253
+ particle.style.opacity = opacity;
254
+ particle.style.animation = `float ${duration}s linear ${delay}s infinite`;
255
+
256
+ if (isBackground) {
257
+ particle.style.position = 'absolute';
258
+ particlesContainer.appendChild(particle);
259
+ gameState.backgroundParticles.push(particle);
260
+ }
261
+
262
+ return particle;
263
+ }
264
+
265
+ // Create floating animation
266
+ const style = document.createElement('style');
267
+ style.innerHTML = `
268
+ @keyframes float {
269
+ 0% { transform: translate(0, 0) rotate(0deg); opacity: ${Math.random() * 0.3 + 0.1}; }
270
+ 50% { transform: translate(${Math.random() * 100 - 50}px, ${Math.random() * 50 - 25}px) rotate(${Math.random() * 180 - 90}deg); opacity: ${Math.random() * 0.5 + 0.3}; }
271
+ 100% { transform: translate(0, 0) rotate(0deg); opacity: ${Math.random() * 0.3 + 0.1}; }
272
+ }
273
+ `;
274
+ document.head.appendChild(style);
275
+
276
+ // Start metronome
277
+ function startMetronome() {
278
+ if (!gameState.audioContext) return;
279
+
280
+ const secondsPerBeat = 60 / gameState.bpm;
281
+ let nextBeatTime = gameState.audioContext.currentTime;
282
+
283
+ gameState.metronomeInterval = setInterval(() => {
284
+ playSound(880, 0.05, 'triangle');
285
+ nextBeatTime += secondsPerBeat;
286
+ }, secondsPerBeat * 1000);
287
+ }
288
+
289
+ // Stop metronome
290
+ function stopMetronome() {
291
+ if (gameState.metronomeInterval) {
292
+ clearInterval(gameState.metronomeInterval);
293
+ gameState.metronomeInterval = null;
294
+ }
295
+ }
296
+
297
+ // Create a cue element
298
+ function createCue() {
299
+ const cue = document.createElement('div');
300
+ const ingredient = gameState.ingredients[Math.floor(Math.random() * gameState.ingredients.length)];
301
+
302
+ cue.className = 'cue absolute w-20 h-20 rounded-full flex items-center justify-center text-4xl glow';
303
+ cue.style.setProperty('--duration', `${gameState.cueSpeed}s`);
304
+ cue.style.top = '-100px';
305
+ cue.style.left = `${Math.random() * 60 + 20}%`;
306
+ cue.textContent = ingredient;
307
+
308
+ // Add to DOM and active cues array
309
+ gameArea.appendChild(cue);
310
+ const cueObj = {
311
+ element: cue,
312
+ targetTime: Date.now() + gameState.cueSpeed * 1000,
313
+ hit: false,
314
+ ingredient: ingredient
315
+ };
316
+ gameState.activeCues.push(cueObj);
317
+
318
+ // Remove cue after animation completes
319
+ setTimeout(() => {
320
+ if (!cueObj.hit) {
321
+ handleMiss(cueObj);
322
+ }
323
+ }, gameState.cueSpeed * 1000);
324
+
325
+ return cueObj;
326
+ }
327
+
328
+ // Show feedback
329
+ function showFeedback(text, isGood) {
330
+ feedbackText.textContent = text;
331
+ feedbackText.className = `absolute left-1/2 transform -translate-x-1/2 text-6xl font-bold text-center glow ${
332
+ isGood ? 'text-green-400' : 'text-red-400'
333
+ }`;
334
+ feedbackText.style.opacity = '1';
335
+
336
+ // Create hit effect
337
+ if (isGood) {
338
+ createHitEffect(feedbackText.getBoundingClientRect());
339
+ }
340
+
341
+ // Hide feedback after delay
342
+ setTimeout(() => {
343
+ feedbackText.style.opacity = '0';
344
+ }, 1000);
345
+ }
346
+
347
+ // Create hit effect
348
+ function createHitEffect(rect) {
349
+ const colors = ['#FFD700', '#FF6347', '#7FFFD4', '#FF69B4', '#9370DB'];
350
+
351
+ for (let i = 0; i < 15; i++) {
352
+ const particle = document.createElement('div');
353
+ particle.className = 'particle';
354
+
355
+ const size = Math.random() * 12 + 4;
356
+ const color = colors[Math.floor(Math.random() * colors.length)];
357
+ const angle = Math.random() * Math.PI * 2;
358
+ const distance = Math.random() * 50 + 20;
359
+ const duration = Math.random() * 1 + 0.5;
360
+
361
+ particle.style.width = `${size}px`;
362
+ particle.style.height = `${size}px`;
363
+ particle.style.left = `${rect.left + rect.width / 2}px`;
364
+ particle.style.top = `${rect.top + rect.height / 2}px`;
365
+ particle.style.backgroundColor = color;
366
+ particle.style.borderRadius = '50%';
367
+ particle.style.opacity = '0.8';
368
+ particle.style.transform = `translate(${Math.cos(angle) * distance}px, ${Math.sin(angle) * distance}px)`;
369
+ particle.style.transition = `all ${duration}s ease-out`;
370
+ particle.style.boxShadow = `0 0 ${size/2}px ${color}`;
371
+
372
+ document.body.appendChild(particle);
373
+
374
+ setTimeout(() => {
375
+ particle.style.opacity = '0';
376
+ particle.style.transform += ` scale(0.5)`;
377
+ setTimeout(() => particle.remove(), duration * 1000);
378
+ }, 10);
379
+ }
380
+ }
381
+
382
+ // Handle successful hit
383
+ function handleHit(cue, accuracy) {
384
+ if (cue.hit) return;
385
+
386
+ cue.hit = true;
387
+
388
+ // Visual feedback on the cue
389
+ cue.element.classList.add('perfect-hit');
390
+ cue.element.style.transform = 'scale(1.2)';
391
+
392
+ setTimeout(() => {
393
+ cue.element.remove();
394
+ }, 200);
395
+
396
+ // Determine hit quality
397
+ let points = 0;
398
+ let feedback = '';
399
+ let soundFreq = 0;
400
+
401
+ if (Math.abs(accuracy) <= gameState.perfectWindow) {
402
+ points = 100;
403
+ feedback = 'PERFECT! ✨';
404
+ soundFreq = 1046.50; // C note
405
+ playSound(soundFreq, 0.2, 'sine');
406
+ playSound(soundFreq/2, 0.3, 'sine');
407
+ } else if (Math.abs(accuracy) <= gameState.goodWindow) {
408
+ points = 60;
409
+ feedback = 'GREAT! 👍';
410
+ soundFreq = 783.99; // G note
411
+ playSound(soundFreq, 0.15, 'square');
412
+ } else {
413
+ points = 30;
414
+ feedback = 'GOOD 👌';
415
+ soundFreq = 523.25; // C note lower
416
+ playSound(soundFreq, 0.1, 'sawtooth');
417
+ }
418
+
419
+ // Update score and combo
420
+ gameState.score += points;
421
+ gameState.combo += 1;
422
+ if (gameState.combo > gameState.maxCombo) {
423
+ gameState.maxCombo = gameState.combo;
424
+ }
425
+
426
+ scoreDisplay.textContent = gameState.score;
427
+ comboDisplay.textContent = gameState.combo;
428
+
429
+ // Show combo if > 1
430
+ if (gameState.combo > 1) {
431
+ comboContainer.classList.remove('hidden');
432
+ }
433
+
434
+ // Show feedback
435
+ showFeedback(feedback, true);
436
+
437
+ // Create ingredient transformation effect
438
+ createIngredientEffect(cue);
439
+ }
440
+
441
+ // Create ingredient transformation effect
442
+ function createIngredientEffect(cue) {
443
+ const rect = cue.element.getBoundingClientRect();
444
+ const effect = document.createElement('div');
445
+ effect.className = 'absolute text-4xl glow';
446
+ effect.style.left = `${rect.left}px`;
447
+ effect.style.top = `${rect.top}px`;
448
+ effect.style.width = `${rect.width}px`;
449
+ effect.style.height = `${rect.height}px`;
450
+ effect.style.display = 'flex';
451
+ effect.style.alignItems = 'center';
452
+ effect.style.justifyContent = 'center';
453
+ effect.textContent = cue.ingredient;
454
+
455
+ document.body.appendChild(effect);
456
+
457
+ // Animate transformation
458
+ setTimeout(() => {
459
+ effect.style.transition = 'all 0.5s ease-out';
460
+ effect.style.transform = 'translateY(-30px) scale(1.5)';
461
+ effect.style.opacity = '0';
462
+
463
+ // Change to a cooked version
464
+ const cookedItems = {
465
+ '🍅': '🍅', // tomato stays tomato
466
+ '🧀': '🧀', // cheese stays cheese
467
+ '🍄': '🍄', // mushroom stays mushroom
468
+ '🥩': '🍖', // raw meat -> cooked meat
469
+ '🥬': '🥗', // lettuce -> salad
470
+ '🍞': '🍞', // bread stays bread
471
+ '🥚': '🍳', // egg -> fried egg
472
+ '🦐': '🍤', // shrimp -> fried shrimp
473
+ '🌽': '🍿', // corn -> popcorn
474
+ '🧅': '🧅' // onion stays onion
475
+ };
476
+
477
+ setTimeout(() => {
478
+ effect.textContent = cookedItems[cue.ingredient] || '🍽️';
479
+ }, 250);
480
+
481
+ setTimeout(() => {
482
+ effect.remove();
483
+ }, 1000);
484
+ }, 10);
485
+ }
486
+
487
+ // Handle miss
488
+ function handleMiss(cue) {
489
+ if (cue.hit) return;
490
+
491
+ cue.hit = true;
492
+ if (cue.element) {
493
+ cue.element.classList.add('opacity-50');
494
+ cue.element.style.transform = 'scale(0.8)';
495
+ setTimeout(() => {
496
+ cue.element.remove();
497
+ }, 500);
498
+ }
499
+
500
+ // Reset combo
501
+ gameState.combo = 0;
502
+ comboDisplay.textContent = '0';
503
+ comboContainer.classList.add('hidden');
504
+
505
+ // Show feedback
506
+ showFeedback('MISS! 😩', false);
507
+ playSound(110, 0.3, 'sawtooth'); // Low buzz for miss
508
+
509
+ // Create break effect
510
+ if (cue.element) {
511
+ const rect = cue.element.getBoundingClientRect();
512
+ for (let i = 0; i < 5; i++) {
513
+ const piece = document.createElement('div');
514
+ piece.className = 'particle absolute text-xl';
515
+ piece.textContent = cue.ingredient;
516
+ piece.style.left = `${rect.left + rect.width/2}px`;
517
+ piece.style.top = `${rect.top + rect.height/2}px`;
518
+ piece.style.transform = `translate(${(Math.random() - 0.5) * 50}px, ${(Math.random() - 0.5) * 50}px) rotate(${Math.random() * 360}deg)`;
519
+ piece.style.opacity = '0.7';
520
+ piece.style.transition = 'all 0.5s ease-out';
521
+
522
+ document.body.appendChild(piece);
523
+
524
+ setTimeout(() => {
525
+ piece.style.opacity = '0';
526
+ piece.style.transform += ` translateY(30px)`;
527
+ setTimeout(() => piece.remove(), 500);
528
+ }, 10);
529
+ }
530
+ }
531
+ }
532
+
533
+ // Start game sequence
534
+ function startSequence() {
535
+ gameState.score = 0;
536
+ gameState.combo = 0;
537
+ gameState.maxCombo = 0;
538
+ gameState.isPlaying = true;
539
+ gameState.activeCues = [];
540
+ gameState.currentSequenceIndex = 0;
541
+ gameState.sequenceStartTime = Date.now();
542
+
543
+ scoreDisplay.textContent = '0';
544
+ comboDisplay.textContent = '0';
545
+ comboContainer.classList.add('hidden');
546
+
547
+ // Create background particles
548
+ createParticles();
549
+
550
+ // Start metronome
551
+ if (gameState.audioContext) {
552
+ startMetronome();
553
+ }
554
+
555
+ // Start spawning cues
556
+ spawnNextCue();
557
+ }
558
+
559
+ // Spawn next cue in sequence
560
+ function spawnNextCue() {
561
+ if (gameState.currentSequenceIndex >= gameState.sequence.length) {
562
+ endSequence();
563
+ return;
564
+ }
565
+
566
+ const currentBeat = gameState.sequence[gameState.currentSequenceIndex].beat;
567
+ const beatsPerSecond = gameState.bpm / 60;
568
+ const beatTime = currentBeat / beatsPerSecond * 1000;
569
+
570
+ // Calculate delay until this cue should spawn
571
+ const spawnDelay = beatTime - (Date.now() - gameState.sequenceStartTime) - (gameState.cueSpeed * 1000);
572
+
573
+ if (spawnDelay <= 0) {
574
+ // We're behind schedule, spawn immediately
575
+ createCue();
576
+ gameState.currentSequenceIndex++;
577
+ spawnNextCue();
578
+ } else {
579
+ // Schedule next cue
580
+ setTimeout(() => {
581
+ createCue();
582
+ gameState.currentSequenceIndex++;
583
+ spawnNextCue();
584
+ }, spawnDelay);
585
+ }
586
+ }
587
+
588
+ // End sequence
589
+ function endSequence() {
590
+ gameState.isPlaying = false;
591
+ stopMetronome();
592
+
593
+ // Clear background particles
594
+ particlesContainer.innerHTML = '';
595
+
596
+ // Determine final dish based on score
597
+ const dishIndex = Math.min(
598
+ Math.floor(gameState.score / 500),
599
+ gameState.dishes.length - 1
600
+ );
601
+ finalDishDisplay.textContent = gameState.dishes[dishIndex];
602
+
603
+ // Wait for last cues to finish
604
+ setTimeout(() => {
605
+ finalScoreDisplay.textContent = gameState.score;
606
+ maxComboDisplay.textContent = gameState.maxCombo;
607
+ endScreen.classList.remove('hidden');
608
+
609
+ // Celebration particles
610
+ for (let i = 0; i < 50; i++) {
611
+ setTimeout(() => {
612
+ createParticle();
613
+ }, i * 50);
614
+ }
615
+ }, gameState.cueSpeed * 1000);
616
+ }
617
+
618
+ // Handle tap input
619
+ function handleTap() {
620
+ if (!gameState.isPlaying) return;
621
+
622
+ const now = Date.now();
623
+ let closestCue = null;
624
+ let closestDiff = Infinity;
625
+
626
+ // Find the closest active cue to target time
627
+ for (const cue of gameState.activeCues) {
628
+ if (!cue.hit) {
629
+ const diff = now - cue.targetTime;
630
+ if (Math.abs(diff) < Math.abs(closestDiff)) {
631
+ closestDiff = diff;
632
+ closestCue = cue;
633
+ }
634
+ }
635
+ }
636
+
637
+ // Visual feedback on target zone
638
+ targetZone.classList.add('perfect-hit');
639
+ setTimeout(() => {
640
+ targetZone.classList.remove('perfect-hit');
641
+ }, 300);
642
+
643
+ // Check if tap was close enough to any cue
644
+ if (closestCue && Math.abs(closestDiff) <= gameState.goodWindow * 2) {
645
+ handleHit(closestCue, closestDiff);
646
+ } else {
647
+ // Penalize random taps
648
+ gameState.combo = 0;
649
+ comboDisplay.textContent = '0';
650
+ comboContainer.classList.add('hidden');
651
+ showFeedback('TOO EARLY! 👎', false);
652
+ playSound(110, 0.3, 'square');
653
+ }
654
+ }
655
+
656
+ // Initialize game
657
+ function initGame() {
658
+ initAudio();
659
+
660
+ // Start button
661
+ startButton.addEventListener('click', () => {
662
+ startScreen.classList.add('opacity-0');
663
+ setTimeout(() => {
664
+ startScreen.classList.add('hidden');
665
+ gameScreen.classList.remove('hidden');
666
+ startSequence();
667
+ }, 500);
668
+ });
669
+
670
+ // Restart button
671
+ restartButton.addEventListener('click', () => {
672
+ endScreen.classList.add('hidden');
673
+ startSequence();
674
+ });
675
+
676
+ // Tap input
677
+ gameArea.addEventListener('click', handleTap);
678
+
679
+ // Touch support
680
+ gameArea.addEventListener('touchstart', (e) => {
681
+ e.preventDefault();
682
+ handleTap();
683
+ });
684
+ }
685
+
686
+ // Start the game when ready
687
+ window.addEventListener('DOMContentLoaded', initGame);
688
+ </script>
689
+ <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=LukasBe/game-4-rhytm-chef" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
690
+ </html>
prompts.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ Okay, here is a detailed, implementation-grade plan for building an interactive demonstrator for the core game mechanics of **Rhythm Chef: Beat Bites**. This focuses on creating a minimal viable product (MVP) specifically for user feedback on the core rhythm interaction feel, keeping the codebase limited. **Assumptions:** * **Engine:** Unity (common choice for hypercasual, good for rapid prototyping). * **Language:** C#. * **Target Platform:** Android (easy for distributing APKs for testing). * **Input Focus:** Start with **Tap** only for simplicity. Hold/Swipe can be added later if the Tap feels good. **I. Demonstrator Objectives** 1. Implement the core rhythm interaction: spawning cues, moving cues, detecting timed player input within a target zone. 2. Provide immediate, clear visual and audio feedback for successful hits and misses. 3. Synchronize cue movement and required input timing to a consistent beat (can be a simple metronome track or internal timer). 4. Allow a user to play through a short, predefined sequence of cues. 5. Keep the scope strictly limited to the core mechanic loop for fast iteration and focused feedback. **II. Scope Definition** * **IN SCOPE:** * Single, non-scrolling conveyor belt or lane for cues. * One type of cue requiring a **Tap** input. * One clearly defined target zone. * Precise timing mechanism for cue spawning and hit detection. * Simple visual representation of cues (e.g., colored circles/squares representing ingredients/actions). * Visual feedback (e.g., color change, simple particle effect, text popup like "Perfect!"/"Miss!"). * Basic audio feedback (hit sound, miss sound, beat/metronome sound). * A predefined, short sequence (~15-30 seconds) of Tap cues. * Minimal UI: Start Button, potentially a simple score/combo counter (optional but helpful). * **OUT OF SCOPE:** * Multiple lanes or complex patterns. * Hold or Swipe input types. * Multiple cue types/actions (chop, fry, etc.). * Any meta-game (restaurant, currency, upgrades). * Scoring beyond basic hit/miss feedback (no stars, complex calculations). * Multiple songs or difficulty levels. * Polished art assets (use placeholders). * Advanced UI, menus, settings. * Saving/loading progress. * Performance optimization beyond basic functionality. **III. Key Components & Implementation Details** 1. **`GameManager.cs`** * **Purpose:** Controls the overall state, timing, and sequence playback. * **Properties:** * `float bpm`: Beats per minute for the rhythm. * `float cueSpeed`: Speed at which cues travel towards the target. * `float targetZonePosition`: Y-coordinate (or X if horizontal) of the target zone center. * `float spawnPosition`: Y-coordinate (or X) where cues appear. * `GameObject cuePrefab`: Prefab for the visual cue object. * `Transform cueSpawnPoint`: Transform where cues are instantiated. * `AudioSource metronomeSource`: Optional, for playing a beat sound. * `List<CueData> sequence`: Holds the predefined sequence of cues (timing). * `float songStartTime`: Time when the sequence began (using `AudioSettings.dspTime` or `Time.timeSinceLevelLoad`). * `int currentSequenceIndex`: Tracks the next cue to spawn. * `bool isPlaying`: Game state flag. * **Methods:** * `StartSequence()`: Initializes timing, resets index, sets `isPlaying = true`. Starts metronome if used. * `Update()`: * If `isPlaying`, check `sequence` if it's time to spawn the `currentSequenceIndex` cue based on `bpm` and `songStartTime`. * If spawning, instantiate `cuePrefab` at `cueSpawnPoint`, calculate its `targetTime` (arrival time at target zone), and pass necessary data to the cue's script. Increment `currentSequenceIndex`. * Handles end of sequence. * `StopSequence()`: Sets `isPlaying = false`. 2. **`CueData.cs` (or Struct)** * **Purpose:** Simple data structure to define a single cue in the sequence. * **Properties:** * `float beatTimestamp`: The beat number (e.g., 1, 1.5, 2) within the sequence when this cue should *hit* the target zone. * `CueType type`: Enum (e.g., `Tap`). (Initially only Tap needed). 3. **`CueObject.cs` (attached to `cuePrefab`)** * **Purpose:** Represents a single moving cue. * **Properties:** * `float speed`: Movement speed (set by `GameManager`). * `float targetTime`: The exact game time (`Time.timeSinceLevelLoad` or `dspTime`) this cue should ideally be hit. * `bool isHit`: Flag to prevent multiple hits. * `bool canBeHit`: Flag to indicate if it's currently within the hittable window around the target zone. * **Methods:** * `Initialize(float targetTime, float speed)`: Called by `GameManager` on spawn. * `Update()`: * Move the cue downwards (or towards the target) at `speed * Time.deltaTime`. * Check if the cue has passed the target zone *without* being hit and *after* its hittable window - trigger a Miss condition if so and destroy/disable self. * `OnTriggerEnter/Exit2D(Collider2D other)`: If using physics triggers for the target zone, set `canBeHit = true/false`. * `ProcessHit()`: Called by `InputHandler` when a hit is registered on this cue. Sets `isHit = true`, triggers success feedback, potentially disables the cue visually, and schedules destruction. 4. **`TargetZone.cs` (attached to a GameObject with a Collider2D)** * **Purpose:** Defines the area where input is registered and cues are evaluated. * **Properties:** * `float perfectWindow`: Time window (+/- seconds) for a perfect hit. * `float okWindow`: Time window (+/- seconds) for an acceptable (non-miss) hit. (Keep simple first: just Perfect/Miss). * **Methods:** * `OnTriggerEnter2D/Exit2D(Collider2D other)`: Detects `CueObject` entering/leaving the zone's collider. Could be used by `CueObject` to set its `canBeHit` flag. * **Note:** Hit timing validation logic might live more centrally in `InputHandler` or `GameManager` rather than distributed here. 5. **`InputHandler.cs`** * **Purpose:** Detects player input and checks if it corresponds to a hittable cue. * **Properties:** * `TargetZone targetZone`: Reference to the target zone script/object. * `LayerMask cueLayer`: Physics layer for cues. * **Methods:** * `Update()`: * Check for Tap input (`Input.GetMouseButtonDown(0)` or `Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Began`). * If Tap detected: * Determine the current game time (`Time.timeSinceLevelLoad` or `AudioSettings.dspTime`). * Find the "closest" active `CueObject` that is currently `canBeHit` (e.g., using Physics2D overlap checks near the target zone, or iterating through active cues and checking position/timing). * If a potential cue is found: * Calculate `timeDifference = currentTime - cue.targetTime`. * If `Mathf.Abs(timeDifference) <= targetZone.perfectWindow`: * Call `cue.ProcessHit()`. * Trigger "Perfect" feedback via `FeedbackManager`. * Else (if outside window but maybe an OK window exists later): * Trigger "Miss" feedback via `FeedbackManager` (or OK if implementing). * Potentially destroy/disable the cue to prevent late hits. * Else (no cue was hittable): * Optional: Trigger a generic "Miss" feedback for tapping empty space. 6. **`FeedbackManager.cs` (Singleton or easily accessible)** * **Purpose:** Centralized handler for triggering visual/audio feedback. * **Properties:** * `GameObject perfectHitEffectPrefab`: Particle effect/animation for perfect hits. * `GameObject missEffectPrefab`: Effect for misses. * `AudioClip hitSound`: Sound for successful hit. * `AudioClip missSound`: Sound for miss/error. * `AudioSource feedbackAudioSource`: Source to play feedback sounds. * `TextMeshProUGUI feedbackText`: UI Text element to display "Perfect!"/"Miss!". * **Methods:** * `ShowHitFeedback(Vector3 position)`: Instantiate `perfectHitEffectPrefab` at `position`, play `hitSound`, show "Perfect!" text briefly. * `ShowMissFeedback(Vector3 position)`: Instantiate `missEffectPrefab` at `position`, play `missSound`, show "Miss!" text briefly. **IV. Timing Implementation (CRITICAL)** * **Consistency is Key:** Use a consistent time source. * **Option A (Simpler):** `Time.timeSinceLevelLoad`. Easier for basic logic but can drift slightly from audio. Good enough for a demonstrator. * **Option B (More Accurate):** `AudioSettings.dspTime`. Provides highly accurate timing synced with the audio engine. Requires careful handling, especially when scheduling future events based on audio playback. * **Calculations:** * Convert `bpm` to seconds per beat (`60f / bpm`). * Calculate cue `targetTime`: `songStartTime + cue.beatTimestamp * secondsPerBeat`. * Calculate spawn time: `targetTime - travelDuration`, where `travelDuration` is `distance / cueSpeed`. Spawn the cue at this calculated spawn time. **V. UI Implementation (Minimal)** * Canvas with: * `Button` to call `GameManager.StartSequence()`. * `TextMeshProUGUI` (optional) for Score/Combo (incremented in `FeedbackManager` on hit, reset on miss). * `TextMeshProUGUI` for "Perfect!"/"Miss!" feedback text (controlled by `FeedbackManager`). **VI. Placeholder Assets** * **Cue:** Simple white Circle or Square sprite. * **Target Zone:** Semi-transparent rectangle/line across the lane. * **Hit Effect:** Simple particle burst (e.g., Unity's default particle system emitting a few sparks) or a quick scaling/fading circle. * **Miss Effect:** Red flash or different particle effect. * **Audio:** * Metronome: Simple "tick" sound. * Hit Sound: Short, satisfying "click" or "pop". * Miss Sound: Dull "thud" or "buzz". **VII. Build & Test Plan** 1. Implement core components (`GameManager`, `CueObject`, `InputHandler`, `TargetZone`, `FeedbackManager`). 2. Define a simple `sequence` in `GameManager` (e.g., 10 taps on consecutive beats). 3. Use precise timing based on `Time.timeSinceLevelLoad` initially. 4. Integrate basic visual and audio feedback. 5. Test internally: Does it *feel* responsive? Is the timing right? 6. Refine timing windows (`perfectWindow`) based on feel. 7. Build an Android APK. 8. Distribute APK to testers. 9. Gather feedback specifically on: * Timing sensitivity (too strict, too lenient?). * Clarity of visual cues. * Effectiveness of feedback (did they know if they hit/missed?). * Overall satisfaction/fun of the core interaction. **VIII. Success Criteria for Demonstrator** * The demonstrator runs smoothly on a target Android device. * Cues spawn and travel predictably, synchronized with the beat. * User taps near the target zone trigger immediate hit/miss feedback. * Feedback (visual and audio) is clear and correctly corresponds to input timing accuracy. * Testers can understand the core mechanic and provide feedback on its "feel" within 5 minutes of playing. * The codebase is minimal and focused solely on the described scope. Okay, here's an ASCII art representation of the UI and user flow for the **Rhythm Chef: Beat Bites** core mechanics demonstrator. **1. User Flow Diagram** ```ascii +-------------------+ +----------------------+ +----------------------+ | Start Screen | ---+->| Gameplay Loop |---+->| End Screen (Simple)| | (Title, [Start]) | User | (Cues, Target, Input)| User | (Score?, [Restart])| +-------------------+ Taps | | Finishes Sequence +----------------------+ Start +--<-------------------+ Or Fails | (Optional) | | | | Back to Start Screen | +----------------------+ +----------------------+ ``` **2. UI Mockups (ASCII Art)** **A. Start Screen** ```ascii +-----------------------------------------+ | | | // RHYTHM CHEF: BEAT BITES // | | (Core Demo) | | | | | | | | | | +-----------+ | | | [ START ]| | | +-----------+ | | | | | +-----------------------------------------+ User taps [ START ] --> Transitions to Gameplay Screen ``` **B. Gameplay Screen (Mid-Sequence)** * Imagine cues `(*)` moving downwards `v` towards the `TARGET ZONE`. * The player needs to tap when a cue is inside the `TARGET ZONE`. ```ascii +-----------------------------------------+ | SCORE: 005 COMBO: 3x | <--- Optional Score/Combo Display |-----------------------------------------| | | | | | (*) | <--- Incoming Cue 1 | v | | | | | | (*) | <--- Incoming Cue 2 | v | | | | ===================================== | \ | | TARGET ZONE | | <--- The Area to Tap In | ===================================== | / | v | | (*) | <--- Cue that just passed (or was missed) | | | | | | |-----------------------------------------| | FEEDBACK: | <--- Area for text feedback +-----------------------------------------+ ``` **C. Gameplay Screen (Moment of Tap - Perfect Hit)** * Player taps as `(*)` enters the `TARGET ZONE`. * Visual & text feedback appears. ```ascii +-----------------------------------------+ | SCORE: 006 COMBO: 4x | <--- Score/Combo Updated |-----------------------------------------| | | | | | (*) | | v | | | | | | (*) | | v | | | | ===================================== | | | > > > PERFECT! < < < | | <--- Cue hit inside, feedback shown | ===================================== | | | | | (Effect) | <--- Visual effect (e.g., ASCII explosion *`*`) | | | | |-----------------------------------------| | FEEDBACK: Perfect! | <--- Text feedback updated +-----------------------------------------+ ``` **D. Gameplay Screen (Moment of Tap - Miss)** * Player taps too early/late, or misses a cue. ```ascii +-----------------------------------------+ | SCORE: 006 COMBO: 0x | <--- Combo Reset |-----------------------------------------| | | | | | (*) | | v | | | | | | (*) | | v | | | | ===================================== | | | TARGET ZONE | | | ===================================== | | v | | (X) | <--- Missed cue indication / effect | | | | |-----------------------------------------| | FEEDBACK: Miss! | <--- Text feedback updated +-----------------------------------------+ ``` **E. End Screen (Simple Demo End)** * Appears after the predefined sequence finishes. ```ascii +-----------------------------------------+ | | | SEQUENCE COMPLETE! | | | | (Final Score: 025) | <--- Optional final score | | | | | +-------------+ | | | [ RESTART ] | | | +-------------+ | | | | | +-----------------------------------------+ User taps [ RESTART ] --> Transitions back to Gameplay Screen (restarts sequence) (Or could go back to the Start Screen) ``` This ASCII representation outlines the essential visual elements and the flow between them for the core mechanics demonstrator, focusing on clarity for user feedback on the rhythm interaction. Okay, here are specific pixel-based dimensions and positions for the UI elements based on a **reference screen resolution of 1080x1920 pixels (Width x Height - Portrait Orientation)**. **Important Considerations:** * **Reference Only:** These are *fixed pixel values* for the specified reference resolution. In a real implementation (e.g., using Unity Canvas), you would use anchors, pivots, and potentially scaling components (like Canvas Scaler UI Scale Mode) to ensure the UI adapts correctly to different screen sizes and aspect ratios. * **Origin Point:** Assume the (0, 0) coordinate is the **bottom-left** corner of the screen, common in some UI systems, or **top-left** (common in others - I will specify based on typical Unity Canvas usage: **(0,0) is Bottom-Left, (1080, 1920) is Top-Right** unless stated otherwise). Positions usually refer to the object's **pivot point** (often the center, unless specified). * **Font Sizes:** Pixel sizes for fonts are approximate and depend heavily on the specific font file used. * **Actors:** Actors like Cues and Effects have positions that change dynamically or are instantiated at specific world/UI coordinates. --- **A. Start Screen (1080x1920)** * **Widget:** `Title Text` (e.g., "RHYTHM CHEF: BEAT BITES") * **Position (Pivot: Center):** (540, 1600) `(Center X, ~83% Height)` * **Dimensions:** Auto-sized by text, constrained if needed. * **Font Size:** 90px * **Anchor Preset (Unity):** Top-Center * **Widget:** `Subtitle Text` (e.g., "(Core Demo)") * **Position (Pivot: Center):** (540, 1480) `(Center X, below Title)` * **Dimensions:** Auto-sized by text. * **Font Size:** 40px * **Anchor Preset (Unity):** Top-Center * **Widget:** `Start Button` * **Position (Pivot: Center):** (540, 400) `(Center X, ~21% Height)` * **Dimensions:** 450px (Width) x 150px (Height) * **Anchor Preset (Unity):** Bottom-Center * **Widget:** `Start Button Text` (e.g., "[ START ]") * **Position:** Centered within the Start Button. * **Font Size:** 60px --- **B. Gameplay Screen (1080x1920)** * **Widget:** `Score Text Label` (e.g., "SCORE:") * **Position (Pivot: Top-Left):** (40, 1880) `(Padding Left, Padding Top)` * **Dimensions:** Auto-sized by text. * **Font Size:** 50px * **Anchor Preset (Unity):** Top-Left * **Widget:** `Score Value Text` (e.g., "000") * **Position (Pivot: Top-Left):** (200, 1880) `(Right of Label, Same Top)` * **Dimensions:** Auto-sized by text (allow space for growth). * **Font Size:** 50px * **Anchor Preset (Unity):** Top-Left * **Widget:** `Combo Text Label` (e.g., "COMBO:") * **Position (Pivot: Top-Right):** (900, 1880) `(Approx position, adjust based on Value width)` * **Dimensions:** Auto-sized by text. * **Font Size:** 50px * **Anchor Preset (Unity):** Top-Right * **Widget:** `Combo Value Text` (e.g., "0x") * **Position (Pivot: Top-Right):** (1040, 1880) `(Padding Right, Same Top)` * **Dimensions:** Auto-sized by text (allow space for growth). * **Font Size:** 50px * **Anchor Preset (Unity):** Top-Right * **Area:** `Cue Travel Area` (Logical, no visual widget) * **Bounds:** Approx X = Center (e.g., 540), Y from 1800 (Spawn) down to ~200 (Despawn below target). * **Widget:** `Target Zone Visual` (The horizontal bar indicator) * **Position (Pivot: Center):** (540, 400) `(Center X, Defined Y)` * **Dimensions:** 900px (Width) x 80px (Height) * **Anchor Preset (Unity):** Position manually or Bottom-Center with Y offset. * **Note:** The *logical* hit detection center Y might be exactly 400. The timing windows (`perfectWindow`, `okWindow`) define the tolerance around this point in *time*, not necessarily pixels vertically (though they are related via cue speed). * **Actor:** `Cue Object` (Visual representation) * **Position:** Dynamic. Spawns near Y=1800, travels downwards to Y=400 (target). X is typically centered (540). * **Dimensions:** 80px (Width) x 80px (Height) (Example, adjust for visual clarity) * **Widget:** `Feedback Text` (e.g., "Perfect!", "Miss!") * **Position (Pivot: Center):** (540, 600) `(Center X, Above Target Zone)` * **Dimensions:** Auto-sized by text. * **Font Size:** 70px * **Anchor Preset (Unity):** Position manually or relative to Target Zone. (Appears temporarily). * **Actor:** `Hit/Miss Feedback Effect` (Particles/Animation) * **Position:** Instantiated at the Cue's position *when* the hit/miss occurs (approx X=540, Y=400). * **Dimensions:** Dynamic based on the effect design (e.g., expands to 150x150px briefly). --- **C. End Screen (1080x1920)** * **Widget:** `Completion Text` (e.g., "SEQUENCE COMPLETE!") * **Position (Pivot: Center):** (540, 1200) `(Center X, ~62% Height)` * **Dimensions:** Auto-sized by text. * **Font Size:** 70px * **Anchor Preset (Unity):** Center * **Widget:** `Final Score Text` (Optional, e.g., "Final Score: 025") * **Position (Pivot: Center):** (540, 1050) `(Center X, below Completion text)` * **Dimensions:** Auto-sized by text. * **Font Size:** 50px * **Anchor Preset (Unity):** Center * **Widget:** `Restart Button` * **Position (Pivot: Center):** (540, 400) `(Center X, ~21% Height - same as Start Button)` * **Dimensions:** 450px (Width) x 150px (Height) * **Anchor Preset (Unity):** Bottom-Center * **Widget:** `Restart Button Text` (e.g., "[ RESTART ]") * **Position:** Centered within the Restart Button. * **Font Size:** 60px --- Remember to implement proper UI scaling and anchoring in your chosen game engine to handle various device resolutions effectively beyond this 1080x1920 reference.
2
+ Make the look and feel 100 times better, employ procedural graphics and emojis as sprites.