Mostly done with the victory modal.

This commit is contained in:
Scott Erickson 2014-10-10 16:11:35 -04:00
parent 70e20efcc7
commit 6ff7cd12cc
11 changed files with 333 additions and 38 deletions

Binary file not shown.

After

(image error) Size: 9.1 KiB

Binary file not shown.

After

(image error) Size: 3.6 KiB

Binary file not shown.

After

(image error) Size: 4.1 KiB

Binary file not shown.

After

(image error) Size: 2.1 KiB

Binary file not shown.

After

(image error) Size: 20 KiB

Binary file not shown.

After

(image error) Size: 9 KiB

View file

@ -1,2 +1,188 @@
#hero-victory-modal
color: red
//- Header
.background-wrapper
background: url("/images/pages/play/level/modal/victory_modal_background.png")
height: 650px
width: 550px
#victory-header
display: block
margin: 40px auto 0
.modal-header
height: 110px
border: none
//- Achievement panels
.modal-body
padding: 0 20px
.achievement-panel
background: url("/images/pages/play/level/modal/achievement_plate.png")
width: 451px
height: 144px
margin: 5px auto
position: relative
-webkit-transition-duration: 1s
-moz-transition-duration: 1s
-o-transition-duration: 1s
transition-duration: 1s
-webkit-filter: grayscale(100%)
-moz-filter: grayscale(100%)
-o-filter: grayscale(100%)
filter: grayscale(100%)
&.earned
-webkit-filter: none
-moz-filter: none
-o-filter: none
filter: none
.achievement-description
position: absolute
text-align: center
left: 95px
right: 98px
top: 10px
color: white
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
.achievement-rewards
position: absolute
left: 25px
right: 23px
top: 41px
bottom: 18px
//- Reward panels
.reward-panel
background: url("/images/pages/play/level/modal/reward_plate.png")
background: url("/images/pages/play/level/modal/reward_plate.png")
width: 77px
height: 85px
float: left
margin: 0 1.8px
position: relative
.reward-image-container
top: 8px
left: 11px
height: 55px
width: 56px
position: relative
-webkit-transform: scale(0, 0)
-moz-transform: scale(0, 0)
-o-transform: scale(0, 0)
transform: scale(0, 0)
-webkit-transition-duration: 0.5s
-moz-transition-duration: 0.5s
-o-transition-duration: 0.5s
transition-duration: 0.5s
&.show
-webkit-transform: scale(1, 1)
-moz-transform: scale(1, 1)
-o-transform: scale(1, 1)
transform: scale(1, 1)
img
margin: 0
position: absolute
top: 50%
left: 50%
margin-right: -50%
-webkit-transition-duration: 0.5s
-moz-transition-duration: 0.5s
-o-transition-duration: 0.5s
transition-duration: 0.5s
-webkit-transform: translate(-50%, -50%)
-moz-transform: translate(-50%, -50%)
-o-transform: translate(-50%, -50%)
transform: translate(-50%, -50%)
max-width: 56px
max-height: 55px
.reward-text
position: absolute
bottom: 6px
left: 4px
right: 3px
height: 15px
text-align: center
color: white
font-weight: bold
font-size: 12px
white-space: nowrap
overflow: hidden
text-overflow: ellipsis
//- Pulse effect
@-webkit-keyframes pulse
from
-webkit-transform: translate(-50%, -50%) scale(1.0)
50%
-webkit-transform: translate(-50%, -50%) scale(1.3)
to
-webkit-transform: translate(-50%, -50%) scale(1.0)
@-moz-keyframes pulse
from
-moz-transform: translate(-50%, -50%) scale(1.0)
50%
-moz-transform: translate(-50%, -50%) scale(1.3)
to
-moz-transform: translate(-50%, -50%) scale(1.0)
@-o-keyframes pulse
from
-o-transform: translate(-50%, -50%) scale(1.0)
50%
-o-transform: translate(-50%, -50%) scale(1.3)
to
-o-transform: translate(-50%, -50%) scale(1.0)
@keyframes pulse
from
transform: translate(-50%, -50%) scale(1.0)
50%
transform: translate(-50%, -50%) scale(1.3)
to
transform: translate(-50%, -50%) scale(1.0)
.pulse
-webkit-animation: pulse 0.5s infinite
-moz-animation: pulse 0.5s infinite
-o-animation: pulse 0.5s infinite
animation: pulse 0.5s infinite
//- Footer
.modal-content
height: 650px // so the footer appears at the bottom
.modal-footer
position: absolute
bottom: 20px
left: 20px
right: 20px
#totals
color: white

View file

@ -1,34 +1,53 @@
extends /templates/modal/modal_base
block modal-header-content
h3
span(data-i18n="play_level.victory_title_prefix")
span= levelName
span(data-i18n="play_level.victory_title_suffix") Complete
img(src="/images/pages/play/level/modal/victory_word.png")#victory-header
block modal-body-content
h4 Achievements Unlocked
for achievement in achievements
.panel
img(src=achievement.getImageURL())
h5= achievement.get('name')
p= achievement.get('description')
if achievement.completed
strong Completed
else
strong Incomplete
p Earned #{achievement.get('worth')} xp.
- var animate = achievement.completed && !achievement.completedAWhileAgo
.achievement-panel(class=achievement.completedAWhileAgo ? 'earned' : '' data-achievement-id=achievement.id data-animate=animate)
- var rewards = achievement.get('rewards') || {};
if rewards.gems
p Earned #{achievement.get('rewards').gems} gems.
if rewards.heroes
for hero in rewards.heroes
- var hero = thangTypes[hero];
img(src=hero.getPortraitURL())
if rewards.items
for item in rewards.items
- var item = thangTypes[item];
img(src=item.getPortraitURL())
div.achievement-description= achievement.get('description')
div.achievement-rewards
- var worth = achievement.get('worth', true);
if worth
.reward-panel.numerical(data-number=worth, data-number-unit='xp')
.reward-image-container(class=animate?'':'show')
img(src="/images/pages/play/level/modal/reward_icon_xp.png")
.reward-text= animate ? 'x0' : '+'+worth
if rewards.gems
.reward-panel.numerical(data-number=rewards.gems, data-number-unit='gem')
.reward-image-container(class=animate?'':'show')
img(src="/images/pages/play/level/modal/reward_icon_gems.png")
.reward-text= animate ? 'x0' : '+'+rewards.gems
if rewards.heroes
for hero in rewards.heroes
- var hero = thangTypes[hero];
.reward-panel
.reward-image-container(class=animate?'':'show')
img(src=hero.getPortraitURL())
.reward-text= hero.get('name')
if rewards.items
for item in rewards.items
- var item = thangTypes[item];
.reward-panel
.reward-image-container(class=animate?'':'show')
img(src=item.getPortraitURL())
.reward-text= item.get('name')
block modal-footer-content
| footer
div#totals.pull-left
span.spr Experience Gained:
span#xp-total +0
br
span.spr Gems Gained:
span#gem-total +0
button.btn.btn-primary.pull-right#continue-button Continue

View file

@ -206,10 +206,6 @@ module.exports = class PlayLevelView extends RootView
@initVolume()
@listenTo(@session, 'change:multiplayer', @onMultiplayerChanged)
# testing
# modal = new HeroVictoryModal({session: @session, level: @level})
# @openModalView(modal)
@originalSessionState = $.extend(true, {}, @session.get('state'))
@register()
@controlBar.setBus(@bus)

View file

