Teach Asteroids Sounds how to load from AssetBundle

@abarth
diff --git a/examples/game/lib/main.dart b/examples/game/lib/main.dart
index bc78445..d18fe06 100644
--- a/examples/game/lib/main.dart
+++ b/examples/game/lib/main.dart
@@ -48,8 +48,8 @@
 
   _app = new GameDemoApp();
 
-  _sounds["explosion"] = new SoundEffect('https://github.com/slembcke/GalacticGuardian.spritebuilder/raw/GDC/Packages/SpriteBuilder%20Resources.sbpack/TempSounds/Explosion.wav');
-  _sounds["laser"] = new SoundEffect('https://github.com/slembcke/GalacticGuardian.spritebuilder/raw/GDC/Packages/SpriteBuilder%20Resources.sbpack/TempSounds/Laser.wav');
+  _sounds["explosion"] = new SoundEffect(_bundle.load('assets/explosion.wav'));
+  _sounds["laser"] = new SoundEffect(_bundle.load('assets/laser.wav'));
 
   await _sounds["explosion"].load();
   await _sounds["laser"].load();
diff --git a/examples/game/lib/sound.dart b/examples/game/lib/sound.dart
index 5e50e7f..b217090 100644
--- a/examples/game/lib/sound.dart
+++ b/examples/game/lib/sound.dart
@@ -6,16 +6,15 @@
 typedef void SoundEffectStreamCallback(SoundEffectStream);
 
 class SoundEffect {
-  SoundEffect(this._url);
+  SoundEffect(this._pipeFuture);
 
   // TODO: Remove load method from SoundEffect
   Future load() async {
-    UrlResponse response = await fetchUrl(_url);
-    _data = response.body;
+    _data = await _pipeFuture;
   }
 
-  String _url;
-  Object _data;
+  Future<MojoDataPipeConsumer> _pipeFuture;
+  MojoDataPipeConsumer _data;
 }
 
 class SoundEffectStream {
diff --git a/examples/game/lib/sound_manager.dart b/examples/game/lib/sound_manager.dart
index 90c03a9..311da05 100644
--- a/examples/game/lib/sound_manager.dart
+++ b/examples/game/lib/sound_manager.dart
@@ -54,7 +54,6 @@
 
   static void purgeSharedInstance() {
     if (_sharedSoundManager == null) return;
-    _sharedSoundManager._running = false;
     _sharedSoundManager = null;
   }
 
@@ -72,7 +71,6 @@
   bool enableBackgroundMusic;
   bool enableSoundEffects;
 
-  bool _running = true;
   int _lastTimeStamp;
 
   void playEvent(SoundEvent evt, [double volume = 1.0, double pitch = 1.0, double pan = 0.0]) {
diff --git a/examples/game/lib/sprites.dart b/examples/game/lib/sprites.dart
index 6522290..8735554 100644
--- a/examples/game/lib/sprites.dart
+++ b/examples/game/lib/sprites.dart
@@ -10,6 +10,7 @@
 import 'dart:typed_data';
 import 'dart:sky';
 
+import 'package:mojo/core.dart';
 import 'package:mojo/mojo/url_response.mojom.dart';
 import 'package:sky/animation/curves.dart';
 import 'package:sky/base/scheduler.dart' as scheduler;
diff --git a/packages/flutter/lib/mojo/asset_bundle.dart b/packages/flutter/lib/mojo/asset_bundle.dart
index bb2ff84..7cce717 100644
--- a/packages/flutter/lib/mojo/asset_bundle.dart
+++ b/packages/flutter/lib/mojo/asset_bundle.dart
@@ -18,6 +18,7 @@
   void close();
   ImageResource loadImage(String key);
   Future<String> loadString(String key);
+  Future<core.MojoDataPipeConsumer> load(String key);
 }
 
 class NetworkAssetBundle extends AssetBundle {
@@ -27,13 +28,15 @@
 
   void close() { }
 
-  ImageResource loadImage(String key) {
-    return image_cache.load(_baseUrl.resolve(key).toString());
+  String _urlFromKey(String key) => _baseUrl.resolve(key).toString();
+
+  Future<core.MojoDataPipeConsumer> load(String key) async {
+    return (await fetchUrl(_urlFromKey(key))).body;
   }
 
-  Future<String> loadString(String key) {
-    return fetchString(_baseUrl.resolve(key).toString());
-  }
+  ImageResource loadImage(String key) => image_cache.load(_urlFromKey(key));
+
+  Future<String> loadString(String key) => fetchString(_urlFromKey(key));
 }
 
 Future _fetchAndUnpackBundle(String relativeUrl, AssetBundleProxy bundle) async {
@@ -66,19 +69,23 @@
   ImageResource loadImage(String key) {
     return _imageCache.putIfAbsent(key, () {
       Completer<sky.Image> completer = new Completer<sky.Image>();
-      _bundle.ptr.getAsStream(key).then((response) {
-        new sky.ImageDecoder(response.assetData.handle.h, completer.complete);
+      load(key).then((assetData) {
+        new sky.ImageDecoder(assetData.handle.h, completer.complete);
       });
       return new ImageResource(completer.future);
     });
   }
 
   Future<String> _fetchString(String key) async {
-    core.MojoDataPipeConsumer pipe = (await _bundle.ptr.getAsStream(key)).assetData;
+    core.MojoDataPipeConsumer pipe = await load(key);
     ByteData data = await core.DataPipeDrainer.drainHandle(pipe);
     return new String.fromCharCodes(new Uint8List.view(data.buffer));
   }
 
+  Future<core.MojoDataPipeConsumer> load(String key) async {
+    return (await _bundle.ptr.getAsStream(key)).assetData;
+  }
+
   Future<String> loadString(String key) {
     return _stringCache.putIfAbsent(key, () => _fetchString(key));
   }
diff --git a/packages/flutter/lib/mojo/net/fetch.dart b/packages/flutter/lib/mojo/net/fetch.dart
index 56a3b22..042e527 100644
--- a/packages/flutter/lib/mojo/net/fetch.dart
+++ b/packages/flutter/lib/mojo/net/fetch.dart
@@ -12,6 +12,8 @@
 import 'package:mojo_services/mojo/url_loader.mojom.dart';
 import 'package:sky/mojo/shell.dart' as shell;
 
+export 'package:mojo/mojo/url_response.mojom.dart' show UrlResponse;
+
 NetworkServiceProxy _initNetworkService() {
   NetworkServiceProxy networkService = new NetworkServiceProxy.unbound();
   shell.requestService("mojo:authenticated_network_service", networkService);