From 7bb22ab2bd898dec51c0dcbc696e9339c3113609 Mon Sep 17 00:00:00 2001 From: Liam Westby Date: Sun, 3 Jun 2018 16:47:45 -0500 Subject: [PATCH] Show countdown while waiting for players --- frontend/prebuild/src/app/entity/card.ts | 72 --------- .../prebuild/src/app/game/game.component.ts | 67 ++++---- .../src/app/{entity => overlay}/bar.ts | 0 frontend/prebuild/src/app/overlay/card.ts | 153 ++++++++++++++++++ 4 files changed, 185 insertions(+), 107 deletions(-) delete mode 100644 frontend/prebuild/src/app/entity/card.ts rename frontend/prebuild/src/app/{entity => overlay}/bar.ts (100%) create mode 100644 frontend/prebuild/src/app/overlay/card.ts diff --git a/frontend/prebuild/src/app/entity/card.ts b/frontend/prebuild/src/app/entity/card.ts deleted file mode 100644 index e4add83..0000000 --- a/frontend/prebuild/src/app/entity/card.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { Container, DisplayObject, Shape, Tween, Ease } from "createjs-module"; - -export class Card { - private readonly ACCENT_WIDTH = 10; - private readonly MARGIN = 20; - private readonly DURATION = 1000; - - object = new Container(); - - get displayObject(): DisplayObject { - return this.object; - } - - width: number; - height: number; - - background = new Shape(); - backgroundCommand: Object; - - accent = new Shape(); - accentCommand: Object; - - mask = new Shape(); - - contents = new Container(); - - get content(): Container { - return this.contents; - } - - get contentWidth(): number { - return this.width - (this.ACCENT_WIDTH + this.MARGIN); - } - - get contentHeight(): number { - return this.height; - } - - constructor(width: number, height: number, color = 'rgb(255, 255, 255)') { - this.width = width; - this.height = height; - - this.contents.setBounds(0, 0, this.contentWidth, this.contentHeight); - - this.accentCommand = this.accent.graphics.beginFill(color).rect(0, 0, this.ACCENT_WIDTH, 0).command; - - this.backgroundCommand = this.background.graphics.beginFill(color).rect(0, 0, 0, height).command; - this.background.alpha = 0; - - this.mask.graphics.beginFill('black').rect(this.ACCENT_WIDTH, 0, width - this.ACCENT_WIDTH, height); - - // Start offscreen to the left - this.contents.x = -(this.contents.getBounds().width); - this.contents.y = 0 - this.contents.alpha = 0 - this.contents.mask = this.mask; - - this.object.addChild(this.background); - this.object.addChild(this.accent); - this.object.addChild(this.contents); - } - - public show() { - Tween.get(this.backgroundCommand).to({w: this.width}, this.DURATION, Ease.quadOut); - Tween.get(this.background).to({alpha: 0.18}, this.DURATION, Ease.quadOut); - - Tween.get(this.accentCommand).to({h: this.height}, this.DURATION, Ease.quadOut); - - Tween.get(this.contents).to({alpha: 1}, this.DURATION, Ease.quadOut); - Tween.get(this.contents).to({x: this.ACCENT_WIDTH + this.MARGIN}, this.DURATION, Ease.quadOut); - } -} diff --git a/frontend/prebuild/src/app/game/game.component.ts b/frontend/prebuild/src/app/game/game.component.ts index ee5d00d..0c040a3 100644 --- a/frontend/prebuild/src/app/game/game.component.ts +++ b/frontend/prebuild/src/app/game/game.component.ts @@ -11,9 +11,9 @@ import { Obstacle } from '../entity/obstacle'; import { PlayerTooltip } from '../entity/player.tooltip'; import { Shape, Stage, Shadow, Text, Ticker, Container, Tween, CSSPlugin, Ease } from 'createjs-module'; import { Constants } from './constants'; -import { Card } from '../entity/card'; -import { bindCallback } from 'rxjs'; -import { Bar } from '../entity/bar'; +import { Card } from '../overlay/card'; +import { bindCallback, timer, Observable, Subscription } from 'rxjs'; +import { Bar } from '../overlay/bar'; @Component({ selector: 'app-game', @@ -41,7 +41,9 @@ export class GameComponent implements OnInit, OnDestroy { overlayContext: CanvasRenderingContext2D; overlayStage: Stage; - card: Card; + waitCard: Card; + waitingTimer: Observable; + waitingSub: Subscription; bar: Bar; players: Map = new Map(); @@ -393,44 +395,39 @@ export class GameComponent implements OnInit, OnDestroy { } startingCountdown(seconds) { - this.overlayStage.removeAllChildren(); + this.waitCard.hide(); + this.waitingSub.unsubscribe(); } waitForPlayers(seconds) { - const contentContainer = new Container(); - const content = new Text( - 'waiting for players', - 'small-caps 28px -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif', - 'rgba(255, 255, 255, 1)' - ); + if (this.waitingSub) { + this.waitingSub.unsubscribe(); + } + this.waitingTimer = timer(0, 1000); + this.waitingSub = this.waitingTimer.subscribe((t) => { + if (this.waitCard) { + this.waitCard.bodyString = `${seconds - t}`; + } + }); - this.bar = new Bar(150); - content.x = this.bar.width / 2 - content.getBounds().width / 2; - content.y = 5; - this.bar.contentContainer.addChild(content); + if (!this.waitCard) { + const width = 400; + const margin = 50; + this.waitCard = new Card(width, "waiting for players", `${seconds}`, true); + const card = this.waitCard.displayObject; + card.x = (Constants.BOARD_SIZE / 2) - (width / 2); + card.y = (Constants.BOARD_SIZE / 2) - (this.waitCard.height / 2); - this.overlayStage.addChild(this.bar.displayObject); - this.overlayStage.update(); + this.overlayStage.addChild(card); + this.overlayStage.update(); - Ticker.on('tick', (evt) => this.updateOverlay(evt)); - Ticker.framerate = 60; - this.bar.show(); + Ticker.on('tick', (evt) => this.updateOverlay(evt)); + Ticker.framerate = 60; + this.waitCard.show(); - // this.card = new Card(960, 150); - // content.x = this.card.contentWidth / 2 - content.getBounds().width / 2; - // content.y = 20; - // this.card.contents.addChild(content); - - // this.card.displayObject.x = Constants.BOARD_SIZE / 2 - this.card.width / 2; - // this.card.displayObject.y = Constants.BOARD_SIZE / 2 - this.card.height / 2; - - // // this.overlayStage.addChild(background); - // this.overlayStage.addChild(this.card.displayObject); - // this.overlayStage.update(); - - // Ticker.on('tick', (evt) => this.updateOverlay(evt)); - // Ticker.framerate = 60; - // this.card.show(); + } else { + this.waitCard.bodyString = `${seconds}`; + } } updateOverlay(event) { diff --git a/frontend/prebuild/src/app/entity/bar.ts b/frontend/prebuild/src/app/overlay/bar.ts similarity index 100% rename from frontend/prebuild/src/app/entity/bar.ts rename to frontend/prebuild/src/app/overlay/bar.ts diff --git a/frontend/prebuild/src/app/overlay/card.ts b/frontend/prebuild/src/app/overlay/card.ts new file mode 100644 index 0000000..f10fdbf --- /dev/null +++ b/frontend/prebuild/src/app/overlay/card.ts @@ -0,0 +1,153 @@ +import { Container, DisplayObject, Shape, Tween, Ease, Text, ColorFilter } from "createjs-module"; + +export class Card { + private static readonly ACCENT_WIDTH = 10; + private static readonly MARGIN = 20; + private static readonly DURATION = 500; + + private static readonly HEADER_TEXT_FONT = 'small-caps 36px -apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'; + private static readonly HEADER_TEXT_COLOR = 'rgba(255, 255, 255, 1)'; + + private static readonly BODY_TEXT_FONT = '64px "Avenir-Black", "Arial Black", "Roboto Black", sans-serif'; + private static readonly BODY_TEXT_COLOR = 'rgba(255, 255, 255, 1)'; + + object = new Container(); + + get displayObject(): DisplayObject { + return this.object; + } + + width: number; + + get height(): number { + return Card.MARGIN + + this.headerText.getBounds().height + + this.bodyText.getBounds().height + + Card.MARGIN; + } + + center: boolean; + + background = new Shape(); + backgroundCommand: Object; + + colorLayer = new Shape(); + colorLayerCommand: Object; + + accent = new Shape(); + accentCommand: Object; + + mask = new Shape(); + + headerText = new Text(); + + get headerString(): string { + return this.headerText.text; + } + + set headerString(newString: string) { + this.headerText.text = newString; + } + + bodyText = new Text(); + + get bodyString(): string { + return this.bodyText.text; + } + + set bodyString(newString: string) { + this.bodyText.text = newString; + } + + constructor(width: number, header: string, body: string, centerHorizontal = false, color = 'rgba(255, 255, 255, 1)') { + this.width = width; + this.center = centerHorizontal; + + // Start offscreen to the left + if (this.center) { + this.headerText.textAlign = 'center'; + } + + this.headerText.text = header; + this.headerText.font = Card.HEADER_TEXT_FONT; + this.headerText.color = Card.HEADER_TEXT_COLOR; + this.headerText.x = -(this.headerText.getBounds().width); + this.headerText.y = Card.MARGIN; + this.headerText.alpha = 0 + this.headerText.mask = this.mask; + + if (this.center) { + this.bodyText.textAlign = 'center'; + } + + this.bodyText.text = body; + this.bodyText.font = Card.BODY_TEXT_FONT; + this.bodyText.color = Card.BODY_TEXT_COLOR; + this.bodyText.x = -(this.bodyText.getBounds().width); + this.bodyText.y = this.headerText.y + this.headerText.getBounds().height; + + this.bodyText.alpha = 0 + this.bodyText.mask = this.mask; + + this.accentCommand = this.accent.graphics.beginFill(color).rect(0, 0, Card.ACCENT_WIDTH, 0).command; + + this.backgroundCommand = this.background.graphics.beginFill('black').rect(0, 0, 0, this.height).command; + this.background.alpha = 0; + + this.colorLayerCommand = this.colorLayer.graphics.beginFill(color).rect(0, 0, 0, this.height).command; + this.colorLayer.alpha = 0; + + this.mask.graphics.beginFill('black').rect(Card.ACCENT_WIDTH, 0, width - Card.ACCENT_WIDTH, this.height); + + this.object.addChild(this.background); + this.object.addChild(this.colorLayer); + this.object.addChild(this.accent); + this.object.addChild(this.headerText); + this.object.addChild(this.bodyText); + } + + public show() { + Tween.get(this.backgroundCommand).to({w: this.width}, Card.DURATION, Ease.quadOut); + Tween.get(this.background).to({alpha: 0.7}, Card.DURATION, Ease.quadOut); + + Tween.get(this.colorLayerCommand).to({w: this.width}, Card.DURATION, Ease.quadOut); + Tween.get(this.colorLayer).to({alpha: 0.18}, Card.DURATION, Ease.quadOut); + + Tween.get(this.accentCommand).to({h: this.height}, Card.DURATION, Ease.quadOut); + + Tween.get(this.headerText).to({alpha: 1}, Card.DURATION, Ease.quadOut); + + // Setting textalign to center effectively registers the text at its center point + // so no adjustment for the width of the text is needed. + const headerX = this.center + ? ((this.width - Card.ACCENT_WIDTH) / 2) + Card.ACCENT_WIDTH + : Card.ACCENT_WIDTH + Card.MARGIN; + Tween.get(this.headerText).to({x: headerX}, Card.DURATION, Ease.quadOut); + + Tween.get(this.bodyText).to({alpha: 1}, Card.DURATION, Ease.quadOut); + + // Setting textalign to center effectively registers the text at its center point + // so no adjustment for the width of the text is needed. + const bodyX = this.center + ? ((this.width - Card.ACCENT_WIDTH) / 2) + Card.ACCENT_WIDTH + : Card.ACCENT_WIDTH + Card.MARGIN; + Tween.get(this.bodyText).to({x: bodyX}, Card.DURATION, Ease.quadOut); + } + + public hide() { + Tween.get(this.backgroundCommand).to({w: 0}, Card.DURATION, Ease.quadOut); + Tween.get(this.background).to({alpha: 0}, Card.DURATION, Ease.quadOut); + + Tween.get(this.colorLayerCommand).to({w: 0}, Card.DURATION, Ease.quadOut); + Tween.get(this.colorLayer).to({alpha: 0}, Card.DURATION, Ease.quadOut); + + Tween.get(this.accentCommand).to({h: 0}, Card.DURATION, Ease.quadOut); + Tween.get(this.accent).to({y: this.height}, Card.DURATION, Ease.quadOut); + + Tween.get(this.headerText).to({alpha: 0}, Card.DURATION, Ease.quadOut); + Tween.get(this.headerText).to({x: -this.width}, Card.DURATION, Ease.quadOut); + + Tween.get(this.bodyText).to({alpha: 0}, Card.DURATION, Ease.quadOut); + Tween.get(this.bodyText).to({x: -this.width}, Card.DURATION, Ease.quadOut); + } +}