@ -1,14 +1,16 @@
ModalView = require 'views/kinds/ModalView'
template = require 'templates/play/level/modal/hero-victory-modal'
Achievement = require 'models/Achievement'
EarnedAchievement = require 'models/EarnedAchievement'
CocoCollection = require 'collections/CocoCollection'
LocalMongo = require 'lib/LocalMongo'
utils = require 'lib/utils'
ThangType = require 'models/ThangType'
module.exports = class UnnamedView extends ModalView
module.exports = class HeroVictoryModal extends ModalView
id: 'hero-victory-modal'
template: template
closeButton: false
constructor: (options) ->
super(options)
@ -24,24 +26,96 @@ module.exports = class UnnamedView extends ModalView
onAchievementsLoaded: ->
thangTypeOriginals = []
achievementIDs = []
for achievement in @achievements.models
rewards = achievement.get('rewards')
console.log 'rewards', rewards
thangTypeOriginals.push rewards.heroes or []
thangTypeOriginals.push rewards.items or []
achievementIDs.push(achievement.id)
thangTypeOriginals = _.uniq _.flatten thangTypeOriginals
console.log 'thang type originals?', thangTypeOriginals
for thangTypeOriginal in thangTypeOriginals
thangType = new ThangType()
thangType.url = "/db/thang.type/#{thangTypeOriginal}/version"
thangType.project = ['original', 'rasterIcon']
thangType.project = ['original', 'rasterIcon', 'name']
@thangTypes[thangTypeOriginal] = @supermodel.loadModel(thangType, 'thang').model
url = "/db/earned_achievement?view=get-by-achievement-ids&achievementIDs=#{achievementIDs.join(',')}"
earnedAchievements = new CocoCollection([], {
url: url
model: EarnedAchievement
})
res = @supermodel.loadCollection(earnedAchievements, 'earned_achievements')
@earnedAchievements = res.model
getRenderData: ->
c = super()
c.levelName = utils.i18n @level.attributes, 'name'
for achievement in @achievements.models
earnedAchievementMap = _.indexBy(@earnedAchievements?.models or [], (ea) -> ea.get('achievement'))
for achievement, index in @achievements.models
achievement.completed = LocalMongo.matchesQuery(@session.attributes, achievement.get('query'))
earnedAchievement = earnedAchievementMap[achievement.id]
if earnedAchievement
achievement.completedAWhileAgo = new Date() - Date.parse(earnedAchievement.get('created')) > 30 * 1000
c.achievements = @achievements.models
# for testing the three states
# if c.achievements.length
# c.achievements = [c.achievements[0].clone(), c.achievements[0].clone(), c.achievements[0].clone()]
# for achievement, index in c.achievements
# achievement.completed = index > 0
# achievement.completedAWhileAgo = index > 1
c.thangTypes = @thangTypes
return c
return c
afterRender: ->
super()
return unless @supermodel.finished()
complete = _.once(_.bind(@beginAnimateNumbers, @))
@animatedPanels = $()
panels = @$el.find('.achievement-panel')
for panel in panels
panel = $(panel)
continue unless panel.data('animate')
@animatedPanels = @animatedPanels.add(panel)
panel.delay(500)
panel.queue(->
$(this).addClass('earned') # animate out the grayscale
$(this).dequeue()
)
panel.delay(500)
panel.queue(->
$(this).find('.reward-image-container').addClass('show')
$(this).dequeue()
)
panel.delay(500)
panel.queue(-> complete())
beginAnimateNumbers: ->
@numericalItemPanels = _.map(@animatedPanels.find('.numerical'), (panel) -> {
number: $(panel).data('number')
textEl: $(panel).find('.reward-text')
rootEl: $(panel)
unit: $(panel).data('number-unit')
})
# TODO: mess with this more later. Doesn't seem to work, often times will pulse background red rather than animate
# itemPanel.rootEl.find('.reward-image-container img').addClass('pulse') for itemPanel in @numericalItemPanels
@numberAnimationStart = new Date()
@totalXP = 0
@totalXP += panel.number for panel in @numericalItemPanels when panel.unit is 'xp'
@totalGems = 0
@totalGems += panel.number for panel in @numericalItemPanels when panel.unit is 'gem'
@gemEl = $('#gem-total')
@XPEl = $('#xp-total')
@numberAnimationInterval = setInterval(@tickNumberAnimation, 15 / 1000)
tickNumberAnimation: =>
pct = Math.min(1, (new Date() - @numberAnimationStart) / 1500)
panel.textEl.text('+'+parseInt(panel.number*pct)) for panel in @numericalItemPanels
@XPEl.text('+'+parseInt(@totalXP * pct))
@gemEl.text('+'+parseInt(@totalGems * pct))
@endAnimateNumbers() if pct is 1
endAnimateNumbers: ->
@$el.find('.pulse').removeClass('pulse')
clearInterval(@numberAnimationInterval)

View file

@ -14,6 +14,26 @@ class EarnedAchievementHandler extends Handler
hasAccess: (req) ->
req.method is 'GET' # or req.user.isAdmin()
get: (req, res) ->
return @getByAchievementIDs(req, res) if req.query.view is 'get-by-achievement-ids'
super(arguments...)
getByAchievementIDs: (req, res) ->
query = { user: req.user._id+''}
ids = req.query.achievementIDs
if (not ids) or (ids.length is 0)
return @sendBadInputError(res, 'For a get-by-achievement-ids request, need to provide ids.')
ids = ids.split(',')
for id in ids
if not Handler.isID(id)
return @sendBadInputError(res, "Not a MongoDB ObjectId: #{id}")
query.achievement = {$in: ids}
EarnedAchievement.find query, (err, earnedAchievements) ->
return @sendDatabaseError(res, err) if err
res.send(earnedAchievements)
recalculate: (req, res) ->
onSuccess = (data) => log.debug 'Finished recalculating achievements'
if 'achievements' of req.body # Support both slugs and IDs separated by commas