mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-01 07:40:22 -04:00
Big performance improvements for scrubbing between frames; look out for bugs.
This commit is contained in:
parent
e20e9d68cf
commit
3cee341887
1 changed files with 33 additions and 23 deletions
|
@ -100,7 +100,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@stage.removeAllEventListeners()
|
||||
@stage.enableDOMEvents false
|
||||
@stage.enableMouseOver 0
|
||||
@playScrubbedSounds = null
|
||||
@onFramesScrubbed = null
|
||||
@onMouseMove = null
|
||||
@onMouseDown = null
|
||||
@tick = null
|
||||
|
@ -202,32 +202,33 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
.get(@)
|
||||
.to({currentFrame:@scrubbingTo}, scrubDuration, createjs.Ease.sineInOut)
|
||||
.call(onTweenEnd)
|
||||
t.addEventListener('change', @playScrubbedSounds)
|
||||
t.addEventListener('change', @onFramesScrubbed)
|
||||
else
|
||||
@currentFrame = @scrubbingTo
|
||||
@playScrubbedSounds()
|
||||
@onFramesScrubbed() # For performance, don't play these for instant transitions.
|
||||
onTweenEnd()
|
||||
|
||||
@updateState true
|
||||
@onFrameChanged()
|
||||
|
||||
playScrubbedSounds: (e) =>
|
||||
# gotta play all the sounds, even when scrubbing!
|
||||
rising = @currentFrame > @lastFrame
|
||||
actualCurrentFrame = @currentFrame
|
||||
tempFrame = if rising then Math.ceil(@lastFrame) else Math.floor(@lastFrame)
|
||||
while true # temporary fix to stop cacophony
|
||||
break if rising and tempFrame > actualCurrentFrame
|
||||
break if (not rising) and tempFrame < actualCurrentFrame
|
||||
@currentFrame = tempFrame
|
||||
frame = @world.getFrame(@getCurrentFrame())
|
||||
frame.restoreState()
|
||||
for thangID, sprite of @spriteBoss.sprites
|
||||
sprite.playSounds false, Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
|
||||
tempFrame += if rising then 1 else -1
|
||||
@currentFrame = actualCurrentFrame
|
||||
onFramesScrubbed: (e) =>
|
||||
if e
|
||||
# Gotta play all the sounds when scrubbing (but not when doing an immediate transition).
|
||||
rising = @currentFrame > @lastFrame
|
||||
actualCurrentFrame = @currentFrame
|
||||
tempFrame = if rising then Math.ceil(@lastFrame) else Math.floor(@lastFrame)
|
||||
while true # temporary fix to stop cacophony
|
||||
break if rising and tempFrame > actualCurrentFrame
|
||||
break if (not rising) and tempFrame < actualCurrentFrame
|
||||
@currentFrame = tempFrame
|
||||
frame = @world.getFrame(@getCurrentFrame())
|
||||
frame.restoreState()
|
||||
for thangID, sprite of @spriteBoss.sprites
|
||||
sprite.playSounds false, Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
|
||||
tempFrame += if rising then 1 else -1
|
||||
@currentFrame = actualCurrentFrame
|
||||
|
||||
# TODO: are these needed, or perhaps do they duplicate things?
|
||||
@restoreWorldState()
|
||||
@spriteBoss.update true
|
||||
@onFrameChanged()
|
||||
|
||||
|
@ -325,7 +326,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
onNewWorld: (event) ->
|
||||
return unless event.world.name is @world.name
|
||||
@casting = false
|
||||
|
||||
|
||||
# This has a tendency to break scripts that are waiting for playback to change when the level is loaded
|
||||
# so only run it after the first world is created.
|
||||
Backbone.Mediator.publish 'level-set-playing', { playing: @wasPlayingWhenCastingBegan } unless event.firstWorld
|
||||
|
@ -493,14 +494,23 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
tick: (e) =>
|
||||
# seems to be a bug where only one object can register with the Ticker...
|
||||
oldFrame = @currentFrame
|
||||
oldWorldFrame = Math.floor oldFrame
|
||||
while true
|
||||
Dropper.tick()
|
||||
@trailmaster.tick() if @trailmaster
|
||||
# Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
|
||||
frameAdvanced = (@playing and @currentFrame < @world.totalFrames) or @totalFramesDrawn < 2
|
||||
@currentFrame += @world.frameRate / @frameRate if frameAdvanced
|
||||
@updateSpriteSounds() if frameAdvanced
|
||||
newWorldFrame = Math.floor @currentFrame
|
||||
worldFrameAdvanced = newWorldFrame isnt oldWorldFrame
|
||||
if worldFrameAdvanced
|
||||
# Only restore world state when it will correspond to an integer WorldFrame, not interpolated frame.
|
||||
@restoreWorldState()
|
||||
oldWorldFrame = newWorldFrame
|
||||
break unless Dropper.drop()
|
||||
if frameAdvanced and not worldFrameAdvanced
|
||||
# We didn't end the above loop on an integer frame, so do the world state update.
|
||||
@restoreWorldState()
|
||||
|
||||
# these are skipped for dropped frames
|
||||
@updateState @currentFrame isnt oldFrame
|
||||
|
@ -513,7 +523,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
Backbone.Mediator.publish('surface:mouse-' + (if mib then "over" else "out"), {})
|
||||
@mouseInBounds = mib
|
||||
|
||||
updateSpriteSounds: ->
|
||||
restoreWorldState: ->
|
||||
@world.getFrame(@getCurrentFrame()).restoreState()
|
||||
current = Math.max(0, Math.min(@currentFrame, @world.totalFrames - 1))
|
||||
if current - Math.floor(current) > 0.01
|
||||
|
@ -523,7 +533,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@spriteBoss.updateSounds()
|
||||
|
||||
updateState: (frameChanged) ->
|
||||
# world state must have been restored in @updateSpriteSounds
|
||||
# world state must have been restored in @restoreWorldState
|
||||
@camera.updateZoom()
|
||||
@spriteBoss.update frameChanged unless @casting
|
||||
@dimmer?.setSprites @spriteBoss.sprites
|
||||
|
|
Loading…
Add table
Reference in a new issue