mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-25 21:43:47 -04:00
Several improvements to the victory modal.
This commit is contained in:
parent
a33bb215d4
commit
7a9014f83a
3 changed files with 72 additions and 37 deletions
app
styles/play/level/modal
templates/play/level/modal
views/play/level/modal
|
@ -19,10 +19,11 @@
|
|||
#victory-header
|
||||
display: block
|
||||
margin: 15px auto 0
|
||||
@include transition(0.25s ease-in)
|
||||
// http://easings.net/#easeOutBack plus tweaked a bit: http://cubic-bezier.com/#.18,.68,.75,2
|
||||
@include transition(0.5s cubic-bezier(0.18, 0.68, 0.75, 2))
|
||||
|
||||
&.out
|
||||
margin-top: -100px
|
||||
@include scale(0)
|
||||
|
||||
.modal-header
|
||||
height: 85px
|
||||
|
@ -95,10 +96,10 @@
|
|||
@include scale(1.5)
|
||||
z-index: 2
|
||||
|
||||
.reward-text
|
||||
font-size: 18px
|
||||
overflow: visible
|
||||
bottom: 9px
|
||||
&.numerical &.animating .reward-text
|
||||
font-size: 18px
|
||||
overflow: visible
|
||||
bottom: 9px
|
||||
|
||||
.reward-image-container
|
||||
top: 8px
|
||||
|
@ -113,6 +114,13 @@
|
|||
&.show
|
||||
@include scale(1)
|
||||
|
||||
&.pending-reward-image
|
||||
img
|
||||
-webkit-filter: brightness(2000%) contrast(25%)
|
||||
-moz-filter: brightness(2000%) contrast(25%)
|
||||
-o-filter: brightness(2000%) contrast(25%)
|
||||
filter: brightness(2000%) contrast(25%)
|
||||
|
||||
img
|
||||
margin: 0
|
||||
position: absolute
|
||||
|
|
|
@ -15,31 +15,31 @@ block modal-body-content
|
|||
- var worth = achievement.get('worth', true);
|
||||
if worth
|
||||
.reward-panel.numerical.xp(data-number=worth, data-number-unit='xp')
|
||||
.reward-image-container(class=animate?'':'show')
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_xp.png")
|
||||
.reward-text= animate ? '+0' : '+'+worth
|
||||
|
||||
if rewards.gems
|
||||
.reward-panel.numerical.gems(data-number=rewards.gems, data-number-unit='gem')
|
||||
.reward-image-container(class=animate?'':'show')
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src="/images/pages/play/level/modal/reward_icon_gems.png")
|
||||
.reward-text= animate ? '+0' : '+'+rewards.gems
|
||||
|
||||
if rewards.heroes
|
||||
for hero in rewards.heroes
|
||||
- var hero = thangTypes[hero];
|
||||
.reward-panel.hero
|
||||
.reward-image-container(class=animate?'':'show')
|
||||
.reward-panel.hero(data-hero-thang-type=hero.get('original'))
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=hero.getPortraitURL())
|
||||
.reward-text= hero.get('name')
|
||||
.reward-text= animate ? 'New Hero' : hero.get('name')
|
||||
|
||||
if rewards.items
|
||||
for item in rewards.items
|
||||
- var item = thangTypes[item];
|
||||
.reward-panel.item
|
||||
.reward-image-container(class=animate?'':'show')
|
||||
.reward-panel.item(data-item-thang-type=item.get('original'))
|
||||
.reward-image-container(class=animate ? 'pending-reward-image' : 'show')
|
||||
img(src=item.getPortraitURL())
|
||||
.reward-text= item.get('name')
|
||||
.reward-text= animate ? 'New Item' : item.get('name')
|
||||
|
||||
|
||||
block modal-footer-content
|
||||
|
@ -60,7 +60,7 @@ block modal-footer-content
|
|||
a.btn.btn-success.world-map-button.hide#continue-button(href="/play-hero", data-dismiss="modal", data-i18n="play_level.victory_play_continue") Continue
|
||||
|
||||
if me.get('anonymous')
|
||||
p.sign-up-poke
|
||||
p.sign-up-poke.hide
|
||||
button.btn.btn-success.sign-up-button.btn-large(data-toggle="coco-modal", data-target="modal/SignupModal", data-i18n="play_level.victory_sign_up") Sign Up to Save Progress
|
||||
span(data-i18n="play_level.victory_sign_up_poke") Want to save your code? Create a free account!
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ LocalMongo = require 'lib/LocalMongo'
|
|||
utils = require 'lib/utils'
|
||||
ThangType = require 'models/ThangType'
|
||||
LadderSubmissionView = require 'views/play/common/LadderSubmissionView'
|
||||
AudioPlayer = require 'lib/AudioPlayer'
|
||||
|
||||
module.exports = class HeroVictoryModal extends ModalView
|
||||
id: 'hero-victory-modal'
|
||||
|
@ -45,7 +46,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
for thangTypeOriginal in thangTypeOriginals
|
||||
thangType = new ThangType()
|
||||
thangType.url = "/db/thang.type/#{thangTypeOriginal}/version"
|
||||
thangType.project = ['original', 'rasterIcon', 'name']
|
||||
thangType.project = ['original', 'rasterIcon', 'name', 'soundTriggers']
|
||||
@thangTypes[thangTypeOriginal] = @supermodel.loadModel(thangType, 'thang').model
|
||||
|
||||
if achievementIDs.length
|
||||
|
@ -86,7 +87,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
## achievement.completedAWhileAgo = index > 1
|
||||
# achievement.completed = true
|
||||
# achievement.completedAWhileAgo = false
|
||||
# achievement.attributes.worth = (index + 1) * achievement.get('worth')
|
||||
# achievement.attributes.worth = (index + 1) * achievement.get('worth', true)
|
||||
# rewards = achievement.get('rewards')
|
||||
# rewards.gems *= (index + 1)
|
||||
|
||||
|
@ -99,10 +100,14 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
afterRender: ->
|
||||
super()
|
||||
return unless @supermodel.finished()
|
||||
@playSelectionSound hero, true for original, hero of @thangTypes # Preload them
|
||||
@$el.addClass 'with-sign-up' if me.get('anonymous')
|
||||
@updateSavingProgressStatus()
|
||||
@$el.find('#victory-header').delay(250).queue(-> $(@).removeClass('out').dequeue())
|
||||
complete = _.once(_.bind(@beginAnimateNumbers, @))
|
||||
@$el.find('#victory-header').delay(250).queue(->
|
||||
$(@).removeClass('out').dequeue()
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'victory-title-appear' # TODO: actually add this
|
||||
)
|
||||
complete = _.once(_.bind(@beginSequentialAnimations, @))
|
||||
@animatedPanels = $()
|
||||
panels = @$el.find('.achievement-panel')
|
||||
for panel in panels
|
||||
|
@ -126,29 +131,34 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
@ladderSubmissionView = new LadderSubmissionView session: @session, level: @level
|
||||
@insertSubView @ladderSubmissionView, @$el.find('.ladder-submission-view')
|
||||
|
||||
beginAnimateNumbers: ->
|
||||
@numericalItemPanels = _.map(@animatedPanels.find('.numerical'), (panel) -> {
|
||||
beginSequentialAnimations: ->
|
||||
@sequentialAnimatedPanels = _.map(@animatedPanels.find('.reward-panel'), (panel) -> {
|
||||
number: $(panel).data('number')
|
||||
textEl: $(panel).find('.reward-text')
|
||||
rootEl: $(panel)
|
||||
unit: $(panel).data('number-unit')
|
||||
hero: $(panel).data('hero-thang-type')
|
||||
item: $(panel).data('item-thang-type')
|
||||
})
|
||||
|
||||
@totalXP = 0
|
||||
@totalXP += panel.number for panel in @numericalItemPanels when panel.unit is 'xp'
|
||||
@totalXP += panel.number for panel in @sequentialAnimatedPanels when panel.unit is 'xp'
|
||||
@totalGems = 0
|
||||
@totalGems += panel.number for panel in @numericalItemPanels when panel.unit is 'gem'
|
||||
@totalGems += panel.number for panel in @sequentialAnimatedPanels when panel.unit is 'gem'
|
||||
@gemEl = $('#gem-total')
|
||||
@XPEl = $('#xp-total')
|
||||
@totalXPAnimated = @totalGemsAnimated = @lastTotalXP = @lastTotalGems = 0
|
||||
@numberAnimationStart = new Date()
|
||||
@numberAnimationInterval = setInterval(@tickNumberAnimation, 1000 / 60)
|
||||
@sequentialAnimationStart = new Date()
|
||||
@sequentialAnimationInterval = setInterval(@tickSequentialAnimation, 1000 / 60)
|
||||
|
||||
tickNumberAnimation: =>
|
||||
tickSequentialAnimation: =>
|
||||
# TODO: make sure the animation pulses happen when the numbers go up and sounds play (up to a max speed)
|
||||
return @endAnimateNumbers() unless panel = @numericalItemPanels[0]
|
||||
duration = Math.log(panel.number + 1) / Math.LN10 * 1000 # Math.log10 is ES6
|
||||
ratio = @getEaseRatio (new Date() - @numberAnimationStart), duration
|
||||
return @endSequentialAnimations() unless panel = @sequentialAnimatedPanels[0]
|
||||
if panel.number
|
||||
duration = Math.log(panel.number + 1) / Math.LN10 * 1000 # Math.log10 is ES6
|
||||
else
|
||||
duration = 1000
|
||||
ratio = @getEaseRatio (new Date() - @sequentialAnimationStart), duration
|
||||
if panel.unit is 'xp'
|
||||
newXP = Math.floor(ratio * panel.number)
|
||||
totalXP = @totalXPAnimated + newXP
|
||||
|
@ -158,7 +168,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
xpTrigger = 'xp-' + (totalXP % 6) # 6 xp sounds
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: xpTrigger, volume: 0.5 + ratio / 2
|
||||
@lastTotalXP = totalXP
|
||||
else
|
||||
else if panel.unit is 'gem'
|
||||
newGems = Math.floor(ratio * panel.number)
|
||||
totalGems = @totalGemsAnimated + newGems
|
||||
if totalGems isnt @lastTotalGems
|
||||
|
@ -167,16 +177,24 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
gemTrigger = 'gem-' + (parseInt(panel.number * ratio) % 4) # 4 gem sounds
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: gemTrigger, volume: 0.5 + ratio / 2
|
||||
@lastTotalGems = totalGems
|
||||
else if panel.item
|
||||
thangType = @thangTypes[panel.item]
|
||||
panel.textEl.text(thangType.get('name'))
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'item-unlocked', volume: 1 if 0.5 < ratio < 0.6
|
||||
else if panel.hero
|
||||
thangType = @thangTypes[panel.hero]
|
||||
panel.textEl.text(thangType.get('name'))
|
||||
@playSelectionSound hero if 0.5 < ratio < 0.6
|
||||
if ratio is 1
|
||||
panel.rootEl.removeClass('animating').find('.reward-image-container img').removeClass('pulse')
|
||||
@numberAnimationStart = new Date()
|
||||
@sequentialAnimationStart = new Date()
|
||||
if panel.unit is 'xp'
|
||||
@totalXPAnimated += panel.number
|
||||
else
|
||||
else if panel.unit is 'gem'
|
||||
@totalGemsAnimated += panel.number
|
||||
@numericalItemPanels.shift()
|
||||
@sequentialAnimatedPanels.shift()
|
||||
return
|
||||
panel.rootEl.addClass('animating').find('.reward-image-container img').addClass('pulse')
|
||||
panel.rootEl.addClass('animating').find('.reward-image-container').removeClass('pending-reward-image').find('img').addClass('pulse')
|
||||
|
||||
getEaseRatio: (timeSinceStart, duration) ->
|
||||
# Ease in/out quadratic - http://gizma.com/easing/
|
||||
|
@ -187,8 +205,8 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
--t
|
||||
-0.5 * (t * (t - 2) - 1)
|
||||
|
||||
endAnimateNumbers: ->
|
||||
clearInterval @numberAnimationInterval
|
||||
endSequentialAnimations: ->
|
||||
clearInterval @sequentialAnimationInterval
|
||||
@animationComplete = true
|
||||
@updateSavingProgressStatus()
|
||||
|
||||
|
@ -196,14 +214,23 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
return unless @animationComplete
|
||||
@$el.find('#saving-progress-label').toggleClass('hide', @readyToContinue)
|
||||
@$el.find('#continue-button').toggleClass('hide', not @readyToContinue)
|
||||
@$el.find('.sign-up-poke').toggleClass('hide', not @readyToContinue)
|
||||
|
||||
onGameSubmitted: (e) ->
|
||||
ladderURL = "/play/ladder/#{@level.get('slug')}#my-matches"
|
||||
Backbone.Mediator.publish 'router:navigate', route: ladderURL
|
||||
|
||||
playSelectionSound: (hero, preload=false) ->
|
||||
return unless sounds = hero.get('soundTriggers')?.selected
|
||||
return unless sound = sounds[Math.floor Math.random() * sounds.length]
|
||||
name = AudioPlayer.nameForSoundReference sound
|
||||
if preload
|
||||
AudioPlayer.preloadSoundReference sound
|
||||
else
|
||||
AudioPlayer.playSound name, 1
|
||||
|
||||
# TODO: award heroes/items and play an awesome sound when you get one
|
||||
|
||||
destroy: ->
|
||||
clearInterval @numberAnimationInterval
|
||||
clearInterval @sequentialAnimationInterval
|
||||
super()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue