|
| 1 | +import {WIDTH, HEIGHT} from '../core/constants.js' |
| 2 | +import {lerp, unlerp} from '../core/utils.js' |
| 3 | +import {ErrorLog} from '../core/ErrorLog.js' |
| 4 | +import {MissingImageError} from './errors/MissingImageError.js' |
| 5 | +import {flagForDestructionOnReinit} from '../core/rendering.js' |
| 6 | +/* global PIXI */ |
| 7 | + |
| 8 | +export class EndScreenModule { |
| 9 | + constructor (assets) { |
| 10 | + this.states = [] |
| 11 | + this.scores = [] |
| 12 | + this.globalData = {} |
| 13 | + this.atEnd = false |
| 14 | + } |
| 15 | + |
| 16 | + static get name () { |
| 17 | + return 'endScreen' |
| 18 | + } |
| 19 | + |
| 20 | + updateScene (previousData, currentData, progress) { |
| 21 | + if (currentData.scores && progress === 1) { |
| 22 | + this.atEnd = true |
| 23 | + } else { |
| 24 | + this.atEnd = false |
| 25 | + } |
| 26 | + } |
| 27 | + |
| 28 | + handleFrameData (frameInfo, data) { |
| 29 | + let scores = null |
| 30 | + let spriteName = null |
| 31 | + if (data) { |
| 32 | + scores = data[0] |
| 33 | + spriteName = data[1] |
| 34 | + } |
| 35 | + const state = { |
| 36 | + number: frameInfo.number, |
| 37 | + scores, |
| 38 | + spriteName |
| 39 | + } |
| 40 | + if (scores) { |
| 41 | + this.scores = scores |
| 42 | + } |
| 43 | + if (spriteName) { |
| 44 | + this.spriteName = spriteName |
| 45 | + } |
| 46 | + this.states.push(state) |
| 47 | + return state |
| 48 | + } |
| 49 | + |
| 50 | + reinitScene (container, canvasData) { |
| 51 | + this.container = container |
| 52 | + this.endLayer = this.createEndScene(this) |
| 53 | + if (this.atEnd) { |
| 54 | + this.initEndScene() |
| 55 | + } |
| 56 | + this.container.addChild(this.endLayer) |
| 57 | + } |
| 58 | + |
| 59 | + animateScene (delta) { |
| 60 | + let step = Math.min(32, delta) |
| 61 | + |
| 62 | + if (this.atEnd) { |
| 63 | + if (!this.animationEnded) { |
| 64 | + this.renderEndScene(step) |
| 65 | + } |
| 66 | + } else { |
| 67 | + if (this.endTime > 0) { |
| 68 | + this.destroyEndScene() |
| 69 | + } |
| 70 | + this.endTime = 0 |
| 71 | + } |
| 72 | + } |
| 73 | + |
| 74 | + destroyEndScene () { |
| 75 | + this.animationEnded = false |
| 76 | + this.endLayer.visible = false |
| 77 | + } |
| 78 | + |
| 79 | + initEndScene () { |
| 80 | + this.animationEnded = false |
| 81 | + this.endLayer.visible = true |
| 82 | + } |
| 83 | + |
| 84 | + renderEndScene (step) { |
| 85 | + var endOfEnd = 10000 |
| 86 | + if (this.endTime === 0) { |
| 87 | + this.initEndScene() |
| 88 | + } |
| 89 | + |
| 90 | + var backS = 0 |
| 91 | + var backD = 400 |
| 92 | + var backP = unlerp(backS, backS + backD, this.endTime) |
| 93 | + this.endLayer.backgroundRanking.alpha = backP * 0.9 |
| 94 | + |
| 95 | + var logoS = 400 |
| 96 | + var logoD = 600 |
| 97 | + var logoP = unlerp(logoS, logoS + logoD, this.endTime) |
| 98 | + this.endLayer.titleRanking.scale.x = this.endLayer.titleRanking.scale.y = 0.001 + lerp(10, 0.8, logoP) |
| 99 | + this.endLayer.titleRanking.visible = !!logoP |
| 100 | + |
| 101 | + var rankS = 1000 |
| 102 | + var rankD = 300 |
| 103 | + for (let i = 0; i < this.finishers.length; ++i) { |
| 104 | + var p = unlerp(rankS + rankD * i, rankS + rankD * i + rankD, this.endTime) |
| 105 | + this.finishers[i].alpha = p |
| 106 | + } |
| 107 | + |
| 108 | + this.endTime += step |
| 109 | + |
| 110 | + if (this.endTime >= endOfEnd) { |
| 111 | + this.animationEnded = true |
| 112 | + } |
| 113 | + } |
| 114 | + |
| 115 | + handleGlobalData (players, globalData) { |
| 116 | + this.globalData = { |
| 117 | + players: players, |
| 118 | + playerCount: players.length |
| 119 | + } |
| 120 | + } |
| 121 | + |
| 122 | + generateText (text, size, align, color) { |
| 123 | + var textEl |
| 124 | + |
| 125 | + textEl = new PIXI.Text(text, { |
| 126 | + fontSize: Math.round(size / 1.2) + 'px', |
| 127 | + fontFamily: 'Lato', |
| 128 | + fontWeight: 'bold', |
| 129 | + fill: color |
| 130 | + }) |
| 131 | + textEl.lineHeight = Math.round(size / 1.2) |
| 132 | + if (align === 'right') { |
| 133 | + textEl.anchor.x = 1 |
| 134 | + } else if (align === 'center') { |
| 135 | + textEl.anchor.x = 0.5 |
| 136 | + } |
| 137 | + return textEl |
| 138 | + } |
| 139 | + |
| 140 | + createFinisher (finisher) { |
| 141 | + var layer = new PIXI.Container() |
| 142 | + |
| 143 | + var avatarContainer = new PIXI.Container() |
| 144 | + avatarContainer.y = 0 |
| 145 | + avatarContainer.x = 0 |
| 146 | + |
| 147 | + var backgroundAvatar = new PIXI.Graphics() |
| 148 | + backgroundAvatar.beginFill(0xffffff) |
| 149 | + backgroundAvatar.alpha = 0.1 |
| 150 | + backgroundAvatar.drawRect(0, 0, 240, 120) |
| 151 | + avatarContainer.addChild(backgroundAvatar) |
| 152 | + |
| 153 | + var avatarBorder = new PIXI.Graphics() |
| 154 | + avatarBorder.lineStyle(1, 0xffffff) |
| 155 | + avatarBorder.alpha = 0.5 |
| 156 | + avatarBorder.drawRect(0, 0, 120, 120) |
| 157 | + avatarContainer.addChild(avatarBorder) |
| 158 | + |
| 159 | + var avatar = new PIXI.Sprite(finisher.player.avatar) |
| 160 | + avatar.width = avatar.height = 120 |
| 161 | + |
| 162 | + var rank = this.generateText(finisher.rank.toString(), 76, 'center', finisher.player.color) |
| 163 | + rank.anchor.y = 0.5 |
| 164 | + rank.position.x = 160 |
| 165 | + rank.position.y = 56 |
| 166 | + avatarContainer.addChild(rank) |
| 167 | + |
| 168 | + var rankLetter = this.generateText(finisher.rank === 1 ? 'ST' : 'ND'.toString(), 34, 'left', finisher.player.color) |
| 169 | + rankLetter.position.x = 184 |
| 170 | + rankLetter.position.y = 32 |
| 171 | + avatarContainer.addChild(rankLetter) |
| 172 | + |
| 173 | + var hudAvatar = new PIXI.Container() |
| 174 | + hudAvatar.addChild(avatar) |
| 175 | + |
| 176 | + avatarContainer.addChild(hudAvatar) |
| 177 | + |
| 178 | + var name = this.generateText(finisher.player.name.toUpperCase(), 50, 'left', finisher.player.color) |
| 179 | + var scoreLabel = this.generateText(((finisher.score >= 0) ? finisher.score.toString() + ' points' : '-'), 64, 'left', finisher.player.color) |
| 180 | + |
| 181 | + name.x = 330 |
| 182 | + name.y = -4 |
| 183 | + scoreLabel.x = 330 |
| 184 | + scoreLabel.y = 50 |
| 185 | + |
| 186 | + layer.addChild(avatarContainer) |
| 187 | + layer.addChild(name) |
| 188 | + layer.addChild(scoreLabel) |
| 189 | + |
| 190 | + return layer |
| 191 | + } |
| 192 | + |
| 193 | + createEndScene () { |
| 194 | + var layer = new PIXI.Container() |
| 195 | + |
| 196 | + var background = new PIXI.Graphics() |
| 197 | + background.beginFill(0, 0.85) |
| 198 | + background.drawRect(0, 0, WIDTH, HEIGHT) |
| 199 | + background.endFill() |
| 200 | + |
| 201 | + layer.backgroundRanking = background |
| 202 | + |
| 203 | + let sprite = this.spriteName |
| 204 | + var titleRanking |
| 205 | + if (PIXI.utils.TextureCache.hasOwnProperty(sprite)) { |
| 206 | + titleRanking = new PIXI.Sprite.fromFrame(sprite) |
| 207 | + } else { |
| 208 | + ErrorLog.push(new MissingImageError(sprite)) |
| 209 | + titleRanking = new PIXI.Sprite(PIXI.Texture.EMPTY) |
| 210 | + } |
| 211 | + titleRanking.anchor.x = titleRanking.anchor.y = 0.5 |
| 212 | + layer.titleRanking = titleRanking |
| 213 | + |
| 214 | + titleRanking.position.x = WIDTH / 2 |
| 215 | + titleRanking.position.y = 230 |
| 216 | + |
| 217 | + var podium = [] |
| 218 | + for (var i = 0; i < this.globalData.playerCount; ++i) { |
| 219 | + podium.push({ |
| 220 | + score: this.scores[i], |
| 221 | + player: this.globalData.players[i], |
| 222 | + rank: 0 |
| 223 | + }) |
| 224 | + } |
| 225 | + podium.sort(function (a, b) { |
| 226 | + return b.score - a.score |
| 227 | + }) |
| 228 | + |
| 229 | + this.finishers = [] |
| 230 | + var finishers = new PIXI.Container() |
| 231 | + var curRank = 1 |
| 232 | + var elem |
| 233 | + for (i = 0; i < podium.length; ++i) { |
| 234 | + if (i > 0 && podium[i - 1].score !== podium[i].score) { |
| 235 | + curRank++ |
| 236 | + } |
| 237 | + |
| 238 | + podium[i].rank = curRank |
| 239 | + elem = this.createFinisher(podium[i]) |
| 240 | + finishers.addChild(elem) |
| 241 | + this.finishers.push(elem) |
| 242 | + } |
| 243 | + |
| 244 | + for (i = 0; i < this.finishers.length; ++i) { |
| 245 | + this.finishers[i].position.x = (WIDTH - this.finishers[0].width) / 2 |
| 246 | + this.finishers[i].position.y = i * 150 |
| 247 | + } |
| 248 | + finishers.y = 400 |
| 249 | + |
| 250 | + layer.addChild(background) |
| 251 | + layer.addChild(titleRanking) |
| 252 | + layer.addChild(finishers) |
| 253 | + |
| 254 | + layer.visible = false |
| 255 | + return layer |
| 256 | + } |
| 257 | +} |
0 commit comments