├── .gitignore
├── README.md
├── docs
└── proposal.md
├── images
├── Virus-128.png
├── background.jpeg
├── pillblue.png
├── pillblueleft.png
├── pillblueright.png
├── pillred.png
├── pillredleft.png
├── pillredright.png
├── pillyellow.png
├── pillyellowleft.png
├── pillyellowright.png
├── virus.jpg
├── virusblue.png
├── virusred.png
└── virusyellow.png
├── index.html
├── lib
├── audio.js
├── bundle.js
├── bundle.js.map
├── drmariojs.js
├── game.js
├── keymaster.js
├── pill.js
└── virus.js
├── package.json
├── sounds
├── bgm.mp3
├── eatblocks.mp3
├── gameover.mp3
├── levelclear.mp3
├── movepill.mp3
└── rotatepill.mp3
├── stylesheets
└── css.css
└── webpack.config.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2 | #
3 | # If you find yourself ignoring temporary files generated by your text editor
4 | # or operating system, you probably want to add a global ignore instead:
5 | # git config --global core.excludesfile '~/.gitignore_global'
6 |
7 | # Ignore bundler config.
8 | /.bundle
9 |
10 | # Ignore all logfiles and tempfiles.
11 | /log/*
12 | /tmp/*
13 | !/log/.keep
14 | !/tmp/.keep
15 |
16 | /node_modules
17 | /yarn-error.log
18 |
19 | .byebug_history
20 |
21 | node_modules/
22 | .byebug_history
23 | .DS_Store
24 | npm-debug.log
25 |
26 | # Ignore application configuration
27 | /config/application.yml
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Dr Mario JS
2 |
3 | [Dr Mario JS](https://swangs.github.io/drmariojs/) is a web browser puzzle game inspired by Dr Mario. It is built entirely with vanilla JavaScript and HTML5.
4 |
5 | ## How to Play
6 | Create rows and columns of four or more matching colors. Destroy all viruses to advance to the next level.
7 |
8 | 
9 |
10 | ## Features
11 | 9 levels with increasing difficulty
12 |
13 | Engineered with object oriented programming in mind; key objects and functions are bundled together with Webpack
14 |
15 | 2D Array Grid and Canvas Element synced to provide foundations for game animation and mechanics.
16 | ```javascript
17 | newBoard(ctx) {
18 | const board = new Array(16);
19 | for (let i = 0; i < board.length; i++) {
20 | board[i] = new Array(8);
21 | }
22 | this.randomizeViruses(ctx, board);
23 | return board;
24 | }
25 |
26 | draw(ctx) {
27 | if (!this.paused && !this.gameOver) {
28 | ctx.clearRect(0, 0, Game.DIM_X, Game.DIM_Y);
29 | this.allObjects().forEach((object) => {
30 | if (object !== undefined) {
31 | object.draw();
32 | }
33 | });
34 | }
35 | }
36 | ```
37 |
--------------------------------------------------------------------------------
/docs/proposal.md:
--------------------------------------------------------------------------------
1 | # Dr. Mario Javascript Project
2 |
3 | Dr. Mario is a tetris-like puzzle game where the goal is to eliminate the viruses on the board by creating rows or columns of 4 matching colors.
4 |
5 | Players will be able to choose the speed and amount of viruses to adjust difficulty.
6 |
7 | ## Functionality and MVP
8 | * Board will be randomly seeded based on difficulty.
9 | * Player controls will be four movements and two rotation buttons.
10 | * Collision detection for viruses and pieces.
11 | * Logic for winning/losing conditions.
12 | * Sounds for BGM, keypress, rotation, and successful match.
13 |
14 | ## Wireframes
15 | 
16 |
17 | ## Architectures and Technologies
18 | * Vanilla Javascript for overall game structure and logic.
19 | * HTML5 Canvas for DOM Manipulation and Rendering.
20 | * Web Audio API for sounds.
21 |
22 | ## Implementation Timeline
23 | ### Day 1
24 | * Set up Board and Pieces.
25 | ### Day 2
26 | * Implement Controls
27 | ### Day 3
28 | * Build logic for winning game
29 | ### Day 4
30 | * Add sound and styling
31 |
32 | ## Bonus Features
33 | * Never Ending Mode - Viruses proliferate periodically.
34 | * Add original sprites and sounds.
35 | * Create Multiplayer
36 |
--------------------------------------------------------------------------------
/images/Virus-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/Virus-128.png
--------------------------------------------------------------------------------
/images/background.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/background.jpeg
--------------------------------------------------------------------------------
/images/pillblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillblue.png
--------------------------------------------------------------------------------
/images/pillblueleft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillblueleft.png
--------------------------------------------------------------------------------
/images/pillblueright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillblueright.png
--------------------------------------------------------------------------------
/images/pillred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillred.png
--------------------------------------------------------------------------------
/images/pillredleft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillredleft.png
--------------------------------------------------------------------------------
/images/pillredright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillredright.png
--------------------------------------------------------------------------------
/images/pillyellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillyellow.png
--------------------------------------------------------------------------------
/images/pillyellowleft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillyellowleft.png
--------------------------------------------------------------------------------
/images/pillyellowright.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/pillyellowright.png
--------------------------------------------------------------------------------
/images/virus.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/virus.jpg
--------------------------------------------------------------------------------
/images/virusblue.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/virusblue.png
--------------------------------------------------------------------------------
/images/virusred.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/virusred.png
--------------------------------------------------------------------------------
/images/virusyellow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/images/virusyellow.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Dr Mario JS
4 |
5 |
6 |
7 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
Controls
30 |
Left - Left Arrow
31 |
Right - Right Arrow
32 |
Down - Down Arrow
33 |
Rotate Left - Z
34 |
Rotate Right - X
35 |
Pause - Space
36 |
Destroy as many Viruses as you can by creating rows and columns of 4 or more matching colors
37 |
38 |
39 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/lib/audio.js:
--------------------------------------------------------------------------------
1 | class Audio {
2 |
3 | toggleMute() {
4 | const sounds = document.getElementsByTagName("audio");
5 | for (let i = 0; i < sounds.length; i++) {
6 | sounds[i].muted = !sounds[i].muted;
7 | }
8 | const muteButton = document.getElementById("muteicon");
9 | if (sounds[0].muted) {
10 | muteButton.classList.remove("fa-volume-up");
11 | muteButton.classList.add("fa-volume-off");
12 | } else {
13 | muteButton.classList.remove("fa-volume-off");
14 | muteButton.classList.add("fa-volume-up");
15 | }
16 | }
17 | startGame() {
18 | const sounds = document.getElementsByTagName("audio");
19 | for (let i = 0; i < sounds.length; i++) {
20 | sounds[i].pause();
21 | sounds.currentTime = 0;
22 | }
23 | const sound = document.getElementById("bgm");
24 | sound.play();
25 | }
26 |
27 | bgmStop() {
28 | const sound = document.getElementById("bgm");
29 | sound.pause();
30 | sound.currentTime = 0;
31 | }
32 |
33 | pausebgm() {
34 | const sound = document.getElementById("bgm");
35 | sound.pause();
36 | }
37 |
38 | playbgm() {
39 | const sound = document.getElementById("bgm");
40 | sound.play();
41 | }
42 |
43 | movePill() {
44 | const sound = document.getElementById("movepill");
45 | sound.currentTime = 0;
46 | sound.play();
47 | }
48 |
49 | rotatePill() {
50 | const sound = document.getElementById("rotatepill");
51 | sound.currentTime = 0;
52 | sound.play();
53 | }
54 |
55 | eatBlocks() {
56 | const sound = document.getElementById("eatblocks");
57 | sound.currentTime = 0;
58 | sound.play();
59 | }
60 |
61 | levelClear() {
62 | const bgm = document.getElementById("bgm");
63 | const sound = document.getElementById("levelclear");
64 | bgm.pause();
65 | bgm.currentTime = 0;
66 | sound.play();
67 | setTimeout(() => {
68 | bgm.play();
69 | }, 2500);
70 | }
71 |
72 | gameOver() {
73 | const sound = document.getElementById("gameover");
74 | sound.play();
75 | }
76 |
77 | }
78 |
79 | export default Audio;
80 |
--------------------------------------------------------------------------------
/lib/bundle.js:
--------------------------------------------------------------------------------
1 | /******/ (function(modules) { // webpackBootstrap
2 | /******/ // The module cache
3 | /******/ var installedModules = {};
4 | /******/
5 | /******/ // The require function
6 | /******/ function __webpack_require__(moduleId) {
7 | /******/
8 | /******/ // Check if module is in cache
9 | /******/ if(installedModules[moduleId]) {
10 | /******/ return installedModules[moduleId].exports;
11 | /******/ }
12 | /******/ // Create a new module (and put it into the cache)
13 | /******/ var module = installedModules[moduleId] = {
14 | /******/ i: moduleId,
15 | /******/ l: false,
16 | /******/ exports: {}
17 | /******/ };
18 | /******/
19 | /******/ // Execute the module function
20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
21 | /******/
22 | /******/ // Flag the module as loaded
23 | /******/ module.l = true;
24 | /******/
25 | /******/ // Return the exports of the module
26 | /******/ return module.exports;
27 | /******/ }
28 | /******/
29 | /******/
30 | /******/ // expose the modules object (__webpack_modules__)
31 | /******/ __webpack_require__.m = modules;
32 | /******/
33 | /******/ // expose the module cache
34 | /******/ __webpack_require__.c = installedModules;
35 | /******/
36 | /******/ // define getter function for harmony exports
37 | /******/ __webpack_require__.d = function(exports, name, getter) {
38 | /******/ if(!__webpack_require__.o(exports, name)) {
39 | /******/ Object.defineProperty(exports, name, {
40 | /******/ configurable: false,
41 | /******/ enumerable: true,
42 | /******/ get: getter
43 | /******/ });
44 | /******/ }
45 | /******/ };
46 | /******/
47 | /******/ // getDefaultExport function for compatibility with non-harmony modules
48 | /******/ __webpack_require__.n = function(module) {
49 | /******/ var getter = module && module.__esModule ?
50 | /******/ function getDefault() { return module['default']; } :
51 | /******/ function getModuleExports() { return module; };
52 | /******/ __webpack_require__.d(getter, 'a', getter);
53 | /******/ return getter;
54 | /******/ };
55 | /******/
56 | /******/ // Object.prototype.hasOwnProperty.call
57 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
58 | /******/
59 | /******/ // __webpack_public_path__
60 | /******/ __webpack_require__.p = "";
61 | /******/
62 | /******/ // Load entry module and return exports
63 | /******/ return __webpack_require__(__webpack_require__.s = 1);
64 | /******/ })
65 | /************************************************************************/
66 | /******/ ([
67 | /* 0 */
68 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
69 |
70 | "use strict";
71 | class Audio {
72 |
73 | toggleMute() {
74 | const sounds = document.getElementsByTagName("audio");
75 | for (let i = 0; i < sounds.length; i++) {
76 | sounds[i].muted = !sounds[i].muted;
77 | }
78 | const muteButton = document.getElementById("muteicon");
79 | if (sounds[0].muted) {
80 | muteButton.classList.remove("fa-volume-up");
81 | muteButton.classList.add("fa-volume-off");
82 | } else {
83 | muteButton.classList.remove("fa-volume-off");
84 | muteButton.classList.add("fa-volume-up");
85 | }
86 | }
87 | startGame() {
88 | const sounds = document.getElementsByTagName("audio");
89 | for (let i = 0; i < sounds.length; i++) {
90 | sounds[i].pause();
91 | sounds.currentTime = 0;
92 | }
93 | const sound = document.getElementById("bgm");
94 | sound.play();
95 | }
96 |
97 | bgmStop() {
98 | const sound = document.getElementById("bgm");
99 | sound.pause();
100 | sound.currentTime = 0;
101 | }
102 |
103 | pausebgm() {
104 | const sound = document.getElementById("bgm");
105 | sound.pause();
106 | }
107 |
108 | playbgm() {
109 | const sound = document.getElementById("bgm");
110 | sound.play();
111 | }
112 |
113 | movePill() {
114 | const sound = document.getElementById("movepill");
115 | sound.currentTime = 0;
116 | sound.play();
117 | }
118 |
119 | rotatePill() {
120 | const sound = document.getElementById("rotatepill");
121 | sound.currentTime = 0;
122 | sound.play();
123 | }
124 |
125 | eatBlocks() {
126 | const sound = document.getElementById("eatblocks");
127 | sound.currentTime = 0;
128 | sound.play();
129 | }
130 |
131 | levelClear() {
132 | const bgm = document.getElementById("bgm");
133 | const sound = document.getElementById("levelclear");
134 | bgm.pause();
135 | bgm.currentTime = 0;
136 | sound.play();
137 | setTimeout(() => {
138 | bgm.play();
139 | }, 2500);
140 | }
141 |
142 | gameOver() {
143 | const sound = document.getElementById("gameover");
144 | sound.play();
145 | }
146 |
147 | }
148 |
149 | /* harmony default export */ __webpack_exports__["a"] = (Audio);
150 |
151 |
152 | /***/ }),
153 | /* 1 */
154 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
155 |
156 | "use strict";
157 | Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
158 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__game__ = __webpack_require__(2);
159 |
160 |
161 | document.addEventListener("DOMContentLoaded", () => {
162 | const canvasEl = document.getElementsByTagName("canvas")[0];
163 | canvasEl.width = __WEBPACK_IMPORTED_MODULE_0__game__["a" /* default */].DIM_X;
164 | canvasEl.height = __WEBPACK_IMPORTED_MODULE_0__game__["a" /* default */].DIM_Y;
165 | const ctx = canvasEl.getContext("2d");
166 |
167 | let game = new __WEBPACK_IMPORTED_MODULE_0__game__["a" /* default */](ctx);
168 | game.start();
169 | });
170 |
171 |
172 | /***/ }),
173 | /* 2 */
174 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
175 |
176 | "use strict";
177 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__pill__ = __webpack_require__(3);
178 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__virus__ = __webpack_require__(4);
179 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__audio__ = __webpack_require__(0);
180 |
181 |
182 |
183 |
184 | class Game {
185 | constructor(ctx) {
186 | this.ctx = ctx;
187 | this.level = 1;
188 | this.speed = 1000;
189 | this.score = 0;
190 | this.newGame = true;
191 | this.gameOver = false;
192 | this.paused = false;
193 | this.checking = false;
194 | this.changed = false;
195 | this.currentPill = null;
196 | this.virusCount = 0;
197 | this.board = this.newBoard(ctx);
198 | this.audio = new __WEBPACK_IMPORTED_MODULE_2__audio__["a" /* default */];
199 | }
200 |
201 | newBoard(ctx) {
202 | const board = new Array(16);
203 | for (let i = 0; i < board.length; i++) {
204 | board[i] = new Array(8);
205 | }
206 | this.randomizeViruses(ctx, board);
207 | return board;
208 | }
209 |
210 | randomizeViruses(ctx, board) {
211 | for (let i = 0; i < this.level * 10; i++) {
212 | let randomX = Math.floor(Math.random() * 8);
213 | let randomY = Math.floor(Math.random() * 12) + 4;
214 | while (board[randomY][randomX] !== undefined) {
215 | randomX = Math.floor(Math.random() * 8);
216 | randomY = Math.floor(Math.random() * 12) + 4;
217 | }
218 | const virusColor = ["yellow", "blue", "red"][Math.floor(Math.random() * 3)];
219 | const virus = new __WEBPACK_IMPORTED_MODULE_1__virus__["a" /* default */](ctx, board, [randomY, randomX], virusColor);
220 | board[randomY][randomX] = virus;
221 | }
222 | }
223 |
224 | newPill(ctx, board) {
225 | if (this.board[0][3] !== undefined || this.board[0][4] !== undefined) {
226 | this.gameOver = true;
227 | }
228 | const pill = new __WEBPACK_IMPORTED_MODULE_0__pill__["a" /* default */](ctx, board);
229 | this.currentPill = pill;
230 | board[0][3] = pill.pill1;
231 | board[0][4] = pill.pill2;
232 | }
233 |
234 | allObjects() {
235 | return [].concat.apply([], this.board);
236 | }
237 |
238 | draw(ctx) {
239 | if (!this.paused && !this.gameOver) {
240 | ctx.clearRect(0, 0, Game.DIM_X, Game.DIM_Y);
241 | this.allObjects().forEach((object) => {
242 | if (object !== undefined) {
243 | object.draw();
244 | }
245 | });
246 | document.getElementById("virus").innerHTML = `Viruses Left: ${this.virusCount}`;
247 | document.getElementById("score").innerHTML = `Score: ${this.score}`;
248 | document.getElementById("level").innerHTML = `Level: ${this.level}`;
249 | }
250 | }
251 |
252 | bindKeyHandlers() {
253 | Object.keys(Game.MOVES).forEach((k) => {
254 | const move = Game.MOVES[k];
255 | key(k, () => {
256 | this.currentPill.move(k);
257 | if (!this.currentPill.active) {
258 | this.checkBoard();
259 | }
260 | this.draw(this.ctx);
261 | });
262 | });
263 | key("space", () => { this.space(); });
264 | }
265 |
266 | space() {
267 | if (this.newGame) {
268 | this.newGame = false;
269 | this.checkBoard();
270 | this.audio.startGame();
271 | requestAnimationFrame(this.animate.bind(this));
272 | } else if (!this.gameOver) {
273 | this.paused = !this.paused;
274 | this.currentPill.active = !this.currentPill.active;
275 | if (this.paused) {
276 | this.audio.pausebgm();
277 | } else {
278 | this.audio.playbgm();
279 | }
280 | this.ctx.font = "60px Arial";
281 | this.ctx.fillStyle = "red";
282 | this.ctx.fillText("PAUSED",25,300);
283 | this.ctx.strokeStyle = "white";
284 | this.ctx.lineWidth = 2;
285 | this.ctx.strokeText("PAUSED",25,300);
286 | this.draw(this.ctx);
287 | } else {
288 | this.level = 1;
289 | this.speed = 1000;
290 | this.score = 0;
291 | this.gameOver = false;
292 | this.board = this.newBoard(this.ctx);
293 | this.checkBoard();
294 | this.audio.startGame();
295 | requestAnimationFrame(this.animate.bind(this));
296 | }
297 | }
298 |
299 | start() {
300 | this.bindKeyHandlers();
301 | requestAnimationFrame(this.animate.bind(this));
302 | this.checkBoard();
303 | }
304 |
305 | animate() {
306 | if (this.newGame) {
307 | document.getElementById("virus").innerHTML = `Viruses Left: ${this.virusCount}`;
308 | document.getElementById("score").innerHTML = `Score: ${this.score}`;
309 | document.getElementById("level").innerHTML = `Level: ${this.level}`;
310 | document.getElementById("mute").addEventListener("click", () => {
311 | this.audio.toggleMute();
312 | document.getElementById("mute").blur();
313 | });
314 | this.ctx.font = "50px Arial";
315 | this.ctx.fillStyle = "red";
316 | this.ctx.fillText("Dr Mario JS",15,250);
317 | this.ctx.strokeStyle = "white";
318 | this.ctx.lineWidth = 2;
319 | this.ctx.strokeText("Dr Mario JS",15,250);
320 | this.ctx.font = "25px Arial";
321 | this.ctx.fillStyle = "red";
322 | this.ctx.fillText("Hit Space to Start",45,300);
323 | this.ctx.strokeStyle = "white";
324 | this.ctx.lineWidth = 1;
325 | this.ctx.strokeText("Hit Space to Start",45,300);
326 | } else if (this.paused) {
327 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
328 | } else if (this.checking){
329 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
330 | } else if (this.virusCount === 0) {
331 | this.audio.levelClear();
332 | if (this.level < 10) {
333 | this.level += 1;
334 | this.speed -= 100;
335 | }
336 | this.board = this.newBoard(this.ctx);
337 | this.checkBoard();
338 | requestAnimationFrame(this.animate.bind(this));
339 | } else if (this.gameOver) {
340 | this.audio.bgmStop();
341 | this.audio.gameOver();
342 | this.ctx.font = "50px Arial";
343 | this.ctx.fillStyle = "red";
344 | this.ctx.fillText("Game Over",15,250);
345 | this.ctx.strokeStyle = "white";
346 | this.ctx.lineWidth = 2;
347 | this.ctx.strokeText("Game Over",15,250);
348 | this.ctx.font = "25px Arial";
349 | this.ctx.fillStyle = "red";
350 | this.ctx.fillText("Hit Space to Restart",30,300);
351 | this.ctx.strokeStyle = "white";
352 | this.ctx.lineWidth = 1;
353 | this.ctx.strokeText("Hit Space to Restart",30,300);
354 | } else {
355 | if (!this.currentPill || !this.currentPill.active) {
356 | this.newPill(this.ctx, this.board);
357 | } else {
358 | this.currentPill.drop();
359 | if (!this.currentPill.active) {
360 | this.checkBoard();
361 | }
362 | }
363 |
364 | this.draw(this.ctx);
365 |
366 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
367 | }
368 | }
369 |
370 | checkBoard() {
371 | this.checking = true;
372 | this.checkCols();
373 | this.checkRows();
374 | if (this.changed) {
375 | this.changed = false;
376 | this.dropPills();
377 | setTimeout(() => {this.checkBoard();}, 500);
378 | } else {
379 | this.checking = false;
380 | }
381 | }
382 |
383 | dropPills() {
384 | const transposedBoard = [];
385 | for (var i = 0; i < 8; i++) {
386 | const newRow = [];
387 | for (var j = 15; j >= 0; j--) {
388 | newRow.push(this.board[j][i]);
389 | }
390 | transposedBoard.push(newRow);
391 | }
392 |
393 | for (i = 0; i < transposedBoard.length; i++) {
394 | for (j = 1; j < transposedBoard[i].length; j++) {
395 | if (transposedBoard[i][j] !== undefined &&
396 | transposedBoard[i][j].type === "pill" &&
397 | transposedBoard[i][j -1 ] === undefined) {
398 | if (transposedBoard[i][j].pair === null) {
399 | transposedBoard[i][j].drop();
400 | transposedBoard[i][j] = undefined;
401 | this.draw(this.ctx);
402 | this.changed = true;
403 | } else if (transposedBoard[i][j].coords[1] === transposedBoard[i][j].pair.coords[1] ||
404 | transposedBoard[i][j].coords[0] !== transposedBoard[i][j].pair.coords[0] ||
405 | this.board[transposedBoard[i][j].pair.coords[0] + 1][transposedBoard[i][j].pair.coords[1]] === undefined) {
406 | transposedBoard[i][j].drop();
407 | transposedBoard[i][j] = undefined;
408 | this.draw(this.ctx);
409 | this.changed = true;
410 | }
411 | }
412 | }
413 | }
414 | }
415 |
416 | checkRows() {
417 | let viruses = [];
418 | let tempRow;
419 | let currentColor;
420 | for (var i = 0; i < this.board.length; i++) {
421 | tempRow = [];
422 | currentColor = null;
423 | for (var j = 0; j < this.board[i].length; j++) {
424 | if (this.board[i][j] !== undefined) {
425 | if (this.board[i][j].type === "virus") {
426 | viruses.push([i, j]);
427 | }
428 | if (currentColor === null) {
429 | currentColor = this.board[i][j].color;
430 | }
431 | if (this.board[i][j].color === currentColor) {
432 | tempRow.push([i, j]);
433 | }
434 | if (this.board[i][j].color !== currentColor || j === 7) {
435 | currentColor = this.board[i][j].color;
436 | if (tempRow.length > 3) {
437 | tempRow.forEach((coord) => {
438 | if (this.board[coord[0]][coord[1]].type === "virus") {
439 | this.score += 100;
440 | }
441 | if (this.board[coord[0]][coord[1]].pair) {
442 | this.board[coord[0]][coord[1]].pair.pair = null;
443 | }
444 | this.board[coord[0]][coord[1]] = undefined;
445 | this.changed = true;
446 | });
447 | this.audio.eatBlocks();
448 | }
449 | tempRow = [];
450 | tempRow.push([i, j]);
451 | }
452 | } else {
453 | if (tempRow.length > 3) {
454 | tempRow.forEach((coord) => {
455 | if (this.board[coord[0]][coord[1]].type === "virus") {
456 | this.score += 100;
457 | }
458 | if (this.board[coord[0]][coord[1]].pair) {
459 | this.board[coord[0]][coord[1]].pair.pair = null;
460 | }
461 | this.board[coord[0]][coord[1]] = undefined;
462 | this.changed = true;
463 | });
464 | this.audio.eatBlocks();
465 | }
466 | tempRow = [];
467 | currentColor = null;
468 | }
469 | }
470 | }
471 | this.virusCount = viruses.length;
472 | }
473 |
474 | checkCols() {
475 | const transposedBoard = [];
476 | for (var i = 0; i < 8; i++) {
477 | const newRow = [];
478 | for (var j = 0; j < this.board.length; j++) {
479 | newRow.push(this.board[j][i]);
480 | }
481 | transposedBoard.push(newRow);
482 | }
483 | let tempCol = [];
484 | let currentColor = null;
485 | for (i = 0; i < transposedBoard.length; i++) {
486 | tempCol = [];
487 | currentColor = null;
488 | for (j = 0; j < transposedBoard[i].length; j++) {
489 | if (transposedBoard[i][j] !== undefined) {
490 | if (currentColor === null) {
491 | currentColor = transposedBoard[i][j].color;
492 | }
493 | if (transposedBoard[i][j].color === currentColor) {
494 | tempCol.push([i, j]);
495 | }
496 | if (transposedBoard[i][j].color !== currentColor || j === 15) {
497 | currentColor = transposedBoard[i][j].color;
498 | if (tempCol.length > 3) {
499 | tempCol.forEach((coord) => {
500 | if (this.board[coord[1]][coord[0]].type === "virus") {
501 | this.score += 100;
502 | }
503 | if (this.board[coord[1]][coord[0]].pair) {
504 | this.board[coord[1]][coord[0]].pair.pair = null;
505 | }
506 | this.board[coord[1]][coord[0]] = undefined;
507 | this.changed = true;
508 | });
509 | this.audio.eatBlocks();
510 | }
511 | tempCol = [];
512 | tempCol.push([i, j]);
513 | }
514 | } else {
515 | if (tempCol.length > 3) {
516 | tempCol.forEach((coord) => {
517 | if (this.board[coord[1]][coord[0]].type === "virus") {
518 | this.score += 100;
519 | }
520 | if (this.board[coord[1]][coord[0]].pair) {
521 | this.board[coord[1]][coord[0]].pair.pair = null;
522 | }
523 | this.board[coord[1]][coord[0]] = undefined;
524 | this.changed = true;
525 | });
526 | this.audio.eatBlocks();
527 | }
528 | tempCol = [];
529 | currentColor = null;
530 | }
531 | }
532 | }
533 | }
534 |
535 |
536 |
537 | }
538 |
539 | Game.DIM_X = 288;
540 | Game.DIM_Y = 576;
541 | Game.MOVES = {
542 | left: "left",
543 | right: "right",
544 | down: "down",
545 | z: "z",
546 | x: "x",
547 | };
548 |
549 |
550 | /* harmony default export */ __webpack_exports__["a"] = (Game);
551 |
552 |
553 | /***/ }),
554 | /* 3 */
555 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
556 |
557 | "use strict";
558 | /* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__audio__ = __webpack_require__(0);
559 |
560 |
561 | class Pill {
562 | constructor(ctx, board) {
563 | this.ctx = ctx;
564 | this.board = board;
565 | this.board1 = [0, 3];
566 | this.board2 = [0, 4];
567 | this.active = true;
568 | this.horizontal = true;
569 | this.audio = new __WEBPACK_IMPORTED_MODULE_0__audio__["a" /* default */];
570 |
571 | this.pill1 = new PillBlock(ctx, board, [0, 3], ["yellow", "blue", "red"][Math.floor(Math.random() * 3)], "left");
572 | this.pill2 = new PillBlock(ctx, board, [0, 4], ["yellow", "blue", "red"][Math.floor(Math.random() * 3)], "right");
573 | this.pill1.pair = this.pill2;
574 | this.pill2.pair = this.pill1;
575 | }
576 |
577 | drop() {
578 | if (
579 | this.board1[0] < 15 &&
580 | this.board2[0] < 15 &&
581 | (this.board[this.board1[0] + 1][this.board1[1]] === undefined || this.board1[0] + 1 === this.board2[0] ) &&
582 | (this.board[this.board2[0] + 1][this.board2[1]] === undefined || this.board2[0] + 1=== this.board1[0] )
583 | ) {
584 |
585 | this.board[this.board1[0]][this.board1[1]] = undefined;
586 | this.board[this.board2[0]][this.board2[1]] = undefined;
587 |
588 | this.board1[0] = this.board1[0] + 1;
589 | this.board2[0] = this.board2[0] + 1;
590 |
591 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
592 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
593 |
594 | this.pill1.coords = [this.board1[0], this.board1[1]];
595 | this.pill2.coords = [this.board2[0], this.board2[1]];
596 | } else {
597 | this.active = false;
598 | }
599 | }
600 |
601 | move(k) {
602 | if (this.active) {
603 | if (k === "down") {
604 | this.drop();
605 | this.audio.movePill();
606 | }
607 | if (k === "right") {
608 | if (
609 | this.board1[1] < 7 &&
610 | this.board2[1] < 7 &&
611 | (this.board[this.board1[0]][this.board1[1] + 1] === undefined || this.board1[1] + 1 == this.board2[1]) &&
612 | (this.board[this.board2[0]][this.board2[1] + 1] === undefined || this.board2[1] + 1 == this.board1[1])
613 | ) {
614 | this.board[this.board1[0]][this.board1[1]] = undefined;
615 | this.board[this.board2[0]][this.board2[1]] = undefined;
616 |
617 | this.board1[1] = this.board1[1] + 1;
618 | this.board2[1] = this.board2[1] + 1;
619 |
620 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
621 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
622 |
623 | this.pill1.coords = [this.board1[0], this.board1[1]];
624 | this.pill2.coords = [this.board2[0], this.board2[1]];
625 |
626 | this.audio.movePill();
627 | }
628 | }
629 | if (k === "left") {
630 | if (
631 | this.board1[1] > 0 &&
632 | this.board2[1] > 0 &&
633 | (this.board[this.board1[0]][this.board1[1] - 1] === undefined || this.board1[1] - 1 == this.board2[1]) &&
634 | (this.board[this.board2[0]][this.board2[1] - 1] === undefined || this.board2[1] - 1 == this.board1[1])
635 | ) {
636 |
637 | this.board[this.board1[0]][this.board1[1]] = undefined;
638 | this.board[this.board2[0]][this.board2[1]] = undefined;
639 |
640 | this.board1[1] = this.board1[1] - 1;
641 | this.board2[1] = this.board2[1] - 1;
642 |
643 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
644 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
645 |
646 | this.pill1.coords = [this.board1[0], this.board1[1]];
647 | this.pill2.coords = [this.board2[0], this.board2[1]];
648 |
649 | this.audio.movePill();
650 | }
651 | }
652 | if (k === "z") {
653 | if (this.horizontal) {
654 | if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {
655 |
656 | this.board[this.board2[0]][this.board2[1]] = undefined;
657 | this.board2[0] = this.board2[0] - 1;
658 | this.board2[1] = this.board2[1] - 1;
659 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
660 | this.pill2.coords = [this.board2[0], this.board2[1]];
661 |
662 | this.pill1.side = "bottom";
663 | this.pill2.side = "top";
664 |
665 | this.horizontal = false;
666 |
667 | this.audio.rotatePill();
668 | }
669 | } else {
670 | if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {
671 | this.board[this.board2[0]][this.board2[1]] = undefined;
672 | this.board2[0] = this.board2[0] + 1;
673 | this.board2[1] = this.board2[1] + 1;
674 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
675 | this.pill2.coords = [this.board2[0], this.board2[1]];
676 |
677 | const tempColor = this.pill1.color;
678 | this.pill1.color = this.pill2.color;
679 | this.pill2.color = tempColor;
680 |
681 | this.pill1.side = "left";
682 | this.pill2.side = "right";
683 |
684 | this.horizontal = true;
685 |
686 | this.audio.rotatePill();
687 | }
688 | }
689 | }
690 | if (k === "x") {
691 | if (this.horizontal) {
692 | if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {
693 | this.board[this.board2[0]][this.board2[1]] = undefined;
694 | this.board2[0] = this.board2[0] - 1;
695 | this.board2[1] = this.board2[1] - 1;
696 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
697 | this.pill2.coords = [this.board2[0], this.board2[1]];
698 |
699 | const tempColor = this.pill1.color;
700 | this.pill1.color = this.pill2.color;
701 | this.pill2.color = tempColor;
702 |
703 | this.pill1.side = "bottom";
704 | this.pill2.side = "top";
705 |
706 | this.horizontal = false;
707 |
708 | this.audio.rotatePill();
709 | }
710 | } else {
711 | if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {
712 | this.board[this.board2[0]][this.board2[1]] = undefined;
713 | this.board2[0] = this.board2[0] + 1;
714 | this.board2[1] = this.board2[1] + 1;
715 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
716 | this.pill2.coords = [this.board2[0], this.board2[1]];
717 |
718 | this.pill1.side = "left";
719 | this.pill2.side = "right";
720 |
721 | this.horizontal = true;
722 |
723 | this.audio.rotatePill();
724 | }
725 | }
726 | }
727 | }
728 |
729 | }
730 | }
731 |
732 | class PillBlock {
733 | constructor(ctx, board, coords, color, side){
734 | this.ctx = ctx;
735 | this.board = board;
736 | this.coords = coords;
737 | this.color = color;
738 | this.type = "pill";
739 | this.pair = null;
740 | this.side = side;
741 | }
742 |
743 | draw() {
744 | let img = new Image();
745 | let x = (this.coords[1] * 36);
746 | let y = (this.coords[0] * 36);
747 | let w = 32;
748 | let h = 32;
749 | let degrees = -90;
750 | if (this.pair === null) {
751 | img.src = `images/pill${this.color}.png`;
752 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
753 | img.onload = () => {
754 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
755 | };
756 | } else if (this.side === "left") {
757 | img.src = `images/pill${this.color}left.png`;
758 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
759 | img.onload = () => {
760 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
761 | };
762 | } else if (this.side === "right"){
763 | img.src = `images/pill${this.color}right.png`;
764 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
765 | img.onload = () => {
766 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
767 | };
768 | } else if (this.side === "top"){
769 | img.src = `images/pill${this.color}right.png`;
770 |
771 | this.ctx.save();
772 | this.ctx.translate(x+w/2, y+h/2);
773 | this.ctx.rotate(degrees*Math.PI/180.0);
774 | this.ctx.translate(-x-w/2, -y-h/2);
775 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
776 | this.ctx.restore();
777 | img.onload = () => {
778 | this.ctx.save();
779 | this.ctx.translate(x+w/2, y+h/2);
780 | this.ctx.rotate(degrees*Math.PI/180.0);
781 | this.ctx.translate(-x-w/2, -y-h/2);
782 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
783 | this.ctx.restore();
784 | };
785 | } else if (this.side === "bottom"){
786 | img.src = `images/pill${this.color}left.png`;
787 |
788 | this.ctx.save();
789 | this.ctx.translate(x+w/2, y+h/2);
790 | this.ctx.rotate(degrees*Math.PI/180.0);
791 | this.ctx.translate(-x-w/2, -y-h/2);
792 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
793 | this.ctx.restore();
794 | img.onload = () => {
795 | this.ctx.save();
796 | this.ctx.translate(x+w/2, y+h/2);
797 | this.ctx.rotate(degrees*Math.PI/180.0);
798 | this.ctx.translate(-x-w/2, -y-h/2);
799 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
800 | this.ctx.restore();
801 | };
802 | }
803 | }
804 |
805 | drop() {
806 | if (
807 | this.coords[0] < 15 &&
808 | this.board[this.coords[0] + 1][this.coords[1]] === undefined
809 | ) {
810 | this.board[this.coords[0]][this.coords[1]] = undefined;
811 | this.coords[0] = this.coords[0] + 1;
812 | this.board[this.coords[0]][this.coords[1]] = this;
813 | }
814 | }
815 | }
816 |
817 |
818 | /* harmony default export */ __webpack_exports__["a"] = (Pill);
819 |
820 |
821 | /***/ }),
822 | /* 4 */
823 | /***/ (function(module, __webpack_exports__, __webpack_require__) {
824 |
825 | "use strict";
826 | class Virus {
827 | constructor(ctx, board, coords, color){
828 | this.ctx = ctx;
829 | this.board = board;
830 | this.coords = coords;
831 | this.color = color;
832 | this.type = "virus";
833 | this.pair = null;
834 | }
835 |
836 | draw() {
837 | this.board[this.coords[0]][this.coords[1]] = this;
838 |
839 | let img = new Image();
840 | img.src = `images/virus${this.color}.png`;
841 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);
842 | img.onload = () => {
843 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);
844 | };
845 | }
846 | }
847 |
848 | /* harmony default export */ __webpack_exports__["a"] = (Virus);
849 |
850 |
851 | /***/ })
852 | /******/ ]);
853 | //# sourceMappingURL=bundle.js.map
--------------------------------------------------------------------------------
/lib/bundle.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["webpack:///webpack/bootstrap cdcbe3fba067e32c6047","webpack:///./lib/audio.js","webpack:///./lib/drmariojs.js","webpack:///./lib/game.js","webpack:///./lib/pill.js","webpack:///./lib/virus.js"],"names":[],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAK;AACL;AACA;;AAEA;AACA;AACA;AACA,mCAA2B,0BAA0B,EAAE;AACvD,yCAAiC,eAAe;AAChD;AACA;AACA;;AAEA;AACA,8DAAsD,+DAA+D;;AAErH;AACA;;AAEA;AACA;;;;;;;;AC7DA;;AAEA;AACA;AACA,mBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA,mBAAmB,mBAAmB;AACtC;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;;AAEA;AACA;AACA;AACA;;AAEA;;AAEA;;;;;;;;;;AC9EA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,CAAC;;;;;;;;;;;ACVD;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,mBAAmB,kBAAkB;AACrC;AACA;AACA;AACA;AACA;;AAEA;AACA,mBAAmB,qBAAqB;AACxC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,oEAAoE,gBAAgB;AACpF,6DAA6D,WAAW;AACxE,6DAA6D,WAAW;AACxE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO;AACP,KAAK;AACL,wBAAwB,cAAc,EAAE;AACxC;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,oEAAoE,gBAAgB;AACpF,6DAA6D,WAAW;AACxE,6DAA6D,WAAW;AACxE;AACA;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,wBAAwB,gDAAgD;AACxE,KAAK;AACL,wBAAwB,gDAAgD;AACxE,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL;AACA;AACA,OAAO;AACP;AACA;AACA;AACA;AACA;;AAEA;;AAEA,wBAAwB,gDAAgD;AACxE;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,wBAAwB,mBAAmB;AAC3C,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA,mBAAmB,OAAO;AAC1B;AACA,sBAAsB,QAAQ;AAC9B;AACA;AACA;AACA;;AAEA,eAAe,4BAA4B;AAC3C,iBAAiB,+BAA+B;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA,mBAAmB,uBAAuB;AAC1C;AACA;AACA,qBAAqB,0BAA0B;AAC/C;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA,mBAAmB,OAAO;AAC1B;AACA,qBAAqB,uBAAuB;AAC5C;AACA;AACA;AACA;AACA;AACA;AACA,eAAe,4BAA4B;AAC3C;AACA;AACA,iBAAiB,+BAA+B;AAChD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,eAAe;AACf;AACA;AACA;AACA;AACA;AACA,SAAS;AACT;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,aAAa;AACb;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AAIA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;;;;;;;;;AClXA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA,KAAK;AACL;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA,WAAW;AACX;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,8BAA8B,WAAW;AACzC;AACA;AACA;AACA;AACA,KAAK;AACL,8BAA8B,WAAW;AACzC;AACA;AACA;AACA;AACA,KAAK;AACL,8BAA8B,WAAW;AACzC;AACA;AACA;AACA;AACA,KAAK;AACL,8BAA8B,WAAW;;AAEzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,KAAK;AACL,8BAA8B,WAAW;;AAEzC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;;;;;;;;ACnQA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;;AAEA;AACA,6BAA6B,WAAW;AACxC;AACA;AACA;AACA;AACA;AACA;;AAEA","file":"./lib/bundle.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 1);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap cdcbe3fba067e32c6047","class Audio {\n\n toggleMute() {\n const sounds = document.getElementsByTagName(\"audio\");\n for (let i = 0; i < sounds.length; i++) {\n sounds[i].muted = !sounds[i].muted;\n }\n const muteButton = document.getElementById(\"muteicon\");\n if (sounds[0].muted) {\n muteButton.classList.remove(\"fa-volume-up\");\n muteButton.classList.add(\"fa-volume-off\");\n } else {\n muteButton.classList.remove(\"fa-volume-off\");\n muteButton.classList.add(\"fa-volume-up\");\n }\n }\n startGame() {\n const sounds = document.getElementsByTagName(\"audio\");\n for (let i = 0; i < sounds.length; i++) {\n sounds[i].pause();\n sounds.currentTime = 0;\n }\n const sound = document.getElementById(\"bgm\");\n sound.play();\n }\n\n bgmStop() {\n const sound = document.getElementById(\"bgm\");\n sound.pause();\n sound.currentTime = 0;\n }\n\n pausebgm() {\n const sound = document.getElementById(\"bgm\");\n sound.pause();\n }\n\n playbgm() {\n const sound = document.getElementById(\"bgm\");\n sound.play();\n }\n\n movePill() {\n const sound = document.getElementById(\"movepill\");\n sound.currentTime = 0;\n sound.play();\n }\n\n rotatePill() {\n const sound = document.getElementById(\"rotatepill\");\n sound.currentTime = 0;\n sound.play();\n }\n\n eatBlocks() {\n const sound = document.getElementById(\"eatblocks\");\n sound.currentTime = 0;\n sound.play();\n }\n\n levelClear() {\n const bgm = document.getElementById(\"bgm\");\n const sound = document.getElementById(\"levelclear\");\n bgm.pause();\n bgm.currentTime = 0;\n sound.play();\n setTimeout(() => {\n bgm.play();\n }, 2500);\n }\n\n gameOver() {\n const sound = document.getElementById(\"gameover\");\n sound.play();\n }\n\n}\n\nexport default Audio;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/audio.js\n// module id = 0\n// module chunks = 0","import Game from './game';\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n const canvasEl = document.getElementsByTagName(\"canvas\")[0];\n canvasEl.width = Game.DIM_X;\n canvasEl.height = Game.DIM_Y;\n const ctx = canvasEl.getContext(\"2d\");\n\n let game = new Game(ctx);\n game.start();\n});\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/drmariojs.js\n// module id = 1\n// module chunks = 0","import Pill from './pill';\nimport Virus from './virus';\nimport Audio from './audio';\n\nclass Game {\n constructor(ctx) {\n this.ctx = ctx;\n this.level = 1;\n this.speed = 1000;\n this.score = 0;\n this.newGame = true;\n this.gameOver = false;\n this.paused = false;\n this.checking = false;\n this.changed = false;\n this.currentPill = null;\n this.virusCount = 0;\n this.board = this.newBoard(ctx);\n this.audio = new Audio;\n }\n\n newBoard(ctx) {\n const board = new Array(16);\n for (let i = 0; i < board.length; i++) {\n board[i] = new Array(8);\n }\n this.randomizeViruses(ctx, board);\n return board;\n }\n\n randomizeViruses(ctx, board) {\n for (let i = 0; i < this.level * 10; i++) {\n let randomX = Math.floor(Math.random() * 8);\n let randomY = Math.floor(Math.random() * 12) + 4;\n while (board[randomY][randomX] !== undefined) {\n randomX = Math.floor(Math.random() * 8);\n randomY = Math.floor(Math.random() * 12) + 4;\n }\n const virusColor = [\"yellow\", \"blue\", \"red\"][Math.floor(Math.random() * 3)];\n const virus = new Virus(ctx, board, [randomY, randomX], virusColor);\n board[randomY][randomX] = virus;\n }\n }\n\n newPill(ctx, board) {\n if (this.board[0][3] !== undefined || this.board[0][4] !== undefined) {\n this.gameOver = true;\n }\n const pill = new Pill(ctx, board);\n this.currentPill = pill;\n board[0][3] = pill.pill1;\n board[0][4] = pill.pill2;\n }\n\n allObjects() {\n return [].concat.apply([], this.board);\n }\n\n draw(ctx) {\n if (!this.paused && !this.gameOver) {\n ctx.clearRect(0, 0, Game.DIM_X, Game.DIM_Y);\n this.allObjects().forEach((object) => {\n if (object !== undefined) {\n object.draw();\n }\n });\n document.getElementById(\"virus\").innerHTML = `Viruses Left: ${this.virusCount}`;\n document.getElementById(\"score\").innerHTML = `Score: ${this.score}`;\n document.getElementById(\"level\").innerHTML = `Level: ${this.level}`;\n }\n }\n\n bindKeyHandlers() {\n Object.keys(Game.MOVES).forEach((k) => {\n const move = Game.MOVES[k];\n key(k, () => {\n this.currentPill.move(k);\n if (!this.currentPill.active) {\n this.checkBoard();\n }\n this.draw(this.ctx);\n });\n });\n key(\"space\", () => { this.space(); });\n }\n\n space() {\n if (this.newGame) {\n this.newGame = false;\n this.checkBoard();\n this.audio.startGame();\n requestAnimationFrame(this.animate.bind(this));\n } else if (!this.gameOver) {\n this.paused = !this.paused;\n this.currentPill.active = !this.currentPill.active;\n if (this.paused) {\n this.audio.pausebgm();\n } else {\n this.audio.playbgm();\n }\n this.ctx.font = \"60px Arial\";\n this.ctx.fillStyle = \"red\";\n this.ctx.fillText(\"PAUSED\",25,300);\n this.ctx.strokeStyle = \"white\";\n this.ctx.lineWidth = 2;\n this.ctx.strokeText(\"PAUSED\",25,300);\n this.draw(this.ctx);\n } else {\n this.level = 1;\n this.speed = 1000;\n this.score = 0;\n this.gameOver = false;\n this.board = this.newBoard(this.ctx);\n this.checkBoard();\n this.audio.startGame();\n requestAnimationFrame(this.animate.bind(this));\n }\n }\n\n start() {\n this.bindKeyHandlers();\n requestAnimationFrame(this.animate.bind(this));\n this.checkBoard();\n }\n\n animate() {\n if (this.newGame) {\n document.getElementById(\"virus\").innerHTML = `Viruses Left: ${this.virusCount}`;\n document.getElementById(\"score\").innerHTML = `Score: ${this.score}`;\n document.getElementById(\"level\").innerHTML = `Level: ${this.level}`;\n document.getElementById(\"mute\").addEventListener(\"click\", () => {\n this.audio.toggleMute();\n document.getElementById(\"mute\").blur();\n });\n this.ctx.font = \"50px Arial\";\n this.ctx.fillStyle = \"red\";\n this.ctx.fillText(\"Dr Mario JS\",15,250);\n this.ctx.strokeStyle = \"white\";\n this.ctx.lineWidth = 2;\n this.ctx.strokeText(\"Dr Mario JS\",15,250);\n this.ctx.font = \"25px Arial\";\n this.ctx.fillStyle = \"red\";\n this.ctx.fillText(\"Hit Space to Start\",45,300);\n this.ctx.strokeStyle = \"white\";\n this.ctx.lineWidth = 1;\n this.ctx.strokeText(\"Hit Space to Start\",45,300);\n } else if (this.paused) {\n setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);\n } else if (this.checking){\n setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);\n } else if (this.virusCount === 0) {\n this.audio.levelClear();\n if (this.level < 10) {\n this.level += 1;\n this.speed -= 100;\n }\n this.board = this.newBoard(this.ctx);\n this.checkBoard();\n requestAnimationFrame(this.animate.bind(this));\n } else if (this.gameOver) {\n this.audio.bgmStop();\n this.audio.gameOver();\n this.ctx.font = \"50px Arial\";\n this.ctx.fillStyle = \"red\";\n this.ctx.fillText(\"Game Over\",15,250);\n this.ctx.strokeStyle = \"white\";\n this.ctx.lineWidth = 2;\n this.ctx.strokeText(\"Game Over\",15,250);\n this.ctx.font = \"25px Arial\";\n this.ctx.fillStyle = \"red\";\n this.ctx.fillText(\"Hit Space to Restart\",30,300);\n this.ctx.strokeStyle = \"white\";\n this.ctx.lineWidth = 1;\n this.ctx.strokeText(\"Hit Space to Restart\",30,300);\n } else {\n if (!this.currentPill || !this.currentPill.active) {\n this.newPill(this.ctx, this.board);\n } else {\n this.currentPill.drop();\n if (!this.currentPill.active) {\n this.checkBoard();\n }\n }\n\n this.draw(this.ctx);\n\n setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);\n }\n }\n\n checkBoard() {\n this.checking = true;\n this.checkCols();\n this.checkRows();\n if (this.changed) {\n this.changed = false;\n this.dropPills();\n setTimeout(() => {this.checkBoard();}, 500);\n } else {\n this.checking = false;\n }\n }\n\n dropPills() {\n const transposedBoard = [];\n for (var i = 0; i < 8; i++) {\n const newRow = [];\n for (var j = 15; j >= 0; j--) {\n newRow.push(this.board[j][i]);\n }\n transposedBoard.push(newRow);\n }\n\n for (i = 0; i < transposedBoard.length; i++) {\n for (j = 1; j < transposedBoard[i].length; j++) {\n if (transposedBoard[i][j] !== undefined &&\n transposedBoard[i][j].type === \"pill\" &&\n transposedBoard[i][j -1 ] === undefined) {\n if (transposedBoard[i][j].pair === null) {\n transposedBoard[i][j].drop();\n transposedBoard[i][j] = undefined;\n this.draw(this.ctx);\n this.changed = true;\n } else if (transposedBoard[i][j].coords[1] === transposedBoard[i][j].pair.coords[1] ||\n transposedBoard[i][j].coords[0] !== transposedBoard[i][j].pair.coords[0] ||\n this.board[transposedBoard[i][j].pair.coords[0] + 1][transposedBoard[i][j].pair.coords[1]] === undefined) {\n transposedBoard[i][j].drop();\n transposedBoard[i][j] = undefined;\n this.draw(this.ctx);\n this.changed = true;\n }\n }\n }\n }\n }\n\n checkRows() {\n let viruses = [];\n let tempRow;\n let currentColor;\n for (var i = 0; i < this.board.length; i++) {\n tempRow = [];\n currentColor = null;\n for (var j = 0; j < this.board[i].length; j++) {\n if (this.board[i][j] !== undefined) {\n if (this.board[i][j].type === \"virus\") {\n viruses.push([i, j]);\n }\n if (currentColor === null) {\n currentColor = this.board[i][j].color;\n }\n if (this.board[i][j].color === currentColor) {\n tempRow.push([i, j]);\n }\n if (this.board[i][j].color !== currentColor || j === 7) {\n currentColor = this.board[i][j].color;\n if (tempRow.length > 3) {\n tempRow.forEach((coord) => {\n if (this.board[coord[0]][coord[1]].type === \"virus\") {\n this.score += 100;\n }\n if (this.board[coord[0]][coord[1]].pair) {\n this.board[coord[0]][coord[1]].pair.pair = null;\n }\n this.board[coord[0]][coord[1]] = undefined;\n this.changed = true;\n });\n this.audio.eatBlocks();\n }\n tempRow = [];\n tempRow.push([i, j]);\n }\n } else {\n if (tempRow.length > 3) {\n tempRow.forEach((coord) => {\n if (this.board[coord[0]][coord[1]].type === \"virus\") {\n this.score += 100;\n }\n if (this.board[coord[0]][coord[1]].pair) {\n this.board[coord[0]][coord[1]].pair.pair = null;\n }\n this.board[coord[0]][coord[1]] = undefined;\n this.changed = true;\n });\n this.audio.eatBlocks();\n }\n tempRow = [];\n currentColor = null;\n }\n }\n }\n this.virusCount = viruses.length;\n }\n\n checkCols() {\n const transposedBoard = [];\n for (var i = 0; i < 8; i++) {\n const newRow = [];\n for (var j = 0; j < this.board.length; j++) {\n newRow.push(this.board[j][i]);\n }\n transposedBoard.push(newRow);\n }\n let tempCol = [];\n let currentColor = null;\n for (i = 0; i < transposedBoard.length; i++) {\n tempCol = [];\n currentColor = null;\n for (j = 0; j < transposedBoard[i].length; j++) {\n if (transposedBoard[i][j] !== undefined) {\n if (currentColor === null) {\n currentColor = transposedBoard[i][j].color;\n }\n if (transposedBoard[i][j].color === currentColor) {\n tempCol.push([i, j]);\n }\n if (transposedBoard[i][j].color !== currentColor || j === 15) {\n currentColor = transposedBoard[i][j].color;\n if (tempCol.length > 3) {\n tempCol.forEach((coord) => {\n if (this.board[coord[1]][coord[0]].type === \"virus\") {\n this.score += 100;\n }\n if (this.board[coord[1]][coord[0]].pair) {\n this.board[coord[1]][coord[0]].pair.pair = null;\n }\n this.board[coord[1]][coord[0]] = undefined;\n this.changed = true;\n });\n this.audio.eatBlocks();\n }\n tempCol = [];\n tempCol.push([i, j]);\n }\n } else {\n if (tempCol.length > 3) {\n tempCol.forEach((coord) => {\n if (this.board[coord[1]][coord[0]].type === \"virus\") {\n this.score += 100;\n }\n if (this.board[coord[1]][coord[0]].pair) {\n this.board[coord[1]][coord[0]].pair.pair = null;\n }\n this.board[coord[1]][coord[0]] = undefined;\n this.changed = true;\n });\n this.audio.eatBlocks();\n }\n tempCol = [];\n currentColor = null;\n }\n }\n }\n }\n\n\n\n}\n\nGame.DIM_X = 288;\nGame.DIM_Y = 576;\nGame.MOVES = {\n left: \"left\",\n right: \"right\",\n down: \"down\",\n z: \"z\",\n x: \"x\",\n};\n\n\nexport default Game;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/game.js\n// module id = 2\n// module chunks = 0","import Audio from './audio';\n\nclass Pill {\n constructor(ctx, board) {\n this.ctx = ctx;\n this.board = board;\n this.board1 = [0, 3];\n this.board2 = [0, 4];\n this.active = true;\n this.horizontal = true;\n this.audio = new Audio;\n\n this.pill1 = new PillBlock(ctx, board, [0, 3], [\"yellow\", \"blue\", \"red\"][Math.floor(Math.random() * 3)], \"left\");\n this.pill2 = new PillBlock(ctx, board, [0, 4], [\"yellow\", \"blue\", \"red\"][Math.floor(Math.random() * 3)], \"right\");\n this.pill1.pair = this.pill2;\n this.pill2.pair = this.pill1;\n }\n\n drop() {\n if (\n this.board1[0] < 15 &&\n this.board2[0] < 15 &&\n (this.board[this.board1[0] + 1][this.board1[1]] === undefined || this.board1[0] + 1 === this.board2[0] ) &&\n (this.board[this.board2[0] + 1][this.board2[1]] === undefined || this.board2[0] + 1=== this.board1[0] )\n ) {\n\n this.board[this.board1[0]][this.board1[1]] = undefined;\n this.board[this.board2[0]][this.board2[1]] = undefined;\n\n this.board1[0] = this.board1[0] + 1;\n this.board2[0] = this.board2[0] + 1;\n\n this.board[this.board1[0]][this.board1[1]] = this.pill1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n\n this.pill1.coords = [this.board1[0], this.board1[1]];\n this.pill2.coords = [this.board2[0], this.board2[1]];\n } else {\n this.active = false;\n }\n }\n\n move(k) {\n if (this.active) {\n if (k === \"down\") {\n this.drop();\n this.audio.movePill();\n }\n if (k === \"right\") {\n if (\n this.board1[1] < 7 &&\n this.board2[1] < 7 &&\n (this.board[this.board1[0]][this.board1[1] + 1] === undefined || this.board1[1] + 1 == this.board2[1]) &&\n (this.board[this.board2[0]][this.board2[1] + 1] === undefined || this.board2[1] + 1 == this.board1[1])\n ) {\n this.board[this.board1[0]][this.board1[1]] = undefined;\n this.board[this.board2[0]][this.board2[1]] = undefined;\n\n this.board1[1] = this.board1[1] + 1;\n this.board2[1] = this.board2[1] + 1;\n\n this.board[this.board1[0]][this.board1[1]] = this.pill1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n\n this.pill1.coords = [this.board1[0], this.board1[1]];\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n this.audio.movePill();\n }\n }\n if (k === \"left\") {\n if (\n this.board1[1] > 0 &&\n this.board2[1] > 0 &&\n (this.board[this.board1[0]][this.board1[1] - 1] === undefined || this.board1[1] - 1 == this.board2[1]) &&\n (this.board[this.board2[0]][this.board2[1] - 1] === undefined || this.board2[1] - 1 == this.board1[1])\n ) {\n\n this.board[this.board1[0]][this.board1[1]] = undefined;\n this.board[this.board2[0]][this.board2[1]] = undefined;\n\n this.board1[1] = this.board1[1] - 1;\n this.board2[1] = this.board2[1] - 1;\n\n this.board[this.board1[0]][this.board1[1]] = this.pill1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n\n this.pill1.coords = [this.board1[0], this.board1[1]];\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n this.audio.movePill();\n }\n }\n if (k === \"z\") {\n if (this.horizontal) {\n if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {\n\n this.board[this.board2[0]][this.board2[1]] = undefined;\n this.board2[0] = this.board2[0] - 1;\n this.board2[1] = this.board2[1] - 1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n this.pill1.side = \"bottom\";\n this.pill2.side = \"top\";\n\n this.horizontal = false;\n\n this.audio.rotatePill();\n }\n } else {\n if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {\n this.board[this.board2[0]][this.board2[1]] = undefined;\n this.board2[0] = this.board2[0] + 1;\n this.board2[1] = this.board2[1] + 1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n const tempColor = this.pill1.color;\n this.pill1.color = this.pill2.color;\n this.pill2.color = tempColor;\n\n this.pill1.side = \"left\";\n this.pill2.side = \"right\";\n\n this.horizontal = true;\n\n this.audio.rotatePill();\n }\n }\n }\n if (k === \"x\") {\n if (this.horizontal) {\n if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {\n this.board[this.board2[0]][this.board2[1]] = undefined;\n this.board2[0] = this.board2[0] - 1;\n this.board2[1] = this.board2[1] - 1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n const tempColor = this.pill1.color;\n this.pill1.color = this.pill2.color;\n this.pill2.color = tempColor;\n\n this.pill1.side = \"bottom\";\n this.pill2.side = \"top\";\n\n this.horizontal = false;\n\n this.audio.rotatePill();\n }\n } else {\n if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {\n this.board[this.board2[0]][this.board2[1]] = undefined;\n this.board2[0] = this.board2[0] + 1;\n this.board2[1] = this.board2[1] + 1;\n this.board[this.board2[0]][this.board2[1]] = this.pill2;\n this.pill2.coords = [this.board2[0], this.board2[1]];\n\n this.pill1.side = \"left\";\n this.pill2.side = \"right\";\n\n this.horizontal = true;\n\n this.audio.rotatePill();\n }\n }\n }\n }\n\n }\n}\n\nclass PillBlock {\n constructor(ctx, board, coords, color, side){\n this.ctx = ctx;\n this.board = board;\n this.coords = coords;\n this.color = color;\n this.type = \"pill\";\n this.pair = null;\n this.side = side;\n }\n\n draw() {\n let img = new Image();\n let x = (this.coords[1] * 36);\n let y = (this.coords[0] * 36);\n let w = 32;\n let h = 32;\n let degrees = -90;\n if (this.pair === null) {\n img.src = `images/pill${this.color}.png`;\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n img.onload = () => {\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n };\n } else if (this.side === \"left\") {\n img.src = `images/pill${this.color}left.png`;\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n img.onload = () => {\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n };\n } else if (this.side === \"right\"){\n img.src = `images/pill${this.color}right.png`;\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n img.onload = () => {\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n };\n } else if (this.side === \"top\"){\n img.src = `images/pill${this.color}right.png`;\n\n this.ctx.save();\n this.ctx.translate(x+w/2, y+h/2);\n this.ctx.rotate(degrees*Math.PI/180.0);\n this.ctx.translate(-x-w/2, -y-h/2);\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n this.ctx.restore();\n img.onload = () => {\n this.ctx.save();\n this.ctx.translate(x+w/2, y+h/2);\n this.ctx.rotate(degrees*Math.PI/180.0);\n this.ctx.translate(-x-w/2, -y-h/2);\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n this.ctx.restore();\n };\n } else if (this.side === \"bottom\"){\n img.src = `images/pill${this.color}left.png`;\n\n this.ctx.save();\n this.ctx.translate(x+w/2, y+h/2);\n this.ctx.rotate(degrees*Math.PI/180.0);\n this.ctx.translate(-x-w/2, -y-h/2);\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n this.ctx.restore();\n img.onload = () => {\n this.ctx.save();\n this.ctx.translate(x+w/2, y+h/2);\n this.ctx.rotate(degrees*Math.PI/180.0);\n this.ctx.translate(-x-w/2, -y-h/2);\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);\n this.ctx.restore();\n };\n }\n }\n\n drop() {\n if (\n this.coords[0] < 15 &&\n this.board[this.coords[0] + 1][this.coords[1]] === undefined\n ) {\n this.board[this.coords[0]][this.coords[1]] = undefined;\n this.coords[0] = this.coords[0] + 1;\n this.board[this.coords[0]][this.coords[1]] = this;\n }\n }\n}\n\n\nexport default Pill;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/pill.js\n// module id = 3\n// module chunks = 0","class Virus {\n constructor(ctx, board, coords, color){\n this.ctx = ctx;\n this.board = board;\n this.coords = coords;\n this.color = color;\n this.type = \"virus\";\n this.pair = null;\n }\n\n draw() {\n this.board[this.coords[0]][this.coords[1]] = this;\n\n let img = new Image();\n img.src = `images/virus${this.color}.png`;\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);\n img.onload = () => {\n this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);\n };\n }\n}\n\nexport default Virus;\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./lib/virus.js\n// module id = 4\n// module chunks = 0"],"sourceRoot":""}
--------------------------------------------------------------------------------
/lib/drmariojs.js:
--------------------------------------------------------------------------------
1 | import Game from './game';
2 |
3 | document.addEventListener("DOMContentLoaded", () => {
4 | const canvasEl = document.getElementsByTagName("canvas")[0];
5 | canvasEl.width = Game.DIM_X;
6 | canvasEl.height = Game.DIM_Y;
7 | const ctx = canvasEl.getContext("2d");
8 |
9 | let game = new Game(ctx);
10 | game.start();
11 | });
12 |
--------------------------------------------------------------------------------
/lib/game.js:
--------------------------------------------------------------------------------
1 | import Pill from './pill';
2 | import Virus from './virus';
3 | import Audio from './audio';
4 |
5 | class Game {
6 | constructor(ctx) {
7 | this.ctx = ctx;
8 | this.level = 1;
9 | this.speed = 1000;
10 | this.score = 0;
11 | this.newGame = true;
12 | this.gameOver = false;
13 | this.paused = false;
14 | this.checking = false;
15 | this.changed = false;
16 | this.currentPill = null;
17 | this.virusCount = 0;
18 | this.board = this.newBoard(ctx);
19 | this.audio = new Audio;
20 | }
21 |
22 | newBoard(ctx) {
23 | const board = new Array(16);
24 | for (let i = 0; i < board.length; i++) {
25 | board[i] = new Array(8);
26 | }
27 | this.randomizeViruses(ctx, board);
28 | return board;
29 | }
30 |
31 | randomizeViruses(ctx, board) {
32 | for (let i = 0; i < this.level * 10; i++) {
33 | let randomX = Math.floor(Math.random() * 8);
34 | let randomY = Math.floor(Math.random() * 12) + 4;
35 | while (board[randomY][randomX] !== undefined) {
36 | randomX = Math.floor(Math.random() * 8);
37 | randomY = Math.floor(Math.random() * 12) + 4;
38 | }
39 | const virusColor = ["yellow", "blue", "red"][Math.floor(Math.random() * 3)];
40 | const virus = new Virus(ctx, board, [randomY, randomX], virusColor);
41 | board[randomY][randomX] = virus;
42 | }
43 | }
44 |
45 | newPill(ctx, board) {
46 | if (this.board[0][3] !== undefined || this.board[0][4] !== undefined) {
47 | this.gameOver = true;
48 | }
49 | const pill = new Pill(ctx, board);
50 | this.currentPill = pill;
51 | board[0][3] = pill.pill1;
52 | board[0][4] = pill.pill2;
53 | }
54 |
55 | allObjects() {
56 | return [].concat.apply([], this.board);
57 | }
58 |
59 | draw(ctx) {
60 | if (!this.paused && !this.gameOver) {
61 | ctx.clearRect(0, 0, Game.DIM_X, Game.DIM_Y);
62 | this.allObjects().forEach((object) => {
63 | if (object !== undefined) {
64 | object.draw();
65 | }
66 | });
67 | document.getElementById("virus").innerHTML = `Viruses Left: ${this.virusCount}`;
68 | document.getElementById("score").innerHTML = `Score: ${this.score}`;
69 | document.getElementById("level").innerHTML = `Level: ${this.level}`;
70 | }
71 | }
72 |
73 | bindKeyHandlers() {
74 | Object.keys(Game.MOVES).forEach((k) => {
75 | const move = Game.MOVES[k];
76 | key(k, () => {
77 | this.currentPill.move(k);
78 | if (!this.currentPill.active) {
79 | this.checkBoard();
80 | }
81 | this.draw(this.ctx);
82 | });
83 | });
84 | key("space", () => { this.space(); });
85 | }
86 |
87 | space() {
88 | if (this.newGame) {
89 | this.newGame = false;
90 | this.checkBoard();
91 | this.audio.startGame();
92 | requestAnimationFrame(this.animate.bind(this));
93 | } else if (!this.gameOver) {
94 | this.paused = !this.paused;
95 | this.currentPill.active = !this.currentPill.active;
96 | if (this.paused) {
97 | this.audio.pausebgm();
98 | } else {
99 | this.audio.playbgm();
100 | }
101 | this.ctx.font = "60px Arial";
102 | this.ctx.fillStyle = "red";
103 | this.ctx.fillText("PAUSED",25,300);
104 | this.ctx.strokeStyle = "white";
105 | this.ctx.lineWidth = 2;
106 | this.ctx.strokeText("PAUSED",25,300);
107 | this.draw(this.ctx);
108 | } else {
109 | this.level = 1;
110 | this.speed = 1000;
111 | this.score = 0;
112 | this.gameOver = false;
113 | this.board = this.newBoard(this.ctx);
114 | this.checkBoard();
115 | this.audio.startGame();
116 | requestAnimationFrame(this.animate.bind(this));
117 | }
118 | }
119 |
120 | start() {
121 | this.bindKeyHandlers();
122 | requestAnimationFrame(this.animate.bind(this));
123 | this.checkBoard();
124 | }
125 |
126 | animate() {
127 | if (this.newGame) {
128 | document.getElementById("virus").innerHTML = `Viruses Left: ${this.virusCount}`;
129 | document.getElementById("score").innerHTML = `Score: ${this.score}`;
130 | document.getElementById("level").innerHTML = `Level: ${this.level}`;
131 | document.getElementById("mute").addEventListener("click", () => {
132 | this.audio.toggleMute();
133 | document.getElementById("mute").blur();
134 | });
135 | this.ctx.font = "50px Arial";
136 | this.ctx.fillStyle = "red";
137 | this.ctx.fillText("Dr Mario JS",15,250);
138 | this.ctx.strokeStyle = "white";
139 | this.ctx.lineWidth = 2;
140 | this.ctx.strokeText("Dr Mario JS",15,250);
141 | this.ctx.font = "25px Arial";
142 | this.ctx.fillStyle = "red";
143 | this.ctx.fillText("Hit Space to Start",45,300);
144 | this.ctx.strokeStyle = "white";
145 | this.ctx.lineWidth = 1;
146 | this.ctx.strokeText("Hit Space to Start",45,300);
147 | } else if (this.paused) {
148 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
149 | } else if (this.checking){
150 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
151 | } else if (this.virusCount === 0) {
152 | this.audio.levelClear();
153 | if (this.level < 10) {
154 | this.level += 1;
155 | this.speed -= 100;
156 | }
157 | this.board = this.newBoard(this.ctx);
158 | this.checkBoard();
159 | requestAnimationFrame(this.animate.bind(this));
160 | } else if (this.gameOver) {
161 | this.audio.bgmStop();
162 | this.audio.gameOver();
163 | this.ctx.font = "50px Arial";
164 | this.ctx.fillStyle = "red";
165 | this.ctx.fillText("Game Over",15,250);
166 | this.ctx.strokeStyle = "white";
167 | this.ctx.lineWidth = 2;
168 | this.ctx.strokeText("Game Over",15,250);
169 | this.ctx.font = "25px Arial";
170 | this.ctx.fillStyle = "red";
171 | this.ctx.fillText("Hit Space to Restart",30,300);
172 | this.ctx.strokeStyle = "white";
173 | this.ctx.lineWidth = 1;
174 | this.ctx.strokeText("Hit Space to Restart",30,300);
175 | } else {
176 | if (!this.currentPill || !this.currentPill.active) {
177 | this.newPill(this.ctx, this.board);
178 | } else {
179 | this.currentPill.drop();
180 | if (!this.currentPill.active) {
181 | this.checkBoard();
182 | }
183 | }
184 |
185 | this.draw(this.ctx);
186 |
187 | setTimeout(() => {requestAnimationFrame(this.animate.bind(this));}, this.speed);
188 | }
189 | }
190 |
191 | checkBoard() {
192 | this.checking = true;
193 | this.checkCols();
194 | this.checkRows();
195 | if (this.changed) {
196 | this.changed = false;
197 | this.dropPills();
198 | setTimeout(() => {this.checkBoard();}, 500);
199 | } else {
200 | this.checking = false;
201 | }
202 | }
203 |
204 | dropPills() {
205 | const transposedBoard = [];
206 | for (var i = 0; i < 8; i++) {
207 | const newRow = [];
208 | for (var j = 15; j >= 0; j--) {
209 | newRow.push(this.board[j][i]);
210 | }
211 | transposedBoard.push(newRow);
212 | }
213 |
214 | for (i = 0; i < transposedBoard.length; i++) {
215 | for (j = 1; j < transposedBoard[i].length; j++) {
216 | if (transposedBoard[i][j] !== undefined &&
217 | transposedBoard[i][j].type === "pill" &&
218 | transposedBoard[i][j -1 ] === undefined) {
219 | if (transposedBoard[i][j].pair === null) {
220 | transposedBoard[i][j].drop();
221 | transposedBoard[i][j] = undefined;
222 | this.draw(this.ctx);
223 | this.changed = true;
224 | } else if (transposedBoard[i][j].coords[1] === transposedBoard[i][j].pair.coords[1] ||
225 | transposedBoard[i][j].coords[0] !== transposedBoard[i][j].pair.coords[0] ||
226 | this.board[transposedBoard[i][j].pair.coords[0] + 1][transposedBoard[i][j].pair.coords[1]] === undefined) {
227 | transposedBoard[i][j].drop();
228 | transposedBoard[i][j] = undefined;
229 | this.draw(this.ctx);
230 | this.changed = true;
231 | }
232 | }
233 | }
234 | }
235 | }
236 |
237 | checkRows() {
238 | let viruses = [];
239 | let tempRow;
240 | let currentColor;
241 | for (var i = 0; i < this.board.length; i++) {
242 | tempRow = [];
243 | currentColor = null;
244 | for (var j = 0; j < this.board[i].length; j++) {
245 | if (this.board[i][j] !== undefined) {
246 | if (this.board[i][j].type === "virus") {
247 | viruses.push([i, j]);
248 | }
249 | if (currentColor === null) {
250 | currentColor = this.board[i][j].color;
251 | }
252 | if (this.board[i][j].color === currentColor) {
253 | tempRow.push([i, j]);
254 | }
255 | if (this.board[i][j].color !== currentColor || j === 7) {
256 | currentColor = this.board[i][j].color;
257 | if (tempRow.length > 3) {
258 | tempRow.forEach((coord) => {
259 | if (this.board[coord[0]][coord[1]].type === "virus") {
260 | this.score += 100;
261 | }
262 | if (this.board[coord[0]][coord[1]].pair) {
263 | this.board[coord[0]][coord[1]].pair.pair = null;
264 | }
265 | this.board[coord[0]][coord[1]] = undefined;
266 | this.changed = true;
267 | });
268 | this.audio.eatBlocks();
269 | }
270 | tempRow = [];
271 | tempRow.push([i, j]);
272 | }
273 | } else {
274 | if (tempRow.length > 3) {
275 | tempRow.forEach((coord) => {
276 | if (this.board[coord[0]][coord[1]].type === "virus") {
277 | this.score += 100;
278 | }
279 | if (this.board[coord[0]][coord[1]].pair) {
280 | this.board[coord[0]][coord[1]].pair.pair = null;
281 | }
282 | this.board[coord[0]][coord[1]] = undefined;
283 | this.changed = true;
284 | });
285 | this.audio.eatBlocks();
286 | }
287 | tempRow = [];
288 | currentColor = null;
289 | }
290 | }
291 | }
292 | this.virusCount = viruses.length;
293 | }
294 |
295 | checkCols() {
296 | const transposedBoard = [];
297 | for (var i = 0; i < 8; i++) {
298 | const newRow = [];
299 | for (var j = 0; j < this.board.length; j++) {
300 | newRow.push(this.board[j][i]);
301 | }
302 | transposedBoard.push(newRow);
303 | }
304 | let tempCol = [];
305 | let currentColor = null;
306 | for (i = 0; i < transposedBoard.length; i++) {
307 | tempCol = [];
308 | currentColor = null;
309 | for (j = 0; j < transposedBoard[i].length; j++) {
310 | if (transposedBoard[i][j] !== undefined) {
311 | if (currentColor === null) {
312 | currentColor = transposedBoard[i][j].color;
313 | }
314 | if (transposedBoard[i][j].color === currentColor) {
315 | tempCol.push([i, j]);
316 | }
317 | if (transposedBoard[i][j].color !== currentColor || j === 15) {
318 | currentColor = transposedBoard[i][j].color;
319 | if (tempCol.length > 3) {
320 | tempCol.forEach((coord) => {
321 | if (this.board[coord[1]][coord[0]].type === "virus") {
322 | this.score += 100;
323 | }
324 | if (this.board[coord[1]][coord[0]].pair) {
325 | this.board[coord[1]][coord[0]].pair.pair = null;
326 | }
327 | this.board[coord[1]][coord[0]] = undefined;
328 | this.changed = true;
329 | });
330 | this.audio.eatBlocks();
331 | }
332 | tempCol = [];
333 | tempCol.push([i, j]);
334 | }
335 | } else {
336 | if (tempCol.length > 3) {
337 | tempCol.forEach((coord) => {
338 | if (this.board[coord[1]][coord[0]].type === "virus") {
339 | this.score += 100;
340 | }
341 | if (this.board[coord[1]][coord[0]].pair) {
342 | this.board[coord[1]][coord[0]].pair.pair = null;
343 | }
344 | this.board[coord[1]][coord[0]] = undefined;
345 | this.changed = true;
346 | });
347 | this.audio.eatBlocks();
348 | }
349 | tempCol = [];
350 | currentColor = null;
351 | }
352 | }
353 | }
354 | }
355 |
356 |
357 |
358 | }
359 |
360 | Game.DIM_X = 288;
361 | Game.DIM_Y = 576;
362 | Game.MOVES = {
363 | left: "left",
364 | right: "right",
365 | down: "down",
366 | z: "z",
367 | x: "x",
368 | };
369 |
370 |
371 | export default Game;
372 |
--------------------------------------------------------------------------------
/lib/keymaster.js:
--------------------------------------------------------------------------------
1 | // keymaster.js
2 | // (c) 2011-2012 Thomas Fuchs
3 | // keymaster.js may be freely distributed under the MIT license.
4 |
5 | ;(function(global){
6 | var k,
7 | _handlers = {},
8 | _mods = { 16: false, 18: false, 17: false, 91: false },
9 | _scope = 'all',
10 | // modifier keys
11 | _MODIFIERS = {
12 | '⇧': 16, shift: 16,
13 | '⌥': 18, alt: 18, option: 18,
14 | '⌃': 17, ctrl: 17, control: 17,
15 | '⌘': 91, command: 91
16 | },
17 | // special keys
18 | _MAP = {
19 | backspace: 8, tab: 9, clear: 12,
20 | enter: 13, 'return': 13,
21 | esc: 27, escape: 27, space: 32,
22 | left: 37, up: 38,
23 | right: 39, down: 40,
24 | del: 46, 'delete': 46,
25 | home: 36, end: 35,
26 | pageup: 33, pagedown: 34,
27 | ',': 188, '.': 190, '/': 191,
28 | '`': 192, '-': 189, '=': 187,
29 | ';': 186, '\'': 222,
30 | '[': 219, ']': 221, '\\': 220
31 | },
32 | code = function(x){
33 | return _MAP[x] || x.toUpperCase().charCodeAt(0);
34 | },
35 | _downKeys = [];
36 |
37 | for(k=1;k<20;k++) _MODIFIERS['f'+k] = 111+k;
38 |
39 | // IE doesn't support Array#indexOf, so have a simple replacement
40 | function index(array, item){
41 | var i = array.length;
42 | while(i--) if(array[i]===item) return i;
43 | return -1;
44 | }
45 |
46 | var modifierMap = {
47 | 16:'shiftKey',
48 | 18:'altKey',
49 | 17:'ctrlKey',
50 | 91:'metaKey'
51 | };
52 | function updateModifierKey(event) {
53 | for(k in _mods) _mods[k] = event[modifierMap[k]];
54 | };
55 |
56 | // handle keydown event
57 | function dispatch(event, scope){
58 | var key, handler, k, i, modifiersMatch;
59 | key = event.keyCode;
60 |
61 | if (index(_downKeys, key) == -1) {
62 | _downKeys.push(key);
63 | }
64 |
65 | // if a modifier key, set the key. property to true and return
66 | if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko
67 | if(key in _mods) {
68 | _mods[key] = true;
69 | // 'assignKey' from inside this closure is exported to window.key
70 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true;
71 | return;
72 | }
73 | updateModifierKey(event);
74 |
75 | // see if we need to ignore the keypress (filter() can can be overridden)
76 | // by default ignore key presses if a select, textarea, or input is focused
77 | if(!assignKey.filter.call(this, event)) return;
78 |
79 | // abort if no potentially matching shortcuts found
80 | if (!(key in _handlers)) return;
81 |
82 | // for each potential shortcut
83 | for (i = 0; i < _handlers[key].length; i++) {
84 | handler = _handlers[key][i];
85 |
86 | // see if it's in the current scope
87 | if(handler.scope == scope || handler.scope == 'all'){
88 | // check if modifiers match if any
89 | modifiersMatch = handler.mods.length > 0;
90 | for(k in _mods)
91 | if((!_mods[k] && index(handler.mods, +k) > -1) ||
92 | (_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false;
93 | // call the handler and stop the event if neccessary
94 | if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){
95 | if(handler.method(event, handler)===false){
96 | if(event.preventDefault) event.preventDefault();
97 | else event.returnValue = false;
98 | if(event.stopPropagation) event.stopPropagation();
99 | if(event.cancelBubble) event.cancelBubble = true;
100 | }
101 | }
102 | }
103 | }
104 | };
105 |
106 | // unset modifier keys on keyup
107 | function clearModifier(event){
108 | var key = event.keyCode, k,
109 | i = index(_downKeys, key);
110 |
111 | // remove key from _downKeys
112 | if (i >= 0) {
113 | _downKeys.splice(i, 1);
114 | }
115 |
116 | if(key == 93 || key == 224) key = 91;
117 | if(key in _mods) {
118 | _mods[key] = false;
119 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false;
120 | }
121 | };
122 |
123 | function resetModifiers() {
124 | for(k in _mods) _mods[k] = false;
125 | for(k in _MODIFIERS) assignKey[k] = false;
126 | }
127 |
128 | // parse and assign shortcut
129 | function assignKey(key, scope, method){
130 | var keys, mods, i, mi;
131 | if (method === undefined) {
132 | method = scope;
133 | scope = 'all';
134 | }
135 | key = key.replace(/\s/g,'');
136 | keys = key.split(',');
137 |
138 | if((keys[keys.length-1])=='')
139 | keys[keys.length-2] += ',';
140 | // for each shortcut
141 | for (i = 0; i < keys.length; i++) {
142 | // set modifier keys if any
143 | mods = [];
144 | key = keys[i].split('+');
145 | if(key.length > 1){
146 | mods = key.slice(0,key.length-1);
147 | for (mi = 0; mi < mods.length; mi++)
148 | mods[mi] = _MODIFIERS[mods[mi]];
149 | key = [key[key.length-1]];
150 | }
151 | // convert to keycode and...
152 | key = key[0]
153 | key = code(key);
154 | // ...store handler
155 | if (!(key in _handlers)) _handlers[key] = [];
156 | _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods });
157 | }
158 | };
159 |
160 | // Returns true if the key with code 'keyCode' is currently down
161 | // Converts strings into key codes.
162 | function isPressed(keyCode) {
163 | if (typeof(keyCode)=='string') {
164 | keyCode = code(keyCode);
165 | }
166 | return index(_downKeys, keyCode) != -1;
167 | }
168 |
169 | function getPressedKeyCodes() {
170 | return _downKeys.slice(0);
171 | }
172 |
173 | function filter(event){
174 | var tagName = (event.target || event.srcElement).tagName;
175 | // ignore keypressed in any elements that support keyboard data input
176 | return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA');
177 | }
178 |
179 | // initialize key. to false
180 | for(k in _MODIFIERS) assignKey[k] = false;
181 |
182 | // set current scope (default 'all')
183 | function setScope(scope){ _scope = scope || 'all' };
184 | function getScope(){ return _scope || 'all' };
185 |
186 | // delete all handlers for a given scope
187 | function deleteScope(scope){
188 | var key, handlers, i;
189 |
190 | for (key in _handlers) {
191 | handlers = _handlers[key];
192 | for (i = 0; i < handlers.length; ) {
193 | if (handlers[i].scope === scope) handlers.splice(i, 1);
194 | else i++;
195 | }
196 | }
197 | };
198 |
199 | // cross-browser events
200 | function addEvent(object, event, method) {
201 | if (object.addEventListener)
202 | object.addEventListener(event, method, false);
203 | else if(object.attachEvent)
204 | object.attachEvent('on'+event, function(){ method(window.event) });
205 | };
206 |
207 | // set the handlers globally on document
208 | addEvent(document, 'keydown', function(event) { dispatch(event, _scope) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48
209 | addEvent(document, 'keyup', clearModifier);
210 |
211 | // reset modifiers to false whenever the window is (re)focused.
212 | addEvent(window, 'focus', resetModifiers);
213 |
214 | // store previously defined key
215 | var previousKey = global.key;
216 |
217 | // restore previously defined key and return reference to our key object
218 | function noConflict() {
219 | var k = global.key;
220 | global.key = previousKey;
221 | return k;
222 | }
223 |
224 | // set window.key and window.key.set/get/deleteScope, and the default filter
225 | global.key = assignKey;
226 | global.key.setScope = setScope;
227 | global.key.getScope = getScope;
228 | global.key.deleteScope = deleteScope;
229 | global.key.filter = filter;
230 | global.key.isPressed = isPressed;
231 | global.key.getPressedKeyCodes = getPressedKeyCodes;
232 | global.key.noConflict = noConflict;
233 |
234 | if(typeof module !== 'undefined') module.exports = key;
235 |
236 | })(this);
237 |
--------------------------------------------------------------------------------
/lib/pill.js:
--------------------------------------------------------------------------------
1 | import Audio from './audio';
2 |
3 | class Pill {
4 | constructor(ctx, board) {
5 | this.ctx = ctx;
6 | this.board = board;
7 | this.board1 = [0, 3];
8 | this.board2 = [0, 4];
9 | this.active = true;
10 | this.horizontal = true;
11 | this.audio = new Audio;
12 |
13 | this.pill1 = new PillBlock(ctx, board, [0, 3], ["yellow", "blue", "red"][Math.floor(Math.random() * 3)], "left");
14 | this.pill2 = new PillBlock(ctx, board, [0, 4], ["yellow", "blue", "red"][Math.floor(Math.random() * 3)], "right");
15 | this.pill1.pair = this.pill2;
16 | this.pill2.pair = this.pill1;
17 | }
18 |
19 | drop() {
20 | if (
21 | this.board1[0] < 15 &&
22 | this.board2[0] < 15 &&
23 | (this.board[this.board1[0] + 1][this.board1[1]] === undefined || this.board1[0] + 1 === this.board2[0] ) &&
24 | (this.board[this.board2[0] + 1][this.board2[1]] === undefined || this.board2[0] + 1=== this.board1[0] )
25 | ) {
26 |
27 | this.board[this.board1[0]][this.board1[1]] = undefined;
28 | this.board[this.board2[0]][this.board2[1]] = undefined;
29 |
30 | this.board1[0] = this.board1[0] + 1;
31 | this.board2[0] = this.board2[0] + 1;
32 |
33 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
34 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
35 |
36 | this.pill1.coords = [this.board1[0], this.board1[1]];
37 | this.pill2.coords = [this.board2[0], this.board2[1]];
38 | } else {
39 | this.active = false;
40 | }
41 | }
42 |
43 | move(k) {
44 | if (this.active) {
45 | if (k === "down") {
46 | this.drop();
47 | this.audio.movePill();
48 | }
49 | if (k === "right") {
50 | if (
51 | this.board1[1] < 7 &&
52 | this.board2[1] < 7 &&
53 | (this.board[this.board1[0]][this.board1[1] + 1] === undefined || this.board1[1] + 1 == this.board2[1]) &&
54 | (this.board[this.board2[0]][this.board2[1] + 1] === undefined || this.board2[1] + 1 == this.board1[1])
55 | ) {
56 | this.board[this.board1[0]][this.board1[1]] = undefined;
57 | this.board[this.board2[0]][this.board2[1]] = undefined;
58 |
59 | this.board1[1] = this.board1[1] + 1;
60 | this.board2[1] = this.board2[1] + 1;
61 |
62 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
63 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
64 |
65 | this.pill1.coords = [this.board1[0], this.board1[1]];
66 | this.pill2.coords = [this.board2[0], this.board2[1]];
67 |
68 | this.audio.movePill();
69 | }
70 | }
71 | if (k === "left") {
72 | if (
73 | this.board1[1] > 0 &&
74 | this.board2[1] > 0 &&
75 | (this.board[this.board1[0]][this.board1[1] - 1] === undefined || this.board1[1] - 1 == this.board2[1]) &&
76 | (this.board[this.board2[0]][this.board2[1] - 1] === undefined || this.board2[1] - 1 == this.board1[1])
77 | ) {
78 |
79 | this.board[this.board1[0]][this.board1[1]] = undefined;
80 | this.board[this.board2[0]][this.board2[1]] = undefined;
81 |
82 | this.board1[1] = this.board1[1] - 1;
83 | this.board2[1] = this.board2[1] - 1;
84 |
85 | this.board[this.board1[0]][this.board1[1]] = this.pill1;
86 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
87 |
88 | this.pill1.coords = [this.board1[0], this.board1[1]];
89 | this.pill2.coords = [this.board2[0], this.board2[1]];
90 |
91 | this.audio.movePill();
92 | }
93 | }
94 | if (k === "z") {
95 | if (this.horizontal) {
96 | if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {
97 |
98 | this.board[this.board2[0]][this.board2[1]] = undefined;
99 | this.board2[0] = this.board2[0] - 1;
100 | this.board2[1] = this.board2[1] - 1;
101 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
102 | this.pill2.coords = [this.board2[0], this.board2[1]];
103 |
104 | this.pill1.side = "bottom";
105 | this.pill2.side = "top";
106 |
107 | this.horizontal = false;
108 |
109 | this.audio.rotatePill();
110 | }
111 | } else {
112 | if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {
113 | this.board[this.board2[0]][this.board2[1]] = undefined;
114 | this.board2[0] = this.board2[0] + 1;
115 | this.board2[1] = this.board2[1] + 1;
116 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
117 | this.pill2.coords = [this.board2[0], this.board2[1]];
118 |
119 | const tempColor = this.pill1.color;
120 | this.pill1.color = this.pill2.color;
121 | this.pill2.color = tempColor;
122 |
123 | this.pill1.side = "left";
124 | this.pill2.side = "right";
125 |
126 | this.horizontal = true;
127 |
128 | this.audio.rotatePill();
129 | }
130 | }
131 | }
132 | if (k === "x") {
133 | if (this.horizontal) {
134 | if (this.board2[0] > 0 && this.board[this.board1[0] - 1][this.board1[1]] === undefined) {
135 | this.board[this.board2[0]][this.board2[1]] = undefined;
136 | this.board2[0] = this.board2[0] - 1;
137 | this.board2[1] = this.board2[1] - 1;
138 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
139 | this.pill2.coords = [this.board2[0], this.board2[1]];
140 |
141 | const tempColor = this.pill1.color;
142 | this.pill1.color = this.pill2.color;
143 | this.pill2.color = tempColor;
144 |
145 | this.pill1.side = "bottom";
146 | this.pill2.side = "top";
147 |
148 | this.horizontal = false;
149 |
150 | this.audio.rotatePill();
151 | }
152 | } else {
153 | if (this.board[this.board1[0]][this.board1[1] + 1] === undefined && this.board1[1] < 7) {
154 | this.board[this.board2[0]][this.board2[1]] = undefined;
155 | this.board2[0] = this.board2[0] + 1;
156 | this.board2[1] = this.board2[1] + 1;
157 | this.board[this.board2[0]][this.board2[1]] = this.pill2;
158 | this.pill2.coords = [this.board2[0], this.board2[1]];
159 |
160 | this.pill1.side = "left";
161 | this.pill2.side = "right";
162 |
163 | this.horizontal = true;
164 |
165 | this.audio.rotatePill();
166 | }
167 | }
168 | }
169 | }
170 |
171 | }
172 | }
173 |
174 | class PillBlock {
175 | constructor(ctx, board, coords, color, side){
176 | this.ctx = ctx;
177 | this.board = board;
178 | this.coords = coords;
179 | this.color = color;
180 | this.type = "pill";
181 | this.pair = null;
182 | this.side = side;
183 | }
184 |
185 | draw() {
186 | let img = new Image();
187 | let x = (this.coords[1] * 36);
188 | let y = (this.coords[0] * 36);
189 | let w = 32;
190 | let h = 32;
191 | let degrees = -90;
192 | if (this.pair === null) {
193 | img.src = `images/pill${this.color}.png`;
194 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
195 | img.onload = () => {
196 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
197 | };
198 | } else if (this.side === "left") {
199 | img.src = `images/pill${this.color}left.png`;
200 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
201 | img.onload = () => {
202 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
203 | };
204 | } else if (this.side === "right"){
205 | img.src = `images/pill${this.color}right.png`;
206 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
207 | img.onload = () => {
208 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
209 | };
210 | } else if (this.side === "top"){
211 | img.src = `images/pill${this.color}right.png`;
212 |
213 | this.ctx.save();
214 | this.ctx.translate(x+w/2, y+h/2);
215 | this.ctx.rotate(degrees*Math.PI/180.0);
216 | this.ctx.translate(-x-w/2, -y-h/2);
217 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
218 | this.ctx.restore();
219 | img.onload = () => {
220 | this.ctx.save();
221 | this.ctx.translate(x+w/2, y+h/2);
222 | this.ctx.rotate(degrees*Math.PI/180.0);
223 | this.ctx.translate(-x-w/2, -y-h/2);
224 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
225 | this.ctx.restore();
226 | };
227 | } else if (this.side === "bottom"){
228 | img.src = `images/pill${this.color}left.png`;
229 |
230 | this.ctx.save();
231 | this.ctx.translate(x+w/2, y+h/2);
232 | this.ctx.rotate(degrees*Math.PI/180.0);
233 | this.ctx.translate(-x-w/2, -y-h/2);
234 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
235 | this.ctx.restore();
236 | img.onload = () => {
237 | this.ctx.save();
238 | this.ctx.translate(x+w/2, y+h/2);
239 | this.ctx.rotate(degrees*Math.PI/180.0);
240 | this.ctx.translate(-x-w/2, -y-h/2);
241 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 32, 32);
242 | this.ctx.restore();
243 | };
244 | }
245 | }
246 |
247 | drop() {
248 | if (
249 | this.coords[0] < 15 &&
250 | this.board[this.coords[0] + 1][this.coords[1]] === undefined
251 | ) {
252 | this.board[this.coords[0]][this.coords[1]] = undefined;
253 | this.coords[0] = this.coords[0] + 1;
254 | this.board[this.coords[0]][this.coords[1]] = this;
255 | }
256 | }
257 | }
258 |
259 |
260 | export default Pill;
261 |
--------------------------------------------------------------------------------
/lib/virus.js:
--------------------------------------------------------------------------------
1 | class Virus {
2 | constructor(ctx, board, coords, color){
3 | this.ctx = ctx;
4 | this.board = board;
5 | this.coords = coords;
6 | this.color = color;
7 | this.type = "virus";
8 | this.pair = null;
9 | }
10 |
11 | draw() {
12 | this.board[this.coords[0]][this.coords[1]] = this;
13 |
14 | let img = new Image();
15 | img.src = `images/virus${this.color}.png`;
16 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);
17 | img.onload = () => {
18 | this.ctx.drawImage(img, this.coords[1] * 36, this.coords[0] * 36, 36, 36);
19 | };
20 | }
21 | }
22 |
23 | export default Virus;
24 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "drmariojs",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "start": "webpack -w",
9 | "postinstall": "webpack"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/swangs/javascript_project.git"
14 | },
15 | "keywords": [],
16 | "author": "",
17 | "license": "ISC",
18 | "bugs": {
19 | "url": "https://github.com/swangs/javascript_project/issues"
20 | },
21 | "homepage": "https://github.com/swangs/javascript_project#readme",
22 | "dependencies": {
23 | "webpack": "^3.11.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/sounds/bgm.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/bgm.mp3
--------------------------------------------------------------------------------
/sounds/eatblocks.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/eatblocks.mp3
--------------------------------------------------------------------------------
/sounds/gameover.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/gameover.mp3
--------------------------------------------------------------------------------
/sounds/levelclear.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/levelclear.mp3
--------------------------------------------------------------------------------
/sounds/movepill.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/movepill.mp3
--------------------------------------------------------------------------------
/sounds/rotatepill.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swangs/drmariojs/5ba12ac05bbf8267360b7ca0a7497e350a84311a/sounds/rotatepill.mp3
--------------------------------------------------------------------------------
/stylesheets/css.css:
--------------------------------------------------------------------------------
1 | body{
2 | background-image: url("../images/virus.jpg");
3 | background-repeat: no-repeat;
4 | background-size: cover;
5 | font-family: 'Orbitron', sans-serif;
6 | color: #ffffff;
7 | display: flex;
8 | align-items: center;
9 | justify-content: space-around;
10 | }
11 |
12 | .gamecontainer {
13 | width: 80%;
14 | height: 80%;
15 | display: flex;
16 | align-items: center;
17 | justify-content: space-around;
18 |
19 | }
20 |
21 | canvas {
22 | background: #000000;
23 | background: linear-gradient(#252525, #252525);
24 | border: 2px solid #FFFFFF;
25 | border-radius: 20px;
26 | }
27 |
28 | h1 {
29 | text-align: center;
30 | }
31 |
32 | h2 {
33 | font-size: 20px;
34 | }
35 |
36 | p {
37 | font-size: 20px;
38 | font-weight: 700;
39 | margin-left: 0px;
40 | }
41 |
42 | .controls {
43 | min-width: 250px;
44 | max-width: 250px;
45 | /* height: 360px; */
46 | background: rgba(25, 25, 25, 0.9);
47 | border-radius: 20px;
48 | padding: 0px 20px;
49 | }
50 |
51 | .information {
52 | min-width: 250px;
53 | max-width: 250px;
54 | height: 150px;
55 | background: rgba(25, 25, 25, 0.9);
56 | border-radius: 20px;
57 | padding: 20px;
58 | display: flex;
59 | flex-direction: column;
60 | justify-content: space-around;
61 | }
62 |
63 | button {
64 | width: 30px;
65 | height: 30px;
66 | }
67 | button:hover{
68 | cursor: pointer;
69 | outline: none;
70 | }
71 |
72 | .swang-links {
73 | position: relative;
74 | /* top: 25px; */
75 | left: 150px;
76 | width: 100px;
77 | height: 50px;
78 | display: flex;
79 | justify-content: space-between;
80 | }
81 |
82 | a {
83 | color: #FFFFFF;
84 | }
85 | a:visited { text-decoration: none; color:#FFFFFF; }
86 | a:hover { text-decoration: none; color:#0074BB; }
87 | a:hover, a:active { text-decoration: none; color:#0074BB }
88 |
89 | #mute {
90 | border-radius: 5px;
91 | min-width: 20px;
92 | min-height: 20px;
93 | position: relative;
94 | bottom: 5px;
95 | }
96 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | entry: "./lib/drmariojs.js",
3 | output: {
4 | filename: "./lib/bundle.js"
5 | },
6 | devtool: 'source-map',
7 | };
8 |
--------------------------------------------------------------------------------