Moved DOM highlight arrows from PlayLevelView to CocoView so that everywhere can use them. Added highlight for next level on world map.

This commit is contained in:
Nick Winter 2014-10-08 10:46:10 -07:00
parent c6b398aae2
commit 589c3b090c
6 changed files with 90 additions and 83 deletions

View file

@ -25,7 +25,7 @@ module.exports = class PlaybackOverScreen extends CocoClass
show: ->
return if @showing
@showing = true
@updateColor 'rgba(212, 212, 212, 0.4' unless @color # If we haven't caught the goal state for the first run, just do something neutral.
@updateColor 'rgba(212, 212, 212, 0.4)' unless @color # If we haven't caught the goal state for the first run, just do something neutral.
@dimLayer.alpha = 0
createjs.Tween.removeTweens @dimLayer
createjs.Tween.get(@dimLayer).to({alpha: 1}, 500)

View file

@ -236,6 +236,17 @@ table.table
.ui-state-default, .ui-state-focus, .ui-state-active, .ui-state-highlight, .ui-state-error
background-image: none
// DOM highlight pointer arrow
.highlight-pointer
position: absolute
left: 0
top: 0
height: 100px
opacity: 0.0
pointer-events: none
z-index: 10
// Fonts
.header-font

View file

@ -97,15 +97,6 @@ $level-resize-transition-time: 0.5s
bottom: 0
@include transition(width $level-resize-transition-time ease-in-out, right $level-resize-transition-time ease-in-out)
#pointer
position: absolute
left: 0
top: 0
height: 100px
opacity: 0.0
pointer-events: none
z-index: 10
// Level Docs
.ui-effects-transfer
border: 2px dotted gray

View file

@ -59,6 +59,7 @@ module.exports = class CocoView extends Backbone.View
@undelegateEvents() # removes both events and subs
view.destroy() for id, view of @subviews
$('#modal-wrapper .modal').off 'hidden.bs.modal', @modalClosed
@endHighlight()
@[key] = undefined for key, value of @
@destroyed = true
@off = doNothing
@ -293,6 +294,78 @@ module.exports = class CocoView extends Backbone.View
delete @subviews[view.parentKey]
view.destroy()
# Pointing stuff out
highlightElement: (selector, options) ->
@endHighlight()
options ?= {}
if delay = options.delay
delete options.delay
return @pointerDelayTimeout = _.delay((=> @highlightElement selector, options), delay)
$pointer = @getPointer()
$target = $(selector + ':visible')
return if parseFloat($target.css('opacity')) is 0.0 # Don't point out invisible elements.
return unless offset = $target.offset() # Don't point out elements we can't locate.
targetLeft = offset.left + $target.outerWidth() * 0.5
targetTop = offset.top + $target.outerHeight() * 0.5
if options.sides
if 'left' in options.sides then targetLeft = offset.left
if 'right' in options.sides then targetLeft = offset.left + $target.outerWidth()
if 'top' in options.sides then targetTop = offset.top
if 'bottom' in options.sides then targetTop = offset.top + $target.outerHeight()
else
# Aim to hit the side if the target is entirely on one side of the screen.
if offset.left > @$el.outerWidth() * 0.5
targetLeft = offset.left
else if offset.left + $target.outerWidth() < @$el.outerWidth() * 0.5
targetLeft = offset.left + $target.outerWidth()
# Aim to hit the bottom or top if the target is entirely on the top or bottom of the screen.
if offset.top > @$el.outerWidth() * 0.5
targetTop = offset.top
else if offset.top + $target.outerHeight() < @$el.outerHeight() * 0.5
targetTop = offset.top + $target.outerHeight()
if options.offset
targetLeft += options.offset.x
targetTop += options.offset.y
@pointerRadialDistance = -47
@pointerRotation = options.rotation ? Math.atan2(@$el.outerWidth() * 0.5 - targetLeft, targetTop - @$el.outerHeight() * 0.5)
$pointer.css
opacity: 1.0
transition: 'none'
transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)"
top: targetTop - 50
left: targetLeft - 50
_.defer =>
return if @destroyed
@animatePointer()
clearInterval @pointerInterval
@pointerInterval = setInterval(@animatePointer, 1200)
if options.duration
@pointerDurationTimeout = _.delay (=> @endHighlight() unless @destroyed), options.duration
animatePointer: =>
$pointer = @getPointer()
$pointer.css transition: 'all 0.6s ease-out', transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance-50}px)"
#Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'dom_highlight', volume: 0.75 # Never mind, this is currently so annoying
setTimeout (=> $pointer.css transition: 'all 0.4s ease-in', transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)"), 800
endHighlight: ->
@getPointer().css('opacity', 0.0)
clearInterval @pointerInterval
clearTimeout @pointerDelayTimeout
clearTimeout @pointerDurationTimeout
@pointerInterval = @pointerDelayTimeout = @pointerDurationTimeout = null
getPointer: ->
return $pointer if ($pointer = @$el.find('.highlight-pointer')) and $pointer.length
$pointer = $('<img src="/images/level/pointer.png" class="highlight-pointer">')
@$el.append($pointer)
$pointer
# Utilities
getQueryVariable: (param, defaultValue) -> CocoView.getQueryVariable(param, defaultValue)

View file

