-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbunny.html
More file actions
233 lines (198 loc) · 9.13 KB
/
bunny.html
File metadata and controls
233 lines (198 loc) · 9.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Bunny Chase Game</title>
<style>
/* Basic Reset & Body Styling */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow: hidden; /* Prevent scrollbars if bunny goes near edge */
background-color: #77dd77; /* Light green background like grass */
}
/* Game Area - takes up full screen and sets cursor */
#game-area {
width: 100vw; /* 100% of viewport width */
height: 100vh; /* 100% of viewport height */
position: relative; /* Needed for absolute positioning of children */
/* Make sure carrot.png is in the same folder as this HTML file */
cursor: url('assets/img/carrot.png') 16 16, auto; /* Use carrot image as cursor, fallback to default */
/* The '16 16' are example hotspot coordinates (center for a 32x32px image). Adjust if needed. */
}
/* Bunny Styling */
#bunny {
width: 100px; /* Adjust size as needed */
height: 100px; /* Adjust size as needed */
/* Make sure bunny.png is in the same folder as this HTML file */
background-image: url('assets/img/bunny.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
position: absolute; /* Allows positioning with top/left */
top: 50%; /* Initial position */
left: 50%;
transform: translate(-50%, -50%); /* Center the bunny */
transition: top 0.1s linear, left 0.1s linear; /* Smooth movement */
/* Hopping Animation */
animation: hop 0.4s infinite ease-in-out;
}
/* Hopping Keyframes */
@keyframes hop {
0%, 100% {
transform: translate(-50%, -50%) translateY(0); /* Base position */
}
50% {
transform: translate(-50%, -50%) translateY(-30px); /* Hop up slightly */
}
}
/* Game Over Message Styling */
#message {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background-color: rgba(0, 0, 0, 0.7);
color: white;
padding: 20px 40px;
border-radius: 10px;
font-size: 1.5em;
font-family: sans-serif;
text-align: center;
z-index: 10; /* Make sure it's above the bunny */
}
.hidden {
display: none; /* Hide message initially */
}
</style>
</head>
<body>
<div id="game-area">
<div id="bunny"></div>
<div id="message" class="hidden">Game Over! The bunny caught the carrot! Click this to play again</div>
</div>
</div> <audio id="background-music" src="assets/audio/guardian.mp3" loop preload="auto"></audio>
<script>
document.addEventListener('DOMContentLoaded', () => {
const gameArea = document.getElementById('game-area');
const bunny = document.getElementById('bunny');
const message = document.getElementById('message');
const backgroundMusic = document.getElementById('background-music'); // <-- ADD THIS LIN
// Check if elements exist
if (!gameArea || !bunny || !message) {
console.error("Game elements not found!");
return;
}
// Game state
let carrotX = 0; // Initialize away from center
let carrotY = 0; // Initialize away from center
let bunnyX = bunny.offsetLeft + bunny.offsetWidth / 2;
let bunnyY = bunny.offsetTop + bunny.offsetHeight / 2;
let gameOver = false;
let gameLoopInterval = null;
// --- Configuration ---
const bunnySpeed = 100; // Adjust for difficulty (pixels per frame)
const collisionDistance = 30; // How close the bunny needs to be to catch (pixels)
const updateRate = 16.67; // Roughly 60fps (1000ms / 60fps ≈ 16.67ms)
// Track carrot (cursor) position
gameArea.addEventListener('mousemove', (event) => {
if (!gameOver) {
carrotX = event.clientX;
carrotY = event.clientY;
}
});
// Game loop function
function gameLoop() {
if (gameOver) return;
// --- Bunny Movement ---
// Get current bunny center position
bunnyX = bunny.offsetLeft + bunny.offsetWidth / 2;
bunnyY = bunny.offsetTop + bunny.offsetHeight / 2;
// Calculate direction towards carrot
let dx = carrotX - bunnyX;
let dy = carrotY - bunnyY;
// Calculate distance
const distance = Math.sqrt(dx * dx + dy * dy);
// Check for collision
if (distance < collisionDistance) {
endGame();
return; // Stop processing this frame
}
// Normalize direction vector (make its length 1)
const normalizationFactor = distance + 0.001; // Add epsilon to prevent division by zero
let moveX = (dx / normalizationFactor) * bunnySpeed;
let moveY = (dy / normalizationFactor) * bunnySpeed;
// Calculate new bunny top-left position
let newBunnyLeft = bunny.offsetLeft + moveX;
let newBunnyTop = bunny.offsetTop + moveY;
// --- Boundary Collision ---
const gameAreaRect = gameArea.getBoundingClientRect();
newBunnyLeft = Math.max(0, Math.min(newBunnyLeft, gameAreaRect.width - bunny.offsetWidth));
newBunnyTop = Math.max(0, Math.min(newBunnyTop, gameAreaRect.height - bunny.offsetHeight));
// Update bunny position using style.left/top
bunny.style.left = `${newBunnyLeft}px`;
bunny.style.top = `${newBunnyTop}px`;
}
// Function to end the game
function endGame() {
gameOver = true;
clearInterval(gameLoopInterval); // Stop the game loop
message.classList.remove('hidden'); // Show game over message
gameArea.style.cursor = 'auto'; // Restore default cursor
// --- ADD MUSIC CONTROL ---
if (backgroundMusic) {
backgroundMusic.pause(); // Pause the music
}
// --- END MUSIC CONTROL ---
console.log("Game Over!");
}
// Function to start/restart the game
function startGame() {
gameOver = false;
message.classList.add('hidden'); // Hide message
// Ensure carrot.png is in the same folder
gameArea.style.cursor = `url('assets/img/carrot.png') 16 16, auto`; // Set carrot cursor
// Reset bunny position
const startX = gameArea.offsetWidth / 2 - bunny.offsetWidth / 2;
const startY = gameArea.offsetHeight / 2 - bunny.offsetHeight / 2;
bunny.style.left = `${startX}px`;
bunny.style.top = `${startY}px`;
bunnyX = startX + bunny.offsetWidth / 2;
bunnyY = startY + bunny.offsetHeight / 2;
carrotX = 0;
carrotY = 0;
// --- ADD/MODIFY MUSIC CONTROL ---
if (backgroundMusic) {
backgroundMusic.currentTime = 0; // Rewind to start
backgroundMusic.play().catch(error => {
// Autoplay might be blocked, log error or handle gracefully
console.error("Audio play failed:", error);
// You might need user interaction (like the first click) to enable audio
});
}
// --- END MUSIC CONTROL ---
// Clear any existing interval before starting a new one
if (gameLoopInterval) {
clearInterval(gameLoopInterval);
}
// Start the game loop
gameLoopInterval = setInterval(gameLoop, updateRate);
}
// --- Start the game after a 2-second delay ---
setTimeout(startGame, 2000); // 2000 milliseconds = 2 seconds
// Add a way to restart the game by clicking the message
message.addEventListener('click', () => {
// Optional: You might want to hide the message immediately when clicked,
// even before the game actually restarts after the delay. If so, uncomment the next line.
message.classList.add('hidden');
// Call startGame after a 2-second delay
setTimeout(startGame, 2000);
});
}); // End DOMContentLoaded
</script>
</body>
</html>