1+ const canvas = document . getElementById ( 'gameCanvas' ) ;
2+ const ctx = canvas . getContext ( '2d' ) ;
3+ const resetButton = document . getElementById ( 'resetButton' ) ;
4+
5+ const GRAVITY = 0.5 ;
6+ let player ;
7+ let platforms = [ ] ;
8+ let goal ;
9+ let keys = {
10+ right : false ,
11+ left : false ,
12+ up : false
13+ } ;
14+ let gameActive = true ;
15+ let winMessage = "You Win!" ;
16+
17+ // Player Class
18+ class Player {
19+ constructor ( ) {
20+ this . position = { x : 100 , y : 400 } ;
21+ this . velocity = { x : 0 , y : 0 } ;
22+ this . width = 30 ;
23+ this . height = 30 ;
24+ this . onGround = false ;
25+ }
26+
27+ draw ( ) {
28+ ctx . fillStyle = '#4CAF50' ;
29+ ctx . fillRect ( this . position . x , this . position . y , this . width , this . height ) ;
30+ }
31+
32+ update ( ) {
33+ this . draw ( ) ;
34+ this . position . x += this . velocity . x ;
35+ this . position . y += this . velocity . y ;
36+
37+ // Apply gravity if not at bottom of canvas
38+ if ( this . position . y + this . height + this . velocity . y < canvas . height ) {
39+ this . velocity . y += GRAVITY ;
40+ this . onGround = false ;
41+ } else {
42+ this . velocity . y = 0 ;
43+ this . position . y = canvas . height - this . height ;
44+ this . onGround = true ;
45+ }
46+
47+ // --- NEW ---
48+ // Restart if player hits horizontal boundaries
49+ if ( this . position . x < 0 || this . position . x + this . width > canvas . width ) {
50+ init ( ) ;
51+ }
52+
53+ // Restart if player falls off bottom
54+ if ( this . position . y > canvas . height ) {
55+ init ( ) ;
56+ }
57+ }
58+ }
59+
60+ // Platform Class
61+ class Platform {
62+ constructor ( x , y , width , height ) {
63+ this . position = { x, y } ;
64+ this . width = width ;
65+ this . height = height ;
66+ }
67+
68+ draw ( ) {
69+ ctx . fillStyle = '#8B4513' ; // Brown color for platforms
70+ ctx . fillRect ( this . position . x , this . position . y , this . width , this . height ) ;
71+ }
72+ }
73+
74+ // Goal Class
75+ class Goal {
76+ constructor ( x , y , width , height ) {
77+ this . position = { x, y } ;
78+ this . width = width ;
79+ this . height = height ;
80+ }
81+
82+ draw ( ) {
83+ ctx . fillStyle = '#FFD700' ; // Gold color for the goal
84+ ctx . fillRect ( this . position . x , this . position . y , this . width , this . height ) ;
85+ }
86+ }
87+
88+ // Initialize game elements
89+ function init ( ) {
90+ gameActive = true ;
91+ player = new Player ( ) ;
92+ platforms = [
93+ new Platform ( 0 , 550 , 300 , 50 ) ,
94+ new Platform ( 400 , 450 , 200 , 50 ) ,
95+ new Platform ( 650 , 350 , 150 , 50 ) ,
96+ new Platform ( 400 , 250 , 100 , 50 )
97+ ] ;
98+ goal = new Goal ( 425 , 200 , 50 , 50 ) ; // Goal on the top platform
99+ }
100+
101+ // Main animation loop
102+ function animate ( ) {
103+ if ( ! gameActive ) {
104+ // Display win message
105+ ctx . fillStyle = 'rgba(0, 0, 0, 0.7)' ;
106+ ctx . fillRect ( 0 , 0 , canvas . width , canvas . height ) ;
107+ ctx . font = '60px Arial' ;
108+ ctx . fillStyle = '#FFD700' ;
109+ ctx . textAlign = 'center' ;
110+ ctx . fillText ( winMessage , canvas . width / 2 , canvas . height / 2 ) ;
111+ return ;
112+ }
113+
114+ requestAnimationFrame ( animate ) ;
115+ ctx . clearRect ( 0 , 0 , canvas . width , canvas . height ) ;
116+
117+ // Draw goal
118+ goal . draw ( ) ;
119+
120+ // Draw platforms
121+ platforms . forEach ( platform => {
122+ platform . draw ( ) ;
123+ } ) ;
124+
125+ // Update player
126+ player . update ( ) ;
127+
128+ // Player movement (boundary checks moved to player.update)
129+ if ( keys . left ) {
130+ player . velocity . x = - 5 ;
131+ } else if ( keys . right ) {
132+ player . velocity . x = 5 ;
133+ } else {
134+ player . velocity . x = 0 ;
135+ }
136+
137+ // Platform collision detection
138+ platforms . forEach ( platform => {
139+ // Check for collision on top of the platform
140+ if (
141+ player . position . y + player . height <= platform . position . y &&
142+ player . position . y + player . height + player . velocity . y >= platform . position . y &&
143+ player . position . x + player . width >= platform . position . x &&
144+ player . position . x <= platform . position . x + platform . width
145+ ) {
146+ player . velocity . y = 0 ;
147+ player . position . y = platform . position . y - player . height ;
148+ player . onGround = true ;
149+ }
150+ } ) ;
151+
152+ // Goal collision detection
153+ if (
154+ player . position . x < goal . position . x + goal . width &&
155+ player . position . x + player . width > goal . position . x &&
156+ player . position . y < goal . position . y + goal . height &&
157+ player . position . y + player . height > goal . position . y
158+ ) {
159+ gameActive = false ; // Stop the game
160+ }
161+ }
162+
163+ // Event Listeners
164+ function handleKeyDown ( { keyCode } ) {
165+ switch ( keyCode ) {
166+ case 37 : // Left Arrow
167+ case 65 : // A
168+ keys . left = true ;
169+ break ;
170+ case 39 : // Right Arrow
171+ case 68 : // D
172+ keys . right = true ;
173+ break ;
174+ case 32 : // Spacebar
175+ case 87 : // W
176+ if ( player . onGround ) {
177+ player . velocity . y = - 12 ; // Jump height
178+ player . onGround = false ;
179+ }
180+ break ;
181+ }
182+ }
183+
184+ function handleKeyUp ( { keyCode } ) {
185+ switch ( keyCode ) {
186+ case 37 : // Left Arrow
187+ case 65 : // A
188+ keys . left = false ;
189+ break ;
190+ case 39 : // Right Arrow
191+ case 68 : // D
192+ keys . right = false ;
193+ break ;
194+ }
195+ }
196+
197+ window . addEventListener ( 'keydown' , handleKeyDown ) ;
198+ window . addEventListener ( 'keyup' , handleKeyUp ) ;
199+
200+ // --- UPDATED ---
201+ // Reset button listener logic fixed
202+ resetButton . addEventListener ( 'click' , ( ) => {
203+ const wasGameStopped = ! gameActive ;
204+ init ( ) ; // Resets gameActive to true
205+ if ( wasGameStopped ) {
206+ animate ( ) ; // Manually restart the animation loop if it was stopped (on win screen)
207+ }
208+ } ) ;
209+
210+ // Start the game
211+ init ( ) ;
212+ animate ( ) ;
0 commit comments