Spaces:
Running
Running
Update index.html
Browse files- index.html +115 -105
index.html
CHANGED
@@ -2,9 +2,9 @@
|
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
5 |
-
<title
|
6 |
<style>
|
7 |
-
* { margin: 0; padding: 0; touch-action:
|
8 |
body { overflow: hidden; background: #000; }
|
9 |
#hud {
|
10 |
position: fixed;
|
@@ -12,7 +12,7 @@
|
|
12 |
left: 15px;
|
13 |
color: #fff;
|
14 |
font-family: 'Courier New', monospace;
|
15 |
-
font-size:
|
16 |
text-shadow: 0 0 10px #00ffff;
|
17 |
z-index: 100;
|
18 |
}
|
@@ -21,27 +21,30 @@
|
|
21 |
position: fixed;
|
22 |
top: 50%;
|
23 |
left: 50%;
|
24 |
-
transform: translate(-
|
25 |
text-align: center;
|
26 |
color: #fff;
|
27 |
-
background: rgba(0,0,0,0.
|
28 |
-
padding:
|
29 |
border-radius: 15px;
|
30 |
-
border: 2px solid #
|
|
|
|
|
31 |
}
|
32 |
#restart {
|
33 |
display: none;
|
34 |
position: fixed;
|
35 |
-
bottom:
|
36 |
left: 50%;
|
37 |
transform: translateX(-50%);
|
38 |
-
padding:
|
39 |
background: #00ff88;
|
40 |
color: #000;
|
41 |
border: none;
|
42 |
border-radius: 25px;
|
43 |
-
font-size:
|
44 |
cursor: pointer;
|
|
|
45 |
}
|
46 |
</style>
|
47 |
</head>
|
@@ -51,22 +54,23 @@
|
|
51 |
<div>LIVES: <span id="lives">3</span></div>
|
52 |
</div>
|
53 |
<div id="gameOver">
|
54 |
-
<h1 style="color: #ff0066">GAME OVER</h1>
|
55 |
-
<p>
|
56 |
</div>
|
57 |
<button id="restart" onclick="location.reload()">PLAY AGAIN</button>
|
58 |
|
59 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
60 |
<script>
|
61 |
const CONFIG = {
|
62 |
-
PLAYER_SPEED: 0.
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
66 |
};
|
67 |
|
68 |
-
let score = 0, lives =
|
69 |
-
let touchStartX = 0, currentX = 0
|
70 |
|
71 |
const scene = new THREE.Scene();
|
72 |
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
|
@@ -74,88 +78,126 @@
|
|
74 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
75 |
document.body.appendChild(renderer.domElement);
|
76 |
|
77 |
-
// Player (
|
78 |
const player = new THREE.Mesh(
|
79 |
-
new THREE.
|
80 |
new THREE.MeshStandardMaterial({
|
81 |
color: 0x00ff88,
|
82 |
emissive: 0x00ff88,
|
83 |
emissiveIntensity: 0.5
|
84 |
})
|
85 |
);
|
|
|
86 |
player.position.z = 3;
|
87 |
scene.add(player);
|
88 |
|
89 |
-
//
|
90 |
-
const
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
|
|
97 |
);
|
98 |
-
|
99 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
100 |
|
101 |
-
// Starfield
|
102 |
const stars = new THREE.Points(
|
103 |
new THREE.BufferGeometry().setFromPoints(
|
104 |
-
Array(
|
105 |
(Math.random() - 0.5) * 100,
|
106 |
(Math.random() - 0.5) * 100,
|
107 |
(Math.random() - 0.5) * 100
|
108 |
))
|
109 |
),
|
110 |
new THREE.PointsMaterial({
|
111 |
-
size: 0.
|
112 |
color: 0xffffff,
|
113 |
transparent: true,
|
114 |
-
opacity: 0.
|
115 |
})
|
116 |
);
|
117 |
scene.add(stars);
|
118 |
|
119 |
// Lighting
|
120 |
-
const ambientLight = new THREE.AmbientLight(0xffffff, 0.
|
121 |
scene.add(ambientLight);
|
122 |
|
123 |
-
// Controls
|
124 |
-
|
125 |
-
document.addEventListener('touchmove', e => {
|
126 |
if(isGameOver) return;
|
127 |
-
currentX =
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
});
|
|
|
|
|
|
|
130 |
|
131 |
// Game Loop
|
132 |
function animate() {
|
133 |
if(isGameOver) return;
|
134 |
|
135 |
-
//
|
136 |
-
if(Math.random() <
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
141 |
// Visual Updates
|
142 |
-
stars.rotation.
|
143 |
-
|
144 |
-
player.rotation.y += 0.02;
|
145 |
|
146 |
-
// Collision
|
147 |
scene.children.forEach(obj => {
|
148 |
-
if(obj
|
149 |
-
if(obj.
|
150 |
-
lives
|
151 |
-
|
152 |
-
|
153 |
-
} else {
|
154 |
-
if(!shield.visible) lives--;
|
155 |
if(lives <= 0) endGame();
|
156 |
}
|
157 |
-
scene.remove(obj);
|
158 |
-
updateHUD();
|
159 |
}
|
160 |
});
|
161 |
|
@@ -163,67 +205,35 @@
|
|
163 |
requestAnimationFrame(animate);
|
164 |
}
|
165 |
|
166 |
-
function spawnObject() {
|
167 |
-
const isPowerUp = Math.random() < CONFIG.POWERUP_CHANCE;
|
168 |
-
const geometry = isPowerUp ?
|
169 |
-
new THREE.IcosahedronGeometry(0.6) :
|
170 |
-
new THREE.OctahedronGeometry(1);
|
171 |
-
|
172 |
-
const obj = new THREE.Mesh(
|
173 |
-
geometry,
|
174 |
-
new THREE.MeshStandardMaterial({
|
175 |
-
color: isPowerUp ? 0x00ffff : 0xff4444,
|
176 |
-
emissive: isPowerUp ? 0x00ffff : 0xff4444,
|
177 |
-
emissiveIntensity: 0.2
|
178 |
-
})
|
179 |
-
);
|
180 |
-
|
181 |
-
obj.position.set(
|
182 |
-
(Math.random() - 0.5) * 14,
|
183 |
-
(Math.random() - 0.5) * 8,
|
184 |
-
-50
|
185 |
-
);
|
186 |
-
|
187 |
-
obj.userData = { isHazard: true, isPowerUp };
|
188 |
-
|
189 |
-
// Animation
|
190 |
-
function move() {
|
191 |
-
obj.position.z += 0.15 * speedMultiplier;
|
192 |
-
obj.rotation.x += 0.02;
|
193 |
-
obj.rotation.y += 0.02;
|
194 |
-
if(obj.position.z > 5) scene.remove(obj);
|
195 |
-
else requestAnimationFrame(move);
|
196 |
-
}
|
197 |
-
|
198 |
-
scene.add(obj);
|
199 |
-
move();
|
200 |
-
}
|
201 |
-
|
202 |
-
function activateShield() {
|
203 |
-
shield.visible = true;
|
204 |
-
setTimeout(() => shield.visible = false, 2000);
|
205 |
-
}
|
206 |
-
|
207 |
function updateHUD() {
|
208 |
-
document.getElementById('score').textContent = score;
|
209 |
document.getElementById('lives').textContent = lives;
|
210 |
-
score +=
|
211 |
}
|
212 |
|
213 |
function endGame() {
|
214 |
isGameOver = true;
|
215 |
document.getElementById('gameOver').style.display = 'block';
|
216 |
document.getElementById('restart').style.display = 'block';
|
|
|
217 |
localStorage.setItem('highScore', Math.max(score, localStorage.getItem('highScore') || 0));
|
218 |
}
|
219 |
|
220 |
-
//
|
221 |
-
camera.position.z =
|
222 |
animate();
|
223 |
updateHUD();
|
224 |
|
225 |
-
//
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
226 |
document.addEventListener('touchend', () => isGameOver && location.reload());
|
|
|
227 |
</script>
|
228 |
</body>
|
229 |
</html>
|
|
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
5 |
+
<title>📱 Cosmic Dodger</title>
|
6 |
<style>
|
7 |
+
* { margin: 0; padding: 0; touch-action: none; }
|
8 |
body { overflow: hidden; background: #000; }
|
9 |
#hud {
|
10 |
position: fixed;
|
|
|
12 |
left: 15px;
|
13 |
color: #fff;
|
14 |
font-family: 'Courier New', monospace;
|
15 |
+
font-size: 26px;
|
16 |
text-shadow: 0 0 10px #00ffff;
|
17 |
z-index: 100;
|
18 |
}
|
|
|
21 |
position: fixed;
|
22 |
top: 50%;
|
23 |
left: 50%;
|
24 |
+
transform: translate(-50%, -50%);
|
25 |
text-align: center;
|
26 |
color: #fff;
|
27 |
+
background: rgba(0,0,0,0.95);
|
28 |
+
padding: 25px;
|
29 |
border-radius: 15px;
|
30 |
+
border: 2px solid #ff0066;
|
31 |
+
width: 80%;
|
32 |
+
max-width: 300px;
|
33 |
}
|
34 |
#restart {
|
35 |
display: none;
|
36 |
position: fixed;
|
37 |
+
bottom: 25px;
|
38 |
left: 50%;
|
39 |
transform: translateX(-50%);
|
40 |
+
padding: 15px 35px;
|
41 |
background: #00ff88;
|
42 |
color: #000;
|
43 |
border: none;
|
44 |
border-radius: 25px;
|
45 |
+
font-size: 20px;
|
46 |
cursor: pointer;
|
47 |
+
font-weight: bold;
|
48 |
}
|
49 |
</style>
|
50 |
</head>
|
|
|
54 |
<div>LIVES: <span id="lives">3</span></div>
|
55 |
</div>
|
56 |
<div id="gameOver">
|
57 |
+
<h1 style="color: #ff0066; font-size: 1.8em">GAME OVER</h1>
|
58 |
+
<p style="font-size: 1.2em">Score: <span id="finalscore">0</span></p>
|
59 |
</div>
|
60 |
<button id="restart" onclick="location.reload()">PLAY AGAIN</button>
|
61 |
|
62 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
63 |
<script>
|
64 |
const CONFIG = {
|
65 |
+
PLAYER_SPEED: 0.25,
|
66 |
+
ASTEROID_SPEED: 0.15,
|
67 |
+
PLAYER_SIZE: 0.6,
|
68 |
+
X_BOUNDS: 6,
|
69 |
+
Y_BOUNDS: 4
|
70 |
};
|
71 |
|
72 |
+
let score = 0, lives = 3, isGameOver = false;
|
73 |
+
let touchStartX = 0, currentX = 0;
|
74 |
|
75 |
const scene = new THREE.Scene();
|
76 |
const camera = new THREE.PerspectiveCamera(75, window.innerWidth/window.innerHeight, 0.1, 1000);
|
|
|
78 |
renderer.setSize(window.innerWidth, window.innerHeight);
|
79 |
document.body.appendChild(renderer.domElement);
|
80 |
|
81 |
+
// Player (Flat Triangle - Mobile Friendly)
|
82 |
const player = new THREE.Mesh(
|
83 |
+
new THREE.ConeGeometry(CONFIG.PLAYER_SIZE, 1.2, 3),
|
84 |
new THREE.MeshStandardMaterial({
|
85 |
color: 0x00ff88,
|
86 |
emissive: 0x00ff88,
|
87 |
emissiveIntensity: 0.5
|
88 |
})
|
89 |
);
|
90 |
+
player.rotation.x = Math.PI/2;
|
91 |
player.position.z = 3;
|
92 |
scene.add(player);
|
93 |
|
94 |
+
// Player Boundary Markers
|
95 |
+
const boundaryMaterial = new THREE.MeshBasicMaterial({
|
96 |
+
color: 0x00ffff,
|
97 |
+
transparent: true,
|
98 |
+
opacity: 0.2
|
99 |
+
});
|
100 |
+
const leftBoundary = new THREE.Mesh(
|
101 |
+
new THREE.PlaneGeometry(0.5, 10),
|
102 |
+
boundaryMaterial
|
103 |
);
|
104 |
+
const rightBoundary = leftBoundary.clone();
|
105 |
+
leftBoundary.position.x = -CONFIG.X_BOUNDS;
|
106 |
+
rightBoundary.position.x = CONFIG.X_BOUNDS;
|
107 |
+
scene.add(leftBoundary, rightBoundary);
|
108 |
+
|
109 |
+
// Asteroids (More Visible)
|
110 |
+
function createAsteroid() {
|
111 |
+
const asteroid = new THREE.Mesh(
|
112 |
+
new THREE.IcosahedronGeometry(0.8),
|
113 |
+
new THREE.MeshStandardMaterial({
|
114 |
+
color: 0xff4444,
|
115 |
+
emissive: 0xff0000,
|
116 |
+
emissiveIntensity: 0.3,
|
117 |
+
wireframe: true
|
118 |
+
})
|
119 |
+
);
|
120 |
+
asteroid.position.set(
|
121 |
+
(Math.random() - 0.5) * 12,
|
122 |
+
(Math.random() - 0.5) * 7,
|
123 |
+
-40
|
124 |
+
);
|
125 |
+
return asteroid;
|
126 |
+
}
|
127 |
|
128 |
+
// Starfield (Optimized)
|
129 |
const stars = new THREE.Points(
|
130 |
new THREE.BufferGeometry().setFromPoints(
|
131 |
+
Array(800).fill().map(() => new THREE.Vector3(
|
132 |
(Math.random() - 0.5) * 100,
|
133 |
(Math.random() - 0.5) * 100,
|
134 |
(Math.random() - 0.5) * 100
|
135 |
))
|
136 |
),
|
137 |
new THREE.PointsMaterial({
|
138 |
+
size: 0.2,
|
139 |
color: 0xffffff,
|
140 |
transparent: true,
|
141 |
+
opacity: 0.7
|
142 |
})
|
143 |
);
|
144 |
scene.add(stars);
|
145 |
|
146 |
// Lighting
|
147 |
+
const ambientLight = new THREE.AmbientLight(0xffffff, 0.8);
|
148 |
scene.add(ambientLight);
|
149 |
|
150 |
+
// Controls (Improved Mobile Handling)
|
151 |
+
function handleMove(x) {
|
|
|
152 |
if(isGameOver) return;
|
153 |
+
currentX = THREE.MathUtils.clamp(
|
154 |
+
(x - touchStartX) * 0.03,
|
155 |
+
-CONFIG.X_BOUNDS,
|
156 |
+
CONFIG.X_BOUNDS
|
157 |
+
);
|
158 |
+
player.position.x = currentX;
|
159 |
+
}
|
160 |
+
|
161 |
+
document.addEventListener('touchstart', e => {
|
162 |
+
e.preventDefault();
|
163 |
+
touchStartX = e.touches[0].clientX;
|
164 |
});
|
165 |
+
document.addEventListener('touchmove', e => handleMove(e.touches[0].clientX));
|
166 |
+
document.addEventListener('mousedown', e => touchStartX = e.clientX);
|
167 |
+
document.addEventListener('mousemove', e => e.buttons === 1 && handleMove(e.clientX));
|
168 |
|
169 |
// Game Loop
|
170 |
function animate() {
|
171 |
if(isGameOver) return;
|
172 |
|
173 |
+
// Spawn Logic
|
174 |
+
if(Math.random() < 0.03 + score/5000) {
|
175 |
+
const asteroid = createAsteroid();
|
176 |
+
scene.add(asteroid);
|
177 |
+
|
178 |
+
// Animate asteroid
|
179 |
+
(function move(obj) {
|
180 |
+
obj.position.z += CONFIG.ASTEROID_SPEED + score/2500;
|
181 |
+
obj.rotation.x += 0.02;
|
182 |
+
obj.rotation.y += 0.02;
|
183 |
+
if(obj.position.z > 5) scene.remove(obj);
|
184 |
+
else requestAnimationFrame(() => move(obj));
|
185 |
+
})(asteroid);
|
186 |
+
}
|
187 |
+
|
188 |
// Visual Updates
|
189 |
+
stars.rotation.y += 0.0003;
|
190 |
+
player.rotation.z = Math.sin(performance.now()*0.005) * 0.3;
|
|
|
191 |
|
192 |
+
// Collision Check
|
193 |
scene.children.forEach(obj => {
|
194 |
+
if(obj !== player && obj.position.z > 0) {
|
195 |
+
if(obj.position.distanceTo(player.position) < 1.2) {
|
196 |
+
lives--;
|
197 |
+
scene.remove(obj);
|
198 |
+
updateHUD();
|
|
|
|
|
199 |
if(lives <= 0) endGame();
|
200 |
}
|
|
|
|
|
201 |
}
|
202 |
});
|
203 |
|
|
|
205 |
requestAnimationFrame(animate);
|
206 |
}
|
207 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
208 |
function updateHUD() {
|
209 |
+
document.getElementById('score').textContent = Math.floor(score);
|
210 |
document.getElementById('lives').textContent = lives;
|
211 |
+
score += 1 + Math.floor(score/1000);
|
212 |
}
|
213 |
|
214 |
function endGame() {
|
215 |
isGameOver = true;
|
216 |
document.getElementById('gameOver').style.display = 'block';
|
217 |
document.getElementById('restart').style.display = 'block';
|
218 |
+
document.getElementById('finalscore').textContent = Math.floor(score);
|
219 |
localStorage.setItem('highScore', Math.max(score, localStorage.getItem('highScore') || 0));
|
220 |
}
|
221 |
|
222 |
+
// Initial Setup
|
223 |
+
camera.position.z = 8;
|
224 |
animate();
|
225 |
updateHUD();
|
226 |
|
227 |
+
// Resize Handler
|
228 |
+
window.addEventListener('resize', () => {
|
229 |
+
camera.aspect = window.innerWidth / window.innerHeight;
|
230 |
+
camera.updateProjectionMatrix();
|
231 |
+
renderer.setSize(window.innerWidth, window.innerHeight);
|
232 |
+
});
|
233 |
+
|
234 |
+
// Restart Handler
|
235 |
document.addEventListener('touchend', () => isGameOver && location.reload());
|
236 |
+
document.addEventListener('mouseup', () => isGameOver && location.reload());
|
237 |
</script>
|
238 |
</body>
|
239 |
</html>
|