blob: c3ac27697b7445acacfa52189334678694923129 [file] [log] [blame]
Collin Jackson633b6502015-07-16 11:54:25 -07001// 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 Seidelb3947162015-08-17 16:41:35 -07005import 'dart:async';
6
Adam Barth65eba902015-10-09 20:44:52 -07007import 'package:flutter/material.dart';
8import 'package:flutter/painting.dart';
9import 'package:flutter/rendering.dart';
10import 'package:flutter/services.dart';
Adam Bartha88a85e2015-10-13 16:34:01 -070011import 'package:flutter_sprites/flutter_sprites.dart';
Collin Jackson633b6502015-07-16 11:54:25 -070012
Ian Fischer1d661372015-08-10 15:02:16 -070013import 'game_demo.dart';
Collin Jackson633b6502015-07-16 11:54:25 -070014
15AssetBundle _initBundle() {
16 if (rootBundle != null)
17 return rootBundle;
Ian Fischer1d661372015-08-10 15:02:16 -070018 return new NetworkAssetBundle(new Uri.directory(Uri.base.origin));
Collin Jackson633b6502015-07-16 11:54:25 -070019}
20
21final AssetBundle _bundle = _initBundle();
22
Eric Seidelb3947162015-08-17 16:41:35 -070023ImageMap _imageMap;
Collin Jackson633b6502015-07-16 11:54:25 -070024SpriteSheet _spriteSheet;
Viktor Lidholt1b4923a2015-07-21 11:30:17 -070025SpriteSheet _spriteSheetUI;
Hixiea6c473e2015-10-22 13:29:12 -070026Map<String, SoundEffect> _sounds = <String, SoundEffect>{};
Collin Jackson633b6502015-07-16 11:54:25 -070027
28main() async {
Eric Seidelb3947162015-08-17 16:41:35 -070029 _imageMap = new ImageMap(_bundle);
Collin Jackson633b6502015-07-16 11:54:25 -070030
Eric Seidelb3947162015-08-17 16:41:35 -070031 // Use a list to wait on all loads in parallel just before starting the app.
32 List loads = [];
33
Hixiea6c473e2015-10-22 13:29:12 -070034 loads.add(_imageMap.load(<String>[
Collin Jackson633b6502015-07-16 11:54:25 -070035 'assets/nebula.png',
36 'assets/sprites.png',
37 'assets/starfield.png',
Viktor Lidholt1b4923a2015-07-21 11:30:17 -070038 'assets/game_ui.png',
Eric Seidelb3947162015-08-17 16:41:35 -070039 ]));
Collin Jackson633b6502015-07-16 11:54:25 -070040
Eric Seidelb3947162015-08-17 16:41:35 -070041 // 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 Lidholtb5294452015-08-13 12:32:50 -070044
Eric Seidelb3947162015-08-17 16:41:35 -070045 loads.addAll([
46 _sounds['explosion'].load(),
47 _sounds['laser'].load(),
48 ]);
Viktor Lidholtb5294452015-08-13 12:32:50 -070049
Viktor Lidholtd9c743e2015-08-18 10:33:34 -070050 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 Lidholtd9c743e2015-08-18 10:33:34 -070059 assert(_spriteSheet.image != null);
60
Viktor Lidholte17f6b72015-08-13 16:00:06 -070061 SoundTrackPlayer stPlayer = SoundTrackPlayer.sharedInstance();
Eric Seidelb3947162015-08-17 16:41:35 -070062 SoundTrack music = await stPlayer.load(_bundle.load('assets/temp_music.aac'));
Viktor Lidholte17f6b72015-08-13 16:00:06 -070063 stPlayer.play(music);
64
Adam Barth5477d462015-10-01 09:26:19 -070065 runApp(new GameDemo());
Collin Jackson633b6502015-07-16 11:54:25 -070066}
67
Adam Barth5477d462015-10-01 09:26:19 -070068// 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.
70final ThemeData _theme = new ThemeData(
71 brightness: ThemeBrightness.light,
72 primarySwatch: Colors.purple
73);
Collin Jackson633b6502015-07-16 11:54:25 -070074
Adam Barth5477d462015-10-01 09:26:19 -070075class GameDemo extends StatefulComponent {
76 GameDemoState createState() => new GameDemoState();
77}
78
79class GameDemoState extends State<GameDemo> {
Viktor Lidholta78370f2015-08-19 13:19:54 -070080 NodeWithSize _game;
Viktor Lidholt6aa8e4b2015-07-29 13:33:10 -070081 int _lastScore = 0;
Viktor Lidholt1b4923a2015-07-21 11:30:17 -070082
Adam Barth5477d462015-10-01 09:26:19 -070083 Widget build(BuildContext context) {
Adam Barthdb3b9e82015-10-09 10:19:35 -070084 return new MaterialApp(
Adam Barth5477d462015-10-01 09:26:19 -070085 title: 'Asteroids',
86 theme: _theme,
Hixiea6c473e2015-10-22 13:29:12 -070087 routes: <String, RouteBuilder>{
Adam Barth5477d462015-10-01 09:26:19 -070088 '/': _buildMainScene,
89 '/game': _buildGameScene
90 }
Viktor Lidholt1b4923a2015-07-21 11:30:17 -070091 );
92 }
93
Hixie90a0f632015-10-02 15:07:35 -070094 Widget _buildGameScene(RouteArguments args) {
Viktor Lidholta78370f2015-08-19 13:19:54 -070095 return new SpriteWidget(_game, SpriteBoxTransformMode.fixedWidth);
Viktor Lidholt1b4923a2015-07-21 11:30:17 -070096 }
97
Hixie90a0f632015-10-02 15:07:35 -070098 Widget _buildMainScene(RouteArguments args) {
Viktor Lidholt52c291a2015-10-30 16:13:26 -070099 NavigatorState navigatorState = Navigator.of(args.context);
100
Hixiea6c473e2015-10-22 13:29:12 -0700101 return new Stack(<Widget>[
Viktor Lidholta78370f2015-08-19 13:19:54 -0700102 new SpriteWidget(new MainScreenBackground(), SpriteBoxTransformMode.fixedWidth),
Hixiea6c473e2015-10-22 13:29:12 -0700103 new Column(<Widget>[
Hixiece28a712015-08-25 10:18:36 -0700104 new TextureButton(
105 onPressed: () {
106 _game = new GameDemoNode(
107 _imageMap,
108 _spriteSheet,
109 _spriteSheetUI,
110 _sounds,
Hixiea6c473e2015-10-22 13:29:12 -0700111 (int lastScore) {
112 setState(() { _lastScore = lastScore; });
Viktor Lidholt52c291a2015-10-30 16:13:26 -0700113 navigatorState.pop();
Hixiece28a712015-08-25 10:18:36 -0700114 }
115 );
Viktor Lidholt52c291a2015-10-30 16:13:26 -0700116 navigatorState.pushNamed('/game');
Hixiece28a712015-08-25 10:18:36 -0700117 },
118 texture: _spriteSheetUI['btn_play_up.png'],
119 textureDown: _spriteSheetUI['btn_play_down.png'],
120 width: 128.0,
121 height: 128.0
122 ),
Viktor Lidholt018cef62015-10-06 09:28:05 -0700123 new DefaultTextStyle(
124 child: new Text(
125 "Last Score: $_lastScore"
126 ),
Hixiece28a712015-08-25 10:18:36 -0700127 style: new TextStyle(fontSize:20.0)
128 )
129 ],
130 justifyContent: FlexJustifyContent.center
131 )
Viktor Lidholtde105aa2015-07-28 17:34:39 -0700132 ]);
Collin Jackson633b6502015-07-16 11:54:25 -0700133 }
134}
Viktor Lidholt9a834382015-07-22 16:52:09 -0700135
Adam Barth5477d462015-10-01 09:26:19 -0700136class TextureButton extends StatefulComponent {
Viktor Lidholt9a834382015-07-22 16:52:09 -0700137 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 Barthd6dc9d42015-10-27 10:21:10 -0700146 final VoidCallback onPressed;
Viktor Lidholt9a834382015-07-22 16:52:09 -0700147 final Texture texture;
148 final Texture textureDown;
149 final double width;
150 final double height;
151
Adam Barth5477d462015-10-01 09:26:19 -0700152 TextureButtonState createState() => new TextureButtonState();
153}
154
Adam Barth3308ff02015-10-08 10:22:33 -0700155class TextureButtonState extends State<TextureButton> {
156 bool _highlight = false;
157
158 Widget build(BuildContext context) {
159 return new GestureDetector(
Viktor Lidholt9a834382015-07-22 16:52:09 -0700160 child: new Container(
Adam Barth5477d462015-10-01 09:26:19 -0700161 width: config.width,
162 height: config.height,
Viktor Lidholt9a834382015-07-22 16:52:09 -0700163 child: new CustomPaint(
Adam Barth529fa952015-10-19 17:22:59 -0700164 onPaint: paintCallback,
Viktor Lidholt9a834382015-07-22 16:52:09 -0700165 token: new _TextureButtonToken(
Adam Barth3308ff02015-10-08 10:22:33 -0700166 _highlight,
Adam Barth5477d462015-10-01 09:26:19 -0700167 config.texture,
168 config.textureDown,
169 config.width,
170 config.height
Viktor Lidholt9a834382015-07-22 16:52:09 -0700171 )
172 )
173 ),
Adam Barth22254052015-10-27 13:28:04 -0700174 onTapDown: (_) {
Adam Barth3308ff02015-10-08 10:22:33 -0700175 setState(() {
176 _highlight = true;
177 });
178 },
179 onTap: () {
180 setState(() {
181 _highlight = false;
182 });
Adam Barth5477d462015-10-01 09:26:19 -0700183 if (config.onPressed != null)
184 config.onPressed();
Adam Barth3308ff02015-10-08 10:22:33 -0700185 },
186 onTapCancel: () {
187 setState(() {
188 _highlight = false;
189 });
Viktor Lidholt9a834382015-07-22 16:52:09 -0700190 }
191 );
192 }
193
194 void paintCallback(PaintingCanvas canvas, Size size) {
Adam Barth5477d462015-10-01 09:26:19 -0700195 if (config.texture == null)
Viktor Lidholt9a834382015-07-22 16:52:09 -0700196 return;
197
Viktor Lidholt430c08f2015-07-29 13:10:02 -0700198 canvas.save();
Adam Barth3308ff02015-10-08 10:22:33 -0700199 if (_highlight && config.textureDown != null) {
Viktor Lidholt9a834382015-07-22 16:52:09 -0700200 // Draw down state
Adam Barth5477d462015-10-01 09:26:19 -0700201 canvas.scale(size.width / config.textureDown.size.width, size.height / config.textureDown.size.height);
202 config.textureDown.drawTexture(canvas, Point.origin, new Paint());
Viktor Lidholt9a834382015-07-22 16:52:09 -0700203 } else {
204 // Draw up state
Adam Barth5477d462015-10-01 09:26:19 -0700205 canvas.scale(size.width / config.texture.size.width, size.height / config.texture.size.height);
206 config.texture.drawTexture(canvas, Point.origin, new Paint());
Viktor Lidholt9a834382015-07-22 16:52:09 -0700207 }
Viktor Lidholt430c08f2015-07-29 13:10:02 -0700208 canvas.restore();
Viktor Lidholt9a834382015-07-22 16:52:09 -0700209 }
210}
211
212class _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 Lidholtde105aa2015-07-28 17:34:39 -0700247
248class MainScreenBackground extends NodeWithSize {
Viktor Lidholta78370f2015-08-19 13:19:54 -0700249 MainScreenBackground() : super(new Size(320.0, 320.0)) {
Viktor Lidholtd9c743e2015-08-18 10:33:34 -0700250 assert(_spriteSheet.image != null);
251
Viktor Lidholtde105aa2015-07-28 17:34:39 -0700252 StarField starField = new StarField(_spriteSheet, 200, true);
253 addChild(starField);
254 }
Viktor Lidholta78370f2015-08-19 13:19:54 -0700255
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 Lidholtde105aa2015-07-28 17:34:39 -0700260}