akhaliq HF staff commited on
Commit
c9175f4
·
verified ·
1 Parent(s): 96af967

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +230 -0
app.py ADDED
@@ -0,0 +1,230 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+
3
+ gr.HTML("""<!DOCTYPE html>
4
+ <html>
5
+ <head>
6
+ <title>Maze Game Demo</title>
7
+ <style>
8
+ body { margin: 0; overflow: hidden; }
9
+ #debug {
10
+ position: absolute;
11
+ top: 10px;
12
+ left: 10px;
13
+ color: white;
14
+ background: rgba(0, 0, 0, 0.7);
15
+ padding: 5px;
16
+ font-family: monospace;
17
+ }
18
+ </style>
19
+ </head>
20
+ <body>
21
+ <div id="debug"></div>
22
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
23
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/loaders/GLTFLoader.js"></script>
24
+ <script src="https://cdn.jsdelivr.net/npm/[email protected]/examples/js/controls/OrbitControls.js"></script>
25
+ <script>
26
+ // Scene setup
27
+ const scene = new THREE.Scene();
28
+ const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
29
+ const renderer = new THREE.WebGLRenderer();
30
+ renderer.setSize(window.innerWidth, window.innerHeight);
31
+ document.body.appendChild(renderer.domElement);
32
+
33
+ // Lighting
34
+ const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.6);
35
+ scene.add(hemiLight);
36
+ const dirLight = new THREE.DirectionalLight(0xffffff, 0.8);
37
+ dirLight.position.set(0, 20, 10);
38
+ scene.add(dirLight);
39
+
40
+ // OrbitControls
41
+ const controls = new THREE.OrbitControls(camera, renderer.domElement);
42
+ controls.enableDamping = true;
43
+
44
+ // Maze generation
45
+ const gridSize = 16;
46
+ const cellSize = 4;
47
+ const maze = [];
48
+ const walls = [];
49
+
50
+ function createTexture(width, height, type) {
51
+ const canvas = document.createElement('canvas');
52
+ canvas.width = width;
53
+ canvas.height = height;
54
+ const ctx = canvas.getContext('2d');
55
+
56
+ if (type === 'floor') {
57
+ ctx.fillStyle = '#8B4513';
58
+ ctx.fillRect(0, 0, width, height);
59
+ ctx.strokeStyle = '#654321';
60
+ ctx.lineWidth = 2;
61
+ ctx.strokeRect(0, 0, width, height);
62
+ } else {
63
+ ctx.fillStyle = '#666666';
64
+ ctx.fillRect(0, 0, width, height);
65
+ for (let i = 0; i < 10; i++) {
66
+ ctx.fillStyle = `rgba(0, 0, 0, ${Math.random() * 0.3})`;
67
+ ctx.fillRect(
68
+ Math.random() * width,
69
+ Math.random() * height,
70
+ Math.random() * width/4,
71
+ Math.random() * height/4
72
+ );
73
+ }
74
+ }
75
+ return new THREE.CanvasTexture(canvas);
76
+ }
77
+
78
+ const floorTexture = createTexture(256, 256, 'floor');
79
+ const wallTexture = createTexture(256, 256, 'wall');
80
+
81
+ // Generate maze
82
+ for (let x = 0; x < gridSize; x++) {
83
+ maze[x] = [];
84
+ for (let z = 0; z < gridSize; z++) {
85
+ const isBoundary = x === 0 || x === gridSize - 1 || z === 0 || z === gridSize - 1;
86
+ const isCenter = x >= 6 && x <= 9 && z >= 6 && z <= 9;
87
+ const isWall = isBoundary || (!isCenter && Math.random() < 0.15);
88
+ maze[x][z] = isWall ? 1 : 0;
89
+
90
+ if (isWall) {
91
+ const wallGeometry = new THREE.BoxGeometry(cellSize, cellSize, cellSize);
92
+ const wallMaterial = new THREE.MeshPhongMaterial({ map: wallTexture });
93
+ const wall = new THREE.Mesh(wallGeometry, wallMaterial);
94
+ wall.position.set(x * cellSize, cellSize/2, z * cellSize);
95
+ scene.add(wall);
96
+ wall.boundingBox = new THREE.Box3().setFromObject(wall);
97
+ walls.push(wall);
98
+ }
99
+ }
100
+ }
101
+
102
+ // Floor
103
+ const floorGeometry = new THREE.PlaneGeometry(gridSize * cellSize, gridSize * cellSize);
104
+ const floorMaterial = new THREE.MeshPhongMaterial({ map: floorTexture });
105
+ const floor = new THREE.Mesh(floorGeometry, floorMaterial);
106
+ floor.rotation.x = -Math.PI / 2;
107
+ scene.add(floor);
108
+
109
+ // Soldier setup
110
+ const loader = new THREE.GLTFLoader();
111
+ const soldiers = [];
112
+ const mixers = [];
113
+
114
+ function createSoldier(team, startX, startZ) {
115
+ loader.load('https://threejs.org/examples/models/gltf/Soldier.glb', (gltf) => {
116
+ const soldier = gltf.scene;
117
+ soldier.scale.set(2, 2, 2);
118
+ soldier.position.set(startX, 0, startZ);
119
+ soldier.team = team;
120
+ soldier.collisionRadius = 1;
121
+ soldier.speed = 0.1;
122
+ scene.add(soldier);
123
+ soldiers.push(soldier);
124
+
125
+ const mixer = new THREE.AnimationMixer(soldier);
126
+ mixers.push(mixer);
127
+
128
+ const idleAction = mixer.clipAction(gltf.animations[0]);
129
+ const runAction = mixer.clipAction(gltf.animations[3]);
130
+
131
+ soldier.actions = { idle: idleAction, run: runAction };
132
+ idleAction.play();
133
+ });
134
+ }
135
+
136
+ // Create two teams
137
+ createSoldier(1, 28, 28); // Team 1
138
+ createSoldier(2, 36, 36); // Team 2
139
+
140
+ camera.position.set(32, 20, 32);
141
+
142
+ // Movement controls
143
+ const keys = { w: false, a: false, s: false, d: false };
144
+ document.addEventListener('keydown', (e) => {
145
+ if (e.key in keys) keys[e.key] = true;
146
+ });
147
+ document.addEventListener('keyup', (e) => {
148
+ if (e.key in keys) keys[e.key] = false;
149
+ });
150
+
151
+ function checkCollision(newPosition, soldier) {
152
+ const soldierBox = new THREE.Sphere(newPosition, soldier.collisionRadius);
153
+ for (const wall of walls) {
154
+ if (soldierBox.intersectsBox(wall.boundingBox)) {
155
+ return true;
156
+ }
157
+ }
158
+ return false;
159
+ }
160
+
161
+ // Animation loop
162
+ const clock = new THREE.Clock();
163
+ function animate() {
164
+ requestAnimationFrame(animate);
165
+ const delta = clock.getDelta();
166
+
167
+ soldiers.forEach((soldier, index) => {
168
+ if (!soldier) return;
169
+
170
+ const moveDirection = new THREE.Vector3();
171
+ if (index === 0) { // Only control first soldier for demo
172
+ const camForward = new THREE.Vector3();
173
+ camera.getWorldDirection(camForward);
174
+ camForward.y = 0;
175
+ camForward.normalize();
176
+ const camLeft = new THREE.Vector3(-camForward.z, 0, camForward.x);
177
+
178
+ if (keys.w) moveDirection.add(camForward);
179
+ if (keys.s) moveDirection.sub(camForward);
180
+ if (keys.a) moveDirection.add(camLeft);
181
+ if (keys.d) moveDirection.sub(camLeft);
182
+ }
183
+
184
+ if (moveDirection.length() > 0) {
185
+ moveDirection.normalize();
186
+ const newPosition = soldier.position.clone()
187
+ .add(moveDirection.multiplyScalar(soldier.speed));
188
+
189
+ if (!checkCollision(newPosition, soldier)) {
190
+ soldier.position.copy(newPosition);
191
+ const angle = Math.atan2(moveDirection.x, moveDirection.z);
192
+ soldier.rotation.y = angle + Math.PI;
193
+
194
+ soldier.actions.idle.fadeOut(0.2);
195
+ soldier.actions.run.fadeIn(0.2);
196
+ }
197
+ } else {
198
+ soldier.actions.run.fadeOut(0.2);
199
+ soldier.actions.idle.fadeIn(0.2);
200
+ }
201
+
202
+ if (index === 0) {
203
+ controls.target.copy(soldier.position);
204
+ controls.update();
205
+
206
+ // Update debug overlay
207
+ document.getElementById('debug').innerHTML = `
208
+ Position: ${soldier.position.x.toFixed(2)},
209
+ ${soldier.position.y.toFixed(2)},
210
+ ${soldier.position.z.toFixed(2)}<br>
211
+ Rotation: ${(soldier.rotation.y * 180 / Math.PI).toFixed(2)}°
212
+ `;
213
+ }
214
+ });
215
+
216
+ mixers.forEach(mixer => mixer.update(delta));
217
+ renderer.render(scene, camera);
218
+ }
219
+
220
+ // Responsive design
221
+ window.addEventListener('resize', () => {
222
+ camera.aspect = window.innerWidth / window.innerHeight;
223
+ camera.updateProjectionMatrix();
224
+ renderer.setSize(window.innerWidth, window.innerHeight);
225
+ });
226
+
227
+ animate();
228
+ </script>
229
+ </body>
230
+ </html>""")