Update index.html
Browse files- index.html +75 -102
index.html
CHANGED
@@ -2,7 +2,7 @@
|
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta charset="utf-8">
|
5 |
-
<title>A-Frame 3D Breakout Shooter Game (
|
6 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/1.2.0/aframe.min.js"></script>
|
7 |
<style>
|
8 |
#hud {
|
@@ -31,75 +31,29 @@
|
|
31 |
<div id="hud">
|
32 |
<div>Score: <span id="score">0</span></div>
|
33 |
<div>Lives: <span id="lives">3</span></div>
|
|
|
34 |
</div>
|
35 |
<div id="instructions">
|
36 |
Move mouse to control paddle | Click to shoot | Press spacebar to launch new ball
|
37 |
</div>
|
38 |
|
39 |
<a-scene background="color: #87CEEB">
|
40 |
-
|
41 |
-
<a-camera look-controls="enabled: false">
|
42 |
-
<a-entity cursor="rayOrigin: mouse"
|
43 |
-
raycaster="objects: .collidable"
|
44 |
-
position="0 0 -1"></a-entity>
|
45 |
-
</a-camera>
|
46 |
-
</a-entity>
|
47 |
-
|
48 |
-
<a-entity id="gameElements">
|
49 |
-
<a-entity id="paddle" class="collidable" geometry="primitive: box; width: 2; height: 0.5; depth: 0.5"
|
50 |
-
material="color: #4CC3D9" position="0 -6 0"></a-entity>
|
51 |
-
|
52 |
-
<a-entity id="balls"></a-entity>
|
53 |
-
<a-entity id="bullets"></a-entity>
|
54 |
-
<a-entity id="blocks"></a-entity>
|
55 |
-
</a-entity>
|
56 |
-
|
57 |
-
<a-plane position="0 0 -0.5" rotation="-90 0 0" width="20" height="20" color="#7BC8A4"></a-plane>
|
58 |
-
<a-plane position="0 0 0" rotation="0 0 0" width="20" height="20" color="#7BC8A4" opacity="0.2"></a-plane>
|
59 |
-
<a-plane position="0 10 0" rotation="180 0 0" width="20" height="20" color="#7BC8A4" opacity="0.2"></a-plane>
|
60 |
</a-scene>
|
61 |
|
62 |
<script>
|
63 |
-
|
64 |
-
let score = 0;
|
65 |
-
let lives = 3;
|
66 |
-
let balls = [];
|
67 |
-
let bullets = [];
|
68 |
-
let gameStarted = false;
|
69 |
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
ballsContainer = document.querySelector('#balls');
|
74 |
-
bulletsContainer = document.querySelector('#bullets');
|
75 |
-
blocksContainer = document.querySelector('#blocks');
|
76 |
-
scoreElement = document.getElementById('score');
|
77 |
-
livesElement = document.getElementById('lives');
|
78 |
-
|
79 |
-
createBlocks();
|
80 |
-
createBall();
|
81 |
|
82 |
-
|
83 |
-
|
84 |
-
document.addEventListener('keydown', startGame);
|
85 |
-
|
86 |
-
requestAnimationFrame(update);
|
87 |
}
|
88 |
|
89 |
function createBlocks() {
|
90 |
-
|
91 |
-
for (let row = 0; row < 5; row++) {
|
92 |
-
for (let col = 0; col < 8; col++) {
|
93 |
-
const block = document.createElement('a-box');
|
94 |
-
block.setAttribute('class', 'block collidable');
|
95 |
-
block.setAttribute('position', {x: -7 + col * 2, y: 6 - row, z: 0});
|
96 |
-
block.setAttribute('width', '1.8');
|
97 |
-
block.setAttribute('height', '0.8');
|
98 |
-
block.setAttribute('depth', '0.5');
|
99 |
-
block.setAttribute('color', colors[row]);
|
100 |
-
blocksContainer.appendChild(block);
|
101 |
-
}
|
102 |
-
}
|
103 |
}
|
104 |
|
105 |
function createBall() {
|
@@ -108,9 +62,16 @@
|
|
108 |
ball.setAttribute('radius', '0.2');
|
109 |
ball.setAttribute('material', 'color: #EF2D5E');
|
110 |
ball.setAttribute('position', {x: 0, y: -5, z: 0});
|
111 |
-
|
|
|
|
|
|
|
|
|
|
|
112 |
ballsContainer.appendChild(ball);
|
113 |
balls.push(ball);
|
|
|
|
|
114 |
}
|
115 |
|
116 |
function shootBullet() {
|
@@ -120,49 +81,22 @@
|
|
120 |
bullet.setAttribute('material', 'color: #FFFFFF');
|
121 |
const paddlePos = paddle.getAttribute('position');
|
122 |
bullet.setAttribute('position', {x: paddlePos.x, y: paddlePos.y + 0.5, z: 0});
|
123 |
-
bullet.velocity = new THREE.Vector3(0,
|
124 |
bulletsContainer.appendChild(bullet);
|
125 |
bullets.push(bullet);
|
126 |
}
|
127 |
|
128 |
-
|
129 |
-
score += 10;
|
130 |
-
scoreElement.textContent = score;
|
131 |
-
}
|
132 |
-
|
133 |
-
function updateLives() {
|
134 |
-
lives--;
|
135 |
-
livesElement.textContent = lives;
|
136 |
-
if (lives <= 0) {
|
137 |
-
endGame();
|
138 |
-
}
|
139 |
-
}
|
140 |
-
|
141 |
-
function endGame() {
|
142 |
-
alert('Game Over! Your score: ' + score);
|
143 |
-
location.reload();
|
144 |
-
}
|
145 |
-
|
146 |
-
function movePaddle(event) {
|
147 |
-
const paddlePos = paddle.getAttribute('position');
|
148 |
-
paddlePos.x = (event.clientX / window.innerWidth) * 16 - 8;
|
149 |
-
paddlePos.x = Math.max(-8, Math.min(8, paddlePos.x));
|
150 |
-
paddle.setAttribute('position', paddlePos);
|
151 |
-
}
|
152 |
-
|
153 |
-
function startGame(e) {
|
154 |
-
if (!gameStarted && e.code === 'Space') {
|
155 |
-
gameStarted = true;
|
156 |
-
createBall();
|
157 |
-
}
|
158 |
-
}
|
159 |
|
160 |
function update() {
|
161 |
-
|
162 |
-
|
|
|
|
|
|
|
163 |
const ballPos = ball.getAttribute('position');
|
164 |
-
ballPos.x += ball.velocity.x;
|
165 |
-
ballPos.y += ball.velocity.y;
|
166 |
|
167 |
// Wall collisions
|
168 |
if (ballPos.x <= -9.8 || ballPos.x >= 9.8) ball.velocity.x *= -1;
|
@@ -170,10 +104,20 @@
|
|
170 |
|
171 |
// Paddle collision
|
172 |
const paddlePos = paddle.getAttribute('position');
|
|
|
173 |
if (ballPos.y <= paddlePos.y + 0.5 && ballPos.y >= paddlePos.y &&
|
174 |
-
ballPos.x >= paddlePos.x -
|
175 |
-
|
176 |
-
ball
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
177 |
}
|
178 |
|
179 |
// Block collisions
|
@@ -182,16 +126,37 @@
|
|
182 |
const blockPos = block.getAttribute('position');
|
183 |
if (ballPos.x >= blockPos.x - 1 && ballPos.x <= blockPos.x + 1 &&
|
184 |
ballPos.y >= blockPos.y - 0.5 && ballPos.y <= blockPos.y + 0.5) {
|
|
|
|
|
|
|
185 |
blocksContainer.removeChild(block);
|
186 |
ball.velocity.y *= -1;
|
187 |
updateScore();
|
188 |
}
|
189 |
});
|
190 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
191 |
// Check if ball is out of bounds
|
192 |
if (ballPos.y < -10) {
|
193 |
ballsContainer.removeChild(ball);
|
194 |
-
balls.splice(
|
|
|
|
|
195 |
if (balls.length === 0) {
|
196 |
updateLives();
|
197 |
if (lives > 0) createBall();
|
@@ -199,19 +164,28 @@
|
|
199 |
} else {
|
200 |
ball.setAttribute('position', ballPos);
|
201 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
202 |
});
|
203 |
|
204 |
-
// Update
|
205 |
bullets.forEach((bullet, index) => {
|
206 |
const bulletPos = bullet.getAttribute('position');
|
207 |
-
bulletPos.y += bullet.velocity.y;
|
208 |
|
209 |
-
// Check for collisions with blocks
|
210 |
const blocks = document.querySelectorAll('.block');
|
211 |
blocks.forEach(block => {
|
212 |
const blockPos = block.getAttribute('position');
|
213 |
if (bulletPos.x >= blockPos.x - 1 && bulletPos.x <= blockPos.x + 1 &&
|
214 |
bulletPos.y >= blockPos.y - 0.5 && bulletPos.y <= blockPos.y + 0.5) {
|
|
|
|
|
|
|
215 |
blocksContainer.removeChild(block);
|
216 |
bulletsContainer.removeChild(bullet);
|
217 |
bullets.splice(index, 1);
|
@@ -219,7 +193,6 @@
|
|
219 |
}
|
220 |
});
|
221 |
|
222 |
-
// Remove bullet if it goes out of bounds
|
223 |
if (bulletPos.y > 10) {
|
224 |
bulletsContainer.removeChild(bullet);
|
225 |
bullets.splice(index, 1);
|
@@ -230,6 +203,7 @@
|
|
230 |
|
231 |
// Check win condition
|
232 |
if (document.querySelectorAll('.block').length === 0) {
|
|
|
233 |
alert('Congratulations! You won! Your score: ' + score);
|
234 |
location.reload();
|
235 |
}
|
@@ -237,7 +211,6 @@
|
|
237 |
requestAnimationFrame(update);
|
238 |
}
|
239 |
|
240 |
-
// Wait for the scene to load before initializing the game
|
241 |
document.querySelector('a-scene').addEventListener('loaded', init);
|
242 |
</script>
|
243 |
</body>
|
|
|
2 |
<html>
|
3 |
<head>
|
4 |
<meta charset="utf-8">
|
5 |
+
<title>A-Frame 3D Breakout Shooter Game (Enhanced Speed)</title>
|
6 |
<script src="https://cdnjs.cloudflare.com/ajax/libs/aframe/1.2.0/aframe.min.js"></script>
|
7 |
<style>
|
8 |
#hud {
|
|
|
31 |
<div id="hud">
|
32 |
<div>Score: <span id="score">0</span></div>
|
33 |
<div>Lives: <span id="lives">3</span></div>
|
34 |
+
<div>Balls: <span id="ballCount">1</span></div>
|
35 |
</div>
|
36 |
<div id="instructions">
|
37 |
Move mouse to control paddle | Click to shoot | Press spacebar to launch new ball
|
38 |
</div>
|
39 |
|
40 |
<a-scene background="color: #87CEEB">
|
41 |
+
<!-- Scene setup remains the same -->
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
</a-scene>
|
43 |
|
44 |
<script>
|
45 |
+
// ... (previous variable declarations remain the same)
|
|
|
|
|
|
|
|
|
|
|
46 |
|
47 |
+
const INITIAL_BALL_SPEED = 10; // Increased from 5
|
48 |
+
const MAX_BALL_SPEED = 25; // Increased from 15
|
49 |
+
const BULLET_SPEED = 30;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
+
function init() {
|
52 |
+
// ... (initialization remains the same)
|
|
|
|
|
|
|
53 |
}
|
54 |
|
55 |
function createBlocks() {
|
56 |
+
// ... (createBlocks function remains the same)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
57 |
}
|
58 |
|
59 |
function createBall() {
|
|
|
62 |
ball.setAttribute('radius', '0.2');
|
63 |
ball.setAttribute('material', 'color: #EF2D5E');
|
64 |
ball.setAttribute('position', {x: 0, y: -5, z: 0});
|
65 |
+
const angle = Math.random() * Math.PI / 2 - Math.PI / 4; // Random angle between -45 and 45 degrees
|
66 |
+
ball.velocity = new THREE.Vector3(
|
67 |
+
Math.sin(angle) * INITIAL_BALL_SPEED,
|
68 |
+
Math.cos(angle) * INITIAL_BALL_SPEED,
|
69 |
+
0
|
70 |
+
);
|
71 |
ballsContainer.appendChild(ball);
|
72 |
balls.push(ball);
|
73 |
+
updateBallCount();
|
74 |
+
updatePaddleSize();
|
75 |
}
|
76 |
|
77 |
function shootBullet() {
|
|
|
81 |
bullet.setAttribute('material', 'color: #FFFFFF');
|
82 |
const paddlePos = paddle.getAttribute('position');
|
83 |
bullet.setAttribute('position', {x: paddlePos.x, y: paddlePos.y + 0.5, z: 0});
|
84 |
+
bullet.velocity = new THREE.Vector3(0, BULLET_SPEED, 0);
|
85 |
bulletsContainer.appendChild(bullet);
|
86 |
bullets.push(bullet);
|
87 |
}
|
88 |
|
89 |
+
// ... (other functions remain the same)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
90 |
|
91 |
function update() {
|
92 |
+
const currentTime = Date.now();
|
93 |
+
const deltaTime = (currentTime - lastUpdateTime) / 1000; // Convert to seconds
|
94 |
+
lastUpdateTime = currentTime;
|
95 |
+
|
96 |
+
balls.forEach((ball, ballIndex) => {
|
97 |
const ballPos = ball.getAttribute('position');
|
98 |
+
ballPos.x += ball.velocity.x * deltaTime;
|
99 |
+
ballPos.y += ball.velocity.y * deltaTime;
|
100 |
|
101 |
// Wall collisions
|
102 |
if (ballPos.x <= -9.8 || ballPos.x >= 9.8) ball.velocity.x *= -1;
|
|
|
104 |
|
105 |
// Paddle collision
|
106 |
const paddlePos = paddle.getAttribute('position');
|
107 |
+
const paddleWidth = paddle.getAttribute('geometry').width;
|
108 |
if (ballPos.y <= paddlePos.y + 0.5 && ballPos.y >= paddlePos.y &&
|
109 |
+
ballPos.x >= paddlePos.x - paddleWidth/2 && ballPos.x <= paddlePos.x + paddleWidth/2) {
|
110 |
+
|
111 |
+
// Realistic ball bounce (remains the same)
|
112 |
+
ball.velocity.y = Math.abs(ball.velocity.y);
|
113 |
+
ball.velocity.x += paddleVelocity.x * 0.5;
|
114 |
+
const hitPosition = (ballPos.x - paddlePos.x) / (paddleWidth / 2);
|
115 |
+
ball.velocity.x += hitPosition * 2;
|
116 |
+
|
117 |
+
// Normalize and scale velocity
|
118 |
+
const speed = Math.sqrt(ball.velocity.x * ball.velocity.x + ball.velocity.y * ball.velocity.y);
|
119 |
+
ball.velocity.x = (ball.velocity.x / speed) * INITIAL_BALL_SPEED;
|
120 |
+
ball.velocity.y = (ball.velocity.y / speed) * INITIAL_BALL_SPEED;
|
121 |
}
|
122 |
|
123 |
// Block collisions
|
|
|
126 |
const blockPos = block.getAttribute('position');
|
127 |
if (ballPos.x >= blockPos.x - 1 && ballPos.x <= blockPos.x + 1 &&
|
128 |
ballPos.y >= blockPos.y - 0.5 && ballPos.y <= blockPos.y + 0.5) {
|
129 |
+
if (block.getAttribute('special') === 'true') {
|
130 |
+
createBall();
|
131 |
+
}
|
132 |
blocksContainer.removeChild(block);
|
133 |
ball.velocity.y *= -1;
|
134 |
updateScore();
|
135 |
}
|
136 |
});
|
137 |
|
138 |
+
// Ball-bullet collisions
|
139 |
+
bullets.forEach((bullet, bulletIndex) => {
|
140 |
+
const bulletPos = bullet.getAttribute('position');
|
141 |
+
const distance = new THREE.Vector3(bulletPos.x - ballPos.x, bulletPos.y - ballPos.y, 0).length();
|
142 |
+
if (distance < 0.3) { // Assuming ball radius (0.2) + bullet radius (0.1)
|
143 |
+
// Accelerate the ball
|
144 |
+
const bulletVelocity = bullet.velocity;
|
145 |
+
ball.velocity.x = bulletVelocity.x;
|
146 |
+
ball.velocity.y = bulletVelocity.y;
|
147 |
+
|
148 |
+
// Remove the bullet
|
149 |
+
bulletsContainer.removeChild(bullet);
|
150 |
+
bullets.splice(bulletIndex, 1);
|
151 |
+
}
|
152 |
+
});
|
153 |
+
|
154 |
// Check if ball is out of bounds
|
155 |
if (ballPos.y < -10) {
|
156 |
ballsContainer.removeChild(ball);
|
157 |
+
balls.splice(ballIndex, 1);
|
158 |
+
updateBallCount();
|
159 |
+
updatePaddleSize();
|
160 |
if (balls.length === 0) {
|
161 |
updateLives();
|
162 |
if (lives > 0) createBall();
|
|
|
164 |
} else {
|
165 |
ball.setAttribute('position', ballPos);
|
166 |
}
|
167 |
+
|
168 |
+
// Limit ball speed
|
169 |
+
const speed = Math.sqrt(ball.velocity.x * ball.velocity.x + ball.velocity.y * ball.velocity.y);
|
170 |
+
if (speed > MAX_BALL_SPEED) {
|
171 |
+
ball.velocity.x = (ball.velocity.x / speed) * MAX_BALL_SPEED;
|
172 |
+
ball.velocity.y = (ball.velocity.y / speed) * MAX_BALL_SPEED;
|
173 |
+
}
|
174 |
});
|
175 |
|
176 |
+
// Update bullets
|
177 |
bullets.forEach((bullet, index) => {
|
178 |
const bulletPos = bullet.getAttribute('position');
|
179 |
+
bulletPos.y += bullet.velocity.y * deltaTime;
|
180 |
|
|
|
181 |
const blocks = document.querySelectorAll('.block');
|
182 |
blocks.forEach(block => {
|
183 |
const blockPos = block.getAttribute('position');
|
184 |
if (bulletPos.x >= blockPos.x - 1 && bulletPos.x <= blockPos.x + 1 &&
|
185 |
bulletPos.y >= blockPos.y - 0.5 && bulletPos.y <= blockPos.y + 0.5) {
|
186 |
+
if (block.getAttribute('special') === 'true') {
|
187 |
+
createBall();
|
188 |
+
}
|
189 |
blocksContainer.removeChild(block);
|
190 |
bulletsContainer.removeChild(bullet);
|
191 |
bullets.splice(index, 1);
|
|
|
193 |
}
|
194 |
});
|
195 |
|
|
|
196 |
if (bulletPos.y > 10) {
|
197 |
bulletsContainer.removeChild(bullet);
|
198 |
bullets.splice(index, 1);
|
|
|
203 |
|
204 |
// Check win condition
|
205 |
if (document.querySelectorAll('.block').length === 0) {
|
206 |
+
clearInterval(paddleColorChangeInterval);
|
207 |
alert('Congratulations! You won! Your score: ' + score);
|
208 |
location.reload();
|
209 |
}
|
|
|
211 |
requestAnimationFrame(update);
|
212 |
}
|
213 |
|
|
|
214 |
document.querySelector('a-scene').addEventListener('loaded', init);
|
215 |
</script>
|
216 |
</body>
|