mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-27 14:33:59 -04:00
Move sync pvp status UI to control bar
Replaces level name UI for hero-ladder levels.
This commit is contained in:
parent
547ba692e1
commit
05cc9c2f46
8 changed files with 123 additions and 129 deletions
app
locale
styles/play/level
templates/play/level
views/play/level
|
@ -207,6 +207,8 @@
|
|||
failing: "Failing"
|
||||
action_timeline: "Action Timeline"
|
||||
click_to_select: "Click on a unit to select it."
|
||||
control_bar_multiplayer: "Multiplayer"
|
||||
control_bar_join_game: "Join Game"
|
||||
reload: "Reload"
|
||||
reload_title: "Reload All Code?"
|
||||
reload_really: "Are you sure you want to reload this level back to the beginning?"
|
||||
|
|
|
@ -112,6 +112,36 @@
|
|||
color: white
|
||||
font-size: 18px
|
||||
|
||||
.multiplayer-area-container
|
||||
position: relative
|
||||
width: 100%
|
||||
height: 50px
|
||||
pointer-events: none
|
||||
|
||||
.multiplayer-area
|
||||
min-width: 200px
|
||||
max-width: 293px
|
||||
height: 60px
|
||||
margin: 0 auto
|
||||
padding: 8px
|
||||
border-image: url(/images/level/control_bar_level_name_background.png) 30 fill round
|
||||
border-width: 0 15px 15px 15px
|
||||
text-align: center
|
||||
position: absolute
|
||||
left: 50%
|
||||
cursor: pointer
|
||||
pointer-events: all
|
||||
@include translate(-50%, 0)
|
||||
|
||||
.multiplayer-label
|
||||
font-size: 12px
|
||||
color: $control-yellow-highlight
|
||||
margin-bottom: -5px
|
||||
|
||||
.multiplayer-status
|
||||
color: white
|
||||
font-size: 18px
|
||||
|
||||
.buttons-area
|
||||
position: absolute
|
||||
right: 35px
|
||||
|
@ -167,6 +197,12 @@ html.no-borderimage
|
|||
background: transparent url(/images/level/control_bar_level_name_background.png)
|
||||
background-size: contain
|
||||
background-repeat: no-repeat
|
||||
#control-bar-view .multiplayer-area
|
||||
border: 0
|
||||
background: transparent url(/images/level/control_bar_level_name_background.png)
|
||||
background-size: contain
|
||||
background-repeat: no-repeat
|
||||
|
||||
|
||||
body:not(.ipad)
|
||||
@media only screen and (max-width: 1300px)
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
// TODO: Replace this devart with nice shinies
|
||||
|
||||
#multiplayer-status-view
|
||||
position: absolute
|
||||
|
||||
.player-count
|
||||
color: white
|
||||
.players-available
|
||||
color: lightblue
|
||||
.players-unavailable
|
||||
color: fuchsia
|
||||
.game-status
|
||||
color: lightgreen
|
|
@ -9,10 +9,19 @@
|
|||
.glyphicon.glyphicon-play
|
||||
span(data-i18n="nav.play").home-text Levels
|
||||
|
||||
.level-name-area-container
|
||||
.level-name-area
|
||||
.level-label(data-i18n="play_level.level")
|
||||
.level-name= worldName
|
||||
if isMultiplayerLevel
|
||||
.multiplayer-area-container
|
||||
.multiplayer-area
|
||||
.multiplayer-label(data-i18n="play_level.control_bar_multiplayer")
|
||||
if multiplayerStatus
|
||||
.multiplayer-status= multiplayerStatus
|
||||
else
|
||||
.multiplayer-status(data-i18n="play_level.control_bar_join_game")
|
||||
else
|
||||
.level-name-area-container
|
||||
.level-name-area
|
||||
.level-label(data-i18n="play_level.level")
|
||||
.level-name= worldName
|
||||
|
||||
.buttons-area
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
//- TODO: Replace this devart with nice shinies
|
||||
|
||||
div
|
||||
button#multiplayer-button Multiplayer
|
||||
//- span.spr
|
||||
//- span.player-count #{playerCount} total players
|
||||
span.spr
|
||||
span.players-available #{playersAvailable} available
|
||||
span.spr
|
||||
span.players-unavailable #{playersUnavailable} playing
|
||||
span.spr
|
||||
span.game-status #{status}
|
|
@ -3,8 +3,10 @@ template = require 'templates/play/level/control_bar'
|
|||
{me} = require 'lib/auth'
|
||||
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
RealTimeModel = require 'models/RealTimeModel'
|
||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
|
||||
module.exports = class ControlBarView extends CocoView
|
||||
id: 'control-bar-view'
|
||||
|
@ -20,13 +22,17 @@ module.exports = class ControlBarView extends CocoView
|
|||
'click #game-menu-button': 'showGameMenuModal'
|
||||
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {}
|
||||
'click .home a': 'onClickHome'
|
||||
'click .multiplayer-area': 'onClickMultiplayer'
|
||||
|
||||
constructor: (options) ->
|
||||
@worldName = options.worldName
|
||||
@session = options.session
|
||||
@level = options.level
|
||||
@levelID = @level.get('slug')
|
||||
@spectateGame = options.spectateGame ? false
|
||||
super options
|
||||
if @isMultiplayerLevel = @level.get('type') in ['hero-ladder']
|
||||
@multiplayerStatusManager = new MultiplayerStatusManager @levelID, @onMultiplayerStateChanged
|
||||
|
||||
setBus: (@bus) ->
|
||||
|
||||
|
@ -40,11 +46,15 @@ module.exports = class ControlBarView extends CocoView
|
|||
text += " (#{numPlayers})" if numPlayers > 1
|
||||
$('#multiplayer-button', @$el).text(text)
|
||||
|
||||
onMultiplayerStateChanged: => @render?()
|
||||
|
||||
getRenderData: (c={}) ->
|
||||
super c
|
||||
c.worldName = @worldName
|
||||
c.multiplayerEnabled = @session.get('multiplayer')
|
||||
c.ladderGame = @level.get('type') in ['ladder', 'hero-ladder']
|
||||
if c.isMultiplayerLevel = @isMultiplayerLevel
|
||||
c.multiplayerStatus = @multiplayerStatusManager?.status
|
||||
c.spectateGame = @spectateGame
|
||||
@homeViewArgs = [{supermodel: @supermodel}]
|
||||
if @level.get('type', true) in ['ladder', 'ladder-tutorial', 'hero-ladder']
|
||||
|
@ -71,7 +81,7 @@ module.exports = class ControlBarView extends CocoView
|
|||
@openModalView gameMenuModal
|
||||
@listenToOnce gameMenuModal, 'change-hero', ->
|
||||
@setupManager?.destroy()
|
||||
@setupManager = new LevelSetupManager({supermodel: @supermodel, levelID: @level.get('slug'), parent: @, session: @session})
|
||||
@setupManager = new LevelSetupManager({supermodel: @supermodel, levelID: @levelID, parent: @, session: @session})
|
||||
@setupManager.open()
|
||||
|
||||
onClickHome: (e) ->
|
||||
|
@ -79,6 +89,9 @@ module.exports = class ControlBarView extends CocoView
|
|||
e.stopImmediatePropagation()
|
||||
Backbone.Mediator.publish 'router:navigate', route: @homeLink, viewClass: @homeViewClass, viewArgs: @homeViewArgs
|
||||
|
||||
onClickMultiplayer: (e) ->
|
||||
@openModalView new GameMenuModal showTab: 'multiplayer', level: @level, session: @session, supermodel: @supermodel
|
||||
|
||||
onDisableControls: (e) -> @toggleControls e, false
|
||||
onEnableControls: (e) -> @toggleControls e, true
|
||||
toggleControls: (e, enabled) ->
|
||||
|
@ -94,4 +107,62 @@ module.exports = class ControlBarView extends CocoView
|
|||
|
||||
destroy: ->
|
||||
@setupManager?.destroy()
|
||||
@multiplayerStatusManager?.destroy()
|
||||
super()
|
||||
|
||||
# MultiplayerStatusManager ######################################################
|
||||
#
|
||||
# Manages the multiplayer status, and calls @statusChangedCallback when it changes.
|
||||
#
|
||||
# It monitors these:
|
||||
# Real-time multiplayer players
|
||||
# Internal multiplayer status
|
||||
#
|
||||
# Real-time state variables:
|
||||
# @playersCollection - Real-time multiplayer players
|
||||
#
|
||||
# TODO: Not currently using player counts. Should remove if we keep simple design.
|
||||
#
|
||||
class MultiplayerStatusManager
|
||||
|
||||
constructor: (@levelID, @statusChangedCallback) ->
|
||||
@status = ''
|
||||
# @players = {}
|
||||
# @playersCollection = new RealTimeCollection('multiplayer_players/' + @levelID)
|
||||
# @playersCollection.on 'add', @onPlayerAdded
|
||||
# @playersCollection.each (player) => @onPlayerAdded player
|
||||
Backbone.Mediator.subscribe 'real-time-multiplayer:player-status', @onMultiplayerPlayerStatus
|
||||
|
||||
destroy: ->
|
||||
Backbone.Mediator.unsubscribe 'real-time-multiplayer:player-status', @onMultiplayerPlayerStatus
|
||||
# @playersCollection?.off 'add', @onPlayerAdded
|
||||
# player.off 'change', @onPlayerChanged for id, player of @players
|
||||
|
||||
onMultiplayerPlayerStatus: (e) =>
|
||||
@status = e.status
|
||||
@statusChangedCallback()
|
||||
|
||||
# onPlayerAdded: (player) =>
|
||||
# unless player.id is me.id
|
||||
# @players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
||||
# @players[player.id].on 'change', @onPlayerChanged
|
||||
# @countPlayers player
|
||||
#
|
||||
# onPlayerChanged: (player) =>
|
||||
# @countPlayers player
|
||||
#
|
||||
# countPlayers: (changedPlayer) =>
|
||||
# # TODO: save this stale hearbeat threshold setting somewhere
|
||||
# staleHeartbeat = new Date()
|
||||
# staleHeartbeat.setMinutes staleHeartbeat.getMinutes() - 3
|
||||
# @playerCount = 0
|
||||
# @playersCollectionAvailable = 0
|
||||
# @playersCollectionUnavailable = 0
|
||||
# @playersCollection.each (player) =>
|
||||
# # Assume changedPlayer is fresher than entry in @playersCollection collection
|
||||
# player = changedPlayer if changedPlayer? and player.id is changedPlayer.id
|
||||
# unless staleHeartbeat >= new Date(player.get('heartbeat'))
|
||||
# @playerCount++
|
||||
# @playersCollectionAvailable++ if player.get('state') is 'available'
|
||||
# @playersCollectionUnavailable++ if player.get('state') is 'unavailable'
|
||||
# @statusChangedCallback()
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/play/level/multiplayer-status'
|
||||
{me} = require 'lib/auth'
|
||||
RealTimeModel = require 'models/RealTimeModel'
|
||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
|
||||
# Real-time Multiplayer ######################################################
|
||||
#
|
||||
# This view displays the real-time multiplayer status for the current level.
|
||||
#
|
||||
# It performs these actions:
|
||||
# Multiplayer button into game-menu multiplayer section
|
||||
# Display number of players waiting for an opponent in this level
|
||||
# Display number of players current playing a pvp game in this level
|
||||
# Status for user's current real-time multiplayer session
|
||||
#
|
||||
# It monitors these:
|
||||
# Real-time multiplayer players
|
||||
# Internal multiplayer status
|
||||
#
|
||||
# Real-time state variables:
|
||||
# @playersCollection - Real-time multiplayer players
|
||||
|
||||
module.exports = class MultiplayerStatusView extends CocoView
|
||||
id: 'multiplayer-status-view'
|
||||
template: template
|
||||
|
||||
subscriptions:
|
||||
'real-time-multiplayer:player-status': 'onRealTimeMultiplayerPlayerStatus'
|
||||
|
||||
events:
|
||||
'click #multiplayer-button': 'onClickMultiplayerButton'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@session = options.session
|
||||
@level = options.level
|
||||
@levelID = options.levelID
|
||||
@status = ''
|
||||
@players = {}
|
||||
@playersCollection = new RealTimeCollection('multiplayer_players/' + @levelID)
|
||||
@playersCollection.on 'add', @onPlayerAdded
|
||||
@playersCollection.each (player) => @onPlayerAdded player
|
||||
|
||||
destroy: ->
|
||||
@playersCollection?.off 'add', @onPlayerAdded
|
||||
player.off 'change', @onPlayerChanged for id, player of @players
|
||||
super()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.playerCount = @playerCount
|
||||
c.playersAvailable = @playersCollectionAvailable
|
||||
c.playersUnavailable = @playersCollectionUnavailable
|
||||
c.status = @status
|
||||
c
|
||||
|
||||
onRealTimeMultiplayerPlayerStatus: (e) ->
|
||||
@status = e.status
|
||||
@render?()
|
||||
|
||||
onClickMultiplayerButton: (e) ->
|
||||
@openModalView new GameMenuModal showTab: 'multiplayer', level: @level, session: @session, supermodel: @supermodel
|
||||
|
||||
onPlayerAdded: (player) =>
|
||||
# console.log 'MultiplayerStatusView onPlayerAdded', player
|
||||
unless player.id is me.id
|
||||
@players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
||||
@players[player.id].on 'change', @onPlayerChanged
|
||||
@countPlayers player
|
||||
|
||||
onPlayerChanged: (player) =>
|
||||
# console.log 'MultiplayerStatusView onPlayerChanged', player
|
||||
@countPlayers player
|
||||
|
||||
countPlayers: (changedPlayer) =>
|
||||
# TODO: save this stale hearbeat threshold setting somewhere
|
||||
staleHeartbeat = new Date()
|
||||
staleHeartbeat.setMinutes staleHeartbeat.getMinutes() - 3
|
||||
@playerCount = 0
|
||||
@playersCollectionAvailable = 0
|
||||
@playersCollectionUnavailable = 0
|
||||
@playersCollection.each (player) =>
|
||||
# Assume changedPlayer is fresher than entry in @playersCollection collection
|
||||
player = changedPlayer if changedPlayer? and player.id is changedPlayer.id
|
||||
unless staleHeartbeat >= new Date(player.get('heartbeat'))
|
||||
@playerCount++
|
||||
@playersCollectionAvailable++ if player.get('state') is 'available'
|
||||
@playersCollectionUnavailable++ if player.get('state') is 'unavailable'
|
||||
# console.log 'MultiplayerStatusView countPlayers', @playerCount, @playersCollectionAvailable, @playersCollectionUnavailable
|
||||
@render()
|
||||
|
|
@ -36,7 +36,6 @@ GoldView = require './LevelGoldView'
|
|||
VictoryModal = require './modal/VictoryModal'
|
||||
HeroVictoryModal = require './modal/HeroVictoryModal'
|
||||
InfiniteLoopModal = require './modal/InfiniteLoopModal'
|
||||
MultiplayerStatusView = require './MultiplayerStatusView'
|
||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||
|
||||
PROFILE_ME = false
|
||||
|
@ -255,8 +254,6 @@ module.exports = class PlayLevelView extends RootView
|
|||
@insertSubView new HUDView {level: @level}
|
||||
@insertSubView new LevelDialogueView {level: @level}
|
||||
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
|
||||
if @level.get('type') in ['hero-ladder']
|
||||
@insertSubView new MultiplayerStatusView levelID: @levelID, session: @session, level: @level
|
||||
@insertSubView new ProblemAlertView {}
|
||||
worldName = utils.i18n @level.attributes, 'name'
|
||||
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue