Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 5 | import 'dart:async'; |
| 6 | |
Adam Barth | 65eba90 | 2015-10-09 20:44:52 -0700 | [diff] [blame] | 7 | import 'package:flutter/material.dart'; |
| 8 | import 'package:flutter/painting.dart'; |
| 9 | import 'package:flutter/rendering.dart'; |
| 10 | import 'package:flutter/services.dart'; |
Adam Barth | a88a85e | 2015-10-13 16:34:01 -0700 | [diff] [blame] | 11 | import 'package:flutter_sprites/flutter_sprites.dart'; |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 12 | |
Ian Fischer | 1d66137 | 2015-08-10 15:02:16 -0700 | [diff] [blame] | 13 | import 'game_demo.dart'; |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 14 | |
| 15 | AssetBundle _initBundle() { |
| 16 | if (rootBundle != null) |
| 17 | return rootBundle; |
Ian Fischer | 1d66137 | 2015-08-10 15:02:16 -0700 | [diff] [blame] | 18 | return new NetworkAssetBundle(new Uri.directory(Uri.base.origin)); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 19 | } |
| 20 | |
| 21 | final AssetBundle _bundle = _initBundle(); |
| 22 | |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 23 | ImageMap _imageMap; |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 24 | SpriteSheet _spriteSheet; |
Viktor Lidholt | 1b4923a | 2015-07-21 11:30:17 -0700 | [diff] [blame] | 25 | SpriteSheet _spriteSheetUI; |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 26 | Map<String, SoundEffect> _sounds = <String, SoundEffect>{}; |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 27 | |
| 28 | main() async { |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 29 | _imageMap = new ImageMap(_bundle); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 30 | |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 31 | // Use a list to wait on all loads in parallel just before starting the app. |
| 32 | List loads = []; |
| 33 | |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 34 | loads.add(_imageMap.load(<String>[ |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 35 | 'assets/nebula.png', |
| 36 | 'assets/sprites.png', |
| 37 | 'assets/starfield.png', |
Viktor Lidholt | 1b4923a | 2015-07-21 11:30:17 -0700 | [diff] [blame] | 38 | 'assets/game_ui.png', |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 39 | ])); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 40 | |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 41 | // TODO(eseidel): SoundEffect doesn't really do anything except hold a future. |
| 42 | _sounds['explosion'] = new SoundEffect(_bundle.load('assets/explosion.wav')); |
| 43 | _sounds['laser'] = new SoundEffect(_bundle.load('assets/laser.wav')); |
Viktor Lidholt | b529445 | 2015-08-13 12:32:50 -0700 | [diff] [blame] | 44 | |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 45 | loads.addAll([ |
| 46 | _sounds['explosion'].load(), |
| 47 | _sounds['laser'].load(), |
| 48 | ]); |
Viktor Lidholt | b529445 | 2015-08-13 12:32:50 -0700 | [diff] [blame] | 49 | |
Viktor Lidholt | d9c743e | 2015-08-18 10:33:34 -0700 | [diff] [blame] | 50 | await Future.wait(loads); |
| 51 | |
| 52 | // TODO(eseidel): These load in serial which is bad for startup! |
| 53 | String json = await _bundle.loadString('assets/sprites.json'); |
| 54 | _spriteSheet = new SpriteSheet(_imageMap['assets/sprites.png'], json); |
| 55 | |
| 56 | json = await _bundle.loadString('assets/game_ui.json'); |
| 57 | _spriteSheetUI = new SpriteSheet(_imageMap['assets/game_ui.png'], json); |
| 58 | |
Viktor Lidholt | d9c743e | 2015-08-18 10:33:34 -0700 | [diff] [blame] | 59 | assert(_spriteSheet.image != null); |
| 60 | |
Viktor Lidholt | e17f6b7 | 2015-08-13 16:00:06 -0700 | [diff] [blame] | 61 | SoundTrackPlayer stPlayer = SoundTrackPlayer.sharedInstance(); |
Eric Seidel | b394716 | 2015-08-17 16:41:35 -0700 | [diff] [blame] | 62 | SoundTrack music = await stPlayer.load(_bundle.load('assets/temp_music.aac')); |
Viktor Lidholt | e17f6b7 | 2015-08-13 16:00:06 -0700 | [diff] [blame] | 63 | stPlayer.play(music); |
| 64 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 65 | runApp(new GameDemo()); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 66 | } |
| 67 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 68 | // TODO(viktork): The task bar purple is the wrong purple, we may need |
| 69 | // a custom theme swatch to match the purples in the sprites. |
| 70 | final ThemeData _theme = new ThemeData( |
| 71 | brightness: ThemeBrightness.light, |
| 72 | primarySwatch: Colors.purple |
| 73 | ); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 74 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 75 | class GameDemo extends StatefulComponent { |
| 76 | GameDemoState createState() => new GameDemoState(); |
| 77 | } |
| 78 | |
| 79 | class GameDemoState extends State<GameDemo> { |
Viktor Lidholt | a78370f | 2015-08-19 13:19:54 -0700 | [diff] [blame] | 80 | NodeWithSize _game; |
Viktor Lidholt | 6aa8e4b | 2015-07-29 13:33:10 -0700 | [diff] [blame] | 81 | int _lastScore = 0; |
Viktor Lidholt | 1b4923a | 2015-07-21 11:30:17 -0700 | [diff] [blame] | 82 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 83 | Widget build(BuildContext context) { |
Adam Barth | db3b9e8 | 2015-10-09 10:19:35 -0700 | [diff] [blame] | 84 | return new MaterialApp( |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 85 | title: 'Asteroids', |
| 86 | theme: _theme, |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 87 | routes: <String, RouteBuilder>{ |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 88 | '/': _buildMainScene, |
| 89 | '/game': _buildGameScene |
| 90 | } |
Viktor Lidholt | 1b4923a | 2015-07-21 11:30:17 -0700 | [diff] [blame] | 91 | ); |
| 92 | } |
| 93 | |
Hixie | 90a0f63 | 2015-10-02 15:07:35 -0700 | [diff] [blame] | 94 | Widget _buildGameScene(RouteArguments args) { |
Viktor Lidholt | a78370f | 2015-08-19 13:19:54 -0700 | [diff] [blame] | 95 | return new SpriteWidget(_game, SpriteBoxTransformMode.fixedWidth); |
Viktor Lidholt | 1b4923a | 2015-07-21 11:30:17 -0700 | [diff] [blame] | 96 | } |
| 97 | |
Hixie | 90a0f63 | 2015-10-02 15:07:35 -0700 | [diff] [blame] | 98 | Widget _buildMainScene(RouteArguments args) { |
Viktor Lidholt | 52c291a | 2015-10-30 16:13:26 -0700 | [diff] [blame] | 99 | NavigatorState navigatorState = Navigator.of(args.context); |
| 100 | |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 101 | return new Stack(<Widget>[ |
Viktor Lidholt | a78370f | 2015-08-19 13:19:54 -0700 | [diff] [blame] | 102 | new SpriteWidget(new MainScreenBackground(), SpriteBoxTransformMode.fixedWidth), |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 103 | new Column(<Widget>[ |
Hixie | ce28a71 | 2015-08-25 10:18:36 -0700 | [diff] [blame] | 104 | new TextureButton( |
| 105 | onPressed: () { |
| 106 | _game = new GameDemoNode( |
| 107 | _imageMap, |
| 108 | _spriteSheet, |
| 109 | _spriteSheetUI, |
| 110 | _sounds, |
Hixie | a6c473e | 2015-10-22 13:29:12 -0700 | [diff] [blame] | 111 | (int lastScore) { |
| 112 | setState(() { _lastScore = lastScore; }); |
Viktor Lidholt | 52c291a | 2015-10-30 16:13:26 -0700 | [diff] [blame] | 113 | navigatorState.pop(); |
Hixie | ce28a71 | 2015-08-25 10:18:36 -0700 | [diff] [blame] | 114 | } |
| 115 | ); |
Viktor Lidholt | 52c291a | 2015-10-30 16:13:26 -0700 | [diff] [blame] | 116 | navigatorState.pushNamed('/game'); |
Hixie | ce28a71 | 2015-08-25 10:18:36 -0700 | [diff] [blame] | 117 | }, |
| 118 | texture: _spriteSheetUI['btn_play_up.png'], |
| 119 | textureDown: _spriteSheetUI['btn_play_down.png'], |
| 120 | width: 128.0, |
| 121 | height: 128.0 |
| 122 | ), |
Viktor Lidholt | 018cef6 | 2015-10-06 09:28:05 -0700 | [diff] [blame] | 123 | new DefaultTextStyle( |
| 124 | child: new Text( |
| 125 | "Last Score: $_lastScore" |
| 126 | ), |
Hixie | ce28a71 | 2015-08-25 10:18:36 -0700 | [diff] [blame] | 127 | style: new TextStyle(fontSize:20.0) |
| 128 | ) |
| 129 | ], |
| 130 | justifyContent: FlexJustifyContent.center |
| 131 | ) |
Viktor Lidholt | de105aa | 2015-07-28 17:34:39 -0700 | [diff] [blame] | 132 | ]); |
Collin Jackson | 633b650 | 2015-07-16 11:54:25 -0700 | [diff] [blame] | 133 | } |
| 134 | } |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 135 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 136 | class TextureButton extends StatefulComponent { |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 137 | TextureButton({ |
| 138 | Key key, |
| 139 | this.onPressed, |
| 140 | this.texture, |
| 141 | this.textureDown, |
| 142 | this.width: 128.0, |
| 143 | this.height: 128.0 |
| 144 | }) : super(key: key); |
| 145 | |
Adam Barth | d6dc9d4 | 2015-10-27 10:21:10 -0700 | [diff] [blame] | 146 | final VoidCallback onPressed; |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 147 | final Texture texture; |
| 148 | final Texture textureDown; |
| 149 | final double width; |
| 150 | final double height; |
| 151 | |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 152 | TextureButtonState createState() => new TextureButtonState(); |
| 153 | } |
| 154 | |
Adam Barth | 3308ff0 | 2015-10-08 10:22:33 -0700 | [diff] [blame] | 155 | class TextureButtonState extends State<TextureButton> { |
| 156 | bool _highlight = false; |
| 157 | |
| 158 | Widget build(BuildContext context) { |
| 159 | return new GestureDetector( |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 160 | child: new Container( |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 161 | width: config.width, |
| 162 | height: config.height, |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 163 | child: new CustomPaint( |
Adam Barth | 529fa95 | 2015-10-19 17:22:59 -0700 | [diff] [blame] | 164 | onPaint: paintCallback, |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 165 | token: new _TextureButtonToken( |
Adam Barth | 3308ff0 | 2015-10-08 10:22:33 -0700 | [diff] [blame] | 166 | _highlight, |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 167 | config.texture, |
| 168 | config.textureDown, |
| 169 | config.width, |
| 170 | config.height |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 171 | ) |
| 172 | ) |
| 173 | ), |
Adam Barth | 2225405 | 2015-10-27 13:28:04 -0700 | [diff] [blame] | 174 | onTapDown: (_) { |
Adam Barth | 3308ff0 | 2015-10-08 10:22:33 -0700 | [diff] [blame] | 175 | setState(() { |
| 176 | _highlight = true; |
| 177 | }); |
| 178 | }, |
| 179 | onTap: () { |
| 180 | setState(() { |
| 181 | _highlight = false; |
| 182 | }); |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 183 | if (config.onPressed != null) |
| 184 | config.onPressed(); |
Adam Barth | 3308ff0 | 2015-10-08 10:22:33 -0700 | [diff] [blame] | 185 | }, |
| 186 | onTapCancel: () { |
| 187 | setState(() { |
| 188 | _highlight = false; |
| 189 | }); |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 190 | } |
| 191 | ); |
| 192 | } |
| 193 | |
| 194 | void paintCallback(PaintingCanvas canvas, Size size) { |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 195 | if (config.texture == null) |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 196 | return; |
| 197 | |
Viktor Lidholt | 430c08f | 2015-07-29 13:10:02 -0700 | [diff] [blame] | 198 | canvas.save(); |
Adam Barth | 3308ff0 | 2015-10-08 10:22:33 -0700 | [diff] [blame] | 199 | if (_highlight && config.textureDown != null) { |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 200 | // Draw down state |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 201 | canvas.scale(size.width / config.textureDown.size.width, size.height / config.textureDown.size.height); |
| 202 | config.textureDown.drawTexture(canvas, Point.origin, new Paint()); |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 203 | } else { |
| 204 | // Draw up state |
Adam Barth | 5477d46 | 2015-10-01 09:26:19 -0700 | [diff] [blame] | 205 | canvas.scale(size.width / config.texture.size.width, size.height / config.texture.size.height); |
| 206 | config.texture.drawTexture(canvas, Point.origin, new Paint()); |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 207 | } |
Viktor Lidholt | 430c08f | 2015-07-29 13:10:02 -0700 | [diff] [blame] | 208 | canvas.restore(); |
Viktor Lidholt | 9a83438 | 2015-07-22 16:52:09 -0700 | [diff] [blame] | 209 | } |
| 210 | } |
| 211 | |
| 212 | class _TextureButtonToken { |
| 213 | _TextureButtonToken( |
| 214 | this._highlight, |
| 215 | this._texture, |
| 216 | this._textureDown, |
| 217 | this._width, |
| 218 | this._height |
| 219 | ); |
| 220 | |
| 221 | final bool _highlight; |
| 222 | final Texture _texture; |
| 223 | final Texture _textureDown; |
| 224 | final double _width; |
| 225 | final double _height; |
| 226 | |
| 227 | bool operator== (other) { |
| 228 | return |
| 229 | other is _TextureButtonToken && |
| 230 | _highlight == other._highlight && |
| 231 | _texture == other._texture && |
| 232 | _textureDown == other._textureDown && |
| 233 | _width == other._width && |
| 234 | _height == other._height; |
| 235 | } |
| 236 | |
| 237 | int get hashCode { |
| 238 | int value = 373; |
| 239 | value = 37 * value * _highlight.hashCode; |
| 240 | value = 37 * value * _texture.hashCode; |
| 241 | value = 37 * value * _textureDown.hashCode; |
| 242 | value = 37 * value * _width.hashCode; |
| 243 | value = 37 * value * _height.hashCode; |
| 244 | return value; |
| 245 | } |
| 246 | } |
Viktor Lidholt | de105aa | 2015-07-28 17:34:39 -0700 | [diff] [blame] | 247 | |
| 248 | class MainScreenBackground extends NodeWithSize { |
Viktor Lidholt | a78370f | 2015-08-19 13:19:54 -0700 | [diff] [blame] | 249 | MainScreenBackground() : super(new Size(320.0, 320.0)) { |
Viktor Lidholt | d9c743e | 2015-08-18 10:33:34 -0700 | [diff] [blame] | 250 | assert(_spriteSheet.image != null); |
| 251 | |
Viktor Lidholt | de105aa | 2015-07-28 17:34:39 -0700 | [diff] [blame] | 252 | StarField starField = new StarField(_spriteSheet, 200, true); |
| 253 | addChild(starField); |
| 254 | } |
Viktor Lidholt | a78370f | 2015-08-19 13:19:54 -0700 | [diff] [blame] | 255 | |
| 256 | void paint(PaintingCanvas canvas) { |
| 257 | canvas.drawRect(new Rect.fromLTWH(0.0, 0.0, 320.0, 320.0), new Paint()..color=new Color(0xff000000)); |
| 258 | super.paint(canvas); |
| 259 | } |
Viktor Lidholt | de105aa | 2015-07-28 17:34:39 -0700 | [diff] [blame] | 260 | } |