| Index: samples/pop_pop_win/lib/src/canvas/game_element.dart
|
| diff --git a/samples/pop_pop_win/lib/src/canvas/game_element.dart b/samples/pop_pop_win/lib/src/canvas/game_element.dart
|
| deleted file mode 100644
|
| index 084f6c6b276f2b945cfc61b43474211ccbc9d084..0000000000000000000000000000000000000000
|
| --- a/samples/pop_pop_win/lib/src/canvas/game_element.dart
|
| +++ /dev/null
|
| @@ -1,382 +0,0 @@
|
| -part of pop_pop_win.canvas;
|
| -
|
| -class GameElement extends ParentThing {
|
| - static const _edgeOffset = 32;
|
| - static const _backgroundSize = const Size(2048, 1536);
|
| - static const _backgroundEdgeOffset = 256;
|
| - static const _backgroundHoleSize = 16 * SquareElement._size + 2 * _edgeOffset;
|
| - static const _boardOffset = const Vector(352, 96);
|
| - static const _popExplodeAnimationOffset = const Vector(-88, -88);
|
| - static const _popAnimationHitFrame = 12;
|
| -
|
| - static const _dartAnimationOffset =
|
| - const Vector(-512 + 0.5 * SquareElement._size,
|
| - -388 + 0.5 * SquareElement._size);
|
| -
|
| - final CanvasThing _canvas = new CanvasThing(0, 0);
|
| - final GameBackgroundElement _background = new GameBackgroundElement();
|
| - final BoardElement _boardElement = new BoardElement();
|
| - final ScoreElement _scoreElement;
|
| - final NewGameElement _newGameElement = new NewGameElement();
|
| - final GameTitleElement _titleElement = new GameTitleElement();
|
| - final TextureAnimationThing _popAnimationLayer, _dartAnimationLayer;
|
| - final TextureData _textureData;
|
| - final EventHandle _targetChanged = new EventHandle();
|
| -
|
| - int _targetX, _targetY;
|
| - double _scale;
|
| - Vector _scaledBoardOffset;
|
| - Box _scaledInnerBox;
|
| - SquareElement _mouseDownElement, _lastHoldUnfreeze;
|
| - Timer _mouseDownTimer;
|
| -
|
| - Game _game;
|
| -
|
| - GameElement(TextureData textureData)
|
| - : _textureData = textureData,
|
| - _popAnimationLayer = new TextureAnimationThing(0, 0, textureData),
|
| - _dartAnimationLayer = new TextureAnimationThing(0, 0, textureData),
|
| - _scoreElement = new ScoreElement(),
|
| - super(100, 100) {
|
| - _canvas.registerParent(this);
|
| - _canvas.add(_background);
|
| - _canvas.add(_boardElement);
|
| - _canvas.add(_newGameElement);
|
| - _canvas.add(_scoreElement);
|
| - _canvas.add(_popAnimationLayer);
|
| - _canvas.add(_titleElement);
|
| - _canvas.add(_dartAnimationLayer);
|
| -
|
| - _newGameElement.clicked.listen((args) => GameAudio.click());
|
| -
|
| - MouseManager.setClickable(_titleElement, true);
|
| - MouseManager.getClickStream(_titleElement).listen((args) =>
|
| - _titleClickedEventHandle.add(EventArgs.empty));
|
| - }
|
| -
|
| - Stream<EventArgs> get newGameClick => _newGameElement.clicked;
|
| -
|
| - Game get game => _game;
|
| -
|
| - void set game(Game value) {
|
| - _game = value;
|
| - if (value == null) {
|
| - size = const Size(100, 100);
|
| - } else {
|
| - _updateSize(value.field.width, value.field.height);
|
| - }
|
| - }
|
| -
|
| - bool get canRevealTarget =>
|
| - _targetX != null && _game.canReveal(_targetX, _targetY);
|
| -
|
| - bool get canFlagTarget =>
|
| - _targetX != null && _game.canToggleFlag(_targetX, _targetY);
|
| -
|
| - void setGameManager(GameManager manager) {
|
| - _scoreElement.setGameManager(manager);
|
| - }
|
| -
|
| - void revealTarget() {
|
| - if (_targetX != null) {
|
| - game.reveal(_targetX, _targetY);
|
| - _target(null, null);
|
| - }
|
| - }
|
| -
|
| - void toggleTargetFlag() {
|
| - if (_targetX != null) {
|
| - final success = _toggleFlag(_targetX, _targetY);
|
| - if (success) {
|
| - _target(null, null);
|
| - }
|
| - }
|
| - }
|
| -
|
| - Stream get targetChanged => _targetChanged.stream;
|
| -
|
| - int get visualChildCount => 1;
|
| -
|
| - Thing getVisualChild(int index) {
|
| - assert(index == 0);
|
| - return _canvas;
|
| - }
|
| -
|
| - void update() {
|
| - super.update();
|
| - final offset = _scaledBoardOffset +
|
| - const Coordinate(_edgeOffset, _edgeOffset);
|
| -
|
| - _canvas.setTopLeft(_boardElement, offset);
|
| - _canvas.setTopLeft(_popAnimationLayer, offset);
|
| - _canvas.setTopLeft(_dartAnimationLayer, offset);
|
| -
|
| - // score offset
|
| - // end of the board - score width
|
| - final x = _scale * (40 + _backgroundSize.width - _boardOffset.x - _scoreElement.width);
|
| -
|
| - _canvas.setTopLeft(_scoreElement, new Coordinate(x, 0));
|
| - _canvas.getChildTransform(_scoreElement).scale(_scale, _scale);
|
| -
|
| - final newGameTopLeft = new Coordinate(
|
| - (_boardOffset.x + _newGameElement.width * 0.2) * _scale, 0);
|
| - _canvas.setTopLeft(_newGameElement, newGameTopLeft);
|
| - _canvas.getChildTransform(_newGameElement).scale(_scale, _scale);
|
| -
|
| - final titleMultiplier = 1.7;
|
| - final titleTopLeft = new Coordinate(_scale * 0.5 * (_backgroundSize.width -
|
| - _titleElement.width * titleMultiplier), 0);
|
| - _canvas.setTopLeft(_titleElement, titleTopLeft);
|
| - _canvas.getChildTransform(_titleElement)
|
| - .scale(titleMultiplier * _scale, titleMultiplier * _scale);
|
| - }
|
| -
|
| - void drawOverride(CanvasRenderingContext2D ctx) {
|
| - // draw children via super
|
| - super.drawOverride(ctx);
|
| -
|
| - // draw target element
|
| - _drawTarget(ctx);
|
| - }
|
| -
|
| - void _drawTarget(CanvasRenderingContext2D ctx) {
|
| - assert((_targetX == null) == (_targetY == null));
|
| - if (_targetX != null) {
|
| - final halfSize = SquareElement._size * 0.5;
|
| - var targetLoc = new Vector(_targetX, _targetY);
|
| - targetLoc = targetLoc.scale(SquareElement._size);
|
| -
|
| - ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';
|
| - CanvasUtil.centeredCircle(ctx,
|
| - targetLoc.x + halfSize, targetLoc.y + halfSize, halfSize);
|
| - ctx.fill();
|
| - }
|
| - }
|
| -
|
| - void _startPopAnimation(Coordinate start, [Iterable<Coordinate> reveals = null]) {
|
| - if(reveals == null) {
|
| - assert(game.state == GameState.lost);
|
| - reveals = new NumberEnumerable.fromRange(0, game.field.length)
|
| - .map((i) {
|
| - final t = game.field.getCoordinate(i);
|
| - final c = new Coordinate(t.item1, t.item2);
|
| - return new Tuple(c, game.getSquareState(c.x, c.y));
|
| - })
|
| - .where((t2) => t2.item2 == SquareState.bomb || t2.item2 == SquareState.hidden)
|
| - .map((t2) => t2.item1)
|
| - .toList();
|
| - }
|
| -
|
| - final values = reveals.map((c) {
|
| - final initialOffset = new Vector(SquareElement._size * c.x,
|
| - SquareElement._size * c.y);
|
| - final squareOffset = _popExplodeAnimationOffset + initialOffset;
|
| -
|
| - var delay = _popAnimationHitFrame + ((c - start).magnitude * 4).toInt();
|
| - delay += rnd.nextInt(10);
|
| -
|
| - return [c, initialOffset, squareOffset, delay];
|
| - }).toList();
|
| -
|
| - values.sort((a, b) {
|
| - final int da = a[3];
|
| - final int db = b[3];
|
| - return da.compareTo(db);
|
| - });
|
| -
|
| - for (final v in values) {
|
| - final Coordinate c = v[0];
|
| - final Vector initialOffset = v[1];
|
| - final Vector squareOffset = v[2];
|
| - final int delay = v[3];
|
| -
|
| - final ss = game.getSquareState(c.x, c.y);
|
| -
|
| - String texturePrefix;
|
| - int frameCount;
|
| -
|
| - switch (ss) {
|
| - case SquareState.revealed:
|
| - case SquareState.hidden:
|
| - texturePrefix = 'balloon_pop';
|
| - frameCount = 28;
|
| - break;
|
| - case SquareState.bomb:
|
| - texturePrefix = 'balloon_explode';
|
| - frameCount = 24;
|
| - break;
|
| - default:
|
| - throw 'not supported';
|
| - }
|
| -
|
| - final request = new TextureAnimationRequest(texturePrefix, frameCount, squareOffset,
|
| - delay: delay, initialFrame: 'balloon.png', initialFrameOffset: initialOffset);
|
| -
|
| - switch (ss) {
|
| - case SquareState.revealed:
|
| - case SquareState.hidden:
|
| - request.started.listen((args) => GameAudio.pop());
|
| - break;
|
| - case SquareState.bomb:
|
| - request.started.listen((args) => GameAudio.bomb());
|
| - break;
|
| - }
|
| -
|
| - _popAnimationLayer.add(request);
|
| - }
|
| - }
|
| -
|
| - void _startDartAnimation(List<Coordinate> points) {
|
| - assert(points.length >= 1);
|
| - GameAudio.throwDart();
|
| - for(final point in points) {
|
| - final squareOffset = _dartAnimationOffset +
|
| - new Vector(SquareElement._size * point.x, SquareElement._size * point.y);
|
| -
|
| - _dartAnimationLayer.add(new TextureAnimationRequest('dart_fly_shadow', 54, squareOffset));
|
| - _dartAnimationLayer.add(new TextureAnimationRequest('dart_fly', 54, squareOffset));
|
| - }
|
| - }
|
| -
|
| - void wireSquareMouseEvent(Thing square) {
|
| - MouseManager.getClickStream(square).listen(_squareClicked);
|
| - MouseManager.getMouseDownStream(square).listen(_squareMouseDown);
|
| - MouseManager.getMouseUpStream(square).listen(_squareMouseUp);
|
| - MouseManager.getMouseMoveStream(square).listen(_squareMouseMove);
|
| - }
|
| -
|
| - void _squareClicked(ThingMouseEventArgs args) {
|
| - if (!_game.gameEnded && _lastHoldUnfreeze == null) {
|
| - final SquareElement se = args.thing;
|
| - _click(se.x, se.y, args.shiftKey);
|
| - }
|
| - }
|
| -
|
| - void _squareMouseDown(ThingMouseEventArgs args) {
|
| - _lastHoldUnfreeze = null;
|
| - if (_mouseDownTimer != null) {
|
| - _mouseDownTimer.cancel();
|
| - }
|
| - final SquareElement se = args.thing;
|
| - _mouseDownElement = se;
|
| - _mouseDownTimer = new Timer(const Duration(seconds: 1), _mouseDownTimeoutHandle);
|
| - }
|
| -
|
| - void _squareMouseMove(ThingMouseEventArgs args) {
|
| - final SquareElement se = args.thing;
|
| - if (_mouseDownElement != se) {
|
| - _clearTimeout();
|
| - }
|
| - }
|
| -
|
| - void _squareMouseUp(ThingMouseEventArgs args) {
|
| - final SquareElement se = args.thing;
|
| - _clearTimeout();
|
| - }
|
| -
|
| - void _mouseDownTimeoutHandle() {
|
| - assert(_mouseDownTimer != null);
|
| - assert(_mouseDownElement != null);
|
| - _click(_mouseDownElement.x, _mouseDownElement.y, true);
|
| - _lastHoldUnfreeze = _mouseDownElement;
|
| - _clearTimeout();
|
| - }
|
| -
|
| - void _clearTimeout() {
|
| - if (_mouseDownTimer != null) {
|
| - _mouseDownTimer.cancel();
|
| - _mouseDownTimer = null;
|
| - }
|
| - _mouseDownElement = null;
|
| - }
|
| -
|
| - void _target(int x, int y) {
|
| - _targetX = x;
|
| - _targetY = y;
|
| - _targetChanged.add(null);
|
| - invalidateDraw();
|
| - }
|
| -
|
| - bool _toggleFlag(int x, int y) {
|
| - assert(!game.gameEnded);
|
| - final ss = game.getSquareState(x, y);
|
| - if (ss == SquareState.hidden) {
|
| - game.setFlag(x, y, true);
|
| - GameAudio.flag();
|
| - return true;
|
| - } else if (ss == SquareState.flagged) {
|
| - game.setFlag(x, y, false);
|
| - GameAudio.unflag();
|
| - return true;
|
| - }
|
| - return false;
|
| - }
|
| -
|
| - void _click(int x, int y, bool alt) {
|
| - assert(!game.gameEnded);
|
| - final ss = game.getSquareState(x, y);
|
| -
|
| - List<Coordinate> reveals = null;
|
| -
|
| - if (alt) {
|
| - if (ss == SquareState.hidden || ss == SquareState.flagged) {
|
| - _toggleFlag(x, y);
|
| - } else if (ss == SquareState.revealed) {
|
| - if (game.canReveal(x, y)) {
|
| - // get adjacent ballons
|
| - final adjHidden = game.field.getAdjacentIndices(x, y)
|
| - .map((i) {
|
| - final t = game.field.getCoordinate(i);
|
| - return new Coordinate(t.item1, t.item2);
|
| - })
|
| - .where((t) => game.getSquareState(t.x, t.y) == SquareState.hidden)
|
| - .toList();
|
| -
|
| - assert(adjHidden.length > 0);
|
| -
|
| - _startDartAnimation(adjHidden);
|
| - reveals = game.reveal(x, y);
|
| - }
|
| - }
|
| - } else {
|
| - if (ss == SquareState.hidden) {
|
| - _startDartAnimation([new Coordinate(x, y)]);
|
| - reveals = game.reveal(x, y);
|
| - }
|
| - }
|
| -
|
| - if (reveals != null && reveals.length > 0) {
|
| - assert(game.state != GameState.lost);
|
| - if (!alt) {
|
| - // if it was a normal click, the first item should be the clicked item
|
| - var first = reveals[0];
|
| - assert(first.x == x);
|
| - assert(first.y == y);
|
| - }
|
| - _startPopAnimation(new Coordinate(x, y), reveals);
|
| - } else if (game.state == GameState.lost) {
|
| - _startPopAnimation(new Coordinate(x, y));
|
| - }
|
| - }
|
| -
|
| - void _updateSize(int w, int h) {
|
| - final sizeX = _getScale(w, _backgroundSize.width, _backgroundHoleSize);
|
| - final sizeY = _getScale(h, _backgroundSize.height, _backgroundHoleSize);
|
| -
|
| - _canvas.size = size = new Size(sizeX, sizeY);
|
| -
|
| - // NOTE: width wins here. Need to do work to make left and right sides
|
| - // scale nicely when not a square
|
| - _scale = sizeX / _backgroundSize.width;
|
| - _scaledBoardOffset = _boardOffset.scale(_scale);
|
| -
|
| - _scaledInnerBox = new Box(_backgroundEdgeOffset * _scale, 0,
|
| - sizeX - 2 * _backgroundEdgeOffset * _scale, sizeY);
|
| - }
|
| -
|
| - static num _getScale(int count, num fullSize, num holeSize) {
|
| - final k = count * SquareElement._size + 2 * _edgeOffset;
|
| -
|
| - return k * fullSize / holeSize;
|
| - }
|
| -}
|
|
|