@ -89,6 +89,7 @@ module.exports = class WorldMapView extends RootView
@$el.find('.level').tooltip()
@$el.addClass _.string.slugify @terrain
@updateVolume()
@highlightElement '.level.next', delay: 8000, duration: 20000, rotation: 0, sides: ['top']
onSessionsLoaded: (e) ->
for session in @sessions.models

View file

@ -49,7 +49,7 @@ module.exports = class PlayLevelView extends RootView
'level:set-volume': (e) -> createjs.Sound.setVolume(if e.volume is 1 then 0.6 else e.volume) # Quieter for now until individual sound FX controls work again.
'level:show-victory': 'onShowVictory'
'level:restart': 'onRestartLevel'
'level:highlight-dom': 'onHighlightDom'
'level:highlight-dom': 'onHighlightDOM'
'level:end-highlight-dom': 'onEndHighlight'
'level:focus-dom': 'onFocusDom'
'level:disable-controls': 'onDisableControls'
@ -430,9 +430,7 @@ module.exports = class PlayLevelView extends RootView
viewArgs: [{supermodel: @supermodel, autoUnveil: true}, @levelID]
}
onWindowResize: (s...) ->
$('#pointer').css('opacity', 0.0)
clearInterval(@pointerInterval)
onWindowResize: (e) -> @endHighlight()
onDisableControls: (e) ->
return if e.controls and not ('level' in e.controls)
@ -500,73 +498,12 @@ module.exports = class PlayLevelView extends RootView
return null unless @getNextLevelID()
"/play/level/#{@getNextLevelID()}"
onHighlightDom: (e) ->
if e.delay
delay = e.delay
delete e.delay
@pointerInterval = _.delay((=> @onHighlightDom e), delay)
return
@addPointer()
selector = e.selector + ':visible'
dom = $(selector)
return if parseFloat(dom.css('opacity')) is 0.0
offset = dom.offset()
return if not offset
target_left = offset.left + dom.outerWidth() * 0.5
target_top = offset.top + dom.outerHeight() * 0.5
onHighlightDOM: (e) -> @highlightElement e.selector, delay: e.delay, sides: e.sides, offset: e.offset, rotation: e.rotation
if e.sides
if 'left' in e.sides then target_left = offset.left
if 'right' in e.sides then target_left = offset.left + dom.outerWidth()
if 'top' in e.sides then target_top = offset.top
if 'bottom' in e.sides then target_top = offset.top + dom.outerHeight()
else
# aim to hit the side if the target is entirely on one side of the screen
if offset.left > @$el.outerWidth()*0.5
target_left = offset.left
else if offset.left + dom.outerWidth() < @$el.outerWidth()*0.5
target_left = offset.left + dom.outerWidth()
# aim to hit the bottom or top if the target is entirely on the top or bottom of the screen
if offset.top > @$el.outerWidth()*0.5
target_top = offset.top
else if offset.top + dom.outerHeight() < @$el.outerHeight()*0.5
target_top = offset.top + dom.outerHeight()
if e.offset
target_left += e.offset.x
target_top += e.offset.y
@pointerRadialDistance = -47 # - Math.sqrt(Math.pow(dom.outerHeight()*0.5, 2), Math.pow(dom.outerWidth()*0.5))
@pointerRotation = e.rotation ? Math.atan2(@$el.outerWidth()*0.5 - target_left, target_top - @$el.outerHeight()*0.5)
pointer = $('#pointer')
pointer
.css('opacity', 1.0)
.css('transition', 'none')
.css('transform', "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)")
.css('top', target_top - 50)
.css('left', target_left - 50)
setTimeout(()=>
return if @destroyed
@animatePointer()
clearInterval(@pointerInterval)
@pointerInterval = setInterval(@animatePointer, 1200)
, 1)
animatePointer: =>
pointer = $('#pointer')
pointer.css('transition', 'all 0.6s ease-out')
pointer.css('transform', "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance-50}px)")
#Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'dom_highlight', volume: 0.75 # Never mind, this is currently so annoying
setTimeout((=>
pointer.css('transform', "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)").css('transition', 'all 0.4s ease-in')), 800)
onEndHighlight: -> @endHighlight()
onFocusDom: (e) -> $(e.selector).focus()
onEndHighlight: ->
$('#pointer').css('opacity', 0.0)
clearInterval(@pointerInterval)
onMultiplayerChanged: (e) ->
if @session.get('multiplayer')
@bus.connect()
@ -574,11 +511,6 @@ module.exports = class PlayLevelView extends RootView
@bus.removeFirebaseData =>
@bus.disconnect()
addPointer: ->
p = $('#pointer')
return if p.length
@$el.append($('<img src="/images/level/pointer.png" id="pointer">'))
preloadNextLevel: =>
# TODO: Loading models in the middle of gameplay causes stuttering. Most of the improvement in loading time is simply from passing the supermodel from this level to the next, but if we can find a way to populate the level early without it being noticeable, that would be even better.
# return if @destroyed
@ -652,7 +584,6 @@ module.exports = class PlayLevelView extends RootView
createjs.Tween.get(ambientSound).to({volume: 0.0}, 1500).call -> ambientSound.stop()
$(window).off 'resize', @onWindowResize
delete window.world # not sure where this is set, but this is one way to clean it up
clearInterval(@pointerInterval)
@bus?.destroy()
#@instance.save() unless @instance.loading
delete window.nextLevelURL