Press Start to begin playing levels. Fixed #1574.
This commit is contained in:
parent
2872de71ce
commit
0d495ba36e
12 changed files with 23 additions and 24 deletions
app
lib
locale
models
schemas/subscriptions
styles/play/level
templates/play/level
views
|
@ -92,7 +92,7 @@ module.exports = class Angel extends CocoClass
|
||||||
Backbone.Mediator.publish 'god:user-code-problem', problem: event.data.problem
|
Backbone.Mediator.publish 'god:user-code-problem', problem: event.data.problem
|
||||||
when 'world-load-progress-changed'
|
when 'world-load-progress-changed'
|
||||||
Backbone.Mediator.publish 'god:world-load-progress-changed', progress: event.data.progress
|
Backbone.Mediator.publish 'god:world-load-progress-changed', progress: event.data.progress
|
||||||
unless event.data.progress is 1 or @work.preload or @work.headless or @work.synchronous or @deserializationQueue.length or @shared.firstWorld
|
unless event.data.progress is 1 or @work.preload or @work.headless or @work.synchronous or @deserializationQueue.length or (@shared.firstWorld and not @shared.spectate)
|
||||||
@worker.postMessage func: 'serializeFramesSoFar' # Stream it!
|
@worker.postMessage func: 'serializeFramesSoFar' # Stream it!
|
||||||
|
|
||||||
# We have some or all of the frames serialized, so let's send the (partially?) simulated world to the Surface.
|
# We have some or all of the frames serialized, so let's send the (partially?) simulated world to the Surface.
|
||||||
|
|
|
@ -24,6 +24,7 @@ module.exports = class God extends CocoClass
|
||||||
@angelsShare =
|
@angelsShare =
|
||||||
workerCode: options.workerCode or '/javascripts/workers/worker_world.js' # Either path or function
|
workerCode: options.workerCode or '/javascripts/workers/worker_world.js' # Either path or function
|
||||||
headless: options.headless # Whether to just simulate the goals, or to deserialize all simulation results
|
headless: options.headless # Whether to just simulate the goals, or to deserialize all simulation results
|
||||||
|
spectate: options.spectate
|
||||||
godNick: @nick
|
godNick: @nick
|
||||||
workQueue: []
|
workQueue: []
|
||||||
firstWorld: true
|
firstWorld: true
|
||||||
|
|
|
@ -146,7 +146,6 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@showLevel()
|
@showLevel()
|
||||||
@updateState true if @loaded
|
@updateState true if @loaded
|
||||||
@onFrameChanged()
|
@onFrameChanged()
|
||||||
Backbone.Mediator.publish 'surface:world-set-up', {world: @world}
|
|
||||||
|
|
||||||
showLevel: ->
|
showLevel: ->
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
|
|
|
@ -418,6 +418,7 @@
|
||||||
skip_tutorial: "Skip (esc)"
|
skip_tutorial: "Skip (esc)"
|
||||||
keyboard_shortcuts: "Key Shortcuts"
|
keyboard_shortcuts: "Key Shortcuts"
|
||||||
loading_ready: "Ready!"
|
loading_ready: "Ready!"
|
||||||
|
loading_start: "Start Level"
|
||||||
tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor."
|
tip_insert_positions: "Shift+Click a point on the map to insert it into the spell editor."
|
||||||
tip_toggle_play: "Toggle play/paused with Ctrl+P."
|
tip_toggle_play: "Toggle play/paused with Ctrl+P."
|
||||||
tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward."
|
tip_scrub_shortcut: "Ctrl+[ and Ctrl+] rewind and fast-forward."
|
||||||
|
|
|
@ -108,7 +108,6 @@ module.exports = class Level extends CocoModel
|
||||||
for original, placeholderComponent of placeholders when not placeholdersUsed[original]
|
for original, placeholderComponent of placeholders when not placeholdersUsed[original]
|
||||||
levelThang.components.push placeholderComponent
|
levelThang.components.push placeholderComponent
|
||||||
|
|
||||||
|
|
||||||
sortSystems: (levelSystems, systemModels) ->
|
sortSystems: (levelSystems, systemModels) ->
|
||||||
[sorted, originalsSeen] = [[], {}]
|
[sorted, originalsSeen] = [[], {}]
|
||||||
visit = (system) ->
|
visit = (system) ->
|
||||||
|
|
|
@ -121,9 +121,6 @@ module.exports = # /app/lib/surface
|
||||||
'sprite:dragged': spriteMouseEventSchema
|
'sprite:dragged': spriteMouseEventSchema
|
||||||
'sprite:mouse-up': spriteMouseEventSchema
|
'sprite:mouse-up': spriteMouseEventSchema
|
||||||
|
|
||||||
'surface:world-set-up': c.object {},
|
|
||||||
world: {type: 'object'}
|
|
||||||
|
|
||||||
'surface:frame-changed': c.object {required: ['frame', 'world', 'progress']},
|
'surface:frame-changed': c.object {required: ['frame', 'world', 'progress']},
|
||||||
frame: {type: 'number', minimum: 0}
|
frame: {type: 'number', minimum: 0}
|
||||||
world: {type: 'object'}
|
world: {type: 'object'}
|
||||||
|
|
|
@ -56,6 +56,9 @@
|
||||||
position: relative
|
position: relative
|
||||||
z-index: 2
|
z-index: 2
|
||||||
|
|
||||||
|
.start-level-button
|
||||||
|
margin-top: 10px
|
||||||
|
|
||||||
.left-wing, .right-wing
|
.left-wing, .right-wing
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
|
@ -43,3 +43,4 @@
|
||||||
|
|
||||||
.errors
|
.errors
|
||||||
|
|
||||||
|
button.start-level-button.btn.btn-lg.btn-success.secret(data-i18n="play_level.loading_start") Start Level
|
||||||
|
|
|
@ -310,7 +310,7 @@ module.exports = class InventoryView extends CocoView
|
||||||
necessaryGear = gearByLevel[@options.levelID]
|
necessaryGear = gearByLevel[@options.levelID]
|
||||||
for slot, item of necessaryGear ? {}
|
for slot, item of necessaryGear ? {}
|
||||||
@equipment[slot] ?= gear[item]
|
@equipment[slot] ?= gear[item]
|
||||||
@allowedItems = _.values gear if necessaryGear # If it's one of these levels, don't show the extra items.
|
@allowedItems = _.union(_.values(gear), _.values(@equipment)) if necessaryGear # If it's one of these levels, don't show the extra items.
|
||||||
|
|
||||||
onHeroSelectionUpdated: (e) ->
|
onHeroSelectionUpdated: (e) ->
|
||||||
@selectedHero = e.hero
|
@selectedHero = e.hero
|
||||||
|
|
|
@ -44,7 +44,6 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
'god:new-world-created': 'onNewWorld'
|
'god:new-world-created': 'onNewWorld'
|
||||||
'god:streaming-world-updated': 'onNewWorld'
|
'god:streaming-world-updated': 'onNewWorld'
|
||||||
'god:infinite-loop': 'onInfiniteLoop'
|
'god:infinite-loop': 'onInfiniteLoop'
|
||||||
'surface:world-set-up': 'onSurfaceSetUpNewWorld'
|
|
||||||
'level:next-game-pressed': 'onNextGamePressed'
|
'level:next-game-pressed': 'onNextGamePressed'
|
||||||
'level:started': 'onLevelStarted'
|
'level:started': 'onLevelStarted'
|
||||||
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
|
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
|
||||||
|
@ -84,7 +83,7 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
opponentSessionID: @sessionTwo
|
opponentSessionID: @sessionTwo
|
||||||
spectateMode: true
|
spectateMode: true
|
||||||
team: @getQueryVariable('team')
|
team: @getQueryVariable('team')
|
||||||
@god = new God maxAngels: 1
|
@god = new God maxAngels: 1, spectate: true
|
||||||
|
|
||||||
getRenderData: ->
|
getRenderData: ->
|
||||||
c = super()
|
c = super()
|
||||||
|
@ -161,12 +160,14 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
@session.set 'multiplayer', false
|
@session.set 'multiplayer', false
|
||||||
|
|
||||||
onLevelStarted: (e) ->
|
onLevelStarted: (e) ->
|
||||||
@loadingView?.unveil()
|
go = => @loadingView?.unveil()
|
||||||
|
_.delay go, 1000
|
||||||
|
|
||||||
onLoadingViewUnveiled: (e) ->
|
onLoadingViewUnveiled: (e) ->
|
||||||
# Don't remove it; we want its decoration around on large screens.
|
# Don't remove it; we want its decoration around on large screens.
|
||||||
#@removeSubView @loadingView
|
#@removeSubView @loadingView
|
||||||
#@loadingView = null
|
#@loadingView = null
|
||||||
|
Backbone.Mediator.publish 'level:set-playing', playing: true
|
||||||
|
|
||||||
onSupermodelLoadedOne: =>
|
onSupermodelLoadedOne: =>
|
||||||
@modelsLoaded ?= 0
|
@modelsLoaded ?= 0
|
||||||
|
@ -229,13 +230,6 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
volume = 1.0 unless volume?
|
volume = 1.0 unless volume?
|
||||||
Backbone.Mediator.publish 'level:set-volume', volume: volume
|
Backbone.Mediator.publish 'level:set-volume', volume: volume
|
||||||
|
|
||||||
onSurfaceSetUpNewWorld: ->
|
|
||||||
return if @alreadyLoadedState
|
|
||||||
@alreadyLoadedState = true
|
|
||||||
state = @originalSessionState
|
|
||||||
if state.playing?
|
|
||||||
Backbone.Mediator.publish 'level:set-playing', playing: state.playing
|
|
||||||
|
|
||||||
register: -> return
|
register: -> return
|
||||||
|
|
||||||
onSessionWillSave: (e) ->
|
onSessionWillSave: (e) ->
|
||||||
|
@ -259,6 +253,7 @@ module.exports = class SpectateLevelView extends RootView
|
||||||
return if @headless
|
return if @headless
|
||||||
scripts = @world.scripts # Since these worlds don't have scripts, preserve them.
|
scripts = @world.scripts # Since these worlds don't have scripts, preserve them.
|
||||||
@world = e.world
|
@world = e.world
|
||||||
|
@world.scripts = scripts
|
||||||
thangTypes = @supermodel.getModels(ThangType)
|
thangTypes = @supermodel.getModels(ThangType)
|
||||||
startFrame = @lastWorldFramesLoaded ? 0
|
startFrame = @lastWorldFramesLoaded ? 0
|
||||||
if @world.frames.length is @world.totalFrames # Finished loading
|
if @world.frames.length is @world.totalFrames # Finished loading
|
||||||
|
|
|
@ -5,7 +5,11 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
id: 'level-loading-view'
|
id: 'level-loading-view'
|
||||||
template: template
|
template: template
|
||||||
|
|
||||||
|
events:
|
||||||
|
'click .start-level-button': 'onClickStartLevel'
|
||||||
|
|
||||||
onLoaded: ->
|
onLoaded: ->
|
||||||
|
|
||||||
afterRender: ->
|
afterRender: ->
|
||||||
@$el.find('.tip.rare').remove() if _.random(1, 10) < 9
|
@$el.find('.tip.rare').remove() if _.random(1, 10) < 9
|
||||||
tips = @$el.find('.tip').addClass('to-remove')
|
tips = @$el.find('.tip').addClass('to-remove')
|
||||||
|
@ -19,12 +23,12 @@ module.exports = class LevelLoadingView extends CocoView
|
||||||
ready = $.i18n.t('play_level.loading_ready', defaultValue: 'Ready!')
|
ready = $.i18n.t('play_level.loading_ready', defaultValue: 'Ready!')
|
||||||
@$el.find('#tip-wrapper .tip').addClass('ready').text ready
|
@$el.find('#tip-wrapper .tip').addClass('ready').text ready
|
||||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'level_loaded', volume: 0.75 # old: loading_ready
|
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'level_loaded', volume: 0.75 # old: loading_ready
|
||||||
|
@$el.find('.start-level-button').removeClass 'secret'
|
||||||
|
|
||||||
|
onClickStartLevel: (e) ->
|
||||||
|
@unveil()
|
||||||
|
|
||||||
unveil: ->
|
unveil: ->
|
||||||
_.delay @reallyUnveil, 1000
|
|
||||||
|
|
||||||
reallyUnveil: =>
|
|
||||||
return if @destroyed
|
|
||||||
@$el.addClass 'unveiled'
|
@$el.addClass 'unveiled'
|
||||||
loadingDetails = @$el.find('.loading-details')
|
loadingDetails = @$el.find('.loading-details')
|
||||||
duration = parseFloat loadingDetails.css 'transition-duration'
|
duration = parseFloat loadingDetails.css 'transition-duration'
|
||||||
|
|
|
@ -60,7 +60,6 @@ module.exports = class PlayLevelView extends RootView
|
||||||
'level:reload-thang-type': 'onLevelReloadThangType'
|
'level:reload-thang-type': 'onLevelReloadThangType'
|
||||||
'level:play-next-level': 'onPlayNextLevel'
|
'level:play-next-level': 'onPlayNextLevel'
|
||||||
'level:edit-wizard-settings': 'showWizardSettingsModal'
|
'level:edit-wizard-settings': 'showWizardSettingsModal'
|
||||||
'surface:world-set-up': 'onSurfaceSetUpNewWorld'
|
|
||||||
'level:session-will-save': 'onSessionWillSave'
|
'level:session-will-save': 'onSessionWillSave'
|
||||||
'level:started': 'onLevelStarted'
|
'level:started': 'onLevelStarted'
|
||||||
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
|
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
|
||||||
|
@ -323,12 +322,12 @@ module.exports = class PlayLevelView extends RootView
|
||||||
if @otherSession
|
if @otherSession
|
||||||
# TODO: colorize name and cloud by team, colorize wizard by user's color config
|
# TODO: colorize name and cloud by team, colorize wizard by user's color config
|
||||||
@surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage')
|
@surface.createOpponentWizard id: @otherSession.get('creator'), name: @otherSession.get('creatorName'), team: @otherSession.get('team'), levelSlug: @level.get('slug'), codeLanguage: @otherSession.get('submittedCodeLanguage')
|
||||||
@loadingView?.unveil()
|
|
||||||
|
|
||||||
onLoadingViewUnveiled: (e) ->
|
onLoadingViewUnveiled: (e) ->
|
||||||
@loadingView.$el.remove()
|
@loadingView.$el.remove()
|
||||||
@removeSubView @loadingView
|
@removeSubView @loadingView
|
||||||
@loadingView = null
|
@loadingView = null
|
||||||
|
@restoreSessionState()
|
||||||
unless @isEditorPreview
|
unless @isEditorPreview
|
||||||
@loadEndTime = new Date()
|
@loadEndTime = new Date()
|
||||||
loadDuration = @loadEndTime - @loadStartTime
|
loadDuration = @loadEndTime - @loadStartTime
|
||||||
|
@ -336,7 +335,7 @@ module.exports = class PlayLevelView extends RootView
|
||||||
application.tracker?.trackEvent 'Finished Level Load', level: @levelID, label: @levelID, loadDuration: loadDuration, ['Google Analytics']
|
application.tracker?.trackEvent 'Finished Level Load', level: @levelID, label: @levelID, loadDuration: loadDuration, ['Google Analytics']
|
||||||
application.tracker?.trackTiming loadDuration, 'Level Load Time', @levelID, @levelID
|
application.tracker?.trackTiming loadDuration, 'Level Load Time', @levelID, @levelID
|
||||||
|
|
||||||
onSurfaceSetUpNewWorld: ->
|
restoreSessionState: ->
|
||||||
return if @alreadyLoadedState
|
return if @alreadyLoadedState
|
||||||
@alreadyLoadedState = true
|
@alreadyLoadedState = true
|
||||||
state = @originalSessionState
|
state = @originalSessionState
|
||||||
|
|
Reference in a new issue