mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 14:03:28 -04:00
Added stop playback button and real-time countdown screen.
This commit is contained in:
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
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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) =>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -358,6 +358,7 @@
|
|||
grid: "Grid"
|
||||
customize_wizard: "Customize Wizard"
|
||||
home: "Home"
|
||||
stop: "Stop"
|
||||
game_menu: "Game Menu"
|
||||
guide: "Guide"
|
||||
restart: "Restart"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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%
|
||||
|
|
|
@ -41,5 +41,5 @@
|
|||
height: 24px
|
||||
|
||||
|
||||
#level-done-button
|
||||
#level-done-button, #stop-real-time-playback-button
|
||||
display: none
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue