diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx
deleted file mode 100644
index cfbc1e2..0000000
--- a/app/(tabs)/_layout.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { Tabs } from 'expo-router';
-import React from 'react';
-import { Platform } from 'react-native';
-
-import { HapticTab } from '@/components/HapticTab';
-import { IconSymbol } from '@/components/ui/IconSymbol';
-import TabBarBackground from '@/components/ui/TabBarBackground';
-import { Colors } from '@/constants/Colors';
-import { useColorScheme } from '@/hooks/useColorScheme';
-
-export default function TabLayout() {
- const colorScheme = useColorScheme();
-
- return (
-
- ,
- }}
- />
- ,
- }}
- />
-
- );
-}
diff --git a/app/(tabs)/explore.tsx b/app/(tabs)/explore.tsx
deleted file mode 100644
index d4fbcaa..0000000
--- a/app/(tabs)/explore.tsx
+++ /dev/null
@@ -1,110 +0,0 @@
-import { Image } from 'expo-image';
-import { Platform, StyleSheet } from 'react-native';
-
-import { Collapsible } from '@/components/Collapsible';
-import { ExternalLink } from '@/components/ExternalLink';
-import ParallaxScrollView from '@/components/ParallaxScrollView';
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
-import { IconSymbol } from '@/components/ui/IconSymbol';
-
-export default function TabTwoScreen() {
- return (
-
- }>
-
- Explore
-
- This app includes example code to help you get started.
-
-
- This app has two screens:{' '}
- app/(tabs)/index.tsx and{' '}
- app/(tabs)/explore.tsx
-
-
- The layout file in app/(tabs)/_layout.tsx{' '}
- sets up the tab navigator.
-
-
- Learn more
-
-
-
-
- You can open this project on Android, iOS, and the web. To open the web version, press{' '}
- w in the terminal running this project.
-
-
-
-
- For static images, you can use the @2x and{' '}
- @3x suffixes to provide files for
- different screen densities
-
-
-
- Learn more
-
-
-
-
- Open app/_layout.tsx to see how to load{' '}
-
- custom fonts such as this one.
-
-
-
- Learn more
-
-
-
-
- This template has light and dark mode support. The{' '}
- useColorScheme() hook lets you inspect
- what the user's current color scheme is, and so you can adjust UI colors accordingly.
-
-
- Learn more
-
-
-
-
- This template includes an example of an animated component. The{' '}
- components/HelloWave.tsx component uses
- the powerful react-native-reanimated{' '}
- library to create a waving hand animation.
-
- {Platform.select({
- ios: (
-
- The components/ParallaxScrollView.tsx{' '}
- component provides a parallax effect for the header image.
-
- ),
- })}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- headerImage: {
- color: '#808080',
- bottom: -90,
- left: -35,
- position: 'absolute',
- },
- titleContainer: {
- flexDirection: 'row',
- gap: 8,
- },
-});
diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx
deleted file mode 100644
index 462e8cd..0000000
--- a/app/(tabs)/index.tsx
+++ /dev/null
@@ -1,75 +0,0 @@
-import { Image } from 'expo-image';
-import { Platform, StyleSheet } from 'react-native';
-
-import { HelloWave } from '@/components/HelloWave';
-import ParallaxScrollView from '@/components/ParallaxScrollView';
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
-
-export default function HomeScreen() {
- return (
-
- }>
-
- Welcome!
-
-
-
- Step 1: Try it
-
- Edit app/(tabs)/index.tsx to see changes.
- Press{' '}
-
- {Platform.select({
- ios: 'cmd + d',
- android: 'cmd + m',
- web: 'F12',
- })}
- {' '}
- to open developer tools.
-
-
-
- Step 2: Explore
-
- {`Tap the Explore tab to learn more about what's included in this starter app.`}
-
-
-
- Step 3: Get a fresh start
-
- {`When you're ready, run `}
- npm run reset-project to get a fresh{' '}
- app directory. This will move the current{' '}
- app to{' '}
- app-example.
-
-
-
- );
-}
-
-const styles = StyleSheet.create({
- titleContainer: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: 8,
- },
- stepContainer: {
- gap: 8,
- marginBottom: 8,
- },
- reactLogo: {
- height: 178,
- width: 290,
- bottom: 0,
- left: 0,
- position: 'absolute',
- },
-});
diff --git a/app/+not-found.tsx b/app/+not-found.tsx
deleted file mode 100644
index 215b0ed..0000000
--- a/app/+not-found.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { Link, Stack } from 'expo-router';
-import { StyleSheet } from 'react-native';
-
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
-
-export default function NotFoundScreen() {
- return (
- <>
-
-
- This screen does not exist.
-
- Go to home screen!
-
-
- >
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: 'center',
- justifyContent: 'center',
- padding: 20,
- },
- link: {
- marginTop: 15,
- paddingVertical: 15,
- },
-});
diff --git a/app/_layout.tsx b/app/_layout.tsx
index 8d506f7..889f341 100644
--- a/app/_layout.tsx
+++ b/app/_layout.tsx
@@ -1,29 +1,5 @@
-import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
-import { useFonts } from 'expo-font';
-import { Stack } from 'expo-router';
-import { StatusBar } from 'expo-status-bar';
-import 'react-native-reanimated';
-
-import { useColorScheme } from '@/hooks/useColorScheme';
+import { Stack } from "expo-router";
export default function RootLayout() {
- const colorScheme = useColorScheme();
- const [loaded] = useFonts({
- SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
- });
-
- if (!loaded) {
- // Async font loading only occurs in development.
- return null;
- }
-
- return (
-
-
-
-
-
-
-
- );
+ return ;
}
diff --git a/app/index.tsx b/app/index.tsx
new file mode 100644
index 0000000..bb03ed8
--- /dev/null
+++ b/app/index.tsx
@@ -0,0 +1,1277 @@
+import { Asset } from 'expo-asset';
+import { GLView } from 'expo-gl';
+import { Renderer } from 'expo-three';
+import React, { useEffect, useRef, useState } from 'react';
+import { Dimensions, PanResponder, StyleSheet, Text, TouchableOpacity, View } from 'react-native';
+import * as THREE from 'three';
+import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js';
+
+import background1 from '@/assets/images/background-1.jpg';
+
+const { width, height } = Dimensions.get('window');
+
+interface HexagonTile {
+ position: THREE.Vector3;
+ mesh?: THREE.Mesh | null;
+ stroke?: THREE.Mesh | null;
+ occupied: boolean;
+ unit?: THREE.Mesh;
+ biome: 'desert' | 'grass' | 'water' | 'forest' | 'rock';
+ modelPath?: string;
+}
+
+interface Unit {
+ id: string;
+ name: string;
+ color: number;
+ cost: number;
+ level: number;
+}
+
+export default function TFTGameScene() {
+ const sceneRef = useRef(null);
+ const cameraRef = useRef(null);
+ const rendererRef = useRef(null);
+ const tilesRef = useRef([]);
+ const animationFrameRef = useRef(null);
+ const [selectedUnit, setSelectedUnit] = useState(null);
+ const [gold, setGold] = useState(10);
+ const [isDragging, setIsDragging] = useState(false);
+ const [dragStartPosition, setDragStartPosition] = useState({ x: 0, y: 0 });
+ const [draggedTile, setDraggedTile] = useState<{ row: number; col: number } | null>(null);
+ const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 });
+ const [draggedUnitMesh, setDraggedUnitMesh] = useState(null);
+ const [availableUnits, setAvailableUnits] = useState([
+ { id: '1', name: 'Warrior', color: 0xff6b6b, cost: 3, level: 1 },
+ { id: '2', name: 'Mage', color: 0x4ecdc4, cost: 4, level: 1 },
+ { id: '3', name: 'Archer', color: 0x45b7d1, cost: 2, level: 1 },
+ { id: '4', name: 'Tank', color: 0x96ceb4, cost: 5, level: 1 },
+ { id: '5', name: 'Assassin', color: 0xfeca57, cost: 3, level: 1 },
+ { id: '6', name: 'Knight', color: 0x9b59b6, cost: 4, level: 1 },
+ { id: '7', name: 'Priest', color: 0xe74c3c, cost: 2, level: 1 },
+ { id: '8', name: 'Wizard', color: 0x3498db, cost: 3, level: 1 },
+ { id: '9', name: 'Ranger', color: 0x2ecc71, cost: 2, level: 1 },
+ { id: '10', name: 'Guardian', color: 0xf39c12, cost: 4, level: 1 },
+ { id: '11', name: 'Berserker', color: 0xe67e22, cost: 3, level: 1 },
+ { id: '12', name: 'Sorcerer', color: 0x8e44ad, cost: 5, level: 1 },
+ { id: '13', name: 'Scout', color: 0x16a085, cost: 2, level: 1 },
+ { id: '14', name: 'Paladin', color: 0xc0392b, cost: 4, level: 1 },
+ { id: '15', name: 'Necromancer', color: 0x7f8c8d, cost: 3, level: 1 },
+ { id: '16', name: 'Dragon', color: 0xe74c3c, cost: 5, level: 1 },
+ ]);
+
+ // GLB model loader
+ const gltfLoader = new GLTFLoader();
+
+ // Load GLB model with proper asset handling
+ const loadGLBModel = async (modelPath: string): Promise => {
+ try {
+ // Use static require for GLB models
+ let asset;
+ switch (modelPath) {
+ case 'hex_sand_detail.gltf.glb':
+ asset = Asset.fromModule(require('../assets/arena/hex_sand_detail.gltf.glb'));
+ break;
+ case 'hex_forest.gltf.glb':
+ asset = Asset.fromModule(require('../assets/arena/hex_forest.gltf.glb'));
+ break;
+ case 'hex_water_detail.gltf.glb':
+ asset = Asset.fromModule(require('../assets/arena/hex_water_detail.gltf.glb'));
+ break;
+ case 'hex_rock_detail.gltf.glb':
+ asset = Asset.fromModule(require('../assets/arena/hex_rock_detail.gltf.glb'));
+ break;
+ case 'hex_sand_roadA.gltf.glb':
+ asset = Asset.fromModule(require('../assets/arena/hex_sand_roadA.gltf.glb'));
+ break;
+ default:
+ console.log('Model not found:', modelPath);
+ return null;
+ }
+
+ await asset.downloadAsync();
+
+ return new Promise((resolve, reject) => {
+ gltfLoader.load(
+ asset.uri,
+ (gltf) => {
+ const model = gltf.scene;
+ // Scale to fit within hexagon (radius = 0.5)
+ model.scale.set(0.4, 0.4, 0.4);
+ // Rotate model to align with our hexagons (vertical)
+ model.rotation.y = Math.PI / 6; // 30 degrees to align with our hexagons
+ // Position underneath hexagon with minimal gap
+ model.position.y = -0.01; // Minimal gap
+ resolve(model);
+ },
+ undefined,
+ (error) => {
+ console.error('Error loading GLB model:', error);
+ reject(error);
+ }
+ );
+ });
+ } catch (error) {
+ console.error('Error loading GLB model:', error);
+ return null;
+ }
+ };
+
+ // Create enhanced geometry for different biomes
+ const createEnhancedGeometry = (biome: string, radius: number = 0.5) => {
+ switch (biome) {
+ case 'desert':
+ // Create sand-like geometry with bumps
+ const sandGeometry = new THREE.CylinderGeometry(radius, radius, 0.1, 6);
+ const sandMaterial = new THREE.MeshLambertMaterial({
+ color: 0xd2b48c,
+ transparent: true,
+ opacity: 0.9
+ });
+ return new THREE.Mesh(sandGeometry, sandMaterial);
+
+ case 'water':
+ // Create water-like geometry with waves
+ const waterGeometry = new THREE.CylinderGeometry(radius, radius, 0.08, 6);
+ const waterMaterial = new THREE.MeshLambertMaterial({
+ color: 0x87CEEB,
+ transparent: true,
+ opacity: 0.7
+ });
+ return new THREE.Mesh(waterGeometry, waterMaterial);
+
+ case 'forest':
+ // Create forest-like geometry with texture
+ const forestGeometry = new THREE.CylinderGeometry(radius, radius, 0.12, 6);
+ const forestMaterial = new THREE.MeshLambertMaterial({
+ color: 0x228B22,
+ transparent: true,
+ opacity: 0.9
+ });
+ return new THREE.Mesh(forestGeometry, forestMaterial);
+
+ case 'rock':
+ // Create rock-like geometry with roughness
+ const rockGeometry = new THREE.CylinderGeometry(radius, radius, 0.15, 6);
+ const rockMaterial = new THREE.MeshLambertMaterial({
+ color: 0x696969,
+ transparent: true,
+ opacity: 0.9
+ });
+ return new THREE.Mesh(rockGeometry, rockMaterial);
+
+ default:
+ // Default grass geometry
+ const grassGeometry = new THREE.CylinderGeometry(radius, radius, 0.1, 6);
+ const grassMaterial = new THREE.MeshLambertMaterial({
+ color: 0x90EE90,
+ transparent: true,
+ opacity: 0.9
+ });
+ return new THREE.Mesh(grassGeometry, grassMaterial);
+ }
+ };
+
+ // Hexagon geometry helper
+ const createHexagonGeometry = (radius: number, height: number) => {
+ const geometry = new THREE.CylinderGeometry(radius, radius, height, 6);
+ return geometry;
+ };
+
+ // Create a single hexagon tile with GLB models
+ const createHexagonTile = async (x: number, z: number, radius: number = 0.5, biome: 'desert' | 'grass' | 'water' | 'forest' | 'rock' = 'grass') => {
+ // Biome-based model paths
+ let modelPath: string | undefined;
+
+ switch (biome) {
+ case 'desert':
+ modelPath = 'hex_sand_detail.gltf.glb';
+ break;
+ case 'grass':
+ modelPath = 'hex_forest.gltf.glb';
+ break;
+ case 'water':
+ modelPath = 'hex_water_detail.gltf.glb';
+ break;
+ case 'forest':
+ modelPath = 'hex_forest.gltf.glb';
+ break;
+ case 'rock':
+ modelPath = 'hex_rock_detail.gltf.glb';
+ break;
+ default:
+ modelPath = 'hex_forest.gltf.glb';
+ }
+
+ return {
+ position: new THREE.Vector3(x, 0, z),
+ mesh: null, // We don't need our custom mesh anymore
+ stroke: null, // We don't need our custom stroke anymore
+ occupied: false,
+ biome,
+ modelPath
+ };
+ };
+
+ // Create a unit cube with proper level scaling
+ const createUnitCube = (color: number = 0xff6b6b, level: number = 1) => {
+ const geometry = new THREE.BoxGeometry(0.3, 0.3, 0.3);
+ const material = new THREE.MeshLambertMaterial({ color });
+ const mesh = new THREE.Mesh(geometry, material);
+ mesh.position.y = 0.5; // Position above GLB models
+
+ // TFT style scaling: Level 1 = normal, Level 2 = 1.2x, Level 3 = 1.4x, Level 4 = 1.6x
+ const scaleMultiplier = 1 + (level - 1) * 0.2;
+ mesh.scale.set(scaleMultiplier, scaleMultiplier, scaleMultiplier);
+
+ return mesh;
+ };
+
+ // Create the beautiful 6x6 hexagonal arena with GLB models
+ const createArena = async () => {
+ const tiles: HexagonTile[][] = [];
+ const hexRadius = 0.5;
+ const hexWidth = hexRadius * 2;
+ const hexHeight = hexRadius * Math.sqrt(3);
+
+ // Calculate arena center offset to center it on screen
+ const arenaWidth = 5 * hexWidth * 0.75; // 6 columns
+ const arenaHeight = 5 * hexHeight; // 6 rows
+ const centerX = -arenaWidth / 2;
+ const centerZ = -arenaHeight / 2;
+
+ // Define biome layout based on the image with roads
+ const biomeLayout = [
+ ['desert', 'desert', 'desert', 'grass', 'grass', 'grass'],
+ ['desert', 'desert', 'grass', 'grass', 'grass', 'grass'],
+ ['desert', 'grass', 'grass', 'grass', 'grass', 'water'],
+ ['grass', 'grass', 'grass', 'forest', 'water', 'water'],
+ ['grass', 'grass', 'forest', 'water', 'water', 'water'],
+ ['grass', 'forest', 'water', 'water', 'water', 'water']
+ ];
+
+ // Define road layout (connecting different biomes)
+ const roadLayout = [
+ [false, false, false, false, false, false],
+ [false, false, true, false, false, false],
+ [false, true, false, true, false, false],
+ [false, false, true, false, true, false],
+ [false, false, false, true, false, true],
+ [false, false, false, false, true, false]
+ ];
+
+ for (let row = 0; row < 6; row++) {
+ tiles[row] = [];
+ for (let col = 0; col < 6; col++) {
+ // Calculate position with offset for hexagonal grid, centered
+ const x = centerX + col * hexWidth * 0.75;
+ const z = centerZ + row * hexHeight + (col % 2) * (hexHeight / 2);
+
+ // Get biome from layout
+ const biome = biomeLayout[row][col] as 'desert' | 'grass' | 'water' | 'forest' | 'rock';
+ const hasRoad = roadLayout[row][col];
+
+ const tile = await createHexagonTile(x, z, hexRadius, biome);
+ tiles[row][col] = tile;
+
+ if (sceneRef.current) {
+ // Only add GLB model - no custom hexagons
+ if (tile.modelPath) {
+ try {
+ const model = await loadGLBModel(tile.modelPath);
+ if (model) {
+ // Center the model with the hexagon position
+ model.position.copy(tile.position);
+ model.position.y = 0.0; // At ground level
+
+ // Add color tint based on area (player vs enemy)
+ const isPlayerArea = row >= 3; // Bottom 3 rows are player area
+ if (isPlayerArea) {
+ // Player area - normal colors
+ model.children.forEach(child => {
+ if (child instanceof THREE.Mesh && child.material) {
+ if (Array.isArray(child.material)) {
+ child.material.forEach(mat => {
+ if (mat instanceof THREE.MeshLambertMaterial) {
+ mat.emissive = new THREE.Color(0x00ff00);
+ mat.emissiveIntensity = 0.1;
+ }
+ });
+ } else if (child.material instanceof THREE.MeshLambertMaterial) {
+ child.material.emissive = new THREE.Color(0x00ff00);
+ child.material.emissiveIntensity = 0.1;
+ }
+ }
+ });
+ } else {
+ // Enemy area - red tint
+ model.children.forEach(child => {
+ if (child instanceof THREE.Mesh && child.material) {
+ if (Array.isArray(child.material)) {
+ child.material.forEach(mat => {
+ if (mat instanceof THREE.MeshLambertMaterial) {
+ mat.emissive = new THREE.Color(0xff0000);
+ mat.emissiveIntensity = 0.2;
+ }
+ });
+ } else if (child.material instanceof THREE.MeshLambertMaterial) {
+ child.material.emissive = new THREE.Color(0xff0000);
+ child.material.emissiveIntensity = 0.2;
+ }
+ }
+ });
+ }
+
+ sceneRef.current.add(model);
+ }
+ } catch (error) {
+ console.log('Using fallback geometry for tile');
+ }
+ }
+ }
+ }
+ }
+
+ tilesRef.current = tiles;
+
+ // Add bases to arena corners (outside the arena) - REMOVED
+ // if (sceneRef.current) {
+ // // Player base (bottom right corner) - Castle style
+ // const playerBaseGeometry = new THREE.CylinderGeometry(1.5, 1.5, 0.4, 8);
+ // const playerBaseMaterial = new THREE.MeshLambertMaterial({
+ // color: 0x4a90e2,
+ // transparent: true,
+ // opacity: 0.9
+ // });
+ // const playerBase = new THREE.Mesh(playerBaseGeometry, playerBaseMaterial);
+ // playerBase.position.set(centerX + 6 * hexWidth * 0.75, 0.2, centerZ + 6 * hexHeight);
+ // sceneRef.current.add(playerBase);
+ //
+ // // Enemy base (top left corner) - Tower style
+ // const enemyBaseGeometry = new THREE.CylinderGeometry(1.2, 1.2, 0.6, 8);
+ // const enemyBaseMaterial = new THREE.MeshLambertMaterial({
+ // color: 0x666666,
+ // transparent: true,
+ // opacity: 0.9
+ // });
+ // const enemyBase = new THREE.Mesh(enemyBaseGeometry, enemyBaseMaterial);
+ // enemyBase.position.set(centerX - hexWidth * 0.75, 0.3, centerZ - hexHeight);
+ // sceneRef.current.add(enemyBase);
+ //
+ // // Add some decorative structures
+ // addDecorations(centerX, centerZ, hexWidth, hexHeight);
+ // }
+ };
+
+ // Add decorative structures to the arena
+ const addDecorations = async (centerX: number, centerZ: number, hexWidth: number, hexHeight: number) => {
+ if (!sceneRef.current) return;
+
+ // Add a castle in the center grass area
+ const castleGeometry = new THREE.BoxGeometry(1.2, 1.5, 1.2);
+ const castleMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
+ const castle = new THREE.Mesh(castleGeometry, castleMaterial);
+ castle.position.set(centerX + 2 * hexWidth * 0.75, 0.75, centerZ + 2 * hexHeight);
+ sceneRef.current.add(castle);
+
+ // Add castle towers
+ for (let i = 0; i < 4; i++) {
+ const towerGeometry = new THREE.CylinderGeometry(0.2, 0.2, 0.8, 8);
+ const towerMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
+ const tower = new THREE.Mesh(towerGeometry, towerMaterial);
+ const angle = (i * Math.PI) / 2;
+ tower.position.set(
+ centerX + 2 * hexWidth * 0.75 + Math.cos(angle) * 0.8,
+ 0.4,
+ centerZ + 2 * hexHeight + Math.sin(angle) * 0.8
+ );
+ sceneRef.current.add(tower);
+ }
+
+ // Add a windmill in the water area
+ const windmillGeometry = new THREE.CylinderGeometry(0.3, 0.3, 1.0, 8);
+ const windmillMaterial = new THREE.MeshLambertMaterial({ color: 0xDEB887 });
+ const windmill = new THREE.Mesh(windmillGeometry, windmillMaterial);
+ windmill.position.set(centerX + 4 * hexWidth * 0.75, 0.5, centerZ + 4 * hexHeight);
+ sceneRef.current.add(windmill);
+
+ // Add windmill blades
+ const bladeGeometry = new THREE.BoxGeometry(0.1, 0.8, 0.05);
+ const bladeMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
+ for (let i = 0; i < 4; i++) {
+ const blade = new THREE.Mesh(bladeGeometry, bladeMaterial);
+ const angle = (i * Math.PI) / 2;
+ blade.position.set(
+ centerX + 4 * hexWidth * 0.75 + Math.cos(angle) * 0.4,
+ 1.0,
+ centerZ + 4 * hexHeight + Math.sin(angle) * 0.4
+ );
+ blade.rotation.y = angle;
+ sceneRef.current.add(blade);
+ }
+
+ // Add some trees in the forest area using GLB models
+ for (let i = 0; i < 3; i++) {
+ try {
+ const treeModel = await loadGLBModel('hex_forest.gltf.glb');
+ if (treeModel) {
+ treeModel.position.set(
+ centerX + (3 + i) * hexWidth * 0.75,
+ 0.4,
+ centerZ + (4 + i % 2) * hexHeight
+ );
+ treeModel.scale.set(0.3, 0.3, 0.3);
+ sceneRef.current.add(treeModel);
+ } else {
+ // Fallback to geometry
+ const treeGeometry = new THREE.ConeGeometry(0.3, 0.8, 8);
+ const treeMaterial = new THREE.MeshLambertMaterial({ color: 0x228B22 });
+ const tree = new THREE.Mesh(treeGeometry, treeMaterial);
+ tree.position.set(
+ centerX + (3 + i) * hexWidth * 0.75,
+ 0.4,
+ centerZ + (4 + i % 2) * hexHeight
+ );
+ sceneRef.current.add(tree);
+ }
+ } catch (error) {
+ console.log('Tree model not loaded, using fallback');
+ const treeGeometry = new THREE.ConeGeometry(0.3, 0.8, 8);
+ const treeMaterial = new THREE.MeshLambertMaterial({ color: 0x228B22 });
+ const tree = new THREE.Mesh(treeGeometry, treeMaterial);
+ tree.position.set(
+ centerX + (3 + i) * hexWidth * 0.75,
+ 0.4,
+ centerZ + (4 + i % 2) * hexHeight
+ );
+ sceneRef.current.add(tree);
+ }
+ }
+
+ // Add rocks in the desert area using GLB models
+ for (let i = 0; i < 2; i++) {
+ try {
+ const rockModel = await loadGLBModel('hex_rock_detail.gltf.glb');
+ if (rockModel) {
+ rockModel.position.set(
+ centerX + i * hexWidth * 0.75,
+ 0.1,
+ centerZ + i * hexHeight
+ );
+ rockModel.scale.set(0.2, 0.2, 0.2);
+ sceneRef.current.add(rockModel);
+ } else {
+ // Fallback to geometry
+ const rockGeometry = new THREE.DodecahedronGeometry(0.2);
+ const rockMaterial = new THREE.MeshLambertMaterial({ color: 0x696969 });
+ const rock = new THREE.Mesh(rockGeometry, rockMaterial);
+ rock.position.set(
+ centerX + i * hexWidth * 0.75,
+ 0.1,
+ centerZ + i * hexHeight
+ );
+ sceneRef.current.add(rock);
+ }
+ } catch (error) {
+ console.log('Rock model not loaded, using fallback');
+ const rockGeometry = new THREE.DodecahedronGeometry(0.2);
+ const rockMaterial = new THREE.MeshLambertMaterial({ color: 0x696969 });
+ const rock = new THREE.Mesh(rockGeometry, rockMaterial);
+ rock.position.set(
+ centerX + i * hexWidth * 0.75,
+ 0.1,
+ centerZ + i * hexHeight
+ );
+ sceneRef.current.add(rock);
+ }
+ }
+
+ // Add a bridge over water
+ const bridgeGeometry = new THREE.BoxGeometry(1.0, 0.1, 0.3);
+ const bridgeMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
+ const bridge = new THREE.Mesh(bridgeGeometry, bridgeMaterial);
+ bridge.position.set(centerX + 3 * hexWidth * 0.75, 0.15, centerZ + 4 * hexHeight);
+ sceneRef.current.add(bridge);
+
+ // Add some houses in the grass area
+ for (let i = 0; i < 2; i++) {
+ const houseGeometry = new THREE.BoxGeometry(0.6, 0.4, 0.6);
+ const houseMaterial = new THREE.MeshLambertMaterial({ color: 0xDEB887 });
+ const house = new THREE.Mesh(houseGeometry, houseMaterial);
+ house.position.set(
+ centerX + (1 + i) * hexWidth * 0.75,
+ 0.2,
+ centerZ + (3 + i) * hexHeight
+ );
+ sceneRef.current.add(house);
+
+ // Add roof
+ const roofGeometry = new THREE.ConeGeometry(0.4, 0.3, 4);
+ const roofMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 });
+ const roof = new THREE.Mesh(roofGeometry, roofMaterial);
+ roof.position.set(
+ centerX + (1 + i) * hexWidth * 0.75,
+ 0.55,
+ centerZ + (3 + i) * hexHeight
+ );
+ roof.rotation.y = Math.PI / 4;
+ sceneRef.current.add(roof);
+ }
+ };
+
+ // Handle unit purchase
+ const handleUnitPurchase = (unit: Unit) => {
+ if (gold >= unit.cost) {
+ setGold(gold - unit.cost);
+ setSelectedUnit(unit);
+ console.log('Unit selected:', unit.name); // Debug log
+ }
+ };
+
+ // Handle tile placement with proper merge logic
+ const handleTilePlacement = (row: number, col: number) => {
+ if (selectedUnit && tilesRef.current[row] && tilesRef.current[row][col]) {
+ const tile = tilesRef.current[row][col];
+ if (!tile.occupied) {
+ // Check for merge first
+ const wasMerged = checkForMerge(selectedUnit);
+
+ if (!wasMerged) {
+ // Place new unit normally - add to scene directly since we don't have tile.mesh
+ const unit = createUnitCube(selectedUnit.color, selectedUnit.level);
+ unit.position.copy(tile.position);
+ unit.position.y = 0.5; // Position above GLB model
+ if (sceneRef.current) {
+ sceneRef.current.add(unit);
+ }
+ tile.occupied = true;
+ tile.unit = unit;
+ }
+
+ setSelectedUnit(null);
+ }
+ }
+ };
+
+ // Add some sample units to the arena (only in user area)
+ const addSampleUnits = () => {
+ const sampleUnits = [
+ { row: 4, col: 2, unit: availableUnits[0] }, // Warrior
+ { row: 5, col: 3, unit: availableUnits[1] }, // Mage
+ { row: 4, col: 4, unit: availableUnits[2] }, // Archer
+ ];
+
+ sampleUnits.forEach(({ row, col, unit }) => {
+ if (tilesRef.current[row] && tilesRef.current[row][col]) {
+ const tile = tilesRef.current[row][col];
+ const mesh = createUnitCube(unit.color, unit.level);
+ mesh.position.copy(tile.position);
+ mesh.position.y = 0.5; // Position above GLB model
+ if (sceneRef.current) {
+ sceneRef.current.add(mesh);
+ }
+ tile.occupied = true;
+ tile.unit = mesh;
+ }
+ });
+ };
+
+ // Get tile at screen position
+ const getTileAtPosition = (x: number, y: number) => {
+ if (!cameraRef.current) return null;
+
+ const mouse = new THREE.Vector2();
+ mouse.x = (x / width) * 2 - 1;
+ mouse.y = -(y / height) * 2 + 1;
+
+ const raycaster = new THREE.Raycaster();
+ raycaster.setFromCamera(mouse, cameraRef.current);
+
+ // Get all GLB models from the scene
+ const modelMeshes: THREE.Mesh[] = [];
+ if (sceneRef.current) {
+ sceneRef.current.children.forEach(child => {
+ if (child.type === 'Group') {
+ child.children.forEach(groupChild => {
+ if (groupChild.type === 'Mesh') {
+ modelMeshes.push(groupChild as THREE.Mesh);
+ }
+ });
+ }
+ });
+ }
+
+ const intersects = raycaster.intersectObjects(modelMeshes);
+
+ if (intersects.length > 0) {
+ const intersectedMesh = intersects[0].object;
+
+ // Find the tile based on the intersected mesh position
+ for (let row = 0; row < 6; row++) {
+ for (let col = 0; col < 6; col++) {
+ const tile = tilesRef.current[row][col];
+ // Check if the intersected mesh belongs to this tile's position
+ if (tile.position.distanceTo(intersectedMesh.position) < 0.5) {
+ return { row, col, tile };
+ }
+ }
+ }
+ }
+ return null;
+ };
+
+ // PanResponder for drag and drop
+ const panResponder = PanResponder.create({
+ onStartShouldSetPanResponder: () => true,
+ onMoveShouldSetPanResponder: () => true,
+ onPanResponderGrant: (event) => {
+ const touch = event.nativeEvent;
+ console.log('Drag started at:', touch.locationX, touch.locationY); // Debug log
+ setDragStartPosition({ x: touch.locationX, y: touch.locationY });
+ setDragPosition({ x: touch.locationX, y: touch.locationY });
+ setIsDragging(true);
+
+ // Check if we're dragging an existing unit
+ const tileInfo = getTileAtPosition(touch.locationX, touch.locationY);
+ console.log('Tile info:', tileInfo); // Debug log
+
+ if (tileInfo && tileInfo.tile.occupied && tileInfo.row >= 3) {
+ console.log('Dragging existing unit'); // Debug log
+ // Dragging an existing unit from user area
+ setDraggedTile({ row: tileInfo.row, col: tileInfo.col });
+ setSelectedUnit(null); // Clear selected unit since we're moving existing one
+
+ // Create a copy of the unit for dragging
+ if (tileInfo.tile.unit) {
+ const unitGeometry = new THREE.BoxGeometry(0.3, 0.3, 0.3);
+ const unitMaterial = new THREE.MeshLambertMaterial({
+ color: tileInfo.tile.unit.material instanceof THREE.MeshLambertMaterial
+ ? tileInfo.tile.unit.material.color
+ : 0xff6b6b,
+ transparent: true,
+ opacity: 0.8
+ });
+ const dragMesh = new THREE.Mesh(unitGeometry, unitMaterial);
+ dragMesh.position.y = 0.5;
+ dragMesh.scale.copy(tileInfo.tile.unit.scale); // Copy the scale (level)
+ setDraggedUnitMesh(dragMesh);
+
+ // Add to scene immediately
+ if (sceneRef.current) {
+ sceneRef.current.add(dragMesh);
+ }
+
+ // Hide the original unit temporarily
+ tileInfo.tile.unit.visible = false;
+ }
+ } else if (selectedUnit) {
+ console.log('Dragging new unit:', selectedUnit.name); // Debug log
+ // Dragging a new unit from bottom panel
+ setDraggedTile(null);
+
+ // Create a new unit mesh for dragging
+ const unitGeometry = new THREE.BoxGeometry(0.3, 0.3, 0.3);
+ const unitMaterial = new THREE.MeshLambertMaterial({
+ color: selectedUnit.color,
+ transparent: true,
+ opacity: 0.8
+ });
+ const dragMesh = new THREE.Mesh(unitGeometry, unitMaterial);
+ dragMesh.position.y = 0.5;
+
+ // Apply proper level scaling
+ const scaleMultiplier = 1 + (selectedUnit.level - 1) * 0.2;
+ dragMesh.scale.set(scaleMultiplier, scaleMultiplier, scaleMultiplier);
+
+ setDraggedUnitMesh(dragMesh);
+
+ // Add to scene immediately
+ if (sceneRef.current) {
+ sceneRef.current.add(dragMesh);
+ }
+ }
+ },
+ onPanResponderMove: (event) => {
+ if (!isDragging) return;
+
+ const touch = event.nativeEvent;
+ setDragPosition({ x: touch.locationX, y: touch.locationY });
+ const tileInfo = getTileAtPosition(touch.locationX, touch.locationY);
+
+ // Update dragged unit position to follow touch
+ if (draggedUnitMesh && cameraRef.current) {
+ const mouse = new THREE.Vector2();
+ mouse.x = (touch.locationX / width) * 2 - 1;
+ mouse.y = -(touch.locationY / height) * 2 + 1;
+
+ const raycaster = new THREE.Raycaster();
+ raycaster.setFromCamera(mouse, cameraRef.current);
+
+ // Get intersection with a plane at y=0
+ const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
+ const intersection = new THREE.Vector3();
+ raycaster.ray.intersectPlane(plane, intersection);
+
+ draggedUnitMesh.position.set(intersection.x, 0.5, intersection.z);
+ }
+ },
+ onPanResponderRelease: (event) => {
+ if (!isDragging) return;
+
+ const touch = event.nativeEvent;
+ console.log('Drag ended at:', touch.locationX, touch.locationY); // Debug log
+ const tileInfo = getTileAtPosition(touch.locationX, touch.locationY);
+ console.log('Final tile info:', tileInfo); // Debug log
+
+ if (draggedTile) {
+ console.log('Moving existing unit'); // Debug log
+ // Moving an existing unit
+ if (tileInfo && !tileInfo.tile.occupied && tileInfo.row >= 3) {
+ console.log('Moving unit to new position'); // Debug log
+ // Move unit to new position
+ const sourceTile = tilesRef.current[draggedTile.row][draggedTile.col];
+ const targetTile = tilesRef.current[tileInfo.row][tileInfo.col];
+
+ if (sourceTile.unit) {
+ // Show the original unit again
+ sourceTile.unit.visible = true;
+
+ // Remove unit from scene
+ if (sceneRef.current) {
+ sceneRef.current.remove(sourceTile.unit);
+ }
+ sourceTile.occupied = false;
+
+ // Add unit to new position
+ sourceTile.unit.position.copy(targetTile.position);
+ sourceTile.unit.position.y = 0.5;
+ if (sceneRef.current) {
+ sceneRef.current.add(sourceTile.unit);
+ }
+ targetTile.occupied = true;
+ targetTile.unit = sourceTile.unit;
+
+ // Clear source tile unit reference
+ sourceTile.unit = undefined;
+ }
+ } else {
+ console.log('Reset dragged unit'); // Debug log
+ // Reset the dragged unit if placement failed
+ const sourceTile = tilesRef.current[draggedTile.row][draggedTile.col];
+ if (sourceTile.unit) {
+ sourceTile.unit.visible = true;
+ }
+ }
+ setDraggedTile(null);
+ } else if (selectedUnit) {
+ console.log('Placing new unit:', selectedUnit.name); // Debug log
+ // Placing a new unit
+ if (tileInfo && !tileInfo.tile.occupied && tileInfo.row >= 3) {
+ console.log('Placing unit at:', tileInfo.row, tileInfo.col); // Debug log
+ // Place new unit normally - add to scene directly since we don't have tile.mesh
+ const unit = createUnitCube(selectedUnit.color, selectedUnit.level);
+ unit.position.copy(tileInfo.tile.position);
+ unit.position.y = 0.5; // Position above GLB model
+ if (sceneRef.current) {
+ sceneRef.current.add(unit);
+ }
+ tileInfo.tile.occupied = true;
+ tileInfo.tile.unit = unit;
+ setSelectedUnit(null);
+ }
+ }
+
+ // Remove dragged unit mesh from scene
+ if (draggedUnitMesh && sceneRef.current) {
+ sceneRef.current.remove(draggedUnitMesh);
+ }
+ setDraggedUnitMesh(null);
+
+ setIsDragging(false);
+ },
+ onPanResponderTerminate: (event) => {
+ if (!isDragging) return;
+
+ const touch = event.nativeEvent;
+ const tileInfo = getTileAtPosition(touch.locationX, touch.locationY);
+
+ if (draggedTile) {
+ // Moving an existing unit
+ if (tileInfo && !tileInfo.tile.occupied && tileInfo.row >= 3) {
+ // Move unit to new position
+ const sourceTile = tilesRef.current[draggedTile.row][draggedTile.col];
+ const targetTile = tilesRef.current[tileInfo.row][tileInfo.col];
+
+ if (sourceTile.unit) {
+ // Show the original unit again
+ sourceTile.unit.visible = true;
+
+ // Remove unit from scene
+ if (sceneRef.current) {
+ sceneRef.current.remove(sourceTile.unit);
+ }
+ sourceTile.occupied = false;
+
+ // Add unit to new position
+ sourceTile.unit.position.copy(targetTile.position);
+ sourceTile.unit.position.y = 0.5;
+ if (sceneRef.current) {
+ sceneRef.current.add(sourceTile.unit);
+ }
+ targetTile.occupied = true;
+ targetTile.unit = sourceTile.unit;
+
+ // Clear source tile unit reference
+ sourceTile.unit = undefined;
+ }
+ } else {
+ // Reset the dragged unit if placement failed
+ const sourceTile = tilesRef.current[draggedTile.row][draggedTile.col];
+ if (sourceTile.unit) {
+ sourceTile.unit.visible = true;
+ }
+ }
+ setDraggedTile(null);
+ } else if (selectedUnit) {
+ // Placing a new unit
+ if (tileInfo && !tileInfo.tile.occupied && tileInfo.row >= 3) {
+ // Place new unit normally - add to scene directly since we don't have tile.mesh
+ const unit = createUnitCube(selectedUnit.color, selectedUnit.level);
+ unit.position.copy(tileInfo.tile.position);
+ unit.position.y = 0.5; // Position above GLB model
+ if (sceneRef.current) {
+ sceneRef.current.add(unit);
+ }
+ tileInfo.tile.occupied = true;
+ tileInfo.tile.unit = unit;
+ setSelectedUnit(null);
+ }
+ }
+
+ // Remove dragged unit mesh from scene
+ if (draggedUnitMesh && sceneRef.current) {
+ sceneRef.current.remove(draggedUnitMesh);
+ }
+ setDraggedUnitMesh(null);
+
+ setIsDragging(false);
+ },
+ });
+
+ // Setup scene
+ const setupScene = async (gl: any) => {
+ // Create renderer
+ const renderer = new Renderer({ gl });
+ rendererRef.current = renderer;
+
+ // Create scene with beautiful background
+ const scene = new THREE.Scene();
+ scene.background = new THREE.Color(0x1a1a2e); // Beautiful dark blue for TFT theme
+ sceneRef.current = scene;
+
+ // Load and set background image
+ try {
+ const bgAsset = Asset.fromModule(background1);
+ await bgAsset.downloadAsync();
+
+ console.log('Asset URI:', bgAsset.uri);
+
+ // Create a new texture loader with more aggressive settings
+ const textureLoader = new THREE.TextureLoader();
+
+ // Try multiple approaches to load the texture
+ const loadTexture = () => {
+ textureLoader.load(
+ bgAsset.uri,
+ (texture) => {
+ console.log('Background texture loaded successfully');
+ if (sceneRef.current) {
+ sceneRef.current.background = texture;
+ }
+ },
+ (progress) => {
+ console.log('Loading progress:', progress);
+ },
+ (error) => {
+ console.log('Error loading background texture:', error);
+ // Try again with a different approach
+ setTimeout(() => {
+ console.log('Retrying texture load...');
+ textureLoader.load(
+ bgAsset.uri,
+ (texture) => {
+ console.log('Background texture loaded on retry');
+ if (sceneRef.current) {
+ sceneRef.current.background = texture;
+ }
+ },
+ undefined,
+ (retryError) => {
+ console.log('Retry failed:', retryError);
+ }
+ );
+ }, 1000);
+ }
+ );
+ };
+
+ // Start loading
+ loadTexture();
+
+ } catch (error) {
+ console.log('Failed to load background image:', error);
+ // Keep the default color
+ }
+
+ // Create fixed camera - positioned to show arena and bases
+ const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 1000);
+ camera.position.set(0, 12, 12); // Closer to arena
+ camera.lookAt(0, 0, 0);
+ cameraRef.current = camera;
+
+ // Add lighting
+ const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
+ scene.add(ambientLight);
+
+ const directionalLight = new THREE.DirectionalLight(0xffffff, 0.9);
+ directionalLight.position.set(5, 15, 10);
+ scene.add(directionalLight);
+
+ // Create arena with GLB models
+ await createArena();
+ addSampleUnits();
+
+ // Animation loop - no camera movement
+ const animate = () => {
+ animationFrameRef.current = requestAnimationFrame(animate);
+ renderer.render(scene, camera);
+ gl.endFrameEXP();
+ };
+
+ animate();
+ };
+
+ // Cleanup on unmount
+ useEffect(() => {
+ return () => {
+ if (animationFrameRef.current) {
+ cancelAnimationFrame(animationFrameRef.current);
+ }
+ };
+ }, []);
+
+ // Get units on arena with proper level detection
+ const getUnitsOnArena = (): Unit[] => {
+ const units: Unit[] = [];
+ tilesRef.current.forEach(row => {
+ row.forEach(tile => {
+ if (tile.occupied && tile.unit) {
+ const unitColor = (tile.unit.material as any)?.color?.getHexString();
+ const unitData = availableUnits.find(u => u.color.toString(16) === unitColor);
+ if (unitData) {
+ // Calculate level based on scale
+ const scale = tile.unit.scale.x;
+ const level = Math.round((scale - 1) / 0.2) + 1;
+ units.push({ ...unitData, level: Math.max(1, Math.min(4, level)) });
+ }
+ }
+ });
+ });
+ return units;
+ };
+
+ // Check for merging opportunities
+ const checkForMerge = (newUnit: Unit) => {
+ const arenaUnits = getUnitsOnArena();
+ const sameTypeUnits = arenaUnits.filter(u => u.name === newUnit.name);
+
+ // TFT style: need 3 units of same type to merge
+ if (sameTypeUnits.length >= 2) {
+ // Calculate new level based on TFT rules
+ const totalUnits = sameTypeUnits.length + 1; // +1 for the new unit
+ const newLevel = Math.min(4, Math.floor(totalUnits / 3) + 1);
+
+ // Create merged unit
+ const mergedUnit: Unit = {
+ ...newUnit,
+ level: newLevel
+ };
+
+ // Remove old units from arena
+ let removedCount = 0;
+ tilesRef.current.forEach(row => {
+ row.forEach(tile => {
+ if (tile.occupied && tile.unit && removedCount < 3) {
+ const unitColor = (tile.unit.material as any)?.color?.getHexString();
+ const unitData = availableUnits.find(u => u.color.toString(16) === unitColor && u.name === newUnit.name);
+ if (unitData) {
+ // Remove unit from scene
+ if (sceneRef.current) {
+ sceneRef.current.remove(tile.unit);
+ }
+ tile.occupied = false;
+ tile.unit = undefined;
+ removedCount++;
+ }
+ }
+ });
+ });
+
+ // Add merged unit to first empty tile
+ for (let row = 3; row < 6; row++) {
+ for (let col = 0; col < 6; col++) {
+ const tile = tilesRef.current[row][col];
+ if (!tile.occupied) {
+ const mergedMesh = createUnitCube(mergedUnit.color, mergedUnit.level);
+ mergedMesh.position.copy(tile.position); // Position the merged unit
+ mergedMesh.position.y = 0.5; // Position above GLB model
+ if (sceneRef.current) {
+ sceneRef.current.add(mergedMesh);
+ }
+ tile.occupied = true;
+ tile.unit = mergedMesh;
+ return true; // Merged successfully
+ }
+ }
+ }
+ }
+
+ return false; // No merge
+ };
+
+ return (
+
+
+
+
+
+ {/* Gold Display - Top Right */}
+
+ š°
+ {gold}
+
+
+ {/* Horizontal Card Slider */}
+
+
+ {/* Main Cards (4 visible) */}
+
+ {availableUnits.slice(0, 4).map((unit, index) => {
+ const isSelected = selectedUnit?.id === unit.id;
+
+ return (
+ handleUnitPurchase(unit)}
+ disabled={gold < unit.cost}
+ >
+ {/* Card Back Pattern */}
+
+
+
+
+
+
+
+
+
+ {/* Unit Info Overlay */}
+
+ {unit.name}
+
+ ā
{unit.level}
+
+ {unit.cost}
+
+
+ );
+ })}
+
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#1a1a2e',
+ },
+ glView: {
+ flex: 1,
+ },
+ glContainer: {
+ flex: 1,
+ },
+ goldDisplay: {
+ position: 'absolute',
+ top: 50,
+ right: 20,
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
+ paddingHorizontal: 15,
+ paddingVertical: 10,
+ borderRadius: 25,
+ flexDirection: 'row',
+ alignItems: 'center',
+ shadowColor: '#feca57',
+ shadowOffset: {
+ width: 0,
+ height: 0,
+ },
+ shadowOpacity: 0.5,
+ shadowRadius: 10,
+ elevation: 10,
+ },
+ goldIcon: {
+ fontSize: 20,
+ marginRight: 8,
+ },
+ goldText: {
+ color: '#feca57',
+ fontSize: 18,
+ fontWeight: 'bold',
+ },
+ cardSlider: {
+ position: 'absolute',
+ bottom: 30,
+ left: 0,
+ right: 0,
+ alignItems: 'center',
+ },
+ sliderContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ width: '100%',
+ height: 100,
+ },
+ mainCardsContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ width: '100%',
+ height: 100,
+ },
+ unitCard: {
+ padding: 12,
+ borderRadius: 15,
+ alignItems: 'center',
+ minWidth: 70,
+ height: 100,
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 4,
+ },
+ shadowOpacity: 0.3,
+ shadowRadius: 8,
+ elevation: 8,
+ borderWidth: 2,
+ borderColor: 'rgba(255, 255, 255, 0.2)',
+ backgroundColor: 'rgba(0, 0, 0, 0.8)',
+ position: 'relative',
+ marginHorizontal: 5,
+ },
+ selectedUnitCard: {
+ borderWidth: 3,
+ borderColor: '#ffffff',
+ shadowColor: '#ffffff',
+ shadowOffset: {
+ width: 0,
+ height: 0,
+ },
+ shadowOpacity: 0.8,
+ shadowRadius: 15,
+ elevation: 15,
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
+ },
+ unitName: {
+ color: '#ffffff',
+ fontSize: 12,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
+ unitLevel: {
+ color: '#feca57',
+ fontSize: 12,
+ fontWeight: 'bold',
+ marginTop: 2,
+ },
+ unitCost: {
+ color: '#feca57',
+ fontSize: 16,
+ fontWeight: 'bold',
+ marginTop: 4,
+ },
+ cardBack: {
+ position: 'absolute',
+ top: 0,
+ left: 0,
+ right: 0,
+ bottom: 0,
+ borderRadius: 20,
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 1,
+ },
+ cardPattern: {
+ width: '100%',
+ height: '100%',
+ borderRadius: 20,
+ backgroundColor: 'rgba(255, 255, 255, 0.1)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ eyePattern: {
+ width: '80%',
+ height: '80%',
+ borderRadius: 40,
+ backgroundColor: 'rgba(255, 255, 255, 0.2)',
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ eyeCenter: {
+ width: '60%',
+ height: '60%',
+ borderRadius: 30,
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
+ },
+ eyeTriangle: {
+ position: 'absolute',
+ top: '50%',
+ left: '50%',
+ width: 0,
+ height: 0,
+ borderLeftWidth: 10,
+ borderRightWidth: 10,
+ borderBottomWidth: 20,
+ borderStyle: 'solid',
+ borderLeftColor: 'transparent',
+ borderRightColor: 'transparent',
+ borderBottomColor: 'transparent',
+ transform: [{ rotate: '90deg' }],
+ },
+ cardInfo: {
+ position: 'absolute',
+ bottom: 10,
+ left: 0,
+ right: 0,
+ alignItems: 'center',
+ zIndex: 2,
+ },
+ levelContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginTop: 2,
+ },
+});
diff --git a/assets/arena/hex_forest.gltf.glb b/assets/arena/hex_forest.gltf.glb
new file mode 100644
index 0000000..133ba2d
Binary files /dev/null and b/assets/arena/hex_forest.gltf.glb differ
diff --git a/assets/arena/hex_forest_detail.gltf.glb b/assets/arena/hex_forest_detail.gltf.glb
new file mode 100644
index 0000000..c9458f9
Binary files /dev/null and b/assets/arena/hex_forest_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadA.gltf.glb b/assets/arena/hex_forest_roadA.gltf.glb
new file mode 100644
index 0000000..6cb121c
Binary files /dev/null and b/assets/arena/hex_forest_roadA.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadA_detail.gltf.glb b/assets/arena/hex_forest_roadA_detail.gltf.glb
new file mode 100644
index 0000000..cec68db
Binary files /dev/null and b/assets/arena/hex_forest_roadA_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadB.gltf.glb b/assets/arena/hex_forest_roadB.gltf.glb
new file mode 100644
index 0000000..0762226
Binary files /dev/null and b/assets/arena/hex_forest_roadB.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadB_detail.gltf.glb b/assets/arena/hex_forest_roadB_detail.gltf.glb
new file mode 100644
index 0000000..9c82dd4
Binary files /dev/null and b/assets/arena/hex_forest_roadB_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadC.gltf.glb b/assets/arena/hex_forest_roadC.gltf.glb
new file mode 100644
index 0000000..d6ba108
Binary files /dev/null and b/assets/arena/hex_forest_roadC.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadC_detail.gltf.glb b/assets/arena/hex_forest_roadC_detail.gltf.glb
new file mode 100644
index 0000000..1e5e5ba
Binary files /dev/null and b/assets/arena/hex_forest_roadC_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadD.gltf.glb b/assets/arena/hex_forest_roadD.gltf.glb
new file mode 100644
index 0000000..76a20af
Binary files /dev/null and b/assets/arena/hex_forest_roadD.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadD_detail.gltf.glb b/assets/arena/hex_forest_roadD_detail.gltf.glb
new file mode 100644
index 0000000..efcb545
Binary files /dev/null and b/assets/arena/hex_forest_roadD_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadE.gltf.glb b/assets/arena/hex_forest_roadE.gltf.glb
new file mode 100644
index 0000000..dda8ef2
Binary files /dev/null and b/assets/arena/hex_forest_roadE.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadE_detail.gltf.glb b/assets/arena/hex_forest_roadE_detail.gltf.glb
new file mode 100644
index 0000000..7662976
Binary files /dev/null and b/assets/arena/hex_forest_roadE_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadF.gltf.glb b/assets/arena/hex_forest_roadF.gltf.glb
new file mode 100644
index 0000000..021de5e
Binary files /dev/null and b/assets/arena/hex_forest_roadF.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadF_detail.gltf.glb b/assets/arena/hex_forest_roadF_detail.gltf.glb
new file mode 100644
index 0000000..6805565
Binary files /dev/null and b/assets/arena/hex_forest_roadF_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadG.gltf.glb b/assets/arena/hex_forest_roadG.gltf.glb
new file mode 100644
index 0000000..f2f59ff
Binary files /dev/null and b/assets/arena/hex_forest_roadG.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadG_detail.gltf.glb b/assets/arena/hex_forest_roadG_detail.gltf.glb
new file mode 100644
index 0000000..565065d
Binary files /dev/null and b/assets/arena/hex_forest_roadG_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadH.gltf.glb b/assets/arena/hex_forest_roadH.gltf.glb
new file mode 100644
index 0000000..362c342
Binary files /dev/null and b/assets/arena/hex_forest_roadH.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadH_detail.gltf.glb b/assets/arena/hex_forest_roadH_detail.gltf.glb
new file mode 100644
index 0000000..f57a562
Binary files /dev/null and b/assets/arena/hex_forest_roadH_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadI.gltf.glb b/assets/arena/hex_forest_roadI.gltf.glb
new file mode 100644
index 0000000..b984ed5
Binary files /dev/null and b/assets/arena/hex_forest_roadI.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadI_detail.gltf.glb b/assets/arena/hex_forest_roadI_detail.gltf.glb
new file mode 100644
index 0000000..963a7a8
Binary files /dev/null and b/assets/arena/hex_forest_roadI_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadJ.gltf.glb b/assets/arena/hex_forest_roadJ.gltf.glb
new file mode 100644
index 0000000..dfc995f
Binary files /dev/null and b/assets/arena/hex_forest_roadJ.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadJ_detail.gltf.glb b/assets/arena/hex_forest_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..a729811
Binary files /dev/null and b/assets/arena/hex_forest_roadJ_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadK.gltf.glb b/assets/arena/hex_forest_roadK.gltf.glb
new file mode 100644
index 0000000..9066744
Binary files /dev/null and b/assets/arena/hex_forest_roadK.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadK_detail.gltf.glb b/assets/arena/hex_forest_roadK_detail.gltf.glb
new file mode 100644
index 0000000..8890565
Binary files /dev/null and b/assets/arena/hex_forest_roadK_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadL.gltf.glb b/assets/arena/hex_forest_roadL.gltf.glb
new file mode 100644
index 0000000..0ea9f95
Binary files /dev/null and b/assets/arena/hex_forest_roadL.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadL_detail.gltf.glb b/assets/arena/hex_forest_roadL_detail.gltf.glb
new file mode 100644
index 0000000..8cef810
Binary files /dev/null and b/assets/arena/hex_forest_roadL_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadM.gltf.glb b/assets/arena/hex_forest_roadM.gltf.glb
new file mode 100644
index 0000000..1d11fe4
Binary files /dev/null and b/assets/arena/hex_forest_roadM.gltf.glb differ
diff --git a/assets/arena/hex_forest_roadM_detail.gltf.glb b/assets/arena/hex_forest_roadM_detail.gltf.glb
new file mode 100644
index 0000000..7f2cc04
Binary files /dev/null and b/assets/arena/hex_forest_roadM_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_transitionA.gltf.glb b/assets/arena/hex_forest_transitionA.gltf.glb
new file mode 100644
index 0000000..01891ad
Binary files /dev/null and b/assets/arena/hex_forest_transitionA.gltf.glb differ
diff --git a/assets/arena/hex_forest_transitionB.gltf.glb b/assets/arena/hex_forest_transitionB.gltf.glb
new file mode 100644
index 0000000..cd474b7
Binary files /dev/null and b/assets/arena/hex_forest_transitionB.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterA.gltf.glb b/assets/arena/hex_forest_waterA.gltf.glb
new file mode 100644
index 0000000..6512d4b
Binary files /dev/null and b/assets/arena/hex_forest_waterA.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterA_detail.gltf.glb b/assets/arena/hex_forest_waterA_detail.gltf.glb
new file mode 100644
index 0000000..500b22b
Binary files /dev/null and b/assets/arena/hex_forest_waterA_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterA_empty.gltf.glb b/assets/arena/hex_forest_waterA_empty.gltf.glb
new file mode 100644
index 0000000..40614d9
Binary files /dev/null and b/assets/arena/hex_forest_waterA_empty.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterB.gltf.glb b/assets/arena/hex_forest_waterB.gltf.glb
new file mode 100644
index 0000000..d7a9800
Binary files /dev/null and b/assets/arena/hex_forest_waterB.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterB_detail.gltf.glb b/assets/arena/hex_forest_waterB_detail.gltf.glb
new file mode 100644
index 0000000..2436c01
Binary files /dev/null and b/assets/arena/hex_forest_waterB_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterB_empty.gltf.glb b/assets/arena/hex_forest_waterB_empty.gltf.glb
new file mode 100644
index 0000000..196c06d
Binary files /dev/null and b/assets/arena/hex_forest_waterB_empty.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterC.gltf.glb b/assets/arena/hex_forest_waterC.gltf.glb
new file mode 100644
index 0000000..7277baf
Binary files /dev/null and b/assets/arena/hex_forest_waterC.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterC_detail.gltf.glb b/assets/arena/hex_forest_waterC_detail.gltf.glb
new file mode 100644
index 0000000..7e854fa
Binary files /dev/null and b/assets/arena/hex_forest_waterC_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterC_empty.gltf.glb b/assets/arena/hex_forest_waterC_empty.gltf.glb
new file mode 100644
index 0000000..eb17e6a
Binary files /dev/null and b/assets/arena/hex_forest_waterC_empty.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterD.gltf.glb b/assets/arena/hex_forest_waterD.gltf.glb
new file mode 100644
index 0000000..ab60f8e
Binary files /dev/null and b/assets/arena/hex_forest_waterD.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterD_detail.gltf.glb b/assets/arena/hex_forest_waterD_detail.gltf.glb
new file mode 100644
index 0000000..ad3c3bb
Binary files /dev/null and b/assets/arena/hex_forest_waterD_detail.gltf.glb differ
diff --git a/assets/arena/hex_forest_waterD_empty.gltf.glb b/assets/arena/hex_forest_waterD_empty.gltf.glb
new file mode 100644
index 0000000..d299200
Binary files /dev/null and b/assets/arena/hex_forest_waterD_empty.gltf.glb differ
diff --git a/assets/arena/hex_rock.gltf.glb b/assets/arena/hex_rock.gltf.glb
new file mode 100644
index 0000000..4c6af9e
Binary files /dev/null and b/assets/arena/hex_rock.gltf.glb differ
diff --git a/assets/arena/hex_rock_detail.gltf.glb b/assets/arena/hex_rock_detail.gltf.glb
new file mode 100644
index 0000000..1e13ce7
Binary files /dev/null and b/assets/arena/hex_rock_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadA.gltf.glb b/assets/arena/hex_rock_roadA.gltf.glb
new file mode 100644
index 0000000..8ded8f0
Binary files /dev/null and b/assets/arena/hex_rock_roadA.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadA_detail.gltf.glb b/assets/arena/hex_rock_roadA_detail.gltf.glb
new file mode 100644
index 0000000..cb535e0
Binary files /dev/null and b/assets/arena/hex_rock_roadA_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadB.gltf.glb b/assets/arena/hex_rock_roadB.gltf.glb
new file mode 100644
index 0000000..3446702
Binary files /dev/null and b/assets/arena/hex_rock_roadB.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadB_detail.gltf.glb b/assets/arena/hex_rock_roadB_detail.gltf.glb
new file mode 100644
index 0000000..0f500ad
Binary files /dev/null and b/assets/arena/hex_rock_roadB_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadC.gltf.glb b/assets/arena/hex_rock_roadC.gltf.glb
new file mode 100644
index 0000000..9017133
Binary files /dev/null and b/assets/arena/hex_rock_roadC.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadC_detail.gltf.glb b/assets/arena/hex_rock_roadC_detail.gltf.glb
new file mode 100644
index 0000000..e29da55
Binary files /dev/null and b/assets/arena/hex_rock_roadC_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadD.gltf.glb b/assets/arena/hex_rock_roadD.gltf.glb
new file mode 100644
index 0000000..e80531d
Binary files /dev/null and b/assets/arena/hex_rock_roadD.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadD_detail.gltf.glb b/assets/arena/hex_rock_roadD_detail.gltf.glb
new file mode 100644
index 0000000..a54117d
Binary files /dev/null and b/assets/arena/hex_rock_roadD_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadE.gltf.glb b/assets/arena/hex_rock_roadE.gltf.glb
new file mode 100644
index 0000000..e5e9c6b
Binary files /dev/null and b/assets/arena/hex_rock_roadE.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadE_detail.gltf.glb b/assets/arena/hex_rock_roadE_detail.gltf.glb
new file mode 100644
index 0000000..e9741a0
Binary files /dev/null and b/assets/arena/hex_rock_roadE_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadF.gltf.glb b/assets/arena/hex_rock_roadF.gltf.glb
new file mode 100644
index 0000000..e46ac18
Binary files /dev/null and b/assets/arena/hex_rock_roadF.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadF_detail.gltf.glb b/assets/arena/hex_rock_roadF_detail.gltf.glb
new file mode 100644
index 0000000..8522ff0
Binary files /dev/null and b/assets/arena/hex_rock_roadF_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadG.gltf.glb b/assets/arena/hex_rock_roadG.gltf.glb
new file mode 100644
index 0000000..0b754e4
Binary files /dev/null and b/assets/arena/hex_rock_roadG.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadG_detail.gltf.glb b/assets/arena/hex_rock_roadG_detail.gltf.glb
new file mode 100644
index 0000000..1e5048a
Binary files /dev/null and b/assets/arena/hex_rock_roadG_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadH.gltf.glb b/assets/arena/hex_rock_roadH.gltf.glb
new file mode 100644
index 0000000..24a489c
Binary files /dev/null and b/assets/arena/hex_rock_roadH.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadH_detail.gltf.glb b/assets/arena/hex_rock_roadH_detail.gltf.glb
new file mode 100644
index 0000000..43007b3
Binary files /dev/null and b/assets/arena/hex_rock_roadH_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadI.gltf.glb b/assets/arena/hex_rock_roadI.gltf.glb
new file mode 100644
index 0000000..60cae61
Binary files /dev/null and b/assets/arena/hex_rock_roadI.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadI_detail.gltf.glb b/assets/arena/hex_rock_roadI_detail.gltf.glb
new file mode 100644
index 0000000..a86b791
Binary files /dev/null and b/assets/arena/hex_rock_roadI_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadJ.gltf.glb b/assets/arena/hex_rock_roadJ.gltf.glb
new file mode 100644
index 0000000..dc85527
Binary files /dev/null and b/assets/arena/hex_rock_roadJ.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadJ_detail.gltf.glb b/assets/arena/hex_rock_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..17abbbc
Binary files /dev/null and b/assets/arena/hex_rock_roadJ_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadK.gltf.glb b/assets/arena/hex_rock_roadK.gltf.glb
new file mode 100644
index 0000000..a07bd62
Binary files /dev/null and b/assets/arena/hex_rock_roadK.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadK_detail.gltf.glb b/assets/arena/hex_rock_roadK_detail.gltf.glb
new file mode 100644
index 0000000..e25dae9
Binary files /dev/null and b/assets/arena/hex_rock_roadK_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadL.gltf.glb b/assets/arena/hex_rock_roadL.gltf.glb
new file mode 100644
index 0000000..2469f38
Binary files /dev/null and b/assets/arena/hex_rock_roadL.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadL_detail.gltf.glb b/assets/arena/hex_rock_roadL_detail.gltf.glb
new file mode 100644
index 0000000..e7343f0
Binary files /dev/null and b/assets/arena/hex_rock_roadL_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadM.gltf.glb b/assets/arena/hex_rock_roadM.gltf.glb
new file mode 100644
index 0000000..a51c637
Binary files /dev/null and b/assets/arena/hex_rock_roadM.gltf.glb differ
diff --git a/assets/arena/hex_rock_roadM_detail.gltf.glb b/assets/arena/hex_rock_roadM_detail.gltf.glb
new file mode 100644
index 0000000..66ce90a
Binary files /dev/null and b/assets/arena/hex_rock_roadM_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_transitionA.gltf.glb b/assets/arena/hex_rock_transitionA.gltf.glb
new file mode 100644
index 0000000..6b0cd0a
Binary files /dev/null and b/assets/arena/hex_rock_transitionA.gltf.glb differ
diff --git a/assets/arena/hex_rock_transitionB.gltf.glb b/assets/arena/hex_rock_transitionB.gltf.glb
new file mode 100644
index 0000000..ab8972a
Binary files /dev/null and b/assets/arena/hex_rock_transitionB.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterA.gltf.glb b/assets/arena/hex_rock_waterA.gltf.glb
new file mode 100644
index 0000000..762dd15
Binary files /dev/null and b/assets/arena/hex_rock_waterA.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterA_detail.gltf.glb b/assets/arena/hex_rock_waterA_detail.gltf.glb
new file mode 100644
index 0000000..b5f57e7
Binary files /dev/null and b/assets/arena/hex_rock_waterA_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterA_empty.gltf.glb b/assets/arena/hex_rock_waterA_empty.gltf.glb
new file mode 100644
index 0000000..49e478c
Binary files /dev/null and b/assets/arena/hex_rock_waterA_empty.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterB.gltf.glb b/assets/arena/hex_rock_waterB.gltf.glb
new file mode 100644
index 0000000..7d36af3
Binary files /dev/null and b/assets/arena/hex_rock_waterB.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterB_detail.gltf.glb b/assets/arena/hex_rock_waterB_detail.gltf.glb
new file mode 100644
index 0000000..b66877c
Binary files /dev/null and b/assets/arena/hex_rock_waterB_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterB_empty.gltf.glb b/assets/arena/hex_rock_waterB_empty.gltf.glb
new file mode 100644
index 0000000..30a0fc0
Binary files /dev/null and b/assets/arena/hex_rock_waterB_empty.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterC.gltf.glb b/assets/arena/hex_rock_waterC.gltf.glb
new file mode 100644
index 0000000..5d04991
Binary files /dev/null and b/assets/arena/hex_rock_waterC.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterC_detail.gltf.glb b/assets/arena/hex_rock_waterC_detail.gltf.glb
new file mode 100644
index 0000000..cb9791a
Binary files /dev/null and b/assets/arena/hex_rock_waterC_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterC_empty.gltf.glb b/assets/arena/hex_rock_waterC_empty.gltf.glb
new file mode 100644
index 0000000..2c9a1bd
Binary files /dev/null and b/assets/arena/hex_rock_waterC_empty.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterD.gltf.glb b/assets/arena/hex_rock_waterD.gltf.glb
new file mode 100644
index 0000000..f43656f
Binary files /dev/null and b/assets/arena/hex_rock_waterD.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterD_detail.gltf.glb b/assets/arena/hex_rock_waterD_detail.gltf.glb
new file mode 100644
index 0000000..9684a26
Binary files /dev/null and b/assets/arena/hex_rock_waterD_detail.gltf.glb differ
diff --git a/assets/arena/hex_rock_waterD_empty.gltf.glb b/assets/arena/hex_rock_waterD_empty.gltf.glb
new file mode 100644
index 0000000..395f5e4
Binary files /dev/null and b/assets/arena/hex_rock_waterD_empty.gltf.glb differ
diff --git a/assets/arena/hex_sand.gltf.glb b/assets/arena/hex_sand.gltf.glb
new file mode 100644
index 0000000..a07f142
Binary files /dev/null and b/assets/arena/hex_sand.gltf.glb differ
diff --git a/assets/arena/hex_sand_detail.gltf.glb b/assets/arena/hex_sand_detail.gltf.glb
new file mode 100644
index 0000000..5a6ece0
Binary files /dev/null and b/assets/arena/hex_sand_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadA.gltf.glb b/assets/arena/hex_sand_roadA.gltf.glb
new file mode 100644
index 0000000..afd2c77
Binary files /dev/null and b/assets/arena/hex_sand_roadA.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadA_detail.gltf.glb b/assets/arena/hex_sand_roadA_detail.gltf.glb
new file mode 100644
index 0000000..4da2335
Binary files /dev/null and b/assets/arena/hex_sand_roadA_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadB.gltf.glb b/assets/arena/hex_sand_roadB.gltf.glb
new file mode 100644
index 0000000..3ecbd54
Binary files /dev/null and b/assets/arena/hex_sand_roadB.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadB_detail.gltf.glb b/assets/arena/hex_sand_roadB_detail.gltf.glb
new file mode 100644
index 0000000..ced06df
Binary files /dev/null and b/assets/arena/hex_sand_roadB_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadC.gltf.glb b/assets/arena/hex_sand_roadC.gltf.glb
new file mode 100644
index 0000000..400366e
Binary files /dev/null and b/assets/arena/hex_sand_roadC.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadC_detail.gltf.glb b/assets/arena/hex_sand_roadC_detail.gltf.glb
new file mode 100644
index 0000000..2bddc33
Binary files /dev/null and b/assets/arena/hex_sand_roadC_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadD.gltf.glb b/assets/arena/hex_sand_roadD.gltf.glb
new file mode 100644
index 0000000..34e0e93
Binary files /dev/null and b/assets/arena/hex_sand_roadD.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadD_detail.gltf.glb b/assets/arena/hex_sand_roadD_detail.gltf.glb
new file mode 100644
index 0000000..42eea3a
Binary files /dev/null and b/assets/arena/hex_sand_roadD_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadE.gltf.glb b/assets/arena/hex_sand_roadE.gltf.glb
new file mode 100644
index 0000000..8c0a832
Binary files /dev/null and b/assets/arena/hex_sand_roadE.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadE_detail.gltf.glb b/assets/arena/hex_sand_roadE_detail.gltf.glb
new file mode 100644
index 0000000..3e64461
Binary files /dev/null and b/assets/arena/hex_sand_roadE_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadF.gltf.glb b/assets/arena/hex_sand_roadF.gltf.glb
new file mode 100644
index 0000000..86b288a
Binary files /dev/null and b/assets/arena/hex_sand_roadF.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadF_detail.gltf.glb b/assets/arena/hex_sand_roadF_detail.gltf.glb
new file mode 100644
index 0000000..2200410
Binary files /dev/null and b/assets/arena/hex_sand_roadF_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadG.gltf.glb b/assets/arena/hex_sand_roadG.gltf.glb
new file mode 100644
index 0000000..7be5c7c
Binary files /dev/null and b/assets/arena/hex_sand_roadG.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadG_detail.gltf.glb b/assets/arena/hex_sand_roadG_detail.gltf.glb
new file mode 100644
index 0000000..210cff0
Binary files /dev/null and b/assets/arena/hex_sand_roadG_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadH.gltf.glb b/assets/arena/hex_sand_roadH.gltf.glb
new file mode 100644
index 0000000..988391f
Binary files /dev/null and b/assets/arena/hex_sand_roadH.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadH_detail.gltf.glb b/assets/arena/hex_sand_roadH_detail.gltf.glb
new file mode 100644
index 0000000..9035841
Binary files /dev/null and b/assets/arena/hex_sand_roadH_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadI.gltf.glb b/assets/arena/hex_sand_roadI.gltf.glb
new file mode 100644
index 0000000..015d4b2
Binary files /dev/null and b/assets/arena/hex_sand_roadI.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadI_detail.gltf.glb b/assets/arena/hex_sand_roadI_detail.gltf.glb
new file mode 100644
index 0000000..38d68ab
Binary files /dev/null and b/assets/arena/hex_sand_roadI_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadJ.gltf.glb b/assets/arena/hex_sand_roadJ.gltf.glb
new file mode 100644
index 0000000..7efd274
Binary files /dev/null and b/assets/arena/hex_sand_roadJ.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadJ_detail.gltf.glb b/assets/arena/hex_sand_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..03b88fd
Binary files /dev/null and b/assets/arena/hex_sand_roadJ_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadK.gltf.glb b/assets/arena/hex_sand_roadK.gltf.glb
new file mode 100644
index 0000000..39f8c22
Binary files /dev/null and b/assets/arena/hex_sand_roadK.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadK_detail.gltf.glb b/assets/arena/hex_sand_roadK_detail.gltf.glb
new file mode 100644
index 0000000..834861a
Binary files /dev/null and b/assets/arena/hex_sand_roadK_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadL.gltf.glb b/assets/arena/hex_sand_roadL.gltf.glb
new file mode 100644
index 0000000..832b7ec
Binary files /dev/null and b/assets/arena/hex_sand_roadL.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadL_detail.gltf.glb b/assets/arena/hex_sand_roadL_detail.gltf.glb
new file mode 100644
index 0000000..0ca1090
Binary files /dev/null and b/assets/arena/hex_sand_roadL_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadM.gltf.glb b/assets/arena/hex_sand_roadM.gltf.glb
new file mode 100644
index 0000000..6cfb232
Binary files /dev/null and b/assets/arena/hex_sand_roadM.gltf.glb differ
diff --git a/assets/arena/hex_sand_roadM_detail.gltf.glb b/assets/arena/hex_sand_roadM_detail.gltf.glb
new file mode 100644
index 0000000..9b7e627
Binary files /dev/null and b/assets/arena/hex_sand_roadM_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_transitionA.gltf.glb b/assets/arena/hex_sand_transitionA.gltf.glb
new file mode 100644
index 0000000..b060fc5
Binary files /dev/null and b/assets/arena/hex_sand_transitionA.gltf.glb differ
diff --git a/assets/arena/hex_sand_transitionB.gltf.glb b/assets/arena/hex_sand_transitionB.gltf.glb
new file mode 100644
index 0000000..c3b9227
Binary files /dev/null and b/assets/arena/hex_sand_transitionB.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterA.gltf.glb b/assets/arena/hex_sand_waterA.gltf.glb
new file mode 100644
index 0000000..2466552
Binary files /dev/null and b/assets/arena/hex_sand_waterA.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterA_detail.gltf.glb b/assets/arena/hex_sand_waterA_detail.gltf.glb
new file mode 100644
index 0000000..620dcdb
Binary files /dev/null and b/assets/arena/hex_sand_waterA_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterA_empty.gltf.glb b/assets/arena/hex_sand_waterA_empty.gltf.glb
new file mode 100644
index 0000000..0421f0d
Binary files /dev/null and b/assets/arena/hex_sand_waterA_empty.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterB.gltf.glb b/assets/arena/hex_sand_waterB.gltf.glb
new file mode 100644
index 0000000..fe72b05
Binary files /dev/null and b/assets/arena/hex_sand_waterB.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterB_detail.gltf.glb b/assets/arena/hex_sand_waterB_detail.gltf.glb
new file mode 100644
index 0000000..da4855a
Binary files /dev/null and b/assets/arena/hex_sand_waterB_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterB_empty.gltf.glb b/assets/arena/hex_sand_waterB_empty.gltf.glb
new file mode 100644
index 0000000..e0b5ce2
Binary files /dev/null and b/assets/arena/hex_sand_waterB_empty.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterC.gltf.glb b/assets/arena/hex_sand_waterC.gltf.glb
new file mode 100644
index 0000000..d639c95
Binary files /dev/null and b/assets/arena/hex_sand_waterC.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterC_detail.gltf.glb b/assets/arena/hex_sand_waterC_detail.gltf.glb
new file mode 100644
index 0000000..c5243cb
Binary files /dev/null and b/assets/arena/hex_sand_waterC_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterC_empty.gltf.glb b/assets/arena/hex_sand_waterC_empty.gltf.glb
new file mode 100644
index 0000000..19ccefb
Binary files /dev/null and b/assets/arena/hex_sand_waterC_empty.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterD.gltf.glb b/assets/arena/hex_sand_waterD.gltf.glb
new file mode 100644
index 0000000..7097113
Binary files /dev/null and b/assets/arena/hex_sand_waterD.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterD_detail.gltf.glb b/assets/arena/hex_sand_waterD_detail.gltf.glb
new file mode 100644
index 0000000..9e44717
Binary files /dev/null and b/assets/arena/hex_sand_waterD_detail.gltf.glb differ
diff --git a/assets/arena/hex_sand_waterD_empty.gltf.glb b/assets/arena/hex_sand_waterD_empty.gltf.glb
new file mode 100644
index 0000000..33f06b1
Binary files /dev/null and b/assets/arena/hex_sand_waterD_empty.gltf.glb differ
diff --git a/assets/arena/hex_water.gltf.glb b/assets/arena/hex_water.gltf.glb
new file mode 100644
index 0000000..36acea2
Binary files /dev/null and b/assets/arena/hex_water.gltf.glb differ
diff --git a/assets/arena/hex_water_detail.gltf.glb b/assets/arena/hex_water_detail.gltf.glb
new file mode 100644
index 0000000..be30de9
Binary files /dev/null and b/assets/arena/hex_water_detail.gltf.glb differ
diff --git a/assets/images/background-1.jpg b/assets/images/background-1.jpg
new file mode 100644
index 0000000..a0b1526
Binary files /dev/null and b/assets/images/background-1.jpg differ
diff --git a/components/Collapsible.tsx b/components/Collapsible.tsx
deleted file mode 100644
index 55bff2f..0000000
--- a/components/Collapsible.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { PropsWithChildren, useState } from 'react';
-import { StyleSheet, TouchableOpacity } from 'react-native';
-
-import { ThemedText } from '@/components/ThemedText';
-import { ThemedView } from '@/components/ThemedView';
-import { IconSymbol } from '@/components/ui/IconSymbol';
-import { Colors } from '@/constants/Colors';
-import { useColorScheme } from '@/hooks/useColorScheme';
-
-export function Collapsible({ children, title }: PropsWithChildren & { title: string }) {
- const [isOpen, setIsOpen] = useState(false);
- const theme = useColorScheme() ?? 'light';
-
- return (
-
- setIsOpen((value) => !value)}
- activeOpacity={0.8}>
-
-
- {title}
-
- {isOpen && {children}}
-
- );
-}
-
-const styles = StyleSheet.create({
- heading: {
- flexDirection: 'row',
- alignItems: 'center',
- gap: 6,
- },
- content: {
- marginTop: 6,
- marginLeft: 24,
- },
-});
diff --git a/components/ExternalLink.tsx b/components/ExternalLink.tsx
deleted file mode 100644
index dfbd23e..0000000
--- a/components/ExternalLink.tsx
+++ /dev/null
@@ -1,24 +0,0 @@
-import { Href, Link } from 'expo-router';
-import { openBrowserAsync } from 'expo-web-browser';
-import { type ComponentProps } from 'react';
-import { Platform } from 'react-native';
-
-type Props = Omit, 'href'> & { href: Href & string };
-
-export function ExternalLink({ href, ...rest }: Props) {
- return (
- {
- if (Platform.OS !== 'web') {
- // Prevent the default behavior of linking to the default browser on native.
- event.preventDefault();
- // Open the link in an in-app browser.
- await openBrowserAsync(href);
- }
- }}
- />
- );
-}
diff --git a/components/HapticTab.tsx b/components/HapticTab.tsx
deleted file mode 100644
index 7f3981c..0000000
--- a/components/HapticTab.tsx
+++ /dev/null
@@ -1,18 +0,0 @@
-import { BottomTabBarButtonProps } from '@react-navigation/bottom-tabs';
-import { PlatformPressable } from '@react-navigation/elements';
-import * as Haptics from 'expo-haptics';
-
-export function HapticTab(props: BottomTabBarButtonProps) {
- return (
- {
- if (process.env.EXPO_OS === 'ios') {
- // Add a soft haptic feedback when pressing down on the tabs.
- Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
- }
- props.onPressIn?.(ev);
- }}
- />
- );
-}
diff --git a/components/HelloWave.tsx b/components/HelloWave.tsx
deleted file mode 100644
index eb6ea61..0000000
--- a/components/HelloWave.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import { useEffect } from 'react';
-import { StyleSheet } from 'react-native';
-import Animated, {
- useAnimatedStyle,
- useSharedValue,
- withRepeat,
- withSequence,
- withTiming,
-} from 'react-native-reanimated';
-
-import { ThemedText } from '@/components/ThemedText';
-
-export function HelloWave() {
- const rotationAnimation = useSharedValue(0);
-
- useEffect(() => {
- rotationAnimation.value = withRepeat(
- withSequence(withTiming(25, { duration: 150 }), withTiming(0, { duration: 150 })),
- 4 // Run the animation 4 times
- );
- }, [rotationAnimation]);
-
- const animatedStyle = useAnimatedStyle(() => ({
- transform: [{ rotate: `${rotationAnimation.value}deg` }],
- }));
-
- return (
-
- š
-
- );
-}
-
-const styles = StyleSheet.create({
- text: {
- fontSize: 28,
- lineHeight: 32,
- marginTop: -6,
- },
-});
diff --git a/components/ParallaxScrollView.tsx b/components/ParallaxScrollView.tsx
deleted file mode 100644
index 5df1d75..0000000
--- a/components/ParallaxScrollView.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import type { PropsWithChildren, ReactElement } from 'react';
-import { StyleSheet } from 'react-native';
-import Animated, {
- interpolate,
- useAnimatedRef,
- useAnimatedStyle,
- useScrollViewOffset,
-} from 'react-native-reanimated';
-
-import { ThemedView } from '@/components/ThemedView';
-import { useBottomTabOverflow } from '@/components/ui/TabBarBackground';
-import { useColorScheme } from '@/hooks/useColorScheme';
-
-const HEADER_HEIGHT = 250;
-
-type Props = PropsWithChildren<{
- headerImage: ReactElement;
- headerBackgroundColor: { dark: string; light: string };
-}>;
-
-export default function ParallaxScrollView({
- children,
- headerImage,
- headerBackgroundColor,
-}: Props) {
- const colorScheme = useColorScheme() ?? 'light';
- const scrollRef = useAnimatedRef();
- const scrollOffset = useScrollViewOffset(scrollRef);
- const bottom = useBottomTabOverflow();
- const headerAnimatedStyle = useAnimatedStyle(() => {
- return {
- transform: [
- {
- translateY: interpolate(
- scrollOffset.value,
- [-HEADER_HEIGHT, 0, HEADER_HEIGHT],
- [-HEADER_HEIGHT / 2, 0, HEADER_HEIGHT * 0.75]
- ),
- },
- {
- scale: interpolate(scrollOffset.value, [-HEADER_HEIGHT, 0, HEADER_HEIGHT], [2, 1, 1]),
- },
- ],
- };
- });
-
- return (
-
-
-
- {headerImage}
-
- {children}
-
-
- );
-}
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- },
- header: {
- height: HEADER_HEIGHT,
- overflow: 'hidden',
- },
- content: {
- flex: 1,
- padding: 32,
- gap: 16,
- overflow: 'hidden',
- },
-});
diff --git a/components/ThemedText.tsx b/components/ThemedText.tsx
deleted file mode 100644
index 9d214a2..0000000
--- a/components/ThemedText.tsx
+++ /dev/null
@@ -1,60 +0,0 @@
-import { StyleSheet, Text, type TextProps } from 'react-native';
-
-import { useThemeColor } from '@/hooks/useThemeColor';
-
-export type ThemedTextProps = TextProps & {
- lightColor?: string;
- darkColor?: string;
- type?: 'default' | 'title' | 'defaultSemiBold' | 'subtitle' | 'link';
-};
-
-export function ThemedText({
- style,
- lightColor,
- darkColor,
- type = 'default',
- ...rest
-}: ThemedTextProps) {
- const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
-
- return (
-
- );
-}
-
-const styles = StyleSheet.create({
- default: {
- fontSize: 16,
- lineHeight: 24,
- },
- defaultSemiBold: {
- fontSize: 16,
- lineHeight: 24,
- fontWeight: '600',
- },
- title: {
- fontSize: 32,
- fontWeight: 'bold',
- lineHeight: 32,
- },
- subtitle: {
- fontSize: 20,
- fontWeight: 'bold',
- },
- link: {
- lineHeight: 30,
- fontSize: 16,
- color: '#0a7ea4',
- },
-});
diff --git a/components/ThemedView.tsx b/components/ThemedView.tsx
deleted file mode 100644
index 4d2cb09..0000000
--- a/components/ThemedView.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { View, type ViewProps } from 'react-native';
-
-import { useThemeColor } from '@/hooks/useThemeColor';
-
-export type ThemedViewProps = ViewProps & {
- lightColor?: string;
- darkColor?: string;
-};
-
-export function ThemedView({ style, lightColor, darkColor, ...otherProps }: ThemedViewProps) {
- const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
-
- return ;
-}
diff --git a/components/ui/IconSymbol.ios.tsx b/components/ui/IconSymbol.ios.tsx
deleted file mode 100644
index 9177f4d..0000000
--- a/components/ui/IconSymbol.ios.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { SymbolView, SymbolViewProps, SymbolWeight } from 'expo-symbols';
-import { StyleProp, ViewStyle } from 'react-native';
-
-export function IconSymbol({
- name,
- size = 24,
- color,
- style,
- weight = 'regular',
-}: {
- name: SymbolViewProps['name'];
- size?: number;
- color: string;
- style?: StyleProp;
- weight?: SymbolWeight;
-}) {
- return (
-
- );
-}
diff --git a/components/ui/IconSymbol.tsx b/components/ui/IconSymbol.tsx
deleted file mode 100644
index b7ece6b..0000000
--- a/components/ui/IconSymbol.tsx
+++ /dev/null
@@ -1,41 +0,0 @@
-// Fallback for using MaterialIcons on Android and web.
-
-import MaterialIcons from '@expo/vector-icons/MaterialIcons';
-import { SymbolWeight, SymbolViewProps } from 'expo-symbols';
-import { ComponentProps } from 'react';
-import { OpaqueColorValue, type StyleProp, type TextStyle } from 'react-native';
-
-type IconMapping = Record['name']>;
-type IconSymbolName = keyof typeof MAPPING;
-
-/**
- * Add your SF Symbols to Material Icons mappings here.
- * - see Material Icons in the [Icons Directory](https://icons.expo.fyi).
- * - see SF Symbols in the [SF Symbols](https://developer.apple.com/sf-symbols/) app.
- */
-const MAPPING = {
- 'house.fill': 'home',
- 'paperplane.fill': 'send',
- 'chevron.left.forwardslash.chevron.right': 'code',
- 'chevron.right': 'chevron-right',
-} as IconMapping;
-
-/**
- * An icon component that uses native SF Symbols on iOS, and Material Icons on Android and web.
- * This ensures a consistent look across platforms, and optimal resource usage.
- * Icon `name`s are based on SF Symbols and require manual mapping to Material Icons.
- */
-export function IconSymbol({
- name,
- size = 24,
- color,
- style,
-}: {
- name: IconSymbolName;
- size?: number;
- color: string | OpaqueColorValue;
- style?: StyleProp;
- weight?: SymbolWeight;
-}) {
- return ;
-}
diff --git a/components/ui/TabBarBackground.ios.tsx b/components/ui/TabBarBackground.ios.tsx
deleted file mode 100644
index 495b2d4..0000000
--- a/components/ui/TabBarBackground.ios.tsx
+++ /dev/null
@@ -1,19 +0,0 @@
-import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs';
-import { BlurView } from 'expo-blur';
-import { StyleSheet } from 'react-native';
-
-export default function BlurTabBarBackground() {
- return (
-
- );
-}
-
-export function useBottomTabOverflow() {
- return useBottomTabBarHeight();
-}
diff --git a/components/ui/TabBarBackground.tsx b/components/ui/TabBarBackground.tsx
deleted file mode 100644
index 70d1c3c..0000000
--- a/components/ui/TabBarBackground.tsx
+++ /dev/null
@@ -1,6 +0,0 @@
-// This is a shim for web and Android where the tab bar is generally opaque.
-export default undefined;
-
-export function useBottomTabOverflow() {
- return 0;
-}
diff --git a/constants/Colors.ts b/constants/Colors.ts
deleted file mode 100644
index 14e6784..0000000
--- a/constants/Colors.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * Below are the colors that are used in the app. The colors are defined in the light and dark mode.
- * There are many other ways to style your app. For example, [Nativewind](https://www.nativewind.dev/), [Tamagui](https://tamagui.dev/), [unistyles](https://reactnativeunistyles.vercel.app), etc.
- */
-
-const tintColorLight = '#0a7ea4';
-const tintColorDark = '#fff';
-
-export const Colors = {
- light: {
- text: '#11181C',
- background: '#fff',
- tint: tintColorLight,
- icon: '#687076',
- tabIconDefault: '#687076',
- tabIconSelected: tintColorLight,
- },
- dark: {
- text: '#ECEDEE',
- background: '#151718',
- tint: tintColorDark,
- icon: '#9BA1A6',
- tabIconDefault: '#9BA1A6',
- tabIconSelected: tintColorDark,
- },
-};
diff --git a/hooks/useColorScheme.ts b/hooks/useColorScheme.ts
deleted file mode 100644
index 17e3c63..0000000
--- a/hooks/useColorScheme.ts
+++ /dev/null
@@ -1 +0,0 @@
-export { useColorScheme } from 'react-native';
diff --git a/hooks/useColorScheme.web.ts b/hooks/useColorScheme.web.ts
deleted file mode 100644
index 7eb1c1b..0000000
--- a/hooks/useColorScheme.web.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { useEffect, useState } from 'react';
-import { useColorScheme as useRNColorScheme } from 'react-native';
-
-/**
- * To support static rendering, this value needs to be re-calculated on the client side for web
- */
-export function useColorScheme() {
- const [hasHydrated, setHasHydrated] = useState(false);
-
- useEffect(() => {
- setHasHydrated(true);
- }, []);
-
- const colorScheme = useRNColorScheme();
-
- if (hasHydrated) {
- return colorScheme;
- }
-
- return 'light';
-}
diff --git a/hooks/useThemeColor.ts b/hooks/useThemeColor.ts
deleted file mode 100644
index 0608e73..0000000
--- a/hooks/useThemeColor.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * Learn more about light and dark modes:
- * https://docs.expo.dev/guides/color-schemes/
- */
-
-import { Colors } from '@/constants/Colors';
-import { useColorScheme } from '@/hooks/useColorScheme';
-
-export function useThemeColor(
- props: { light?: string; dark?: string },
- colorName: keyof typeof Colors.light & keyof typeof Colors.dark
-) {
- const theme = useColorScheme() ?? 'light';
- const colorFromProps = props[theme];
-
- if (colorFromProps) {
- return colorFromProps;
- } else {
- return Colors[theme][colorName];
- }
-}
diff --git a/metro.config.js b/metro.config.js
new file mode 100644
index 0000000..9a11768
--- /dev/null
+++ b/metro.config.js
@@ -0,0 +1,17 @@
+const { getDefaultConfig } = require('expo/metro-config');
+
+const config = getDefaultConfig(__dirname);
+
+// Add GLB file support
+config.resolver.assetExts.push('glb', 'gltf', 'jpg');
+
+// Serve static files from public directory
+config.server = {
+ ...config.server,
+ static: {
+ directory: 'public',
+ publicPath: '/'
+ }
+};
+
+module.exports = config;
\ No newline at end of file
diff --git a/package-lock.json b/package-lock.json
index 81d2916..a2de195 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -13,9 +13,12 @@
"@react-navigation/elements": "^2.3.8",
"@react-navigation/native": "^7.1.6",
"expo": "~53.0.20",
+ "expo-asset": "^11.1.7",
"expo-blur": "~14.1.5",
"expo-constants": "~17.1.7",
+ "expo-file-system": "^18.1.11",
"expo-font": "~13.3.2",
+ "expo-gl": "~15.1.7",
"expo-haptics": "~14.1.4",
"expo-image": "~2.4.0",
"expo-linking": "~7.1.7",
@@ -24,6 +27,7 @@
"expo-status-bar": "~2.2.3",
"expo-symbols": "~0.4.5",
"expo-system-ui": "~5.0.10",
+ "expo-three": "^8.0.0",
"expo-web-browser": "~14.2.0",
"react": "19.0.0",
"react-dom": "19.0.0",
@@ -33,11 +37,13 @@
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
"react-native-web": "~0.20.0",
- "react-native-webview": "13.13.5"
+ "react-native-webview": "13.13.5",
+ "three": "^0.166.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~19.0.10",
+ "@types/three": "^0.178.1",
"eslint": "^9.25.0",
"eslint-config-expo": "~9.2.0",
"typescript": "~5.8.3"
@@ -1429,6 +1435,12 @@
"node": ">=6.9.0"
}
},
+ "node_modules/@dimforge/rapier3d-compat": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz",
+ "integrity": "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow==",
+ "dev": true
+ },
"node_modules/@egjs/hammerjs": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
@@ -2910,6 +2922,12 @@
"@sinonjs/commons": "^3.0.0"
}
},
+ "node_modules/@tweenjs/tween.js": {
+ "version": "23.1.3",
+ "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
+ "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA==",
+ "dev": true
+ },
"node_modules/@tybys/wasm-util": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.0.tgz",
@@ -3030,6 +3048,33 @@
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
"integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw=="
},
+ "node_modules/@types/stats.js": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.4.tgz",
+ "integrity": "sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA==",
+ "dev": true
+ },
+ "node_modules/@types/three": {
+ "version": "0.178.1",
+ "resolved": "https://registry.npmjs.org/@types/three/-/three-0.178.1.tgz",
+ "integrity": "sha512-WSabew1mgWgRx2RfLfKY+9h4wyg6U94JfLbZEGU245j/WY2kXqU0MUfghS+3AYMV5ET1VlILAgpy77cB6a3Itw==",
+ "dev": true,
+ "dependencies": {
+ "@dimforge/rapier3d-compat": "~0.12.0",
+ "@tweenjs/tween.js": "~23.1.3",
+ "@types/stats.js": "*",
+ "@types/webxr": "*",
+ "@webgpu/types": "*",
+ "fflate": "~0.8.2",
+ "meshoptimizer": "~0.18.1"
+ }
+ },
+ "node_modules/@types/webxr": {
+ "version": "0.5.22",
+ "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.22.tgz",
+ "integrity": "sha512-Vr6Stjv5jPRqH690f5I5GLjVk8GSsoQSYJ2FVd/3jJF7KaqfwPi3ehfBS96mlQ2kPCwZaX6U0rG2+NGHBKkA/A==",
+ "dev": true
+ },
"node_modules/@types/yargs": {
"version": "17.0.33",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
@@ -3571,6 +3616,12 @@
"@urql/core": "^5.0.0"
}
},
+ "node_modules/@webgpu/types": {
+ "version": "0.1.64",
+ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.64.tgz",
+ "integrity": "sha512-84kRIAGV46LJTlJZWxShiOrNL30A+9KokD7RB3dRCIqODFjodS5tCD5yyiZ8kIReGVZSDfA3XkkwyyOIF6K62A==",
+ "dev": true
+ },
"node_modules/@xmldom/xmldom": {
"version": "0.8.10",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
@@ -3622,6 +3673,16 @@
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
+ "node_modules/adaptive-bezier-curve": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/adaptive-bezier-curve/-/adaptive-bezier-curve-1.0.3.tgz",
+ "integrity": "sha512-mDcwN284LlNAdunqnVmS0PAoDNHKze/PY8zvpCdxzyXD+ZZFeMWQ3FKNBw0VMOd9IfnhIyzAWJDXzRcWnXtoSg=="
+ },
+ "node_modules/adaptive-quadratic-curve": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/adaptive-quadratic-curve/-/adaptive-quadratic-curve-1.0.2.tgz",
+ "integrity": "sha512-D6NxIKnelgRDqQijGR6FQzdWPgs4bC7H54LyukFKxTkoZW4+zNemU2JevF4BuMraoxYogvAIMRc2LD5oSCL34g=="
+ },
"node_modules/agent-base": {
"version": "7.1.4",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
@@ -4701,6 +4762,12 @@
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
},
+ "node_modules/core-js": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz",
+ "integrity": "sha512-ZiPp9pZlgxpWRu0M+YWbm6+aQ84XEfH1JRXvfOc/fILWI0VKhLC2LX13X1NYq4fULzLMq7Hfh43CSo2/aIaUPA==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js."
+ },
"node_modules/core-js-compat": {
"version": "3.44.0",
"resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.44.0.tgz",
@@ -4796,6 +4863,11 @@
"node": ">=8"
}
},
+ "node_modules/css-font-parser": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/css-font-parser/-/css-font-parser-0.2.3.tgz",
+ "integrity": "sha512-QhdfNV+RjQLVg24d/ls4I8UrA/5WCeEfUmi1je8ISPr7RGZJXwWU2AwZpCiUmWuLZW7dKaB3ER0Bq1W9UhEUag=="
+ },
"node_modules/css-in-js-utils": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz",
@@ -5000,6 +5072,20 @@
"node": ">=0.10.0"
}
},
+ "node_modules/domexception": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
+ "integrity": "sha512-raigMkn7CJNNo6Ihro1fzG7wr3fHuYVytzquZKX5n0yizGsTcYgzdIUwj1X9pK0VvjeihV+XiclP+DjwbsSKug==",
+ "deprecated": "Use your platform's native DOMException instead",
+ "dependencies": {
+ "webidl-conversions": "^4.0.2"
+ }
+ },
+ "node_modules/domexception/node_modules/webidl-conversions": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz",
+ "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="
+ },
"node_modules/dotenv": {
"version": "16.4.7",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
@@ -5039,6 +5125,11 @@
"node": ">= 0.4"
}
},
+ "node_modules/earcut": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.1.1.tgz",
+ "integrity": "sha512-+BGT9Mffq3Oxf2nDOtzaJDd9P8g/z3WNYGO84Q23hDBot5VU8DNGY73Vc94eVDvHjMyhonnuEg+DNwEQ6iZn3w=="
+ },
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -5067,6 +5158,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
"node_modules/env-editor": {
"version": "0.4.2",
"resolved": "https://registry.npmjs.org/env-editor/-/env-editor-0.4.2.tgz",
@@ -5742,6 +5841,39 @@
}
}
},
+ "node_modules/expo-2d-context": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/expo-2d-context/-/expo-2d-context-0.0.3.tgz",
+ "integrity": "sha512-loO/cIj5owNXv0GJxEQ7Sm1vlGOYoJwHCaf2uiPKG3BZm+gQw6GnDgxN+2WDisNZKLTjnMLUGP1HhBsNnElt6g==",
+ "dependencies": {
+ "adaptive-bezier-curve": "1.0.3",
+ "adaptive-quadratic-curve": "1.0.2",
+ "color-convert": "^1.9.3",
+ "css-font-parser": "0.2.3",
+ "domexception": "1.0.1",
+ "earcut": "2.1.1",
+ "gl-matrix": "^2.4.0",
+ "parse-bmfont-ascii": "1.0.6",
+ "string-format": "0.5.0",
+ "tess2": "^1.0.0"
+ },
+ "peerDependencies": {
+ "expo-asset": "*"
+ }
+ },
+ "node_modules/expo-2d-context/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/expo-2d-context/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="
+ },
"node_modules/expo-asset": {
"version": "11.1.7",
"resolved": "https://registry.npmjs.org/expo-asset/-/expo-asset-11.1.7.tgz",
@@ -5756,6 +5888,18 @@
"react-native": "*"
}
},
+ "node_modules/expo-asset-utils": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/expo-asset-utils/-/expo-asset-utils-3.0.0.tgz",
+ "integrity": "sha512-CgIbNvTqKqQi1lrlptmwoaCMu4ZVOZf8tghmytlor23CjIOuorw6cfuOqiqWkJLz23arTt91maYEU9XLMPB23A==",
+ "peerDependencies": {
+ "expo-asset": "*",
+ "expo-file-system": "*",
+ "expo-font": "*",
+ "expo-modules-core": "*",
+ "react-native": "*"
+ }
+ },
"node_modules/expo-blur": {
"version": "14.1.5",
"resolved": "https://registry.npmjs.org/expo-blur/-/expo-blur-14.1.5.tgz",
@@ -5800,6 +5944,25 @@
"react": "*"
}
},
+ "node_modules/expo-gl": {
+ "version": "15.1.7",
+ "resolved": "https://registry.npmjs.org/expo-gl/-/expo-gl-15.1.7.tgz",
+ "integrity": "sha512-ozvaQn3Ev1oZ3lraOpp6PJpSCbb5DRxu29K/prtfUdygrNJbCFhhxG7zgpEcPaFZXj4b1Yc7jzn1UzOylfUdaw==",
+ "dependencies": {
+ "invariant": "^2.2.4"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "react": "*",
+ "react-native": "*",
+ "react-native-web": "*"
+ },
+ "peerDependenciesMeta": {
+ "react-native-web": {
+ "optional": true
+ }
+ }
+ },
"node_modules/expo-haptics": {
"version": "14.1.4",
"resolved": "https://registry.npmjs.org/expo-haptics/-/expo-haptics-14.1.4.tgz",
@@ -5978,6 +6141,61 @@
}
}
},
+ "node_modules/expo-three": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/expo-three/-/expo-three-8.0.0.tgz",
+ "integrity": "sha512-aGSxS7UEA0DtkdY9UdAHWW4JsJh4Q2vtOQNb3oocIP5bBazb6qTm0PtsXUF0YYo5s9TCJfm4t2ED+0LUz7QwaQ==",
+ "dependencies": {
+ "@expo/browser-polyfill": "^1.0.1",
+ "expo-asset-utils": "~3.0.0"
+ },
+ "peerDependencies": {
+ "expo": "*",
+ "expo-asset": "*",
+ "expo-file-system": "*",
+ "expo-gl": "*",
+ "react-native": "*",
+ "three": "^0.166.0"
+ }
+ },
+ "node_modules/expo-three/node_modules/@expo/browser-polyfill": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@expo/browser-polyfill/-/browser-polyfill-1.0.1.tgz",
+ "integrity": "sha512-0K6USycVKDj/k9Gr2UYa+7MiCjb0f2NznsE4LX11H85vQMJma5JS3a2oe6lxCfleY9hDcQ/9zKCYS8O6crsv3A==",
+ "dependencies": {
+ "expo-2d-context": "^0.0.3",
+ "fbemitter": "^2.1.1",
+ "text-encoding": "^0.7.0",
+ "uuid": "^8.3.2",
+ "xmldom-qsa": "^1.0.3"
+ },
+ "peerDependencies": {
+ "expo-file-system": "^13.2.0",
+ "react": "^17.0.1",
+ "react-native": "^0.64.3"
+ }
+ },
+ "node_modules/expo-three/node_modules/react": {
+ "version": "17.0.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-17.0.1.tgz",
+ "integrity": "sha512-lG9c9UuMHdcAexXtigOZLX8exLWkW0Ku29qPRU8uhF2R9BN96dLCt0psvzPLlHc5OWkgymP3qwTRgbnw5BKx3w==",
+ "peer": true,
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "object-assign": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/expo-three/node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
"node_modules/expo-web-browser": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/expo-web-browser/-/expo-web-browser-14.2.0.tgz",
@@ -6068,6 +6286,61 @@
"bser": "2.1.1"
}
},
+ "node_modules/fbemitter": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fbemitter/-/fbemitter-2.1.1.tgz",
+ "integrity": "sha512-hd8PgD+Q6RQtlcGrkM9oY3MFIjq6CA6wurCK1TKn2eaA76Ww4VAOihmq98NyjRhjJi/axgznZnh9lF8+TcTsNQ==",
+ "dependencies": {
+ "fbjs": "^0.8.4"
+ }
+ },
+ "node_modules/fbemitter/node_modules/fbjs": {
+ "version": "0.8.18",
+ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.18.tgz",
+ "integrity": "sha512-EQaWFK+fEPSoibjNy8IxUtaFOMXcWsY0JaVrQoZR9zC8N2Ygf9iDITPWjUTVIax95b6I742JFLqASHfsag/vKA==",
+ "dependencies": {
+ "core-js": "^1.0.0",
+ "isomorphic-fetch": "^2.1.1",
+ "loose-envify": "^1.0.0",
+ "object-assign": "^4.1.0",
+ "promise": "^7.1.1",
+ "setimmediate": "^1.0.5",
+ "ua-parser-js": "^0.7.30"
+ }
+ },
+ "node_modules/fbemitter/node_modules/promise": {
+ "version": "7.3.1",
+ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
+ "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==",
+ "dependencies": {
+ "asap": "~2.0.3"
+ }
+ },
+ "node_modules/fbemitter/node_modules/ua-parser-js": {
+ "version": "0.7.40",
+ "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.40.tgz",
+ "integrity": "sha512-us1E3K+3jJppDBa3Tl0L3MOJiGhe1C6P0+nIvQAFYbxlMAx0h81eOwLmU57xgqToduDDPx3y5QsdjPfDu+FgOQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/ua-parser-js"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/faisalman"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/faisalman"
+ }
+ ],
+ "bin": {
+ "ua-parser-js": "script/cli.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/fbjs": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz",
@@ -6109,6 +6382,12 @@
}
}
},
+ "node_modules/fflate": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
+ "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==",
+ "dev": true
+ },
"node_modules/file-entry-cache": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
@@ -6413,6 +6692,11 @@
"node": ">=6"
}
},
+ "node_modules/gl-matrix": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-2.8.1.tgz",
+ "integrity": "sha512-0YCjVpE3pS5XWlN3J4X7AiAx65+nqAI54LndtVFnQZB6G/FVLkZH8y8V6R3cIoOQR4pUdfwQGd1iwyoXHJ4Qfw=="
+ },
"node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
@@ -6684,6 +6968,17 @@
"resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz",
"integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw=="
},
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
@@ -7137,6 +7432,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/is-stream": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/is-string": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
@@ -7250,6 +7553,24 @@
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
+ "node_modules/isomorphic-fetch": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz",
+ "integrity": "sha512-9c4TNAKYXM5PRyVcwUZrF3W09nQ+sO7+jydgs4ZGW9dhsLG2VOlISJABombdQqQRXCwuYG3sYV/puGf5rp0qmA==",
+ "dependencies": {
+ "node-fetch": "^1.0.1",
+ "whatwg-fetch": ">=0.10.0"
+ }
+ },
+ "node_modules/isomorphic-fetch/node_modules/node-fetch": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.3.tgz",
+ "integrity": "sha512-NhZ4CsKx7cYm2vSrBAr2PvFOe6sWDf0UYLRqA6svUYg7+/TSfVAu49jYC4BvQ4Sms9SZgdqGBgroqfDhJdTyKQ==",
+ "dependencies": {
+ "encoding": "^0.1.11",
+ "is-stream": "^1.0.1"
+ }
+ },
"node_modules/istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
@@ -8015,6 +8336,12 @@
"node": ">= 8"
}
},
+ "node_modules/meshoptimizer": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz",
+ "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw==",
+ "dev": true
+ },
"node_modules/metro": {
"version": "0.82.5",
"resolved": "https://registry.npmjs.org/metro/-/metro-0.82.5.tgz",
@@ -8944,6 +9271,11 @@
"node": ">=6"
}
},
+ "node_modules/parse-bmfont-ascii": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
+ "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA=="
+ },
"node_modules/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
@@ -9985,6 +10317,11 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ },
"node_modules/sax": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
@@ -10574,6 +10911,11 @@
"node": ">=4"
}
},
+ "node_modules/string-format": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/string-format/-/string-format-0.5.0.tgz",
+ "integrity": "sha512-c/CiKQMy7uuEzi+Tsvnn63/PQw/F7IOSLHNuQ44Eypd0x5VvFnDXMd2T9H0ntphv8nrHAKoZcINPb/yitOAB/g=="
+ },
"node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
@@ -10927,6 +11269,11 @@
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
+ "node_modules/tess2": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/tess2/-/tess2-1.0.0.tgz",
+ "integrity": "sha512-iSWBSOUoPn3cCT26L5Wi6mvVgL11RV4kReSnVIIPdMN7qNpkL5SLKen5BJcWj+ZTN7kK6JrHBdqTV7vvL8g+9w=="
+ },
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
@@ -10960,6 +11307,12 @@
"url": "https://github.com/sponsors/isaacs"
}
},
+ "node_modules/text-encoding": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/text-encoding/-/text-encoding-0.7.0.tgz",
+ "integrity": "sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA==",
+ "deprecated": "no longer maintained"
+ },
"node_modules/thenify": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
@@ -10979,6 +11332,11 @@
"node": ">=0.8"
}
},
+ "node_modules/three": {
+ "version": "0.166.1",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.166.1.tgz",
+ "integrity": "sha512-LtuafkKHHzm61AQA1be2MAYIw1IjmhOUxhBa0prrLpEMWbV7ijvxCRHjSgHPGp2493wLBzwKV46tA9nivLEgKg=="
+ },
"node_modules/throat": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz",
@@ -11787,6 +12145,14 @@
"node": ">=8.0"
}
},
+ "node_modules/xmldom-qsa": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/xmldom-qsa/-/xmldom-qsa-1.1.3.tgz",
+ "integrity": "sha512-IJBOczBpAYrIBJFFsmCBwfBhwe4zdMR3Xz0ZBX0OFtgO49rLy/BWbhkegOwsthdBWb1gUtFK6ZZnGdT8ZqPRBA==",
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
diff --git a/package.json b/package.json
index f79c1f4..a8fb339 100644
--- a/package.json
+++ b/package.json
@@ -16,9 +16,12 @@
"@react-navigation/elements": "^2.3.8",
"@react-navigation/native": "^7.1.6",
"expo": "~53.0.20",
+ "expo-asset": "^11.1.7",
"expo-blur": "~14.1.5",
"expo-constants": "~17.1.7",
+ "expo-file-system": "^18.1.11",
"expo-font": "~13.3.2",
+ "expo-gl": "~15.1.7",
"expo-haptics": "~14.1.4",
"expo-image": "~2.4.0",
"expo-linking": "~7.1.7",
@@ -27,6 +30,7 @@
"expo-status-bar": "~2.2.3",
"expo-symbols": "~0.4.5",
"expo-system-ui": "~5.0.10",
+ "expo-three": "^8.0.0",
"expo-web-browser": "~14.2.0",
"react": "19.0.0",
"react-dom": "19.0.0",
@@ -36,14 +40,16 @@
"react-native-safe-area-context": "5.4.0",
"react-native-screens": "~4.11.1",
"react-native-web": "~0.20.0",
- "react-native-webview": "13.13.5"
+ "react-native-webview": "13.13.5",
+ "three": "^0.166.1"
},
"devDependencies": {
"@babel/core": "^7.25.2",
"@types/react": "~19.0.10",
- "typescript": "~5.8.3",
+ "@types/three": "^0.178.1",
"eslint": "^9.25.0",
- "eslint-config-expo": "~9.2.0"
+ "eslint-config-expo": "~9.2.0",
+ "typescript": "~5.8.3"
},
"private": true
}
diff --git a/public/assets/arena/hex_forest.gltf.glb b/public/assets/arena/hex_forest.gltf.glb
new file mode 100644
index 0000000..133ba2d
Binary files /dev/null and b/public/assets/arena/hex_forest.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_detail.gltf.glb b/public/assets/arena/hex_forest_detail.gltf.glb
new file mode 100644
index 0000000..c9458f9
Binary files /dev/null and b/public/assets/arena/hex_forest_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadA.gltf.glb b/public/assets/arena/hex_forest_roadA.gltf.glb
new file mode 100644
index 0000000..6cb121c
Binary files /dev/null and b/public/assets/arena/hex_forest_roadA.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadA_detail.gltf.glb b/public/assets/arena/hex_forest_roadA_detail.gltf.glb
new file mode 100644
index 0000000..cec68db
Binary files /dev/null and b/public/assets/arena/hex_forest_roadA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadB.gltf.glb b/public/assets/arena/hex_forest_roadB.gltf.glb
new file mode 100644
index 0000000..0762226
Binary files /dev/null and b/public/assets/arena/hex_forest_roadB.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadB_detail.gltf.glb b/public/assets/arena/hex_forest_roadB_detail.gltf.glb
new file mode 100644
index 0000000..9c82dd4
Binary files /dev/null and b/public/assets/arena/hex_forest_roadB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadC.gltf.glb b/public/assets/arena/hex_forest_roadC.gltf.glb
new file mode 100644
index 0000000..d6ba108
Binary files /dev/null and b/public/assets/arena/hex_forest_roadC.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadC_detail.gltf.glb b/public/assets/arena/hex_forest_roadC_detail.gltf.glb
new file mode 100644
index 0000000..1e5e5ba
Binary files /dev/null and b/public/assets/arena/hex_forest_roadC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadD.gltf.glb b/public/assets/arena/hex_forest_roadD.gltf.glb
new file mode 100644
index 0000000..76a20af
Binary files /dev/null and b/public/assets/arena/hex_forest_roadD.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadD_detail.gltf.glb b/public/assets/arena/hex_forest_roadD_detail.gltf.glb
new file mode 100644
index 0000000..efcb545
Binary files /dev/null and b/public/assets/arena/hex_forest_roadD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadE.gltf.glb b/public/assets/arena/hex_forest_roadE.gltf.glb
new file mode 100644
index 0000000..dda8ef2
Binary files /dev/null and b/public/assets/arena/hex_forest_roadE.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadE_detail.gltf.glb b/public/assets/arena/hex_forest_roadE_detail.gltf.glb
new file mode 100644
index 0000000..7662976
Binary files /dev/null and b/public/assets/arena/hex_forest_roadE_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadF.gltf.glb b/public/assets/arena/hex_forest_roadF.gltf.glb
new file mode 100644
index 0000000..021de5e
Binary files /dev/null and b/public/assets/arena/hex_forest_roadF.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadF_detail.gltf.glb b/public/assets/arena/hex_forest_roadF_detail.gltf.glb
new file mode 100644
index 0000000..6805565
Binary files /dev/null and b/public/assets/arena/hex_forest_roadF_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadG.gltf.glb b/public/assets/arena/hex_forest_roadG.gltf.glb
new file mode 100644
index 0000000..f2f59ff
Binary files /dev/null and b/public/assets/arena/hex_forest_roadG.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadG_detail.gltf.glb b/public/assets/arena/hex_forest_roadG_detail.gltf.glb
new file mode 100644
index 0000000..565065d
Binary files /dev/null and b/public/assets/arena/hex_forest_roadG_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadH.gltf.glb b/public/assets/arena/hex_forest_roadH.gltf.glb
new file mode 100644
index 0000000..362c342
Binary files /dev/null and b/public/assets/arena/hex_forest_roadH.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadH_detail.gltf.glb b/public/assets/arena/hex_forest_roadH_detail.gltf.glb
new file mode 100644
index 0000000..f57a562
Binary files /dev/null and b/public/assets/arena/hex_forest_roadH_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadI.gltf.glb b/public/assets/arena/hex_forest_roadI.gltf.glb
new file mode 100644
index 0000000..b984ed5
Binary files /dev/null and b/public/assets/arena/hex_forest_roadI.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadI_detail.gltf.glb b/public/assets/arena/hex_forest_roadI_detail.gltf.glb
new file mode 100644
index 0000000..963a7a8
Binary files /dev/null and b/public/assets/arena/hex_forest_roadI_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadJ.gltf.glb b/public/assets/arena/hex_forest_roadJ.gltf.glb
new file mode 100644
index 0000000..dfc995f
Binary files /dev/null and b/public/assets/arena/hex_forest_roadJ.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadJ_detail.gltf.glb b/public/assets/arena/hex_forest_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..a729811
Binary files /dev/null and b/public/assets/arena/hex_forest_roadJ_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadK.gltf.glb b/public/assets/arena/hex_forest_roadK.gltf.glb
new file mode 100644
index 0000000..9066744
Binary files /dev/null and b/public/assets/arena/hex_forest_roadK.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadK_detail.gltf.glb b/public/assets/arena/hex_forest_roadK_detail.gltf.glb
new file mode 100644
index 0000000..8890565
Binary files /dev/null and b/public/assets/arena/hex_forest_roadK_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadL.gltf.glb b/public/assets/arena/hex_forest_roadL.gltf.glb
new file mode 100644
index 0000000..0ea9f95
Binary files /dev/null and b/public/assets/arena/hex_forest_roadL.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadL_detail.gltf.glb b/public/assets/arena/hex_forest_roadL_detail.gltf.glb
new file mode 100644
index 0000000..8cef810
Binary files /dev/null and b/public/assets/arena/hex_forest_roadL_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadM.gltf.glb b/public/assets/arena/hex_forest_roadM.gltf.glb
new file mode 100644
index 0000000..1d11fe4
Binary files /dev/null and b/public/assets/arena/hex_forest_roadM.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_roadM_detail.gltf.glb b/public/assets/arena/hex_forest_roadM_detail.gltf.glb
new file mode 100644
index 0000000..7f2cc04
Binary files /dev/null and b/public/assets/arena/hex_forest_roadM_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_transitionA.gltf.glb b/public/assets/arena/hex_forest_transitionA.gltf.glb
new file mode 100644
index 0000000..01891ad
Binary files /dev/null and b/public/assets/arena/hex_forest_transitionA.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_transitionB.gltf.glb b/public/assets/arena/hex_forest_transitionB.gltf.glb
new file mode 100644
index 0000000..cd474b7
Binary files /dev/null and b/public/assets/arena/hex_forest_transitionB.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterA.gltf.glb b/public/assets/arena/hex_forest_waterA.gltf.glb
new file mode 100644
index 0000000..6512d4b
Binary files /dev/null and b/public/assets/arena/hex_forest_waterA.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterA_detail.gltf.glb b/public/assets/arena/hex_forest_waterA_detail.gltf.glb
new file mode 100644
index 0000000..500b22b
Binary files /dev/null and b/public/assets/arena/hex_forest_waterA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterA_empty.gltf.glb b/public/assets/arena/hex_forest_waterA_empty.gltf.glb
new file mode 100644
index 0000000..40614d9
Binary files /dev/null and b/public/assets/arena/hex_forest_waterA_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterB.gltf.glb b/public/assets/arena/hex_forest_waterB.gltf.glb
new file mode 100644
index 0000000..d7a9800
Binary files /dev/null and b/public/assets/arena/hex_forest_waterB.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterB_detail.gltf.glb b/public/assets/arena/hex_forest_waterB_detail.gltf.glb
new file mode 100644
index 0000000..2436c01
Binary files /dev/null and b/public/assets/arena/hex_forest_waterB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterB_empty.gltf.glb b/public/assets/arena/hex_forest_waterB_empty.gltf.glb
new file mode 100644
index 0000000..196c06d
Binary files /dev/null and b/public/assets/arena/hex_forest_waterB_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterC.gltf.glb b/public/assets/arena/hex_forest_waterC.gltf.glb
new file mode 100644
index 0000000..7277baf
Binary files /dev/null and b/public/assets/arena/hex_forest_waterC.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterC_detail.gltf.glb b/public/assets/arena/hex_forest_waterC_detail.gltf.glb
new file mode 100644
index 0000000..7e854fa
Binary files /dev/null and b/public/assets/arena/hex_forest_waterC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterC_empty.gltf.glb b/public/assets/arena/hex_forest_waterC_empty.gltf.glb
new file mode 100644
index 0000000..eb17e6a
Binary files /dev/null and b/public/assets/arena/hex_forest_waterC_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterD.gltf.glb b/public/assets/arena/hex_forest_waterD.gltf.glb
new file mode 100644
index 0000000..ab60f8e
Binary files /dev/null and b/public/assets/arena/hex_forest_waterD.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterD_detail.gltf.glb b/public/assets/arena/hex_forest_waterD_detail.gltf.glb
new file mode 100644
index 0000000..ad3c3bb
Binary files /dev/null and b/public/assets/arena/hex_forest_waterD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_forest_waterD_empty.gltf.glb b/public/assets/arena/hex_forest_waterD_empty.gltf.glb
new file mode 100644
index 0000000..d299200
Binary files /dev/null and b/public/assets/arena/hex_forest_waterD_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_rock.gltf.glb b/public/assets/arena/hex_rock.gltf.glb
new file mode 100644
index 0000000..4c6af9e
Binary files /dev/null and b/public/assets/arena/hex_rock.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_detail.gltf.glb b/public/assets/arena/hex_rock_detail.gltf.glb
new file mode 100644
index 0000000..1e13ce7
Binary files /dev/null and b/public/assets/arena/hex_rock_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadA.gltf.glb b/public/assets/arena/hex_rock_roadA.gltf.glb
new file mode 100644
index 0000000..8ded8f0
Binary files /dev/null and b/public/assets/arena/hex_rock_roadA.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadA_detail.gltf.glb b/public/assets/arena/hex_rock_roadA_detail.gltf.glb
new file mode 100644
index 0000000..cb535e0
Binary files /dev/null and b/public/assets/arena/hex_rock_roadA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadB.gltf.glb b/public/assets/arena/hex_rock_roadB.gltf.glb
new file mode 100644
index 0000000..3446702
Binary files /dev/null and b/public/assets/arena/hex_rock_roadB.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadB_detail.gltf.glb b/public/assets/arena/hex_rock_roadB_detail.gltf.glb
new file mode 100644
index 0000000..0f500ad
Binary files /dev/null and b/public/assets/arena/hex_rock_roadB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadC.gltf.glb b/public/assets/arena/hex_rock_roadC.gltf.glb
new file mode 100644
index 0000000..9017133
Binary files /dev/null and b/public/assets/arena/hex_rock_roadC.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadC_detail.gltf.glb b/public/assets/arena/hex_rock_roadC_detail.gltf.glb
new file mode 100644
index 0000000..e29da55
Binary files /dev/null and b/public/assets/arena/hex_rock_roadC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadD.gltf.glb b/public/assets/arena/hex_rock_roadD.gltf.glb
new file mode 100644
index 0000000..e80531d
Binary files /dev/null and b/public/assets/arena/hex_rock_roadD.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadD_detail.gltf.glb b/public/assets/arena/hex_rock_roadD_detail.gltf.glb
new file mode 100644
index 0000000..a54117d
Binary files /dev/null and b/public/assets/arena/hex_rock_roadD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadE.gltf.glb b/public/assets/arena/hex_rock_roadE.gltf.glb
new file mode 100644
index 0000000..e5e9c6b
Binary files /dev/null and b/public/assets/arena/hex_rock_roadE.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadE_detail.gltf.glb b/public/assets/arena/hex_rock_roadE_detail.gltf.glb
new file mode 100644
index 0000000..e9741a0
Binary files /dev/null and b/public/assets/arena/hex_rock_roadE_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadF.gltf.glb b/public/assets/arena/hex_rock_roadF.gltf.glb
new file mode 100644
index 0000000..e46ac18
Binary files /dev/null and b/public/assets/arena/hex_rock_roadF.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadF_detail.gltf.glb b/public/assets/arena/hex_rock_roadF_detail.gltf.glb
new file mode 100644
index 0000000..8522ff0
Binary files /dev/null and b/public/assets/arena/hex_rock_roadF_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadG.gltf.glb b/public/assets/arena/hex_rock_roadG.gltf.glb
new file mode 100644
index 0000000..0b754e4
Binary files /dev/null and b/public/assets/arena/hex_rock_roadG.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadG_detail.gltf.glb b/public/assets/arena/hex_rock_roadG_detail.gltf.glb
new file mode 100644
index 0000000..1e5048a
Binary files /dev/null and b/public/assets/arena/hex_rock_roadG_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadH.gltf.glb b/public/assets/arena/hex_rock_roadH.gltf.glb
new file mode 100644
index 0000000..24a489c
Binary files /dev/null and b/public/assets/arena/hex_rock_roadH.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadH_detail.gltf.glb b/public/assets/arena/hex_rock_roadH_detail.gltf.glb
new file mode 100644
index 0000000..43007b3
Binary files /dev/null and b/public/assets/arena/hex_rock_roadH_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadI.gltf.glb b/public/assets/arena/hex_rock_roadI.gltf.glb
new file mode 100644
index 0000000..60cae61
Binary files /dev/null and b/public/assets/arena/hex_rock_roadI.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadI_detail.gltf.glb b/public/assets/arena/hex_rock_roadI_detail.gltf.glb
new file mode 100644
index 0000000..a86b791
Binary files /dev/null and b/public/assets/arena/hex_rock_roadI_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadJ.gltf.glb b/public/assets/arena/hex_rock_roadJ.gltf.glb
new file mode 100644
index 0000000..dc85527
Binary files /dev/null and b/public/assets/arena/hex_rock_roadJ.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadJ_detail.gltf.glb b/public/assets/arena/hex_rock_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..17abbbc
Binary files /dev/null and b/public/assets/arena/hex_rock_roadJ_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadK.gltf.glb b/public/assets/arena/hex_rock_roadK.gltf.glb
new file mode 100644
index 0000000..a07bd62
Binary files /dev/null and b/public/assets/arena/hex_rock_roadK.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadK_detail.gltf.glb b/public/assets/arena/hex_rock_roadK_detail.gltf.glb
new file mode 100644
index 0000000..e25dae9
Binary files /dev/null and b/public/assets/arena/hex_rock_roadK_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadL.gltf.glb b/public/assets/arena/hex_rock_roadL.gltf.glb
new file mode 100644
index 0000000..2469f38
Binary files /dev/null and b/public/assets/arena/hex_rock_roadL.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadL_detail.gltf.glb b/public/assets/arena/hex_rock_roadL_detail.gltf.glb
new file mode 100644
index 0000000..e7343f0
Binary files /dev/null and b/public/assets/arena/hex_rock_roadL_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadM.gltf.glb b/public/assets/arena/hex_rock_roadM.gltf.glb
new file mode 100644
index 0000000..a51c637
Binary files /dev/null and b/public/assets/arena/hex_rock_roadM.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_roadM_detail.gltf.glb b/public/assets/arena/hex_rock_roadM_detail.gltf.glb
new file mode 100644
index 0000000..66ce90a
Binary files /dev/null and b/public/assets/arena/hex_rock_roadM_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_transitionA.gltf.glb b/public/assets/arena/hex_rock_transitionA.gltf.glb
new file mode 100644
index 0000000..6b0cd0a
Binary files /dev/null and b/public/assets/arena/hex_rock_transitionA.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_transitionB.gltf.glb b/public/assets/arena/hex_rock_transitionB.gltf.glb
new file mode 100644
index 0000000..ab8972a
Binary files /dev/null and b/public/assets/arena/hex_rock_transitionB.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterA.gltf.glb b/public/assets/arena/hex_rock_waterA.gltf.glb
new file mode 100644
index 0000000..762dd15
Binary files /dev/null and b/public/assets/arena/hex_rock_waterA.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterA_detail.gltf.glb b/public/assets/arena/hex_rock_waterA_detail.gltf.glb
new file mode 100644
index 0000000..b5f57e7
Binary files /dev/null and b/public/assets/arena/hex_rock_waterA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterA_empty.gltf.glb b/public/assets/arena/hex_rock_waterA_empty.gltf.glb
new file mode 100644
index 0000000..49e478c
Binary files /dev/null and b/public/assets/arena/hex_rock_waterA_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterB.gltf.glb b/public/assets/arena/hex_rock_waterB.gltf.glb
new file mode 100644
index 0000000..7d36af3
Binary files /dev/null and b/public/assets/arena/hex_rock_waterB.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterB_detail.gltf.glb b/public/assets/arena/hex_rock_waterB_detail.gltf.glb
new file mode 100644
index 0000000..b66877c
Binary files /dev/null and b/public/assets/arena/hex_rock_waterB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterB_empty.gltf.glb b/public/assets/arena/hex_rock_waterB_empty.gltf.glb
new file mode 100644
index 0000000..30a0fc0
Binary files /dev/null and b/public/assets/arena/hex_rock_waterB_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterC.gltf.glb b/public/assets/arena/hex_rock_waterC.gltf.glb
new file mode 100644
index 0000000..5d04991
Binary files /dev/null and b/public/assets/arena/hex_rock_waterC.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterC_detail.gltf.glb b/public/assets/arena/hex_rock_waterC_detail.gltf.glb
new file mode 100644
index 0000000..cb9791a
Binary files /dev/null and b/public/assets/arena/hex_rock_waterC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterC_empty.gltf.glb b/public/assets/arena/hex_rock_waterC_empty.gltf.glb
new file mode 100644
index 0000000..2c9a1bd
Binary files /dev/null and b/public/assets/arena/hex_rock_waterC_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterD.gltf.glb b/public/assets/arena/hex_rock_waterD.gltf.glb
new file mode 100644
index 0000000..f43656f
Binary files /dev/null and b/public/assets/arena/hex_rock_waterD.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterD_detail.gltf.glb b/public/assets/arena/hex_rock_waterD_detail.gltf.glb
new file mode 100644
index 0000000..9684a26
Binary files /dev/null and b/public/assets/arena/hex_rock_waterD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_rock_waterD_empty.gltf.glb b/public/assets/arena/hex_rock_waterD_empty.gltf.glb
new file mode 100644
index 0000000..395f5e4
Binary files /dev/null and b/public/assets/arena/hex_rock_waterD_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_sand.gltf.glb b/public/assets/arena/hex_sand.gltf.glb
new file mode 100644
index 0000000..a07f142
Binary files /dev/null and b/public/assets/arena/hex_sand.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_detail.gltf.glb b/public/assets/arena/hex_sand_detail.gltf.glb
new file mode 100644
index 0000000..5a6ece0
Binary files /dev/null and b/public/assets/arena/hex_sand_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadA.gltf.glb b/public/assets/arena/hex_sand_roadA.gltf.glb
new file mode 100644
index 0000000..afd2c77
Binary files /dev/null and b/public/assets/arena/hex_sand_roadA.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadA_detail.gltf.glb b/public/assets/arena/hex_sand_roadA_detail.gltf.glb
new file mode 100644
index 0000000..4da2335
Binary files /dev/null and b/public/assets/arena/hex_sand_roadA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadB.gltf.glb b/public/assets/arena/hex_sand_roadB.gltf.glb
new file mode 100644
index 0000000..3ecbd54
Binary files /dev/null and b/public/assets/arena/hex_sand_roadB.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadB_detail.gltf.glb b/public/assets/arena/hex_sand_roadB_detail.gltf.glb
new file mode 100644
index 0000000..ced06df
Binary files /dev/null and b/public/assets/arena/hex_sand_roadB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadC.gltf.glb b/public/assets/arena/hex_sand_roadC.gltf.glb
new file mode 100644
index 0000000..400366e
Binary files /dev/null and b/public/assets/arena/hex_sand_roadC.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadC_detail.gltf.glb b/public/assets/arena/hex_sand_roadC_detail.gltf.glb
new file mode 100644
index 0000000..2bddc33
Binary files /dev/null and b/public/assets/arena/hex_sand_roadC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadD.gltf.glb b/public/assets/arena/hex_sand_roadD.gltf.glb
new file mode 100644
index 0000000..34e0e93
Binary files /dev/null and b/public/assets/arena/hex_sand_roadD.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadD_detail.gltf.glb b/public/assets/arena/hex_sand_roadD_detail.gltf.glb
new file mode 100644
index 0000000..42eea3a
Binary files /dev/null and b/public/assets/arena/hex_sand_roadD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadE.gltf.glb b/public/assets/arena/hex_sand_roadE.gltf.glb
new file mode 100644
index 0000000..8c0a832
Binary files /dev/null and b/public/assets/arena/hex_sand_roadE.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadE_detail.gltf.glb b/public/assets/arena/hex_sand_roadE_detail.gltf.glb
new file mode 100644
index 0000000..3e64461
Binary files /dev/null and b/public/assets/arena/hex_sand_roadE_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadF.gltf.glb b/public/assets/arena/hex_sand_roadF.gltf.glb
new file mode 100644
index 0000000..86b288a
Binary files /dev/null and b/public/assets/arena/hex_sand_roadF.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadF_detail.gltf.glb b/public/assets/arena/hex_sand_roadF_detail.gltf.glb
new file mode 100644
index 0000000..2200410
Binary files /dev/null and b/public/assets/arena/hex_sand_roadF_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadG.gltf.glb b/public/assets/arena/hex_sand_roadG.gltf.glb
new file mode 100644
index 0000000..7be5c7c
Binary files /dev/null and b/public/assets/arena/hex_sand_roadG.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadG_detail.gltf.glb b/public/assets/arena/hex_sand_roadG_detail.gltf.glb
new file mode 100644
index 0000000..210cff0
Binary files /dev/null and b/public/assets/arena/hex_sand_roadG_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadH.gltf.glb b/public/assets/arena/hex_sand_roadH.gltf.glb
new file mode 100644
index 0000000..988391f
Binary files /dev/null and b/public/assets/arena/hex_sand_roadH.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadH_detail.gltf.glb b/public/assets/arena/hex_sand_roadH_detail.gltf.glb
new file mode 100644
index 0000000..9035841
Binary files /dev/null and b/public/assets/arena/hex_sand_roadH_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadI.gltf.glb b/public/assets/arena/hex_sand_roadI.gltf.glb
new file mode 100644
index 0000000..015d4b2
Binary files /dev/null and b/public/assets/arena/hex_sand_roadI.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadI_detail.gltf.glb b/public/assets/arena/hex_sand_roadI_detail.gltf.glb
new file mode 100644
index 0000000..38d68ab
Binary files /dev/null and b/public/assets/arena/hex_sand_roadI_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadJ.gltf.glb b/public/assets/arena/hex_sand_roadJ.gltf.glb
new file mode 100644
index 0000000..7efd274
Binary files /dev/null and b/public/assets/arena/hex_sand_roadJ.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadJ_detail.gltf.glb b/public/assets/arena/hex_sand_roadJ_detail.gltf.glb
new file mode 100644
index 0000000..03b88fd
Binary files /dev/null and b/public/assets/arena/hex_sand_roadJ_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadK.gltf.glb b/public/assets/arena/hex_sand_roadK.gltf.glb
new file mode 100644
index 0000000..39f8c22
Binary files /dev/null and b/public/assets/arena/hex_sand_roadK.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadK_detail.gltf.glb b/public/assets/arena/hex_sand_roadK_detail.gltf.glb
new file mode 100644
index 0000000..834861a
Binary files /dev/null and b/public/assets/arena/hex_sand_roadK_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadL.gltf.glb b/public/assets/arena/hex_sand_roadL.gltf.glb
new file mode 100644
index 0000000..832b7ec
Binary files /dev/null and b/public/assets/arena/hex_sand_roadL.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadL_detail.gltf.glb b/public/assets/arena/hex_sand_roadL_detail.gltf.glb
new file mode 100644
index 0000000..0ca1090
Binary files /dev/null and b/public/assets/arena/hex_sand_roadL_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadM.gltf.glb b/public/assets/arena/hex_sand_roadM.gltf.glb
new file mode 100644
index 0000000..6cfb232
Binary files /dev/null and b/public/assets/arena/hex_sand_roadM.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_roadM_detail.gltf.glb b/public/assets/arena/hex_sand_roadM_detail.gltf.glb
new file mode 100644
index 0000000..9b7e627
Binary files /dev/null and b/public/assets/arena/hex_sand_roadM_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_transitionA.gltf.glb b/public/assets/arena/hex_sand_transitionA.gltf.glb
new file mode 100644
index 0000000..b060fc5
Binary files /dev/null and b/public/assets/arena/hex_sand_transitionA.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_transitionB.gltf.glb b/public/assets/arena/hex_sand_transitionB.gltf.glb
new file mode 100644
index 0000000..c3b9227
Binary files /dev/null and b/public/assets/arena/hex_sand_transitionB.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterA.gltf.glb b/public/assets/arena/hex_sand_waterA.gltf.glb
new file mode 100644
index 0000000..2466552
Binary files /dev/null and b/public/assets/arena/hex_sand_waterA.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterA_detail.gltf.glb b/public/assets/arena/hex_sand_waterA_detail.gltf.glb
new file mode 100644
index 0000000..620dcdb
Binary files /dev/null and b/public/assets/arena/hex_sand_waterA_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterA_empty.gltf.glb b/public/assets/arena/hex_sand_waterA_empty.gltf.glb
new file mode 100644
index 0000000..0421f0d
Binary files /dev/null and b/public/assets/arena/hex_sand_waterA_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterB.gltf.glb b/public/assets/arena/hex_sand_waterB.gltf.glb
new file mode 100644
index 0000000..fe72b05
Binary files /dev/null and b/public/assets/arena/hex_sand_waterB.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterB_detail.gltf.glb b/public/assets/arena/hex_sand_waterB_detail.gltf.glb
new file mode 100644
index 0000000..da4855a
Binary files /dev/null and b/public/assets/arena/hex_sand_waterB_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterB_empty.gltf.glb b/public/assets/arena/hex_sand_waterB_empty.gltf.glb
new file mode 100644
index 0000000..e0b5ce2
Binary files /dev/null and b/public/assets/arena/hex_sand_waterB_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterC.gltf.glb b/public/assets/arena/hex_sand_waterC.gltf.glb
new file mode 100644
index 0000000..d639c95
Binary files /dev/null and b/public/assets/arena/hex_sand_waterC.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterC_detail.gltf.glb b/public/assets/arena/hex_sand_waterC_detail.gltf.glb
new file mode 100644
index 0000000..c5243cb
Binary files /dev/null and b/public/assets/arena/hex_sand_waterC_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterC_empty.gltf.glb b/public/assets/arena/hex_sand_waterC_empty.gltf.glb
new file mode 100644
index 0000000..19ccefb
Binary files /dev/null and b/public/assets/arena/hex_sand_waterC_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterD.gltf.glb b/public/assets/arena/hex_sand_waterD.gltf.glb
new file mode 100644
index 0000000..7097113
Binary files /dev/null and b/public/assets/arena/hex_sand_waterD.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterD_detail.gltf.glb b/public/assets/arena/hex_sand_waterD_detail.gltf.glb
new file mode 100644
index 0000000..9e44717
Binary files /dev/null and b/public/assets/arena/hex_sand_waterD_detail.gltf.glb differ
diff --git a/public/assets/arena/hex_sand_waterD_empty.gltf.glb b/public/assets/arena/hex_sand_waterD_empty.gltf.glb
new file mode 100644
index 0000000..33f06b1
Binary files /dev/null and b/public/assets/arena/hex_sand_waterD_empty.gltf.glb differ
diff --git a/public/assets/arena/hex_water.gltf.glb b/public/assets/arena/hex_water.gltf.glb
new file mode 100644
index 0000000..36acea2
Binary files /dev/null and b/public/assets/arena/hex_water.gltf.glb differ
diff --git a/public/assets/arena/hex_water_detail.gltf.glb b/public/assets/arena/hex_water_detail.gltf.glb
new file mode 100644
index 0000000..be30de9
Binary files /dev/null and b/public/assets/arena/hex_water_detail.gltf.glb differ
diff --git a/public/assets/images/background-1.jpg b/public/assets/images/background-1.jpg
new file mode 100644
index 0000000..fe682ce
Binary files /dev/null and b/public/assets/images/background-1.jpg differ
diff --git a/scripts/reset-project.js b/scripts/reset-project.js
deleted file mode 100755
index 51dff15..0000000
--- a/scripts/reset-project.js
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env node
-
-/**
- * This script is used to reset the project to a blank state.
- * It deletes or moves the /app, /components, /hooks, /scripts, and /constants directories to /app-example based on user input and creates a new /app directory with an index.tsx and _layout.tsx file.
- * You can remove the `reset-project` script from package.json and safely delete this file after running it.
- */
-
-const fs = require("fs");
-const path = require("path");
-const readline = require("readline");
-
-const root = process.cwd();
-const oldDirs = ["app", "components", "hooks", "constants", "scripts"];
-const exampleDir = "app-example";
-const newAppDir = "app";
-const exampleDirPath = path.join(root, exampleDir);
-
-const indexContent = `import { Text, View } from "react-native";
-
-export default function Index() {
- return (
-
- Edit app/index.tsx to edit this screen.
-
- );
-}
-`;
-
-const layoutContent = `import { Stack } from "expo-router";
-
-export default function RootLayout() {
- return ;
-}
-`;
-
-const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
-});
-
-const moveDirectories = async (userInput) => {
- try {
- if (userInput === "y") {
- // Create the app-example directory
- await fs.promises.mkdir(exampleDirPath, { recursive: true });
- console.log(`š /${exampleDir} directory created.`);
- }
-
- // Move old directories to new app-example directory or delete them
- for (const dir of oldDirs) {
- const oldDirPath = path.join(root, dir);
- if (fs.existsSync(oldDirPath)) {
- if (userInput === "y") {
- const newDirPath = path.join(root, exampleDir, dir);
- await fs.promises.rename(oldDirPath, newDirPath);
- console.log(`ā”ļø /${dir} moved to /${exampleDir}/${dir}.`);
- } else {
- await fs.promises.rm(oldDirPath, { recursive: true, force: true });
- console.log(`ā /${dir} deleted.`);
- }
- } else {
- console.log(`ā”ļø /${dir} does not exist, skipping.`);
- }
- }
-
- // Create new /app directory
- const newAppDirPath = path.join(root, newAppDir);
- await fs.promises.mkdir(newAppDirPath, { recursive: true });
- console.log("\nš New /app directory created.");
-
- // Create index.tsx
- const indexPath = path.join(newAppDirPath, "index.tsx");
- await fs.promises.writeFile(indexPath, indexContent);
- console.log("š app/index.tsx created.");
-
- // Create _layout.tsx
- const layoutPath = path.join(newAppDirPath, "_layout.tsx");
- await fs.promises.writeFile(layoutPath, layoutContent);
- console.log("š app/_layout.tsx created.");
-
- console.log("\nā
Project reset complete. Next steps:");
- console.log(
- `1. Run \`npx expo start\` to start a development server.\n2. Edit app/index.tsx to edit the main screen.${
- userInput === "y"
- ? `\n3. Delete the /${exampleDir} directory when you're done referencing it.`
- : ""
- }`
- );
- } catch (error) {
- console.error(`ā Error during script execution: ${error.message}`);
- }
-};
-
-rl.question(
- "Do you want to move existing files to /app-example instead of deleting them? (Y/n): ",
- (answer) => {
- const userInput = answer.trim().toLowerCase() || "y";
- if (userInput === "y" || userInput === "n") {
- moveDirectories(userInput).finally(() => rl.close());
- } else {
- console.log("ā Invalid input. Please enter 'Y' or 'N'.");
- rl.close();
- }
- }
-);