Skip to content

Commit 36082fb

Browse files
committed
feat: Add infinite runner game with Web3 educational quizzes
- Created full-screen infinite runner game similar to Chrome dinosaur game - Integrated baby character from /images/character/baby-full.png - Added double jump mechanic for better gameplay - Implemented 8 enemy types with unique behaviors (cactus, rock, bird, drone, satellite, meteor, blockchain, crypto) - Added dynamic flying enemies with wave motion patterns - Created Web3 quiz system that triggers every 1000 points for level progression - Added invulnerability system (5s on start, 4s after level up) for fair gameplay - Implemented arcade machine border with realistic frame, bezel, and CRT effects - Added collapsible controls section with smooth animations - Integrated XP/points saving to account system - Disabled page scrolling during gameplay - Enhanced duck mechanics with improved hitbox - Added 4 progressive themes (Day, Sunset, Night, Cyber) - Created context-aware back button for embedded vs standalone modes - Hidden footer during gameplay for better UX - Game embedded directly in /mini-games/[gameId] for instant play
1 parent d96c769 commit 36082fb

File tree

5 files changed

+1520
-152
lines changed

5 files changed

+1520
-152
lines changed

GAME_FEATURES.md

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# 🎮 Infinite Runner Game - Features & Documentation
2+
3+
## Overview
4+
A full-screen infinite runner game similar to Chrome's dinosaur game, integrated with the Trustless Work platform's account and reward system.
5+
6+
## 🚀 Features Implemented
7+
8+
### 1. Full-Screen Game Experience
9+
- **Route**: `/play/[gameId]`
10+
- **Layout**: Header visible with account info, rest is full-screen game canvas
11+
- **Responsive**: Adapts to different screen sizes
12+
13+
### 2. Infinite Runner Gameplay
14+
Based on Chrome's dinosaur game with enhancements:
15+
16+
#### Player Controls
17+
- **Space/Arrow Up**: Jump
18+
- **Arrow Down**: Duck/Crouch
19+
- **Arrow Right**: Speed up (1.5x)
20+
- **Arrow Left**: Slow down (0.5x)
21+
- **ESC**: Pause/Resume
22+
23+
#### Game Mechanics
24+
- SVG-based graphics for smooth rendering
25+
- Physics-based jumping with gravity
26+
- Collision detection with obstacles
27+
- Coin collection system (+50 points per coin)
28+
- Scrolling background
29+
- Progressive difficulty
30+
31+
### 3. Progressive Difficulty System
32+
33+
#### Level Progression
34+
- **Level 1 (Day Theme)**: Basic obstacles (cactus, rocks)
35+
- **Level 2 (Sunset Theme)**: Added flying obstacles (birds) and blockchain icons
36+
- **Level 3 (Night Theme)**: All obstacle types active, faster speed
37+
- **Level 4+ (Cyber Theme)**: Maximum difficulty with crypto obstacles
38+
39+
#### Difficulty Scaling
40+
- Levels up every 60 seconds (3600 frames)
41+
- Speed increases with each level
42+
- New obstacle types unlock at higher levels
43+
- Obstacle spawn rate increases
44+
- Visual theme changes to indicate difficulty
45+
46+
### 4. Reward System
47+
48+
#### Scoring
49+
- **Base Score**: +1 per frame while alive
50+
- **Coin Bonus**: +50 points per coin collected
51+
- **High Score**: Tracked locally in browser
52+
53+
#### XP & Points Integration
54+
- **XP Earned**: 1 XP per 10 score points
55+
- **Account Points**: 1 point per 10 score points
56+
- **Auto-Save**: Progress automatically saved to account on game over
57+
- **Visual Feedback**: Save status displayed on game over screen
58+
59+
### 5. Visual Themes
60+
61+
Each level has a unique theme:
62+
63+
1. **Day (Level 1)**
64+
- Blue sky background
65+
- Green ground
66+
- White clouds
67+
- Beginner difficulty
68+
69+
2. **Sunset (Level 2)**
70+
- Orange/pink/purple gradient
71+
- Orange ground
72+
- Enhanced visuals
73+
- Medium difficulty
74+
75+
3. **Night (Level 3)**
76+
- Dark indigo/purple/black
77+
- Gray ground
78+
- Stars instead of clouds
79+
- Hard difficulty
80+
81+
4. **Cyber (Level 4+)**
82+
- Cyan/purple/pink neon
83+
- Purple ground
84+
- Futuristic aesthetic
85+
- Expert difficulty
86+
87+
### 6. Obstacle Types
88+
89+
Different obstacles with unique behaviors:
90+
91+
- **Cactus**: Ground-level, static
92+
- **Rock**: Ground-level, triangular
93+
- **Bird**: Flying, mid-air height
94+
- **Blockchain**: Chained blocks icon
95+
- **Crypto**: Bitcoin symbol coin
96+
97+
### 7. Game States
98+
99+
- **Ready**: Initial screen with instructions
100+
- **Playing**: Active gameplay
101+
- **Paused**: ESC to pause/resume
102+
- **Game Over**: Shows stats and save status
103+
104+
## 🎯 How to Play
105+
106+
1. Navigate to `/mini-games/[gameId]`
107+
2. Click "START GAME" (requires connected wallet)
108+
3. Game opens in full-screen at `/play/[gameId]`
109+
4. Use controls to avoid obstacles and collect coins
110+
5. Survive as long as possible to earn XP and points
111+
6. Progress automatically saves to your account
112+
113+
## 💾 Account Integration
114+
115+
### Requirements
116+
- User must have connected wallet
117+
- Account must be created
118+
119+
### Benefits
120+
- XP earned adds to account experience
121+
- Points earned add to account total
122+
- Progress contributes to leveling up
123+
- Stats tracked for leaderboards
124+
125+
### Saves Automatically
126+
- On game over (1 second delay)
127+
- Shows save status on end screen
128+
- Toast notification on successful save
129+
- Error handling with retry option
130+
131+
## 🎨 Technical Implementation
132+
133+
### Technologies
134+
- **React**: Component-based architecture
135+
- **TypeScript**: Type-safe development
136+
- **SVG**: Scalable graphics
137+
- **Next.js**: Routing and SSR
138+
- **Firebase**: Account data persistence
139+
- **RequestAnimationFrame**: Smooth 60fps gameplay
140+
141+
### Performance Optimizations
142+
- Efficient collision detection
143+
- Object pooling for obstacles/coins
144+
- Cleanup of off-screen objects
145+
- Optimized render loop
146+
147+
### Code Structure
148+
```
149+
/app/play/[gameId]/page.tsx # Main game route
150+
/components/games/InfiniteRunner.tsx # Game component
151+
```
152+
153+
## 🔧 Future Enhancements
154+
155+
Potential additions:
156+
- Multiplayer leaderboards
157+
- Daily challenges
158+
- Power-ups and special abilities
159+
- More obstacle types and themes
160+
- Mobile touch controls
161+
- Sound effects and music
162+
- Achievements and badges
163+
- Social sharing
164+
165+
## 🐛 Known Issues
166+
167+
None currently! All features working as expected.
168+
169+
## 📝 Testing Checklist
170+
171+
- [x] Player controls (jump, duck, speed)
172+
- [x] Collision detection
173+
- [x] Coin collection
174+
- [x] Level progression
175+
- [x] Theme changes
176+
- [x] Score tracking
177+
- [x] XP calculation
178+
- [x] Account integration
179+
- [x] Auto-save functionality
180+
- [x] Pause/Resume
181+
- [x] Navigation
182+
- [x] Responsive design
183+
184+
---
185+
186+
**Enjoy the game!** 🎮🚀
187+

