From c88d0aecf263f041d0d5b52fc82c09b560093bc1 Mon Sep 17 00:00:00 2001 From: Alexander Zeier Date: Tue, 12 Apr 2016 15:58:30 +0200 Subject: [PATCH 1/3] Wait for TexturePreloader before displaying board --- ts/TexturePreloader.ts | 37 +++++++++++++++++++++++++++++++---- ts/components/GameWidget.tsx | 1 + ts/components/GameWrapper.tsx | 10 ++++++++++ ts/interfaces.d.ts | 2 ++ ts/run.tsx | 3 +++ 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/ts/TexturePreloader.ts b/ts/TexturePreloader.ts index 33e3bd02..ba0151ea 100644 --- a/ts/TexturePreloader.ts +++ b/ts/TexturePreloader.ts @@ -7,6 +7,9 @@ class TexturePreloader extends Stream.Writable { protected textureQueue = ['GAME_005']; protected images = []; private working = 0; + private assetCount = 0; + private textureCount = 0; + private heroPowerCount = 0; protected assetQueue = ['cardback', 'hero_frame', 'hero_power', 'inhand_minion', 'inhand_spell', 'inhand_weapon', 'inhand_minion_legendary', 'mana_crystal', 'inplay_minion', 'effect_sleep', 'hero_power_exhausted', 'hero_armor', 'hero_attack', 'icon_deathrattle', 'icon_inspire', @@ -55,18 +58,23 @@ class TexturePreloader extends Stream.Writable { this.consume(); }; + let isAsset = false; + let isHeroPower = false; let file = this.assetQueue.shift(); if (!!this.assetDirectory && file) { file = this.assetDirectory + 'images/' + file + '.png'; + isAsset = true; } else { let cardId = this.textureQueue.shift(); - if (!this.cards.get(cardId)) { + let card = this.cards.get(cardId); + if (!card) { console.warn('No texture for ' + cardId + ' to preload'); next(); return; } - file = this.textureDirectory + this.cards.get(cardId).texture + '.jpg'; + isHeroPower = card.type == 'HERO_POWER' + file = this.textureDirectory + card.texture + '.jpg'; } if (this.fired[file]) { @@ -76,9 +84,22 @@ class TexturePreloader extends Stream.Writable { this.fired[file] = true; + let updateProgress = (asset: boolean, heroPower: boolean) => { + if (asset) { + this.assetCount++; + } + else { + this.textureCount++; + if (heroPower) { + this.heroPowerCount++; + } + } + next(); + }; + let image = new Image; - image.onload = next; - image.onerror = next; + image.onload =() => updateProgress(isAsset, isHeroPower); + image.onerror = () => updateProgress(isAsset, isHeroPower); image.src = file; this.images[this.images.length] = image; @@ -89,6 +110,14 @@ class TexturePreloader extends Stream.Writable { public canPreload(): boolean { return !!this.assetDirectory || !!this.textureDirectory; } + + public texturesReady(): boolean { + return (this.textureCount > 20 || !this.working) && this.heroPowerCount > 1; + } + + public assetsReady(): boolean { + return this.assetCount > 10 || !this.working; + } } export default TexturePreloader; diff --git a/ts/components/GameWidget.tsx b/ts/components/GameWidget.tsx index 29de451f..b93c527e 100644 --- a/ts/components/GameWidget.tsx +++ b/ts/components/GameWidget.tsx @@ -125,6 +125,7 @@ class GameWidget extends React.Component { assetDirectory={this.props.assetDirectory} textureDirectory={this.props.textureDirectory} cards={this.state.cards} swapPlayers={this.state.swapPlayers} cardOracle={this.state.isRevealingCards && this.state.cardOracle} + preloader={this.props.preloader} />); if (this.props.scrubber) { diff --git a/ts/components/GameWrapper.tsx b/ts/components/GameWrapper.tsx index a38677c3..bf176a09 100644 --- a/ts/components/GameWrapper.tsx +++ b/ts/components/GameWrapper.tsx @@ -8,9 +8,11 @@ import Option from "../Option"; import PlayerEntity from "../Player"; import {InteractiveBackend, CardOracleProps, AssetDirectoryProps, TextureDirectoryProps} from "../interfaces"; import {Zone} from "../enums"; +import TexturePreloader from "../TexturePreloader"; interface GameWrapperProps extends CardDataProps, CardOracleProps, AssetDirectoryProps, TextureDirectoryProps, React.Props { state: GameState; + preloader?: TexturePreloader; interaction?: InteractiveBackend; swapPlayers?: boolean; } @@ -51,6 +53,14 @@ class GameWrapper extends React.Component { return

Waiting for players…

; } + if (this.props.preloader && !this.props.preloader.assetsReady()) { + return

Waiting for assets…

; + } + + if (this.props.preloader && !this.props.preloader.texturesReady()) { + return

Waiting for textures…

; + } + // check if we need to swap the players if (!this.hasCheckedForSwap) { let player = players.first(); diff --git a/ts/interfaces.d.ts b/ts/interfaces.d.ts index e8deea7c..dc122634 100644 --- a/ts/interfaces.d.ts +++ b/ts/interfaces.d.ts @@ -9,6 +9,7 @@ import GameStateSink from "./state/GameStateSink"; import GameStateScrubber from "./state/GameStateScrubber"; import GameStateHistory from "./state/GameStateHistory"; import Player from "./Player"; +import TexturePreloader from "./TexturePreloader"; export interface DropTargetProps { connectDropTarget?(jsx); @@ -154,6 +155,7 @@ export interface GameWidgetProps extends AssetDirectoryProps, TextureDirectoryPr getImageURL?: (cardId: string) => string; exitGame?: () => void; cardOracle: CardOracle; + preloader?: TexturePreloader; width?: any; height?: any; } diff --git a/ts/run.tsx b/ts/run.tsx index fe255ab2..91ed5b63 100644 --- a/ts/run.tsx +++ b/ts/run.tsx @@ -98,6 +98,9 @@ class Viewer { this.opts.sink = sink; this.opts.scrubber = scrubber; this.opts.cardOracle = decoder; + if (preloader.canPreload()) { + this.opts.preloader = preloader; + } this.render(); } From 407b6b555fa38991ab749248ef2223414e024c09 Mon Sep 17 00:00:00 2001 From: Alexander Zeier Date: Wed, 13 Apr 2016 18:03:33 +0200 Subject: [PATCH 2/3] Add loading screen --- assets/images/logo.png | Bin 0 -> 11690 bytes less/joust.less | 59 +++++++++++++++++++++++++++++++--- ts/components/GameWrapper.tsx | 54 +++++++++++++++++++++++++++---- 3 files changed, 102 insertions(+), 11 deletions(-) create mode 100644 assets/images/logo.png diff --git a/assets/images/logo.png b/assets/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..deb3f731fa5575f9cb053e85e461147dd63e6f58 GIT binary patch literal 11690 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 ykv4vlR)72SiOW?sfJ`E5 { private hasCheckedForSwap = false; private swapPlayers = false; + private lastLog: string; + private currentMessage: string; + private lastUpdate = 0; + private messages = ['Sorting decks...', 'Painting cards...', 'Calculating lethal...', 'Calling customer service...', + 'SMOrc', 'Verifying the face is the place...', 'Summoning heroes...', 'Nerfing cards...', 'Buffing cards...']; public render(): JSX.Element { var gameState = this.props.state; if (!gameState) { - return

Waiting for game state…

; + this.log('Waiting for game state...'); + return this.getLoadingScreen(); } var entityTree = gameState.getEntityTree(); @@ -38,27 +44,32 @@ class GameWrapper extends React.Component { // check if any entites are present var allEntities = gameState.getEntities(); if (!allEntities) { - return

Waiting for entities…

; + this.log('Waiting for entities...'); + return this.getLoadingScreen(); } // find the game entity var game = allEntities.filter(GameWrapper.filterByCardType(CardType.GAME)).first(); if (!game) { - return

Waiting for game…

; + this.log('Waiting for game...'); + return this.getLoadingScreen(); } // find the players var players = allEntities.filter(GameWrapper.filterByCardType(CardType.PLAYER)) as Immutable.Iterable; if (players.count() == 0) { - return

Waiting for players…

; + this.log('Waiting for players...'); + return this.getLoadingScreen(players); } if (this.props.preloader && !this.props.preloader.assetsReady()) { - return

Waiting for assets…

; + this.log('Waiting for assets...'); + return this.getLoadingScreen(players); } if (this.props.preloader && !this.props.preloader.texturesReady()) { - return

Waiting for textures…

; + this.log('Waiting for textures...'); + return this.getLoadingScreen(players); } // check if we need to swap the players @@ -110,6 +121,35 @@ class GameWrapper extends React.Component { return !!entity && entity.getCardType() === cardType; }; }; + + private getLoadingScreenMessage(): string { + var now = new Date().getTime(); + if (!!this.messages.length && (now - this.lastUpdate) > 3000) { + var index = Math.floor(Math.random()*this.messages.length); + this.currentMessage = this.messages.splice(index, 1)[0]; + this.lastUpdate = now; + } + return this.currentMessage; + } + + private getLoadingScreen(players?: Immutable.Iterable): JSX.Element { + return
{players ? +
+ {players.first().getName()} + VS + {players.last().getName()} +
:
} + + {this.getLoadingScreenMessage()} +
; + } + + private log(message: string) { + if (message != this.lastLog) { + console.debug(message); + this.lastLog = message; + } + } } export default GameWrapper; From 178363d57f3299f50855077e9e94e5e2fa365746 Mon Sep 17 00:00:00 2001 From: Alexander Zeier Date: Wed, 13 Apr 2016 19:11:44 +0200 Subject: [PATCH 3/3] [fixup] moved loading screen to it's own component --- ts/components/GameWrapper.tsx | 41 +++++++-------------------------- ts/components/LoadingScreen.tsx | 40 ++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 33 deletions(-) create mode 100644 ts/components/LoadingScreen.tsx diff --git a/ts/components/GameWrapper.tsx b/ts/components/GameWrapper.tsx index 1dc8f0d9..6cca8138 100644 --- a/ts/components/GameWrapper.tsx +++ b/ts/components/GameWrapper.tsx @@ -9,6 +9,7 @@ import PlayerEntity from "../Player"; import {InteractiveBackend, CardOracleProps, AssetDirectoryProps, TextureDirectoryProps} from "../interfaces"; import {Zone} from "../enums"; import TexturePreloader from "../TexturePreloader"; +import LoadingScreen from "./LoadingScreen" interface GameWrapperProps extends CardDataProps, CardOracleProps, AssetDirectoryProps, TextureDirectoryProps, React.Props { state: GameState; @@ -26,16 +27,12 @@ class GameWrapper extends React.Component { private hasCheckedForSwap = false; private swapPlayers = false; private lastLog: string; - private currentMessage: string; - private lastUpdate = 0; - private messages = ['Sorting decks...', 'Painting cards...', 'Calculating lethal...', 'Calling customer service...', - 'SMOrc', 'Verifying the face is the place...', 'Summoning heroes...', 'Nerfing cards...', 'Buffing cards...']; public render(): JSX.Element { var gameState = this.props.state; if (!gameState) { this.log('Waiting for game state...'); - return this.getLoadingScreen(); + return ; } var entityTree = gameState.getEntityTree(); @@ -45,31 +42,31 @@ class GameWrapper extends React.Component { var allEntities = gameState.getEntities(); if (!allEntities) { this.log('Waiting for entities...'); - return this.getLoadingScreen(); + return ; } // find the game entity var game = allEntities.filter(GameWrapper.filterByCardType(CardType.GAME)).first(); if (!game) { this.log('Waiting for game...'); - return this.getLoadingScreen(); + return ; } // find the players var players = allEntities.filter(GameWrapper.filterByCardType(CardType.PLAYER)) as Immutable.Iterable; if (players.count() == 0) { - this.log('Waiting for players...'); - return this.getLoadingScreen(players); + this.log('Waiting for players...') + return ; } if (this.props.preloader && !this.props.preloader.assetsReady()) { this.log('Waiting for assets...'); - return this.getLoadingScreen(players); + return ; } if (this.props.preloader && !this.props.preloader.texturesReady()) { this.log('Waiting for textures...'); - return this.getLoadingScreen(players); + return ; } // check if we need to swap the players @@ -122,28 +119,6 @@ class GameWrapper extends React.Component { }; }; - private getLoadingScreenMessage(): string { - var now = new Date().getTime(); - if (!!this.messages.length && (now - this.lastUpdate) > 3000) { - var index = Math.floor(Math.random()*this.messages.length); - this.currentMessage = this.messages.splice(index, 1)[0]; - this.lastUpdate = now; - } - return this.currentMessage; - } - - private getLoadingScreen(players?: Immutable.Iterable): JSX.Element { - return
{players ? -
- {players.first().getName()} - VS - {players.last().getName()} -
:
} - - {this.getLoadingScreenMessage()} -
; - } - private log(message: string) { if (message != this.lastLog) { console.debug(message); diff --git a/ts/components/LoadingScreen.tsx b/ts/components/LoadingScreen.tsx new file mode 100644 index 00000000..0793b72f --- /dev/null +++ b/ts/components/LoadingScreen.tsx @@ -0,0 +1,40 @@ +import * as React from "react"; +import PlayerEntity from "../Player"; +import {AssetDirectoryProps} from "../interfaces"; + +interface LoadingScreenProps extends AssetDirectoryProps, React.Props { + players?: Immutable.Iterable; +} + +class LoadingScreen extends React.Component { + + private currentMessage: string; + private lastUpdate = 0; + private messages = ['Sorting decks...', 'Painting cards...', 'Calculating lethal...', 'Calling customer service...', + 'SMOrc', 'Verifying the face is the place...', 'Summoning heroes...', 'Nerfing cards...', 'Buffing cards...']; + + + private getMessage(): string { + var now = new Date().getTime(); + if (!!this.messages.length && (now - this.lastUpdate) > 3000) { + var index = Math.floor(Math.random()*this.messages.length); + this.currentMessage = this.messages.splice(index, 1)[0]; + this.lastUpdate = now; + } + return this.currentMessage; + } + + public render(): JSX.Element { + return
{this.props.players ? +
+ {this.props.players.first().getName()} + VS + {this.props.players.last().getName()} +
:
} + + {this.getMessage()} +
; + } +} + +export default LoadingScreen;