mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 17:45:40 -05:00
Full-screen playback during real-time mode.
This commit is contained in:
parent
f2adb7ec7f
commit
c79541f669
7 changed files with 91 additions and 12 deletions
|
@ -196,7 +196,8 @@ module.exports = class LevelBus extends Bus
|
|||
|
||||
onNewGoalStates: ({goalStates})->
|
||||
state = @session.get 'state'
|
||||
unless utils.kindaEqual state.goalStates, goalStates # Only save when goals really change
|
||||
unless utils.kindaEqual state.goalStates, goalStates # Only save when goals really change
|
||||
# TODO: this log doesn't capture when null-status goals are being set during world streaming. Where can they be coming from?
|
||||
return console.error("Somehow trying to save null goal states!", goalStates) if _.find(goalStates, (gs) -> not gs.status)
|
||||
state.goalStates = goalStates
|
||||
@session.set 'state', state
|
||||
|
|
|
@ -67,6 +67,8 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
'level-set-letterbox': 'onSetLetterbox'
|
||||
'application:idle-changed': 'onIdleChanged'
|
||||
'camera:zoom-updated': 'onZoomUpdated'
|
||||
'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
|
||||
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
|
||||
|
||||
shortcuts:
|
||||
'ctrl+\\, ⌘+\\': 'onToggleDebug'
|
||||
|
@ -82,7 +84,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@options = _.extend(@options, givenOptions) if givenOptions
|
||||
@initEasel()
|
||||
@initAudio()
|
||||
@onResize = _.debounce @onResize, 500
|
||||
@onResize = _.debounce @onResize, 250
|
||||
$(window).on 'resize', @onResize
|
||||
if @world.ended
|
||||
_.defer => @setWorld @world
|
||||
|
@ -367,7 +369,8 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
@setWorld event.world
|
||||
@onFrameChanged(true)
|
||||
if @playing and (ffToFrame = Math.min(event.firstChangedFrame, @frameBeforeCast, event.world.frames.length)) and ffToFrame > @currentFrame
|
||||
fastForwardBuffer = 2 # Make sure that real-time playback doesn't need to buffer more than this many seconds.
|
||||
if @playing and (ffToFrame = Math.min(event.firstChangedFrame, @frameBeforeCast, event.world.frames.length)) and ffToFrame > @currentFrame + fastForwardBuffer * @world.frameRate
|
||||
@fastForwardingToFrame = ffToFrame
|
||||
@fastForwardingSpeed = Math.max 4, 4 * 90 / (@world.maxTotalFrames * @world.dt)
|
||||
|
||||
|
@ -402,8 +405,17 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
onResize: (e) =>
|
||||
oldWidth = parseInt @canvas.attr('width'), 10
|
||||
oldHeight = parseInt @canvas.attr('height'), 10
|
||||
newWidth = @canvas.width()
|
||||
newHeight = @canvas.height()
|
||||
aspectRatio = oldWidth / oldHeight
|
||||
pageWidth = $('#page-container').width() - 17 # 17px nano scroll bar
|
||||
if @realTime
|
||||
pageHeight = $('#page-container').height() - $('#control-bar-view').outerHeight() - $('#playback-view').outerHeight()
|
||||
newWidth = Math.min pageWidth, pageHeight * aspectRatio
|
||||
newHeight = newWidth / aspectRatio
|
||||
else
|
||||
newWidth = 0.55 * pageWidth
|
||||
newHeight = newWidth / aspectRatio
|
||||
@canvas.width newWidth
|
||||
@canvas.height newHeight
|
||||
return unless newWidth > 0 and newHeight > 0
|
||||
#if InstallTrigger? # Firefox rendering performance goes down as canvas size goes up
|
||||
# newWidth = Math.min 924, newWidth
|
||||
|
@ -600,6 +612,15 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
++@totalFramesDrawn
|
||||
@stage.update e
|
||||
|
||||
# Real-time playback
|
||||
onRealTimePlaybackStarted: (e) ->
|
||||
@realTime = true
|
||||
@onResize()
|
||||
|
||||
onRealTimePlaybackEnded: (e) ->
|
||||
@realTime = false
|
||||
@onResize()
|
||||
|
||||
# paths - TODO: move to SpriteBoss? but only update on frame drawing instead of on every frame update?
|
||||
|
||||
updatePaths: ->
|
||||
|
|
|
@ -105,6 +105,14 @@ module.exports =
|
|||
'playback:manually-scrubbed':
|
||||
{} # TODO schema
|
||||
|
||||
'playback:real-time-playback-started':
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
|
||||
'playback:real-time-playback-ended':
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
|
||||
'change:editor-config':
|
||||
{} # TODO schema
|
||||
|
||||
|
|
|
@ -10,6 +10,28 @@ body.is-playing
|
|||
margin: 0 auto
|
||||
@include user-select(none)
|
||||
|
||||
&.real-time
|
||||
// Hmm, somehow the #page-container is cutting us off by ~17px on the right, looks a bit off.
|
||||
|
||||
#canvas-wrapper
|
||||
width: 100%
|
||||
canvas#surface
|
||||
margin: 0 auto
|
||||
#control-bar-view, #playback-view
|
||||
width: 100%
|
||||
#code-area, #thang-hud, #goals-view
|
||||
display: none
|
||||
visibility: hidden
|
||||
#gold-view
|
||||
right: 1%
|
||||
#control-bar-view .title
|
||||
left: 0
|
||||
width: 100%
|
||||
text-align: center
|
||||
|
||||
.level-content
|
||||
margin: 0px auto
|
||||
|
||||
.level-content
|
||||
position: relative
|
||||
|
||||
|
@ -17,12 +39,13 @@ body.is-playing
|
|||
width: 55%
|
||||
position: relative
|
||||
overflow: hidden
|
||||
@include transition(0.5s ease-out)
|
||||
|
||||
canvas#surface
|
||||
background-color: #333
|
||||
width: 100%
|
||||
display: block
|
||||
z-index: 1
|
||||
@include transition(0.5s ease-out)
|
||||
|
||||
min-width: 1024px
|
||||
position: relative
|
||||
|
|
|
@ -19,11 +19,11 @@
|
|||
.title
|
||||
position: absolute
|
||||
display: inline-block
|
||||
margin-left: 50%
|
||||
right: 0
|
||||
color: #BEBEBE
|
||||
line-height: 15px
|
||||
left: 0
|
||||
width: 100%
|
||||
text-align: center
|
||||
|
||||
max-width: 1920px
|
||||
margin: 0 auto
|
||||
|
|
|
@ -24,6 +24,7 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
'god:new-world-created': 'onNewWorld'
|
||||
'god:streaming-world-updated': 'onNewWorld' # Maybe?
|
||||
'level-set-letterbox': 'onSetLetterbox'
|
||||
'tome:cast-spells': 'onTomeCast'
|
||||
|
||||
events:
|
||||
'click #debug-toggle': 'onToggleDebug'
|
||||
|
@ -151,10 +152,19 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
@$el.find('#music-button').toggleClass('music-on', me.get('music'))
|
||||
|
||||
onSetLetterbox: (e) ->
|
||||
buttons = @$el.find '#play-button, .scrubber-handle'
|
||||
buttons.css 'visibility', if e.on then 'hidden' else 'visible'
|
||||
@togglePlaybackControls !e.on
|
||||
@disabled = e.on
|
||||
|
||||
togglePlaybackControls: (to) ->
|
||||
buttons = @$el.find '#play-button, .scrubber-handle'
|
||||
buttons.css 'visibility', if to then 'visible' else 'hidden'
|
||||
|
||||
onTomeCast: (e) ->
|
||||
return unless e.realTime
|
||||
@realTime = true
|
||||
@togglePlaybackControls false
|
||||
Backbone.Mediator.publish 'playback:real-time-playback-started', {}
|
||||
|
||||
onWindowResize: (s...) =>
|
||||
@barWidth = $('.progress', @$el).width()
|
||||
|
||||
|
@ -276,11 +286,16 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
updateProgress: (progress, world) ->
|
||||
if world.frames.length isnt @lastLoadedFrameCount
|
||||
@updateBarWidth world.frames.length, world.maxTotalFrames, world.dt
|
||||
@worldCompletelyLoaded = world.frames.length is world.totalFrames
|
||||
$('.scrubber .progress-bar', @$el).css('width', "#{progress * 100}%")
|
||||
|
||||
updatePlayButton: (progress) ->
|
||||
if progress >= 0.99 and @lastProgress < 0.99
|
||||
if @worldCompletelyLoaded and progress >= 0.99 and @lastProgress < 0.99
|
||||
$('#play-button').removeClass('playing').removeClass('paused').addClass('ended')
|
||||
if @realTime
|
||||
@realTime = false
|
||||
@togglePlaybackControls true
|
||||
Backbone.Mediator.publish 'playback:real-time-playback-ended', {}
|
||||
if progress < 0.99 and @lastProgress >= 0.99
|
||||
b = $('#play-button').removeClass('ended')
|
||||
if @playing then b.addClass('playing') else b.addClass('paused')
|
||||
|
@ -326,7 +341,7 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
return if @shouldIgnore()
|
||||
Backbone.Mediator.publish 'level-set-time', ratio: ratio, scrubDuration: duration
|
||||
|
||||
shouldIgnore: -> return @disabled
|
||||
shouldIgnore: -> return @disabled or @realTime
|
||||
|
||||
onTogglePlay: (e) ->
|
||||
e?.preventDefault()
|
||||
|
|
|
@ -64,6 +64,8 @@ module.exports = class PlayLevelView extends RootView
|
|||
'level:set-team': 'setTeam'
|
||||
'level:started': 'onLevelStarted'
|
||||
'level:loading-view-unveiled': 'onLoadingViewUnveiled'
|
||||
'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
|
||||
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
|
||||
|
||||
events:
|
||||
'click #level-done-button': 'onDonePressed'
|
||||
|
@ -513,6 +515,15 @@ module.exports = class PlayLevelView extends RootView
|
|||
continue unless sound = AudioPlayer.soundForDialogue message, thangType.get('soundTriggers')
|
||||
AudioPlayer.preloadSoundReference sound
|
||||
|
||||
# Real-time playback
|
||||
onRealTimePlaybackStarted: (e) ->
|
||||
@$el.addClass 'real-time'
|
||||
@onWindowResize()
|
||||
|
||||
onRealTimePlaybackEnded: (e) ->
|
||||
@$el.removeClass 'real-time'
|
||||
@onWindowResize()
|
||||
|
||||
destroy: ->
|
||||
@levelLoader?.destroy()
|
||||
@surface?.destroy()
|
||||
|
|
Loading…
Reference in a new issue