app/globals.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,16 @@ body {
496496
}
497497
}
498498

499+
/* Game animations */
500+
@keyframes flap {
501+
0% {
502+
transform: scaleY(1) translateY(0);
503+
}
504+
100% {
505+
transform: scaleY(0.7) translateY(-2px);
506+
}
507+
}
508+
499509
.animate-fade-in {
500510
animation: fade-in 0.5s ease-out;
501511
}

app/mini-games/[gameId]/page.tsx

Lines changed: 11 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { NexusPrime } from '@/components/layout/NexusPrime';
1111
import XboxStyleConsole from '@/components/ui/XboxStyleConsole';
1212
import RetroArcadeSidebar from '@/components/ui/RetroArcadeSidebar';
1313
import { useGlobalWallet } from '@/contexts/wallet/WalletContext';
14+
import InfiniteRunner from '@/components/games/InfiniteRunner';
1415
import Image from 'next/image';
1516

1617
// Game data with detailed information - synced with MiniGameStore
@@ -349,155 +350,19 @@ export default function GamePage() {
349350
{/* Game Ready Screen */}
350351
{loadingState === 'ready' && (
351352
<>
352-
{/* Beta Games - Start Screen */}
353-
{game.status === 'beta' && (
354-
<div className='space-y-8 mt-10'>
355-
{/* Epic Game Start Screen */}
356-
<div className='relative'>
357-
{/* Animated Background Effect */}
358-
<div className='absolute inset-0 bg-gradient-to-br from-cyan-500/10 via-purple-500/10 to-pink-500/10 rounded-3xl blur-3xl animate-pulse'></div>
359-
360-
{/* Main Game Screen Container */}
361-
<div className='relative bg-gradient-to-br from-slate-900/95 via-purple-900/95 to-slate-900/95 backdrop-blur-xl border-4 border-cyan-400/30 rounded-3xl p-8 md:p-12 shadow-2xl overflow-hidden'>
362-
{/* Animated Corner Accents */}
363-
<div className='absolute top-0 left-0 w-32 h-32 bg-gradient-to-br from-cyan-400/20 to-transparent rounded-br-full'></div>
364-
<div className='absolute bottom-0 right-0 w-32 h-32 bg-gradient-to-tl from-purple-400/20 to-transparent rounded-tl-full'></div>
365-
366-
{/* Game Title Section */}
367-
<div className='relative text-center mb-12'>
368-
<div className='flex justify-center mb-6'>
369-
<div className='text-9xl animate-bounce drop-shadow-2xl'>
370-
{game.icon}
371-
</div>
372-
</div>
373-
374-
<h1 className='text-6xl md:text-8xl font-black text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-purple-400 to-pink-400 mb-4 animate-pulse tracking-tight'>
375-
{game.title}
376-
</h1>
377-
378-
<div className='inline-block px-6 py-2 bg-blue-500/30 border-2 border-blue-400 rounded-full mb-6'>
379-
<span className='text-blue-300 font-bold text-lg uppercase tracking-wider'>
380-
🎮 Beta Access Available
381-
</span>
382-
</div>
383-
384-
<p className='text-2xl text-white/90 font-semibold max-w-2xl mx-auto leading-relaxed'>
385-
{game.subtitle}
386-
</p>
387-
</div>
388-
389-
{/* Stats Grid */}
390-
<div className='grid grid-cols-1 md:grid-cols-3 gap-6 mb-12'>
391-
{/* XP Reward */}
392-
<div className='bg-gradient-to-br from-yellow-500/20 to-orange-500/20 border-2 border-yellow-400/50 rounded-2xl p-6 text-center transform hover:scale-105 transition-all duration-300'>
393-
<div className='text-5xl mb-3'></div>
394-
<div className='text-yellow-300 text-sm font-semibold uppercase tracking-wider mb-2'>
395-
Earn XP
396-
</div>
397-
<div className='text-white text-3xl font-black'>
398-
{game.rewards.split('+')[0].trim()}
399-
</div>
400-
</div>
401-
402-
{/* NFT Badge */}
403-
<div className='bg-gradient-to-br from-purple-500/20 to-pink-500/20 border-2 border-purple-400/50 rounded-2xl p-6 text-center transform hover:scale-105 transition-all duration-300'>
404-
<div className='text-5xl mb-3'>🏆</div>
405-
<div className='text-purple-300 text-sm font-semibold uppercase tracking-wider mb-2'>
406-
Unlock Badge
407-
</div>
408-
<div className='text-white text-xl font-black'>
409-
{game.rewards.includes('+') ? game.rewards.split('+')[1].trim() : 'Exclusive NFT'}
410-
</div>
411-
</div>
412-
413-
{/* Difficulty */}
414-
<div className='bg-gradient-to-br from-cyan-500/20 to-blue-500/20 border-2 border-cyan-400/50 rounded-2xl p-6 text-center transform hover:scale-105 transition-all duration-300'>
415-
<div className='text-5xl mb-3'>🎯</div>
416-
<div className='text-cyan-300 text-sm font-semibold uppercase tracking-wider mb-2'>
417-
Difficulty
418-
</div>
419-
<div className='text-white text-2xl font-black'>
420-
{game.difficulty}
421-
</div>
422-
</div>
423-
</div>
424-
425-
{/* Additional Info Row */}
426-
<div className='flex flex-wrap justify-center gap-4 mb-12'>
427-
<div className='flex items-center gap-2 px-4 py-2 bg-white/10 rounded-full border border-white/20'>
428-
<span className='text-2xl'>⏱️</span>
429-
<span className='text-white font-semibold'>{game.estimatedTime}</span>
430-
</div>
431-
<div className='flex items-center gap-2 px-4 py-2 bg-white/10 rounded-full border border-white/20'>
432-
<span className='text-2xl'>👥</span>
433-
<span className='text-white font-semibold'>{game.currentPlayers.toLocaleString()} Players</span>
434-
</div>
435-
<div className='flex items-center gap-2 px-4 py-2 bg-white/10 rounded-full border border-white/20'>
436-
<span className='text-2xl'></span>
437-
<span className='text-white font-semibold'>{game.rating}/5.0</span>
438-
</div>
439-
</div>
440-
441-
{/* Start Button */}
442-
<div className='text-center'>
443-
<button
444-
disabled={!isConnected}
445-
className={`group relative px-16 py-6 text-3xl font-black uppercase tracking-wider rounded-2xl transform transition-all duration-300 ${
446-
isConnected
447-
? 'bg-gradient-to-r from-cyan-500 via-purple-500 to-pink-500 hover:from-cyan-400 hover:via-purple-400 hover:to-pink-400 text-white shadow-2xl hover:scale-110 hover:shadow-cyan-500/50 animate-pulse'
448-
: 'bg-gray-600 text-gray-400 cursor-not-allowed'
449-
}`}
450-
>
451-
<span className='relative z-10 flex items-center justify-center gap-3'>
452-
{isConnected ? (
453-
<>
454-
<span>🎮</span>
455-
<span>Start Game</span>
456-
<span>🚀</span>
457-
</>
458-
) : (
459-
<>
460-
<span>🔒</span>
461-
<span>Connect Wallet to Play</span>
462-
</>
463-
)}
464-
</span>
465-
{isConnected && (
466-
<div className='absolute inset-0 bg-gradient-to-r from-cyan-400 via-purple-400 to-pink-400 rounded-2xl blur-xl opacity-50 group-hover:opacity-75 transition-opacity'></div>
467-
)}
468-
</button>
469-
470-
{!isConnected && (
471-
<p className='text-white/70 text-sm mt-4'>
472-
Connect your wallet to start playing and earning rewards
473-
</p>
474-
)}
475-
</div>
476-
477-
{/* Feature Pills */}
478-
<div className='mt-12 pt-8 border-t border-white/20'>
479-
<h4 className='text-center text-white/80 font-semibold mb-4 text-lg'>
480-
What You'll Master:
481-
</h4>
482-
<div className='flex flex-wrap justify-center gap-3'>
483-
{game.features.map((feature, index) => (
484-
<span
485-
key={index}
486-
className='px-4 py-2 bg-gradient-to-r from-purple-500/30 to-pink-500/30 border border-purple-400/50 text-purple-200 text-sm font-semibold rounded-full'
487-
>
488-
{feature}
489-
</span>
490-
))}
491-
</div>
492-
</div>
493-
</div>
353+
{/* Beta/Available Games - Show Actual Game */}
354+
{(game.status === 'beta' || game.status === 'available') && (
355+
<div className='mt-10'>
356+
{/* Game Container */}
357+
<div className='relative' style={{ height: 'calc(100vh - 200px)', minHeight: '600px' }}>
358+
<InfiniteRunner gameId={gameId} gameTitle={game.title} embedded={true} />
494359
</div>
495360
</div>
496361
)}
497362

498-
{/* Development Games - Info Screen (Keep Current Design) */}
363+
{/* Development Games - Show Info Screen (old behavior) */}
499364
{game.status === 'development' && (
500-
<div className='space-y-12 mt-10'>
365+
<div className='space-y-8 mt-10 mb-20'>
501366
{/* Game Header */}
502367
<div className='text-center'>
503368
<h1 className='text-5xl md:text-7xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-cyan-400 via-purple-400 to-pink-400 mb-4'>
@@ -618,7 +483,8 @@ export default function GamePage() {
618483
autoOpen={false}
619484
/>
620485

621-
<Footer />
486+
{/* Hide footer for beta games (where game is shown) */}
487+
{game.status !== 'beta' && game.status !== 'available' && <Footer />}
622488
</div>
623489
);
624490
}

0 commit comments

Comments
 (0)