Skip to content

Commit 54af73d

Browse files
committed
Add new project
1 parent e1ad3a3 commit 54af73d

File tree

1 file changed

+265
-0
lines changed

1 file changed

+265
-0
lines changed

10-stack-game/index.html

+265
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
<!DOCTYPE html>
2+
<html lang="es">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>10 - Stack Game</title>
8+
<style>
9+
body {
10+
background: #000;
11+
margin: 0;
12+
display: grid;
13+
place-content: center;
14+
height: 100vh;
15+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
16+
}
17+
18+
canvas {
19+
border: 1px solid white;
20+
}
21+
22+
span {
23+
color: white;
24+
font-size: 12px;
25+
}
26+
</style>
27+
28+
<script type="module">
29+
const canvas = document.querySelector('canvas')
30+
const context = canvas.getContext('2d')
31+
32+
const score = document.querySelector('#score')
33+
34+
// CONSTANTS
35+
const MODES = {
36+
FALL: 'fall',
37+
BOUNCE: 'bounce',
38+
GAMEOVER: 'gameover'
39+
}
40+
const INITIAL_BOX_WIDTH = 200
41+
const INITIAL_BOX_Y = 600
42+
43+
const BOX_HEIGHT = 50
44+
const INITIAL_Y_SPEED = 5
45+
const INITIAL_X_SPEED = 2
46+
47+
// STATE
48+
let boxes = []
49+
let debris = { x: 0, y: 0, width: 0 }
50+
let scrollCounter, cameraY, current, mode, xSpeed, ySpeed
51+
52+
function createStepColor(step) {
53+
if (step === 0) return 'white'
54+
55+
const red = Math.floor(Math.random() * 255)
56+
const green = Math.floor(Math.random() * 255)
57+
const blue = Math.floor(Math.random() * 255)
58+
59+
return `rgb(${red}, ${green}, ${blue})`
60+
}
61+
62+
function updateCamera() {
63+
if (scrollCounter > 0) {
64+
cameraY++
65+
scrollCounter--
66+
}
67+
}
68+
69+
function initializeGameState() {
70+
boxes = [{
71+
x: (canvas.width / 2) - (INITIAL_BOX_WIDTH / 2),
72+
y: 200,
73+
width: INITIAL_BOX_WIDTH,
74+
color: 'white'
75+
}]
76+
77+
debris = { x: 0, y: 0, width: 0 }
78+
current = 1
79+
mode = MODES.BOUNCE
80+
xSpeed = INITIAL_X_SPEED
81+
ySpeed = INITIAL_Y_SPEED
82+
scrollCounter = 0
83+
cameraY = 0
84+
85+
createNewBox()
86+
}
87+
88+
function restart() {
89+
initializeGameState()
90+
draw()
91+
}
92+
93+
function draw() {
94+
if (mode === MODES.GAMEOVER) return
95+
96+
drawBackground()
97+
drawBoxes()
98+
drawDebris()
99+
100+
if (mode === MODES.BOUNCE) {
101+
moveAndDetectCollision()
102+
} else if (mode === MODES.FALL) {
103+
updateFallMode()
104+
}
105+
106+
debris.y -= ySpeed
107+
updateCamera()
108+
109+
window.requestAnimationFrame(draw)
110+
}
111+
112+
function drawBackground() {
113+
context.fillStyle = 'rgba(0, 0, 0, 0.5)'
114+
context.fillRect(0, 0, canvas.width, canvas.height)
115+
}
116+
117+
function drawDebris() {
118+
const { x, y, width } = debris
119+
const newY = INITIAL_BOX_Y - y + cameraY
120+
121+
context.fillStyle = 'red'
122+
context.fillRect(x, newY, width, BOX_HEIGHT)
123+
}
124+
125+
function drawBoxes() {
126+
boxes.forEach((box) => {
127+
const { x, y, width, color } = box
128+
const newY = INITIAL_BOX_Y - y + cameraY
129+
130+
context.fillStyle = color
131+
context.fillRect(x, newY, width, BOX_HEIGHT)
132+
})
133+
}
134+
135+
function createNewBox() {
136+
boxes[current] = {
137+
x: 0,
138+
y: (current + 10) * BOX_HEIGHT,
139+
width: boxes[current - 1].width,
140+
color: createStepColor(current)
141+
}
142+
}
143+
144+
function createNewDebris(difference) {
145+
const currentBox = boxes[current]
146+
const previousBox = boxes[current - 1]
147+
148+
const debrisX = currentBox.x > previousBox.x
149+
? currentBox.x + currentBox.width
150+
: currentBox.x
151+
152+
debris = {
153+
x: debrisX,
154+
y: currentBox.y,
155+
width: difference
156+
}
157+
}
158+
159+
function updateFallMode() {
160+
const currentBox = boxes[current]
161+
currentBox.y -= ySpeed
162+
163+
const positionPreviousBox = boxes[current - 1].y + BOX_HEIGHT
164+
165+
if (currentBox.y === positionPreviousBox) {
166+
handleBoxLanding()
167+
}
168+
}
169+
170+
function adjustCurrentBox(difference) {
171+
const currentBox = boxes[current]
172+
const previousBox = boxes[current - 1]
173+
174+
if (currentBox.x > previousBox.x) {
175+
currentBox.width -= difference
176+
} else {
177+
currentBox.width += difference
178+
currentBox.x = previousBox.x
179+
}
180+
}
181+
182+
function gameOver() {
183+
mode = MODES.GAMEOVER
184+
185+
context.fillStyle = 'rgba(255, 0, 0, 0.5)'
186+
context.fillRect(0, 0, canvas.width, canvas.height)
187+
188+
context.font = 'bold 20px Arial'
189+
context.fillStyle = 'white'
190+
context.textAlign = 'center'
191+
context.fillText(
192+
'Game Over',
193+
canvas.width / 2,
194+
canvas.height / 2
195+
)
196+
}
197+
198+
function handleBoxLanding() {
199+
const currentBox = boxes[current]
200+
const previousBox = boxes[current - 1]
201+
202+
const difference = currentBox.x - previousBox.x
203+
204+
if (Math.abs(difference) >= currentBox.width) {
205+
gameOver()
206+
return
207+
}
208+
209+
adjustCurrentBox(difference)
210+
createNewDebris(difference)
211+
212+
xSpeed += xSpeed > 0 ? 1 : -1
213+
current++
214+
scrollCounter = BOX_HEIGHT
215+
mode = MODES.BOUNCE
216+
217+
score.textContent = current - 1
218+
219+
createNewBox()
220+
}
221+
222+
function moveAndDetectCollision() {
223+
const currentBox = boxes[current]
224+
currentBox.x += xSpeed
225+
226+
const isMovingRight = xSpeed > 0
227+
const isMovingLeft = xSpeed < 0
228+
229+
const hasHitRightSide =
230+
currentBox.x + currentBox.width > canvas.width
231+
232+
const hasHitLeftSide = currentBox.x < 0
233+
234+
if (
235+
(isMovingRight && hasHitRightSide) ||
236+
(isMovingLeft && hasHitLeftSide)
237+
) {
238+
xSpeed = -xSpeed
239+
}
240+
}
241+
242+
document.addEventListener('keydown', (event) => {
243+
if (event.key === ' ' && mode === MODES.BOUNCE) {
244+
mode = MODES.FALL
245+
}
246+
})
247+
248+
canvas.onpointerdown = () => {
249+
if (mode === MODES.GAMEOVER) {
250+
restart()
251+
} else if (mode === MODES.BOUNCE) {
252+
mode = MODES.FALL
253+
}
254+
}
255+
256+
restart()
257+
</script>
258+
</head>
259+
260+
<body>
261+
<span>Puntuación: <span id="score">0</span></span>
262+
<canvas id="canvas" width="320" height="500"></canvas>
263+
</body>
264+
265+
</html>

0 commit comments

Comments
 (0)