openfree commited on
Commit
c05bf1e
·
verified ·
1 Parent(s): 80f8c29

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +262 -211
index.html CHANGED
@@ -1,283 +1,334 @@
1
  <!DOCTYPE html>
2
- <html lang="en">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
- <title>Login & Register</title>
7
  <style>
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
12
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
13
  }
14
 
15
  body {
16
- min-height: 100vh;
17
  display: flex;
18
- justify-content: center;
19
  align-items: center;
20
- background: linear-gradient(45deg, #6b5b95, #feb236);
21
- }
22
-
23
- .container {
24
- background: rgba(255, 255, 255, 0.95);
25
- border-radius: 20px;
26
- padding: 40px;
27
- box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
28
- width: 400px;
29
- }
30
-
31
- .form-group {
32
- margin-bottom: 20px;
33
- }
34
-
35
- h2 {
36
- text-align: center;
37
- color: #333;
38
- margin-bottom: 30px;
39
  }
40
 
41
- input {
42
- width: 100%;
43
- padding: 12px;
44
- border: 2px solid #ddd;
45
  border-radius: 8px;
46
- font-size: 16px;
47
- transition: all 0.3s ease;
48
- outline: none;
49
  }
50
 
51
- input:focus {
52
- border-color: #6b5b95;
 
 
53
  }
54
 
55
  button {
56
- width: 100%;
57
- padding: 12px;
58
- background: #6b5b95;
59
- color: white;
60
- border: none;
61
- border-radius: 8px;
62
  font-size: 16px;
 
 
63
  cursor: pointer;
64
- transition: all 0.3s ease;
 
 
 
 
 
65
  }
66
 
67
  button:hover {
68
- background: #574a7a;
69
- }
70
-
71
- .switch-form {
72
- text-align: center;
73
- margin-top: 20px;
74
  }
75
 
76
- .switch-form a {
77
- color: #6b5b95;
78
- text-decoration: none;
79
- font-weight: 600;
 
80
  }
81
 
82
- .alert {
83
- padding: 10px;
84
- margin: 10px 0;
85
- border-radius: 8px;
86
- display: none;
87
- }
88
-
89
- .alert-success {
90
- background: #d4edda;
91
- color: #155724;
92
- border: 1px solid #c3e6cb;
93
  }
94
 
95
- .alert-error {
96
- background: #f8d7da;
97
- color: #721c24;
98
- border: 1px solid #f5c6cb;
99
  }
100
 
101
- .password-requirements {
102
- font-size: 12px;
103
- color: #666;
104
- margin-top: 5px;
105
  }
106
 
107
- .loading {
108
- display: none;
 
109
  text-align: center;
110
- margin-top: 10px;
111
- }
112
-
113
- .loading::after {
114
- content: "...";
115
- animation: dots 1s steps(5, end) infinite;
116
- }
117
-
118
- @keyframes dots {
119
- 0%, 20% { content: "."; }
120
- 40% { content: ".."; }
121
- 60%, 100% { content: "..."; }
122
  }
123
  </style>
124
  </head>
125
  <body>
126
- <div class="container">
127
- <div id="loginForm">
128
- <h2>Login</h2>
129
- <div class="alert alert-error" id="loginError"></div>
130
- <form onsubmit="handleLogin(event)">
131
- <div class="form-group">
132
- <input type="email" id="loginEmail" placeholder="Email" required>
133
- </div>
134
- <div class="form-group">
135
- <input type="password" id="loginPassword" placeholder="Password" required>
136
- </div>
137
- <button type="submit">Login</button>
138
- <div class="loading" id="loginLoading">Processing</div>
139
- </form>
140
- <div class="switch-form">
141
- Don't have an account? <a href="#" onclick="toggleForms()">Register</a>
142
- </div>
143
- </div>
144
-
145
- <div id="registerForm" style="display: none;">
146
- <h2>Register</h2>
147
- <div class="alert alert-success" id="registerSuccess"></div>
148
- <div class="alert alert-error" id="registerError"></div>
149
- <form onsubmit="handleRegister(event)">
150
- <div class="form-group">
151
- <input type="email" id="registerEmail" placeholder="Email" required>
152
- </div>
153
- <div class="form-group">
154
- <input type="password" id="registerPassword" placeholder="Password" required>
155
- <div class="password-requirements">
156
- Password must be at least 8 characters long and contain letters and numbers
157
- </div>
158
- </div>
159
- <div class="form-group">
160
- <input type="password" id="confirmPassword" placeholder="Confirm Password" required>
161
- </div>
162
- <button type="submit">Register</button>
163
- <div class="loading" id="registerLoading">Processing</div>
164
- </form>
165
- <div class="switch-form">
166
- Already have an account? <a href="#" onclick="toggleForms()">Login</a>
167
- </div>
168
- </div>
169
  </div>
170
 
171
  <script>
172
- // Mock user database
173
- let users = [];
174
-
175
- function toggleForms() {
176
- const loginForm = document.getElementById('loginForm');
177
- const registerForm = document.getElementById('registerForm');
178
-
179
- if (loginForm.style.display === 'none') {
180
- loginForm.style.display = 'block';
181
- registerForm.style.display = 'none';
182
- } else {
183
- loginForm.style.display = 'none';
184
- registerForm.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  }
186
-
187
- // Clear all alerts and forms
188
- clearAlerts();
189
- document.querySelectorAll('form').forEach(form => form.reset());
190
  }
191
 
192
- function clearAlerts() {
193
- document.querySelectorAll('.alert').forEach(alert => {
194
- alert.style.display = 'none';
195
- });
196
- document.querySelectorAll('.loading').forEach(loading => {
197
- loading.style.display = 'none';
198
- });
 
 
 
 
199
  }
200
 
201
- function validatePassword(password) {
202
- const minLength = 8;
203
- const hasLetter = /[a-zA-Z]/.test(password);
204
- const hasNumber = /\d/.test(password);
205
- return password.length >= minLength && hasLetter && hasNumber;
 
 
 
206
  }
207
 
208
- async function handleRegister(event) {
209
- event.preventDefault();
210
- clearAlerts();
211
-
212
- const email = document.getElementById('registerEmail').value;
213
- const password = document.getElementById('registerPassword').value;
214
- const confirmPassword = document.getElementById('confirmPassword').value;
215
- const loading = document.getElementById('registerLoading');
216
- const success = document.getElementById('registerSuccess');
217
- const error = document.getElementById('registerError');
218
-
219
- if (!validatePassword(password)) {
220
- error.textContent = 'Password must be at least 8 characters long and contain both letters and numbers';
221
- error.style.display = 'block';
222
- return;
 
 
223
  }
 
224
 
225
- if (password !== confirmPassword) {
226
- error.textContent = 'Passwords do not match';
227
- error.style.display = 'block';
228
- return;
229
- }
 
 
230
 
231
- if (users.some(user => user.email === email)) {
232
- error.textContent = 'Email already registered';
233
- error.style.display = 'block';
234
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  }
 
236
 
237
- loading.style.display = 'block';
 
238
 
239
- // Simulate API call
240
- await new Promise(resolve => setTimeout(resolve, 1500));
 
 
 
 
241
 
242
- users.push({ email, password });
243
-
244
- loading.style.display = 'none';
245
- success.textContent = 'Registration successful! Please login.';
246
- success.style.display = 'block';
 
 
 
 
 
 
 
 
 
247
 
248
- // Clear form
249
- event.target.reset();
 
 
 
 
250
 
251
- // Switch to login form after 2 seconds
252
- setTimeout(toggleForms, 2000);
253
- }
254
 
255
- async function handleLogin(event) {
256
- event.preventDefault();
257
- clearAlerts();
258
 
259
- const email = document.getElementById('loginEmail').value;
260
- const password = document.getElementById('loginPassword').value;
261
- const loading = document.getElementById('loginLoading');
262
- const error = document.getElementById('loginError');
 
 
 
 
263
 
264
- loading.style.display = 'block';
 
 
 
 
 
 
 
265
 
266
- // Simulate API call
267
- await new Promise(resolve => setTimeout(resolve, 1500));
 
 
 
 
268
 
269
- const user = users.find(u => u.email === email && u.password === password);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
270
 
271
- loading.style.display = 'none';
 
 
272
 
273
- if (user) {
274
- alert('Login successful!');
275
- event.target.reset();
276
- } else {
277
- error.textContent = 'Invalid email or password';
278
- error.style.display = 'block';
279
  }
280
- }
 
 
 
 
 
 
 
281
  </script>
282
  </body>
283
  </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="ko">
3
  <head>
4
  <meta charset="UTF-8">
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>네온 벽돌깨기 게임</title>
7
  <style>
8
  * {
9
  margin: 0;
10
  padding: 0;
11
  box-sizing: border-box;
 
12
  }
13
 
14
  body {
 
15
  display: flex;
16
+ flex-direction: column;
17
  align-items: center;
18
+ min-height: 100vh;
19
+ background: #111;
20
+ font-family: 'Noto Sans KR', sans-serif;
21
+ color: #fff;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
 
24
+ canvas {
25
+ background: rgba(0,0,0,0.8);
 
 
26
  border-radius: 8px;
27
+ box-shadow: 0 0 20px rgba(0,255,255,0.3);
28
+ margin: 20px 0;
 
29
  }
30
 
31
+ .controls {
32
+ display: flex;
33
+ gap: 15px;
34
+ margin-bottom: 20px;
35
  }
36
 
37
  button {
38
+ padding: 12px 24px;
 
 
 
 
 
39
  font-size: 16px;
40
+ border: none;
41
+ border-radius: 5px;
42
  cursor: pointer;
43
+ background: transparent;
44
+ color: #fff;
45
+ border: 2px solid #0ff;
46
+ box-shadow: 0 0 10px #0ff;
47
+ text-shadow: 0 0 5px #0ff;
48
+ transition: all 0.3s;
49
  }
50
 
51
  button:hover {
52
+ background: rgba(0,255,255,0.2);
53
+ box-shadow: 0 0 20px #0ff;
 
 
 
 
54
  }
55
 
56
+ .score {
57
+ font-size: 24px;
58
+ margin-bottom: 15px;
59
+ color: #0ff;
60
+ text-shadow: 0 0 10px #0ff;
61
  }
62
 
63
+ .speed-control {
64
+ margin: 15px 0;
65
+ display: flex;
66
+ align-items: center;
67
+ gap: 10px;
 
 
 
 
 
 
68
  }
69
 
70
+ .speed-control label {
71
+ color: #0ff;
72
+ text-shadow: 0 0 5px #0ff;
 
73
  }
74
 
75
+ input[type="range"] {
76
+ width: 200px;
77
+ accent-color: #0ff;
 
78
  }
79
 
80
+ .speed-value {
81
+ color: #0ff;
82
+ min-width: 30px;
83
  text-align: center;
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
  </style>
86
  </head>
87
  <body>
88
+ <div class="score">점수: <span id="score">0</span></div>
89
+ <canvas id="gameCanvas" width="480" height="320"></canvas>
90
+ <div class="speed-control">
91
+ <label>속도 조절:</label>
92
+ <input type="range" id="speedControl" min="1" max="10" value="3">
93
+ <span class="speed-value" id="speedValue">3</span>
94
+ </div>
95
+ <div class="controls">
96
+ <button id="startBtn">시작하기</button>
97
+ <button id="resetBtn">다시하기</button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  </div>
99
 
100
  <script>
101
+ const canvas = document.getElementById("gameCanvas");
102
+ const ctx = canvas.getContext("2d");
103
+ const startBtn = document.getElementById("startBtn");
104
+ const resetBtn = document.getElementById("resetBtn");
105
+ const scoreElement = document.getElementById("score");
106
+ const speedControl = document.getElementById("speedControl");
107
+ const speedValue = document.getElementById("speedValue");
108
+
109
+ let score = 0;
110
+ let gameRunning = false;
111
+ let baseSpeed = 3;
112
+
113
+ const colors = [
114
+ '#ff0000', '#00ff00', '#0000ff', '#ff00ff', '#ffff00', '#00ffff'
115
+ ];
116
+
117
+ const ball = {
118
+ x: canvas.width / 2,
119
+ y: canvas.height - 30,
120
+ dx: baseSpeed,
121
+ dy: -baseSpeed,
122
+ radius: 7,
123
+ color: '#fff'
124
+ };
125
+
126
+ const paddle = {
127
+ width: 75,
128
+ height: 10,
129
+ x: (canvas.width - 75) / 2,
130
+ color: '#0ff'
131
+ };
132
+
133
+ const brickRowCount = 5;
134
+ const brickColumnCount = 8;
135
+ const brickWidth = 50;
136
+ const brickHeight = 20;
137
+ const brickPadding = 10;
138
+ const brickOffsetTop = 30;
139
+ const brickOffsetLeft = 25;
140
+
141
+ const bricks = [];
142
+ for(let c=0; c<brickColumnCount; c++) {
143
+ bricks[c] = [];
144
+ for(let r=0; r<brickRowCount; r++) {
145
+ bricks[c][r] = {
146
+ x: 0,
147
+ y: 0,
148
+ status: 1,
149
+ color: colors[Math.floor(Math.random() * colors.length)]
150
+ };
151
  }
 
 
 
 
152
  }
153
 
154
+ let rightPressed = false;
155
+ let leftPressed = false;
156
+
157
+ function drawBall() {
158
+ ctx.beginPath();
159
+ ctx.arc(ball.x, ball.y, ball.radius, 0, Math.PI*2);
160
+ ctx.fillStyle = ball.color;
161
+ ctx.fill();
162
+ ctx.shadowBlur = 15;
163
+ ctx.shadowColor = ball.color;
164
+ ctx.closePath();
165
  }
166
 
167
+ function drawPaddle() {
168
+ ctx.beginPath();
169
+ ctx.rect(paddle.x, canvas.height-paddle.height, paddle.width, paddle.height);
170
+ ctx.fillStyle = paddle.color;
171
+ ctx.fill();
172
+ ctx.shadowBlur = 15;
173
+ ctx.shadowColor = paddle.color;
174
+ ctx.closePath();
175
  }
176
 
177
+ function drawBricks() {
178
+ for(let c=0; c<brickColumnCount; c++) {
179
+ for(let r=0; r<brickRowCount; r++) {
180
+ if(bricks[c][r].status === 1) {
181
+ const brickX = (c*(brickWidth+brickPadding))+brickOffsetLeft;
182
+ const brickY = (r*(brickHeight+brickPadding))+brickOffsetTop;
183
+ bricks[c][r].x = brickX;
184
+ bricks[c][r].y = brickY;
185
+ ctx.beginPath();
186
+ ctx.rect(brickX, brickY, brickWidth, brickHeight);
187
+ ctx.fillStyle = bricks[c][r].color;
188
+ ctx.fill();
189
+ ctx.shadowBlur = 15;
190
+ ctx.shadowColor = bricks[c][r].color;
191
+ ctx.closePath();
192
+ }
193
+ }
194
  }
195
+ }
196
 
197
+ function updateSpeed() {
198
+ const newSpeed = parseInt(speedControl.value);
199
+ speedValue.textContent = newSpeed;
200
+ const speedMultiplier = newSpeed / baseSpeed;
201
+ ball.dx = Math.sign(ball.dx) * Math.abs(baseSpeed * speedMultiplier);
202
+ ball.dy = Math.sign(ball.dy) * Math.abs(baseSpeed * speedMultiplier);
203
+ }
204
 
205
+ speedControl.addEventListener('input', updateSpeed);
206
+
207
+ function collisionDetection() {
208
+ for(let c=0; c<brickColumnCount; c++) {
209
+ for(let r=0; r<brickRowCount; r++) {
210
+ const b = bricks[c][r];
211
+ if(b.status === 1) {
212
+ if(ball.x > b.x && ball.x < b.x+brickWidth && ball.y > b.y && ball.y < b.y+brickHeight) {
213
+ ball.dy = -ball.dy;
214
+ b.status = 0;
215
+ ball.color = b.color;
216
+ score++;
217
+ scoreElement.textContent = score;
218
+ if(score === brickRowCount*brickColumnCount) {
219
+ alert("축하합니다! 승리하셨습니다!");
220
+ gameRunning = false;
221
+ }
222
+ }
223
+ }
224
+ }
225
  }
226
+ }
227
 
228
+ function draw() {
229
+ if (!gameRunning) return;
230
 
231
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
232
+ ctx.shadowBlur = 0;
233
+ drawBricks();
234
+ drawBall();
235
+ drawPaddle();
236
+ collisionDetection();
237
 
238
+ if(ball.x + ball.dx > canvas.width-ball.radius || ball.x + ball.dx < ball.radius) {
239
+ ball.dx = -ball.dx;
240
+ }
241
+ if(ball.y + ball.dy < ball.radius) {
242
+ ball.dy = -ball.dy;
243
+ } else if(ball.y + ball.dy > canvas.height-ball.radius) {
244
+ if(ball.x > paddle.x && ball.x < paddle.x + paddle.width) {
245
+ ball.dy = -ball.dy;
246
+ } else {
247
+ alert("게임 오버");
248
+ gameRunning = false;
249
+ return;
250
+ }
251
+ }
252
 
253
+ if(rightPressed && paddle.x < canvas.width-paddle.width) {
254
+ paddle.x += 7;
255
+ }
256
+ else if(leftPressed && paddle.x > 0) {
257
+ paddle.x -= 7;
258
+ }
259
 
260
+ ball.x += ball.dx;
261
+ ball.y += ball.dy;
 
262
 
263
+ requestAnimationFrame(draw);
264
+ }
 
265
 
266
+ function keyDownHandler(e) {
267
+ if(e.key === "Right" || e.key === "ArrowRight") {
268
+ rightPressed = true;
269
+ }
270
+ else if(e.key === "Left" || e.key === "ArrowLeft") {
271
+ leftPressed = true;
272
+ }
273
+ }
274
 
275
+ function keyUpHandler(e) {
276
+ if(e.key === "Right" || e.key === "ArrowRight") {
277
+ rightPressed = false;
278
+ }
279
+ else if(e.key === "Left" || e.key === "ArrowLeft") {
280
+ leftPressed = false;
281
+ }
282
+ }
283
 
284
+ function mouseMoveHandler(e) {
285
+ const relativeX = e.clientX - canvas.offsetLeft;
286
+ if(relativeX > 0 && relativeX < canvas.width) {
287
+ paddle.x = relativeX - paddle.width/2;
288
+ }
289
+ }
290
 
291
+ function resetGame() {
292
+ score = 0;
293
+ scoreElement.textContent = score;
294
+ ball.x = canvas.width / 2;
295
+ ball.y = canvas.height - 30;
296
+ updateSpeed();
297
+ ball.color = '#fff';
298
+ paddle.x = (canvas.width - paddle.width) / 2;
299
+
300
+ for(let c=0; c<brickColumnCount; c++) {
301
+ for(let r=0; r<brickRowCount; r++) {
302
+ bricks[c][r].status = 1;
303
+ bricks[c][r].color = colors[Math.floor(Math.random() * colors.length)];
304
+ }
305
+ }
306
+
307
+ if (!gameRunning) {
308
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
309
+ drawBricks();
310
+ drawBall();
311
+ drawPaddle();
312
+ }
313
+ }
314
 
315
+ document.addEventListener("keydown", keyDownHandler, false);
316
+ document.addEventListener("keyup", keyUpHandler, false);
317
+ document.addEventListener("mousemove", mouseMoveHandler, false);
318
 
319
+ startBtn.addEventListener("click", () => {
320
+ if (!gameRunning) {
321
+ gameRunning = true;
322
+ draw();
 
 
323
  }
324
+ });
325
+
326
+ resetBtn.addEventListener("click", () => {
327
+ gameRunning = false;
328
+ resetGame();
329
+ });
330
+
331
+ resetGame();
332
  </script>
333
  </body>
334
  </html>