Browse Source

Audio using Howler library

Inderjit Gill 7 months ago
parent
commit
4115f625bf
13 changed files with 107 additions and 23 deletions
  1. 12
    21
      package-lock.json
  2. 3
    0
      package.json
  3. 33
    0
      src/game.rs
  4. 2
    2
      src/harbour.rs
  5. 5
    0
      src/lib.rs
  6. 43
    0
      web/js/Audio.js
  7. 9
    0
      web/js/index.js
  8. BIN
      web/sfx/fanfare1.mp3
  9. BIN
      web/sfx/fanfare2.mp3
  10. BIN
      web/sfx/fanfare3.mp3
  11. BIN
      web/sfx/negative1.mp3
  12. BIN
      web/sfx/pause2_in.mp3
  13. BIN
      web/sfx/pause2_out.mp3

+ 12
- 21
package-lock.json View File

@@ -1986,14 +1986,12 @@
1986 1986
         "balanced-match": {
1987 1987
           "version": "1.0.0",
1988 1988
           "bundled": true,
1989
-          "dev": true,
1990
-          "optional": true
1989
+          "dev": true
1991 1990
         },
1992 1991
         "brace-expansion": {
1993 1992
           "version": "1.1.11",
1994 1993
           "bundled": true,
1995 1994
           "dev": true,
1996
-          "optional": true,
1997 1995
           "requires": {
1998 1996
             "balanced-match": "^1.0.0",
1999 1997
             "concat-map": "0.0.1"
@@ -2008,20 +2006,17 @@
2008 2006
         "code-point-at": {
2009 2007
           "version": "1.1.0",
2010 2008
           "bundled": true,
2011
-          "dev": true,
2012
-          "optional": true
2009
+          "dev": true
2013 2010
         },
2014 2011
         "concat-map": {
2015 2012
           "version": "0.0.1",
2016 2013
           "bundled": true,
2017
-          "dev": true,
2018
-          "optional": true
2014
+          "dev": true
2019 2015
         },
2020 2016
         "console-control-strings": {
2021 2017
           "version": "1.1.0",
2022 2018
           "bundled": true,
2023
-          "dev": true,
2024
-          "optional": true
2019
+          "dev": true
2025 2020
         },
2026 2021
         "core-util-is": {
2027 2022
           "version": "1.0.2",
@@ -2138,8 +2133,7 @@
2138 2133
         "inherits": {
2139 2134
           "version": "2.0.3",
2140 2135
           "bundled": true,
2141
-          "dev": true,
2142
-          "optional": true
2136
+          "dev": true
2143 2137
         },
2144 2138
         "ini": {
2145 2139
           "version": "1.3.5",
@@ -2151,7 +2145,6 @@
2151 2145
           "version": "1.0.0",
2152 2146
           "bundled": true,
2153 2147
           "dev": true,
2154
-          "optional": true,
2155 2148
           "requires": {
2156 2149
             "number-is-nan": "^1.0.0"
2157 2150
           }
@@ -2166,7 +2159,6 @@
2166 2159
           "version": "3.0.4",
2167 2160
           "bundled": true,
2168 2161
           "dev": true,
2169
-          "optional": true,
2170 2162
           "requires": {
2171 2163
             "brace-expansion": "^1.1.7"
2172 2164
           }
@@ -2174,14 +2166,12 @@
2174 2166
         "minimist": {
2175 2167
           "version": "0.0.8",
2176 2168
           "bundled": true,
2177
-          "dev": true,
2178
-          "optional": true
2169
+          "dev": true
2179 2170
         },
2180 2171
         "minipass": {
2181 2172
           "version": "2.2.4",
2182 2173
           "bundled": true,
2183 2174
           "dev": true,
2184
-          "optional": true,
2185 2175
           "requires": {
2186 2176
             "safe-buffer": "^5.1.1",
2187 2177
             "yallist": "^3.0.0"
@@ -2200,7 +2190,6 @@
2200 2190
           "version": "0.5.1",
2201 2191
           "bundled": true,
2202 2192
           "dev": true,
2203
-          "optional": true,
2204 2193
           "requires": {
2205 2194
             "minimist": "0.0.8"
2206 2195
           }
@@ -2281,8 +2270,7 @@
2281 2270
         "number-is-nan": {
2282 2271
           "version": "1.0.1",
2283 2272
           "bundled": true,
2284
-          "dev": true,
2285
-          "optional": true
2273
+          "dev": true
2286 2274
         },
2287 2275
         "object-assign": {
2288 2276
           "version": "4.1.1",
@@ -2294,7 +2282,6 @@
2294 2282
           "version": "1.4.0",
2295 2283
           "bundled": true,
2296 2284
           "dev": true,
2297
-          "optional": true,
2298 2285
           "requires": {
2299 2286
             "wrappy": "1"
2300 2287
           }
@@ -2416,7 +2403,6 @@
2416 2403
           "version": "1.0.2",
2417 2404
           "bundled": true,
2418 2405
           "dev": true,
2419
-          "optional": true,
2420 2406
           "requires": {
2421 2407
             "code-point-at": "^1.0.0",
2422 2408
             "is-fullwidth-code-point": "^1.0.0",
@@ -2682,6 +2668,11 @@
2682 2668
       "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==",
2683 2669
       "dev": true
2684 2670
     },
2671
+    "howler": {
2672
+      "version": "2.0.14",
2673
+      "resolved": "https://registry.npmjs.org/howler/-/howler-2.0.14.tgz",
2674
+      "integrity": "sha512-U2ao6mRaPjjzOtwQTDA2OMk9ftQ+k+CrdaBrSIxcO6artSNBtK4kwdx8vUoajMvv6vGZWYiQOmBYnffOFWHt7w=="
2675
+    },
2685 2676
     "hpack.js": {
2686 2677
       "version": "2.1.6",
2687 2678
       "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",

+ 3
- 0
package.json View File

@@ -11,5 +11,8 @@
11 11
     "webpack": "4.16.1",
12 12
     "webpack-cli": "3.1.0",
13 13
     "webpack-dev-server": "3.1.4"
14
+  },
15
+  "dependencies": {
16
+    "howler": "2.0.14"
14 17
   }
15 18
 }

+ 33
- 0
src/game.rs View File

@@ -2,6 +2,7 @@ use controller::Controller;
2 2
 use error;
3 3
 use geometry::Geometry;
4 4
 use log;
5
+use audio_play;
5 6
 use sen_colour::{Colour, Format};
6 7
 use sprite::Sprite;
7 8
 use std::collections::HashMap;
@@ -9,6 +10,17 @@ use units::*;
9 10
 use Config;
10 11
 
11 12
 #[derive(Clone, Copy)]
13
+pub enum SoundEffect {
14
+    GameOver = 1,
15
+    Line1 = 2,
16
+    Line2 = 3,
17
+    Line3 = 4,
18
+    Line4 = 5,
19
+    PauseIn = 6,
20
+    PauseOut = 7,
21
+}
22
+
23
+#[derive(Clone, Copy)]
12 24
 pub struct Block {
13 25
     occupied: bool,
14 26
     offset: Vec2D,
@@ -277,6 +289,14 @@ impl Game {
277 289
         }
278 290
     }
279 291
 
292
+    pub fn game_mode_changed_to_paused(&self) {
293
+        play_sound(SoundEffect::PauseIn);
294
+    }
295
+
296
+    pub fn game_mode_changed_to_playing(&self) {
297
+        play_sound(SoundEffect::PauseOut);
298
+    }
299
+
280 300
     // counting on the fact that delta will always be a 'sensible' value.
281 301
     // so if the player has paused the game for a while, on the first resumed call to tick_playing
282 302
     // delta should be 0 rather than a large multi-second value
@@ -328,11 +348,20 @@ impl Game {
328 348
                 }
329 349
 
330 350
                 if num_lines > 0 {
351
+                    match num_lines {
352
+                        1 => play_sound(SoundEffect::Line1),
353
+                        2 => play_sound(SoundEffect::Line2),
354
+                        3 => play_sound(SoundEffect::Line3),
355
+                        4 => play_sound(SoundEffect::Line4),
356
+                        _ => ()
357
+                    };
358
+
331 359
                     update_score(self, num_lines);
332 360
                 }
333 361
 
334 362
                 use_next_shape(self, random)?;
335 363
                 if check_for_game_over(self) {
364
+                    play_sound(SoundEffect::GameOver);
336 365
                     log(&format!("i_count: {}", self.i_count));
337 366
                     log(&format!("j_count: {}", self.j_count));
338 367
                     log(&format!("l_count: {}", self.l_count));
@@ -362,6 +391,10 @@ impl Game {
362 391
     }
363 392
 }
364 393
 
394
+fn play_sound(sound_effect: SoundEffect) {
395
+    audio_play(sound_effect as i32);
396
+}
397
+
365 398
 fn update_score(game: &mut Game, num_lines: i32) {
366 399
     game.lines += num_lines;
367 400
     game.score += score_for_current_move(game, num_lines);

+ 2
- 2
src/harbour.rs View File

@@ -62,10 +62,10 @@ impl Harbour {
62 62
 
63 63
         if button == ControllerButton::Start && action == ControllerAction::Up {
64 64
             if self.mode == GameMode::Playing {
65
-                log("Paused");
65
+                self.game.game_mode_changed_to_paused();
66 66
                 self.mode = GameMode::Paused;
67 67
             } else {
68
-                log("Playing");
68
+                self.game.game_mode_changed_to_playing();
69 69
                 self.mode = GameMode::Playing;
70 70
                 self.resume_from_paused = true;
71 71
                 return true;

+ 5
- 0
src/lib.rs View File

@@ -29,6 +29,11 @@ extern "C" {
29 29
 }
30 30
 
31 31
 #[wasm_bindgen]
32
+extern {
33
+    fn audio_play(id: i32);
34
+}
35
+
36
+#[wasm_bindgen]
32 37
 pub struct KeyEventReturn {
33 38
     call_tick: bool,
34 39
     prevent_default: bool,

+ 43
- 0
web/js/Audio.js View File

@@ -0,0 +1,43 @@
1
+import { Howl, Howler } from "howler";
2
+
3
+export class Audio {
4
+  constructor(config) {
5
+    this.game_over = new Howl({
6
+      src: ['/web/sfx/negative1.mp3']
7
+    });
8
+    this.line1 = new Howl({
9
+      src: ['/web/sfx/fanfare1.mp3']
10
+    });
11
+    this.line2 = new Howl({
12
+      src: ['/web/sfx/fanfare1.mp3']
13
+    });
14
+    this.line3 = new Howl({
15
+      src: ['/web/sfx/fanfare2.mp3']
16
+    });
17
+    this.line4 = new Howl({
18
+      src: ['/web/sfx/fanfare3.mp3']
19
+    });
20
+    this.pause_in = new Howl({
21
+      src: ['/web/sfx/pause2_in.mp3']
22
+    });
23
+    this.pause_out = new Howl({
24
+      src: ['/web/sfx/pause2_out.mp3']
25
+    });
26
+  }
27
+
28
+  play(label) {
29
+    console.log(`audio: play ${label}`);
30
+
31
+    switch(label) {
32
+    case 1: this.game_over.play(); break;
33
+    case 2: this.line1.play(); break;
34
+    case 3: this.line2.play(); break;
35
+    case 4: this.line3.play(); break;
36
+    case 5: this.line4.play(); break;
37
+    case 6: this.pause_in.play(); break;
38
+    case 7: this.pause_out.play(); break;
39
+    default: console.error(`Audio: unable to play: ${label}`);
40
+    }
41
+
42
+  }
43
+}

+ 9
- 0
web/js/index.js View File

@@ -1,6 +1,7 @@
1 1
 import { Bridge, Config } from "../wasm_tetris";
2 2
 import { memory } from "../wasm_tetris_bg";
3 3
 import { GLRenderer } from "./GLRenderer";
4
+import { Audio } from "./Audio";
4 5
 
5 6
 let gState = {
6 7
   canvasId: 'render-canvas',
@@ -12,6 +13,7 @@ let gState = {
12 13
   bridge: undefined,
13 14
   animationId: undefined,
14 15
   renderer: undefined,
16
+  audio: undefined,
15 17
 
16 18
   performanceNow: performance.now()
17 19
 };
@@ -59,8 +61,13 @@ function reconfigure() {
59 61
   gState.bridge.reconfigure(gState.config);
60 62
 }
61 63
 
64
+function audio_play(id) {
65
+  gState.audio.play(id);
66
+}
67
+
62 68
 window.reconfigure = reconfigure;
63 69
 window.config = gState.config;
70
+window.audio_play = audio_play;
64 71
 
65 72
 function get_canvas_aspect_ratio(config) {
66 73
 
@@ -133,6 +140,8 @@ function main() {
133 140
 
134 141
   resize_canvas_element(canvasElement, gState.config);
135 142
 
143
+  gState.audio = new Audio(config);
144
+
136 145
   let renderer = new GLRenderer(gState.config, canvasElement);
137 146
   renderer.loadTexture(gState.tileset).then(([tilesetWidth, tilesetHeight]) => {
138 147
 

BIN
web/sfx/fanfare1.mp3 View File


BIN
web/sfx/fanfare2.mp3 View File


BIN
web/sfx/fanfare3.mp3 View File


BIN
web/sfx/negative1.mp3 View File


BIN
web/sfx/pause2_in.mp3 View File


BIN
web/sfx/pause2_out.mp3 View File