Added stop playback button and real-time countdown screen.

This commit is contained in:
Nick Winter 2014-08-25 22:05:24 -07:00
parent ea3ade5bbc
commit e666ee1dac
12 changed files with 51 additions and 12 deletions
app
assets/javascripts/workers
lib
locale
schemas/subscriptions
styles/play
templates/play/level
views/play/level

View file

@ -464,6 +464,11 @@ self.addFlagEvent = function addFlagEvent(flagEvent) {
self.world.addFlagEvent(flagEvent);
};
self.stopRealTimePlayback = function stopRealTimePlayback() {
if(!self.world) return;
self.world.realTime = false;
};
self.addEventListener('message', function(event) {
self[event.data.func](event.data.args);
});

View file

@ -14,6 +14,7 @@ module.exports = class Angel extends CocoClass
subscriptions:
'level:flag-updated': 'onFlagEvent'
'playback:stop-real-time-playback': 'onStopRealTimePlayback'
constructor: (@shared) ->
super()
@ -212,6 +213,10 @@ module.exports = class Angel extends CocoClass
return unless @running and @work.realTime
@worker.postMessage func: 'addFlagEvent', args: e
onStopRealTimePlayback: (e) ->
return unless @running and @work.realTime
@work.realTime = false
@worker.postMessage func: 'stopRealTimePlayback'
#### Synchronous code for running worlds on main thread (profiling / IE9) ####
simulateSync: (work) =>

View file

@ -65,7 +65,7 @@ module.exports = class God extends CocoClass
isPreloading = angel.running and angel.work.preload and _.isEqual angel.work.userCodeMap, userCodeMap, (a, b) ->
return a.raw is b.raw if a?.raw? and b?.raw?
undefined # Let default equality test suffice.
if not hadPreloader and isPreloading
if not hadPreloader and isPreloading and not realTime
angel.finalizePreload()
hadPreloader = true
else if preload and angel.running and not angel.work.preload

View file

@ -8,6 +8,7 @@ CameraBorder = require './CameraBorder'
Layer = require './Layer'
Letterbox = require './Letterbox'
Dimmer = require './Dimmer'
CountdownScreen = require './CountdownScreen'
PlaybackOverScreen = require './PlaybackOverScreen'
DebugDisplay = require './DebugDisplay'
CoordinateDisplay = require './CoordinateDisplay'
@ -100,6 +101,7 @@ module.exports = Surface = class Surface extends CocoClass
@spriteBoss.destroy()
@chooser?.destroy()
@dimmer?.destroy()
@countdownScreen?.destroy()
@playbackOverScreen?.destroy()
@stage.clear()
@musicPlayer?.destroy()
@ -402,6 +404,7 @@ module.exports = Surface = class Surface extends CocoClass
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
@spriteBoss = new SpriteBoss camera: @camera, surfaceLayer: @surfaceLayer, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
@countdownScreen ?= new CountdownScreen camera: @camera, layer: @screenLayer
@playbackOverScreen ?= new PlaybackOverScreen camera: @camera, layer: @screenLayer
@stage.enableMouseOver(10)
@stage.addEventListener 'stagemousemove', @onMouseMove
@ -414,6 +417,7 @@ module.exports = Surface = class Surface extends CocoClass
@onResize()
onResize: (e) =>
return if @destroyed
oldWidth = parseInt @canvas.attr('width'), 10
oldHeight = parseInt @canvas.attr('height'), 10
aspectRatio = oldWidth / oldHeight
@ -630,6 +634,7 @@ module.exports = Surface = class Surface extends CocoClass
@realTime = true
@onResize()
@spriteBoss.selfWizardSprite?.toggle false
@playing = false # Will start when countdown is done.
onRealTimePlaybackEnded: (e) ->
@realTime = false

View file

@ -15,6 +15,7 @@ DESERIALIZATION_INTERVAL = 10
REAL_TIME_BUFFER_MIN = 2 * PROGRESS_UPDATE_INTERVAL
REAL_TIME_BUFFER_MAX = 3 * PROGRESS_UPDATE_INTERVAL
REAL_TIME_BUFFERED_WAIT_INTERVAL = 0.5 * PROGRESS_UPDATE_INTERVAL
REAL_TIME_COUNTDOWN_DELAY = 3000 # match CountdownScreen
ITEM_ORIGINAL = '53e12043b82921000051cdf9'
module.exports = class World
@ -93,12 +94,14 @@ module.exports = class World
loadFrames: (loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) ->
return if @aborted
console.log 'Warning: loadFrames called on empty World (no thangs).' unless @thangs.length
continueLaterFn = =>
@loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) unless @destroyed
if @realTime and not @countdownFinished
return setTimeout @finishCountdown(continueLaterFn), REAL_TIME_COUNTDOWN_DELAY
t1 = now()
@t0 ?= t1
@worldLoadStartTime ?= t1
@lastRealTimeUpdate ?= 0
continueLaterFn = =>
@loadFrames(loadedCallback, errorCallback, loadProgressCallback, skipDeferredLoading, loadUntilFrame) unless @destroyed
frameToLoadUntil = if loadUntilFrame then loadUntilFrame + 1 else @totalFrames # Might stop early if debugging.
i = @frames.length
while i < frameToLoadUntil and i < @totalFrames
@ -123,6 +126,11 @@ module.exports = class World
loadProgressCallback? 1
loadedCallback()
finishCountdown: (continueLaterFn) -> =>
return if @destroyed
@countdownFinished = true
continueLaterFn()
shouldDelayRealTimeSimulation: (t) ->
return false unless @realTime
timeSinceStart = t - @worldLoadStartTime

