1818
1919### NPM
2020
21- ``` bash
21+ ``` shell
2222npm create vite@latest my-bottlecap-game -- --template vanilla # vanilla-ts for TypeScript
2323
2424npm i bottlecap
@@ -57,155 +57,144 @@ Check out a live demo on [Replit](https://replit.com/@harshsinghdev/bottlecap-ex
5757import * as Bottlecap from ' https://unpkg.com/bottlecap@latest' ;
5858
5959class MyGame extends Bottlecap .Game {
60+ constructor () {
61+ super ();
62+ this .score = 0 ;
63+ }
6064
6165 init () {
66+ this .setupCanvas ();
67+ this .setupCamera ();
68+ this .loaderSetup ();
69+ console .log (' Game Initialized' );
70+ }
6271
63- // create a canvas with width and height equal to window's width and height and set its background color to lightgreen
64-
72+ setupCanvas () {
6573 this .canvas = Bottlecap .createCanvas (window .innerWidth , window .innerHeight , ' lightgreen' );
66-
6774 this .ctx = this .canvas .getContext (' 2d' );
68-
6975 this .ctx .imageSmoothingEnabled = false ;
70-
71- // append the canvas element to the document's body
72-
7376 document .body .appendChild (this .canvas );
77+ }
7478
75- // create a camera
76-
79+ setupCamera () {
7780 this .camera = new Bottlecap.Camera (this .ctx );
81+ }
7882
83+ loaderSetup () {
7984 this .loader = new Bottlecap.Loader ();
80-
8185 this .loader .on (' load' , this .onLoadingComplete .bind (this ));
82-
8386 this .loader .on (' error' , console .error );
8487
8588 this .loader
8689 .addImage (' coin' , ' ./coin.png' )
8790 .addImage (' playerSprite' , ' ./player.png' )
8891 .addSound (' coinpickup' , ' ./coin-pickup.wav' )
8992 .load ();
90-
91- console .log (' Game Initialised' );
92-
9393 }
9494
9595 onLoadingComplete (assets ) {
9696 this .assets = assets;
97+ this .createPlayer ();
98+ this .createCoins ();
99+ }
97100
98- this .score = 0 ;
99-
101+ createPlayer () {
100102 const playerSprite = new Bottlecap.AnimatedSprite (this .ctx , this .assets .image .playerSprite , 6 , 1 , 0 , 0 , 64 , 64 );
101-
102103 playerSprite .addAnimation (" default" , 0 , 5 , 80 );
103-
104104 playerSprite .play (" default" );
105105
106106 this .player = {
107107 speed: 100 ,
108108 sprite: playerSprite
109109 };
110+ }
110111
112+ createCoins () {
111113 this .coins = [];
112114
113115 for (let i = 0 ; i < 20 ; i++ ) {
114116 const x = Bottlecap .Utils .randomInt (100 , this .canvas .width - 100 );
115117 const y = Bottlecap .Utils .randomInt (100 , this .canvas .height - 100 );
116-
117118 const sprite = new Bottlecap.AnimatedSprite (this .ctx , this .assets .image .coin , 18 , 1 , x, y, 16 , 16 );
118-
119119 sprite .addAnimation (" spin" , 0 , 8 , 30 );
120-
121120 sprite .play (" spin" );
122121
123122 this .coins .push ({
124123 sprite,
125124 visible: true
126125 });
127126 }
128-
129127 }
130128
131129 update (dt ) {
132- if (this .loader .loading ) {
133- return ;
134- }
135-
136- const direction = Bottlecap .Keyboard .getDirection (); // { x, y }
130+ if (this .loader .loading ) return ;
137131
138- this .player .sprite .position .x += direction .x * this .player .speed * dt; // move player left or right depending on direction.x's value [1, -1]
139- this .player .sprite .position .y += direction .y * this .player .speed * dt; // move player up or down depending on direction.y's value [1, -1]
132+ this .updatePlayer (dt);
133+ this .updateCoins (dt);
134+ this .updateCamera (dt);
135+ }
140136
141- if (direction .x === 1 ) {
142- this .player .sprite .flipX = false ;
143- } else if (direction .x === - 1 ) {
144- this .player .sprite .flipX = true ;
145- }
137+ updatePlayer (dt ) {
138+ const direction = Bottlecap .Keyboard .getDirection ();
139+ this .player .sprite .position .x += direction .x * this .player .speed * dt;
140+ this .player .sprite .position .y += direction .y * this .player .speed * dt;
146141
142+ this .player .sprite .flipX = direction .x === - 1 ;
147143 this .player .sprite .update (dt);
144+ }
148145
146+ updateCoins (dt ) {
149147 this .coins .forEach (coin => {
150- // if the coin is visible &&
151- // the coin (circle) is colliding with the player (rect)
152- coin .sprite .update (dt);
153-
154- if (
155- coin .visible &&
156- Bottlecap .Collision .rectInRect (
157- coin .sprite .position .x ,
158- coin .sprite .position .y ,
159- coin .sprite .size .x ,
160- coin .sprite .size .y ,
161- this .player .sprite .position .x ,
162- this .player .sprite .position .y ,
163- this .player .sprite .size .x ,
164- this .player .sprite .size .y
165- )
166- ) {
167- coin .visible = false ; // set the visiblity of the coin to false
168- this .score += 10 ; // add 10 to player's total score
169- Bottlecap .Sound .play (null , this .assets .sound .coinpickup ); // play sound, use default gainNode
148+ if (coin .visible && this .checkCoinCollision (coin)) {
149+ coin .visible = false ;
150+ this .score += 10 ;
151+ Bottlecap .Sound .play (null , this .assets .sound .coinpickup );
170152 }
153+ coin .sprite .update (dt);
171154 });
155+ }
172156
173- this .camera .lookAt (this .player .sprite .position .x , this .player .sprite .position .y ); // update camera's target location
174-
175- this .camera .update (dt); // update the camera
157+ checkCoinCollision (coin ) {
158+ return coin .visible && Bottlecap .Collision .rectInRect (
159+ coin .sprite .position .x , coin .sprite .position .y , coin .sprite .size .x , coin .sprite .size .y ,
160+ this .player .sprite .position .x , this .player .sprite .position .y , this .player .sprite .size .x , this .player .sprite .size .y
161+ );
162+ }
176163
164+ updateCamera (dt ) {
165+ this .camera .lookAt (this .player .sprite .position .x , this .player .sprite .position .y );
166+ this .camera .update (dt);
177167 }
178168
179169 render () {
180-
181- this .ctx .clearRect (0 , 0 , this .canvas .width , this .canvas .height );
182-
170+ this .clearCanvas ();
183171 if (this .loader .loading ) {
184172 this .renderLoadingScreen ();
185173 return ;
186174 }
187175
188- this .camera .attach (); // -- camera attached
176+ this .camera .attach ();
177+ this .renderCoins ();
178+ this .player .sprite .render ();
179+ this .camera .detach ();
189180
190- // Render coins
181+ this .renderScore ();
182+ }
191183
184+ clearCanvas () {
185+ this .ctx .clearRect (0 , 0 , this .canvas .width , this .canvas .height );
186+ }
187+
188+ renderCoins () {
192189 this .coins .forEach (coin => {
193- // render coin only if it is visible
194- if (coin .visible ) {
195- coin .sprite .render ();
196- }
190+ if (coin .visible ) coin .sprite .render ();
197191 });
192+ }
198193
199- this .player .sprite .render ();
200-
201- this .camera .detach (); // -- camera detached
202-
194+ renderScore () {
203195 this .ctx .fillStyle = " #000" ;
204-
205196 this .ctx .font = " 32px sans-serif" ;
206-
207- this .ctx .fillText (` Score: ${ this .score } ` , 32 , 32 + 20 ); // display the score
208-
197+ this .ctx .fillText (` Score: ${ this .score } ` , 32 , 32 + 20 );
209198 }
210199
211200 renderLoadingScreen () {
@@ -219,30 +208,28 @@ class MyGame extends Bottlecap.Game {
219208 this .canvas .height / 2
220209 );
221210 }
222-
223211}
224212
225213const initGame = () => {
226- const game = new MyGame (); // create an instance of the game
227-
228- game .run (); // runs the game
214+ const game = new MyGame ();
215+ game .run ();
229216};
230217
231- // call initGame when DOM state is ready
232-
233218Bottlecap .DOM .ready (initGame);
234219```
235220
236221** index.html:**
237222``` html
238- <!Doctype html>
239- <html >
223+ <!DOCTYPE html>
224+ <html lang = " en " >
240225<head >
226+ <meta charset =" UTF-8" >
227+ <meta name =" viewport" content =" width=device-width, initial-scale=1.0" >
241228 <title >My Game</title >
242229</head >
243230<body >
244231
245- <script src =" ./game.js" type = " module " ></script >
232+ <script type = " module " src =" ./game.js" ></script >
246233
247234</body >
248235</html >
0 commit comments