Web-based location game mirip Pokemon GO. Player membuka browser โ muncul peta real-time (Mapbox GL JS) berpusat di lokasi mereka โ monster/object spawn di sekitar berdasarkan GPS โ player berjalan mendekati โ tap untuk encounter โ mini battle/catch UI.
| Layer | Teknologi |
|---|---|
| Framework | React 19 + TypeScript (sudah ada) |
| Build Tool | Vite 8 (sudah ada) |
| Peta | Mapbox GL JS v3.x (npm: mapbox-gl) |
| State Management | Zustand (ringan, minimal boilerplate) |
| Geolocation | Browser Geolocation API (watchPosition) |
| Asset | Dummy sprites via CSS / SVG / emoji (tanpa 3D berat) |
| Storage | LocalStorage (save progress, inventory) |
| Deployment | Vite build โ static hosting |
src/
โโโ main.tsx # Entry point
โโโ App.tsx # Root component + routing
โโโ index.css # Global styles & design tokens
โ
โโโ config/
โ โโโ mapbox.ts # Mapbox access token & map config
โ โโโ creatures.ts # Data dummy creature/monster
โ โโโ constants.ts # Game constants (spawn radius, catch rate, dll)
โ
โโโ store/
โ โโโ useGameStore.ts # Zustand store (inventory, score, status)
โ
โโโ hooks/
โ โโโ useGeolocation.ts # Wrapper Geolocation API (watchPosition)
โ โโโ useSpawnManager.ts # Logic spawn creature berdasarkan lokasi
โ โโโ useMapbox.ts # Hook inisialisasi & kontrol Mapbox map
โ
โโโ components/
โ โโโ Map/
โ โ โโโ GameMap.tsx # Komponen peta utama (Mapbox GL)
โ โ โโโ PlayerMarker.tsx # Marker player di peta
โ โ โโโ CreatureMarker.tsx # Marker creature yang spawn
โ โ
โ โโโ HUD/
โ โ โโโ TopBar.tsx # Status bar (level, nama, dll)
โ โ โโโ BottomNav.tsx # Navigasi bawah (Map, Inventory, Profile)
โ โ โโโ Compass.tsx # Arah kompas (optional)
โ โ
โ โโโ Encounter/
โ โ โโโ EncounterScreen.tsx # Layar encounter saat tap creature
โ โ โโโ CatchAnimation.tsx # Animasi menangkap
โ โ โโโ CreatureCard.tsx # Card detail creature
โ โ
โ โโโ Inventory/
โ โ โโโ InventoryScreen.tsx # List creature yang sudah ditangkap
โ โ โโโ CreatureEntry.tsx # Item creature di inventory
โ โ
โ โโโ UI/
โ โโโ Modal.tsx # Reusable modal
โ โโโ Button.tsx # Styled button
โ โโโ LoadingScreen.tsx # Loading / GPS waiting screen
โ
โโโ utils/
โ โโโ geo.ts # Haversine distance, bearing, dll
โ โโโ random.ts # Random spawn logic
โ โโโ storage.ts # LocalStorage helpers
โ
โโโ types/
โโโ index.ts # TypeScript types (Creature, Player, Position, dll)
Map fullscreen + player marker bergerak real-time
Tasks:
- Install
mapbox-gl+@types/mapbox-gl - Buat
config/mapbox.tsโ simpan access token + default map style - Buat
hooks/useGeolocation.tsโ wrappernavigator.geolocation.watchPositiondengan error handling & high accuracy - Buat
hooks/useMapbox.tsโ init map, set center, handle resize - Buat
components/Map/GameMap.tsxโ fullscreen Mapbox map (dark/game style) - Buat
components/Map/PlayerMarker.tsxโ pulsing blue dot marker di posisi user - Buat
components/UI/LoadingScreen.tsxโ tampilkan saat menunggu GPS fix - Setup global CSS: fullscreen layout, dark theme, mobile-first
Catatan Optimasi:
- Gunakan
mapbox://styles/mapbox/dark-v11untuk nuansa game watchPositiondenganenableHighAccuracy: true,maximumAge: 2000- Map: disable rotation & pitch untuk performa mobile, enable kembali jika perlu
- Gunakan
map.easeTo()untuk smooth camera follow
Monster muncul di sekitar player berdasarkan lokasi
Tasks:
- Buat
types/index.tsโ defineCreature,SpawnPoint,PlayerState,Position - Buat
config/creatures.tsโ daftar 10-15 dummy creatures (nama, tipe, rarity, emoji/icon, stats) - Buat
config/constants.tsโ spawn radius (50-200m), max active spawns (8), spawn interval (15s), despawn time (5min) - Buat
utils/geo.tsโhaversineDistance(),randomPointInRadius(),isWithinRange() - Buat
utils/random.tsโ weighted random berdasarkan rarity - Buat
hooks/useSpawnManager.ts:- Generate spawn points di sekitar player
- Spawn interval timer
- Despawn creature yang sudah expired / terlalu jauh
- Max spawns limiter
- Buat
components/Map/CreatureMarker.tsxโ marker animasi di peta (bounce/glow effect) - Render creature markers di
GameMap.tsx
Catatan Optimasi:
- Spawn logic di
requestIdleCallbackatau throttled interval - Marker menggunakan HTML overlay (Mapbox
Markerclass), bukan canvas layer โ lebih fleksibel untuk animasi CSS - Creature data minimal di memory, no image preloading sampai encounter
- Gunakan
Set/Mapuntuk tracking spawn IDs, avoid array scanning
UI overlay di atas peta: status bar, navigasi, info
Tasks:
- Buat
store/useGameStore.tsโ Zustand store: player info, inventory, active encounter - Buat
components/HUD/TopBar.tsxโ player name, level, XP bar - Buat
components/HUD/BottomNav.tsxโ tab navigation (Map / Inventory / Profile) - Buat
components/UI/Button.tsxโ reusable styled button dengan variants - Buat
components/UI/Modal.tsxโ reusable modal/drawer - Integrasikan HUD overlay di
App.tsx - Tambah proximity indicator โ jika creature dekat, UI feedback (pulse, glow border)
Design Notes:
- UI harus semi-transparent / glassmorphism agar peta tetap terlihat
- Gunakan
backdrop-filter: blur()untuk glass effect - Z-index management: Map (0) โ Creature markers (10) โ HUD (100) โ Modal (200)
- Semua animasi pakai CSS transitions / keyframes, bukan JS
Tap creature โ encounter screen โ catch mechanic
Tasks:
- Buat
components/Encounter/EncounterScreen.tsx:- Fullscreen overlay
- Creature display (besar, animasi idle)
- Info: nama, tipe, CP/level
- Tombol "Throw Ball" / catch action
- Catch probability system (random + rarity modifier)
- Result: caught / fled
- Buat
components/Encounter/CatchAnimation.tsxโ animasi lempar bola (CSS keyframes) - Buat
components/Encounter/CreatureCard.tsxโ card detail creature - Update
useGameStoreโ handle encounter flow, add to inventory on catch - Buat
utils/storage.tsโ save/load game state ke LocalStorage - Auto-save setiap catch / event penting
Catch Mechanic (Simple):
catchRate = baseCatchRate(rarity) - (creatureLevel * 0.02)
roll = Math.random()
if (roll < catchRate) โ CAUGHT
else if (roll > 0.85) โ FLED
else โ MISSED (bisa coba lagi)
Lihat dan kelola creature yang sudah ditangkap
Tasks:
- Buat
components/Inventory/InventoryScreen.tsxโ grid/list semua creature - Buat
components/Inventory/CreatureEntry.tsxโ card per creature (nama, tipe, CP, waktu tangkap) - Filter & sort (by tipe, rarity, waktu)
- Detail view saat tap creature
- Collection progress โ "X / Total caught"
- Empty state yang menarik
Final touches untuk experience premium
Tasks:
- Tambah sound effects (optional, Web Audio API)
- Haptic feedback via
navigator.vibrate()saat catch - Smooth transitions antar screen
- Error boundaries & fallback UI
- Offline indicator
- Performance audit:
- Bundle size check
- Lazy load Encounter & Inventory screens
- Debounce/throttle geolocation updates
- Remove unused Mapbox features
- PWA support (manifest.json, service worker โ optional)
- Responsive: pastikan optimal di mobile portrait
interface Position {
lat: number;
lng: number;
accuracy?: number;
timestamp: number;
}
interface Creature {
id: string;
name: string;
type: "fire" | "water" | "grass" | "electric" | "dark" | "normal";
rarity: "common" | "uncommon" | "rare" | "legendary";
emoji: string; // Dummy visual
baseCatchRate: number; // 0.0 - 1.0
baseCP: number; // Base combat power
description: string;
}
interface SpawnPoint {
id: string;
creature: Creature;
position: Position;
spawnedAt: number; // timestamp
expiresAt: number; // timestamp
cp: number; // Rolled CP for this instance
}
interface CaughtCreature {
id: string;
creature: Creature;
cp: number;
caughtAt: number;
caughtLocation: Position;
}
interface PlayerState {
name: string;
level: number;
xp: number;
inventory: CaughtCreature[];
totalCaught: number;
totalSeen: number;
}| Nama | Tipe | Rarity | Emoji | Base Catch Rate |
|---|---|---|---|---|
| Flamepup | Fire | Common | ๐ฅ | 0.70 |
| Aquafin | Water | Common | ๐ | 0.70 |
| Leafling | Grass | Common | ๐ฟ | 0.70 |
| Voltkit | Electric | Uncommon | โก | 0.50 |
| Shadowmew | Dark | Uncommon | ๐ | 0.50 |
| Blazewolf | Fire | Rare | ๐บ | 0.30 |
| Tideclaw | Water | Rare | ๐ฆ | 0.30 |
| Thornvine | Grass | Rare | ๐น | 0.30 |
| Stormdrake | Electric | Legendary | ๐ | 0.10 |
| Voidreaper | Dark | Legendary | ๐ป | 0.10 |
- Code splitting: Lazy load
EncounterScreendanInventoryScreen(React.lazy + Suspense) - Mapbox GL JS: ~200KB gzipped โ load sekali, cache browser
- Tree shaking: import hanya yang dibutuhkan
- Preload: CSS & font di
<head>
watchPositiondenganmaximumAge: 3000msuntuk hemat battery- Throttle map updates ke max 1x per detik
- Fallback ke
getCurrentPositionjika watch gagal
- Batasi creature markers on-screen (max 8-10)
- Gunakan
will-change: transformpada elemen yang sering bergerak - CSS animations > JS animations (GPU accelerated)
React.memopada marker components- Avoid re-render map saat HUD update (isolasi state)
- Cleanup spawns yang expired
- Dispose Mapbox markers yang di-remove
- LocalStorage max 5MB โ compress inventory jika perlu
touch-action: manipulationโ no double-tap zoom delay- Viewport meta:
width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no - Full-height:
100dvh(dynamic viewport height)
// config/mapbox.ts
export const MAPBOX_CONFIG = {
accessToken: "YOUR_MAPBOX_ACCESS_TOKEN", // Perlu diisi
style: "mapbox://styles/mapbox/dark-v11",
defaultZoom: 17, // Street-level zoom untuk game
maxZoom: 19,
minZoom: 14,
pitchEnabled: false, // Disable 3D tilt untuk performa
rotateEnabled: false, // Disable rotasi untuk konsistensi
};Important
Mapbox Access Token diperlukan untuk menjalankan peta. Daftar gratis di https://account.mapbox.com โ free tier: 50,000 map loads/bulan.
Note
Semua creature menggunakan emoji/SVG sebagai dummy. Bisa diganti asset real nanti. Tidak ada backend/server โ semua logic client-side, data di LocalStorage.
Fase 1 (Foundation) โ bisa demo: peta + player marker
Fase 2 (Spawning) โ bisa demo: creature muncul di sekitar
Fase 3 (HUD) โ bisa demo: UI game lengkap
Fase 4 (Encounter) โ bisa demo: tangkap creature
Fase 5 (Inventory) โ bisa demo: lihat koleksi
Fase 6 (Polish) โ production ready
Setiap fase menghasilkan demo-able increment โ bisa di-test dan di-review sebelum lanjut.