View file

@ -358,6 +358,7 @@
grid: "Grid"
customize_wizard: "Customize Wizard"
home: "Home"
stop: "Stop"
game_menu: "Game Menu"
guide: "Guide"
restart: "Restart"

View file

@ -147,6 +147,10 @@ module.exports =
'playback:manually-scrubbed':
{} # TODO schema
'playback:stop-real-time-playback':
type: 'object'
additionalProperties: false
'playback:real-time-playback-started':
type: 'object'
additionalProperties: false

View file

@ -19,6 +19,10 @@ body.is-playing
margin: 0 auto
#control-bar-view
width: 100%
button, h4
display: none
#stop-real-time-playback-button
display: block
#playback-view
$flags-width: 200px
width: 90%

View file

@ -41,5 +41,5 @@
height: 24px
#level-done-button
#level-done-button, #stop-real-time-playback-button
display: none

View file

@ -9,6 +9,9 @@ h4.title
| -
a(href=editorLink, data-i18n="nav.editor", title="Open " + worldName + " in the Level Editor") Editor
button.btn.btn-xs.btn-warning.banner#stop-real-time-playback-button(title="Stop real-time playback", data-i18n="play_level.stop") Stop
button.btn.btn-xs.btn-inverse.banner#game-menu-button(title="Show game menu", data-i18n="play_level.game_menu") Game Menu
button.btn.btn-xs.btn-success.banner#docs-button(title="Show level instructions", data-i18n="play_level.guide") Guide

View file

@ -16,13 +16,13 @@ module.exports = class ControlBarView extends CocoView
window.tracker?.trackEvent 'Clicked Docs', level: @level.get('name'), label: @level.get('name')
@showGuideModal()
'click #next-game-button': ->
Backbone.Mediator.publish 'next-game-pressed'
'click #next-game-button': -> Backbone.Mediator.publish 'next-game-pressed', {}
'click #game-menu-button': ->
@showGameMenuModal()
'click #game-menu-button': 'showGameMenuModal'
'click': -> Backbone.Mediator.publish 'tome:focus-editor'
'click #stop-real-time-playback-button': -> Backbone.Mediator.publish 'playback:stop-real-time-playback', {}
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {}
constructor: (options) ->
@worldName = options.worldName

View file

@ -26,6 +26,7 @@ module.exports = class LevelPlaybackView extends CocoView
'level-set-letterbox': 'onSetLetterbox'
'tome:cast-spells': 'onTomeCast'
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
'playback:stop-real-time-playback': 'onStopRealTimePlayback'
events:
'click #debug-toggle': 'onToggleDebug'
@ -34,11 +35,11 @@ module.exports = class LevelPlaybackView extends CocoView
'click #edit-editor-config': 'onEditEditorConfig'
'click #view-keyboard-shortcuts': 'onViewKeyboardShortcuts'
'click #music-button': 'onToggleMusic'
'click #zoom-in-button': -> Backbone.Mediator.publish('camera-zoom-in') unless @shouldIgnore()
'click #zoom-out-button': -> Backbone.Mediator.publish('camera-zoom-out') unless @shouldIgnore()
'click #zoom-in-button': -> Backbone.Mediator.publish('camera-zoom-in', {}) unless @shouldIgnore()
'click #zoom-out-button': -> Backbone.Mediator.publish('camera-zoom-out', {}) unless @shouldIgnore()
'click #volume-button': 'onToggleVolume'
'click #play-button': 'onTogglePlay'
'click': -> Backbone.Mediator.publish 'tome:focus-editor' unless @realTime
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {} unless @realTime
'mouseenter #timeProgress': 'onProgressEnter'
'mouseleave #timeProgress': 'onProgressLeave'
'mousemove #timeProgress': 'onProgressHover'
@ -308,6 +309,9 @@ module.exports = class LevelPlaybackView extends CocoView
@realTime = false
@togglePlaybackControls true
onStopRealTimePlayback: (e) ->
Backbone.Mediator.publish 'playback:real-time-playback-ended', {}
onSetDebug: (e) ->
flag = $('#debug-toggle i.icon-ok')
flag.toggleClass 'invisible', not e.debug