| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:async'; |
| |
| import 'package:sky/mojo/asset_bundle.dart'; |
| import 'package:sky/theme/colors.dart' as colors; |
| import 'package:sky/rendering/object.dart'; |
| import 'package:sky/painting/text_style.dart'; |
| import 'package:sky/widgets/basic.dart'; |
| import 'package:sky/widgets/button_base.dart'; |
| import 'package:sky/widgets/navigator.dart'; |
| import 'package:sky/widgets/framework.dart'; |
| import 'package:sky/widgets/title.dart'; |
| import 'package:sky/widgets/theme.dart'; |
| |
| import 'game_demo.dart'; |
| import 'sprites.dart'; |
| |
| AssetBundle _initBundle() { |
| if (rootBundle != null) |
| return rootBundle; |
| return new NetworkAssetBundle(new Uri.directory(Uri.base.origin)); |
| } |
| |
| final AssetBundle _bundle = _initBundle(); |
| |
| ImageMap _imageMap; |
| SpriteSheet _spriteSheet; |
| SpriteSheet _spriteSheetUI; |
| GameDemoApp _app; |
| Map<String,SoundEffect> _sounds = {}; |
| |
| main() async { |
| _imageMap = new ImageMap(_bundle); |
| |
| // Use a list to wait on all loads in parallel just before starting the app. |
| List loads = []; |
| |
| loads.add(_imageMap.load([ |
| 'assets/nebula.png', |
| 'assets/sprites.png', |
| 'assets/starfield.png', |
| 'assets/game_ui.png', |
| ])); |
| |
| // TODO(eseidel): SoundEffect doesn't really do anything except hold a future. |
| _sounds['explosion'] = new SoundEffect(_bundle.load('assets/explosion.wav')); |
| _sounds['laser'] = new SoundEffect(_bundle.load('assets/laser.wav')); |
| |
| loads.addAll([ |
| _sounds['explosion'].load(), |
| _sounds['laser'].load(), |
| ]); |
| |
| await Future.wait(loads); |
| |
| // TODO(eseidel): These load in serial which is bad for startup! |
| String json = await _bundle.loadString('assets/sprites.json'); |
| _spriteSheet = new SpriteSheet(_imageMap['assets/sprites.png'], json); |
| |
| json = await _bundle.loadString('assets/game_ui.json'); |
| _spriteSheetUI = new SpriteSheet(_imageMap['assets/game_ui.png'], json); |
| |
| _app = new GameDemoApp(); |
| |
| assert(_spriteSheet.image != null); |
| |
| SoundTrackPlayer stPlayer = SoundTrackPlayer.sharedInstance(); |
| SoundTrack music = await stPlayer.load(_bundle.load('assets/temp_music.aac')); |
| stPlayer.play(music); |
| |
| runApp(_app); |
| } |
| |
| class GameDemoApp extends App { |
| |
| NavigationState _navigationState; |
| NodeWithSize _game; |
| int _lastScore = 0; |
| |
| void initState() { |
| _navigationState = new NavigationState([ |
| new Route( |
| name: '/', |
| builder: _buildMainScene |
| ), |
| new Route( |
| name: '/game', |
| builder: _buildGameScene |
| ), |
| ]); |
| super.initState(); |
| } |
| |
| Widget build() { |
| // TODO(viktork): The task bar purple is the wrong purple, we may need |
| // a custom theme swatch to match the purples in the sprites. |
| ThemeData theme = new ThemeData( |
| brightness: ThemeBrightness.light, |
| primarySwatch: colors.Purple |
| ); |
| |
| return new Theme( |
| data: theme, |
| child: new Title( |
| title: 'Asteroids', |
| child: new Navigator(_navigationState) |
| ) |
| ); |
| } |
| |
| Widget _buildGameScene(navigator, route) { |
| return new SpriteWidget(_game, SpriteBoxTransformMode.fixedWidth); |
| } |
| |
| Widget _buildMainScene(navigator, route) { |
| return new Stack([ |
| new SpriteWidget(new MainScreenBackground(), SpriteBoxTransformMode.fixedWidth), |
| new Flex([ |
| new TextureButton( |
| onPressed: () { |
| _game = new GameDemoNode( |
| _imageMap, |
| _spriteSheet, |
| _spriteSheetUI, |
| _sounds, |
| (lastScore) { |
| setState(() {_lastScore = lastScore;}); |
| navigator.pop(); |
| } |
| ); |
| navigator.pushNamed('/game'); |
| }, |
| texture: _spriteSheetUI['btn_play_up.png'], |
| textureDown: _spriteSheetUI['btn_play_down.png'], |
| width: 128.0, |
| height: 128.0 |
| ), |
| new Text( |
| "Last Score: $_lastScore", |
| style: new TextStyle(fontSize:20.0) |
| ) |
| ], |
| direction: FlexDirection.vertical, |
| justifyContent: FlexJustifyContent.center) |
| ]); |
| } |
| } |
| |
| class TextureButton extends ButtonBase { |
| TextureButton({ |
| Key key, |
| this.onPressed, |
| this.texture, |
| this.textureDown, |
| this.width: 128.0, |
| this.height: 128.0 |
| }) : super(key: key); |
| |
| final Function onPressed; |
| final Texture texture; |
| final Texture textureDown; |
| final double width; |
| final double height; |
| |
| Widget buildContent() { |
| return new Listener( |
| child: new Container( |
| width: width, |
| height: height, |
| child: new CustomPaint( |
| callback: paintCallback, |
| token: new _TextureButtonToken( |
| highlight, |
| texture, |
| textureDown, |
| width, |
| height |
| ) |
| ) |
| ), |
| onPointerUp: (_) { |
| if (onPressed != null) onPressed(); |
| } |
| ); |
| } |
| |
| void paintCallback(PaintingCanvas canvas, Size size) { |
| if (texture == null) |
| return; |
| |
| canvas.save(); |
| if (highlight && textureDown != null) { |
| // Draw down state |
| canvas.scale(size.width / textureDown.size.width, size.height / textureDown.size.height); |
| textureDown.drawTexture(canvas, Point.origin, new Paint()); |
| } else { |
| // Draw up state |
| canvas.scale(size.width / texture.size.width, size.height / texture.size.height); |
| texture.drawTexture(canvas, Point.origin, new Paint()); |
| } |
| canvas.restore(); |
| } |
| } |
| |
| class _TextureButtonToken { |
| _TextureButtonToken( |
| this._highlight, |
| this._texture, |
| this._textureDown, |
| this._width, |
| this._height |
| ); |
| |
| final bool _highlight; |
| final Texture _texture; |
| final Texture _textureDown; |
| final double _width; |
| final double _height; |
| |
| bool operator== (other) { |
| return |
| other is _TextureButtonToken && |
| _highlight == other._highlight && |
| _texture == other._texture && |
| _textureDown == other._textureDown && |
| _width == other._width && |
| _height == other._height; |
| } |
| |
| int get hashCode { |
| int value = 373; |
| value = 37 * value * _highlight.hashCode; |
| value = 37 * value * _texture.hashCode; |
| value = 37 * value * _textureDown.hashCode; |
| value = 37 * value * _width.hashCode; |
| value = 37 * value * _height.hashCode; |
| return value; |
| } |
| } |
| |
| class MainScreenBackground extends NodeWithSize { |
| MainScreenBackground() : super(new Size(320.0, 320.0)) { |
| assert(_spriteSheet.image != null); |
| |
| StarField starField = new StarField(_spriteSheet, 200, true); |
| addChild(starField); |
| } |
| |
| void paint(PaintingCanvas canvas) { |
| canvas.drawRect(new Rect.fromLTWH(0.0, 0.0, 320.0, 320.0), new Paint()..color=new Color(0xff000000)); |
| super.paint(canvas); |
| } |
| } |