mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-27 09:35:39 -05:00
Refactored CocoSprite -> Lank, lank.imageObject -> lank.sprite, SpriteBoss -> LankBoss, spriteLayers -> layerAdapters, sprite -> lank in general. Also got the ThangTypeEditView working again.
This commit is contained in:
parent
64a8322ec0
commit
f081d9ed4b
22 changed files with 833 additions and 803 deletions
|
@ -53,11 +53,11 @@ module.exports = class LevelBus extends Bus
|
||||||
super()
|
super()
|
||||||
|
|
||||||
onSelfWizardCreated: (e) ->
|
onSelfWizardCreated: (e) ->
|
||||||
@selfWizardSprite = e.sprite
|
@selfWizardLank = e.sprite
|
||||||
|
|
||||||
onSelfWizardTargetChanged: (e) ->
|
onSelfWizardTargetChanged: (e) ->
|
||||||
@wizardRef?.child('targetPos').set(@selfWizardSprite?.targetPos or null)
|
@wizardRef?.child('targetPos').set(@selfWizardLank?.targetPos or null)
|
||||||
@wizardRef?.child('targetSprite').set(@selfWizardSprite?.targetSprite?.thang.id or null)
|
@wizardRef?.child('targetSprite').set(@selfWizardLank?.targetSprite?.thang.id or null)
|
||||||
|
|
||||||
onMeSynced: =>
|
onMeSynced: =>
|
||||||
super()
|
super()
|
||||||
|
@ -66,8 +66,8 @@ module.exports = class LevelBus extends Bus
|
||||||
join: ->
|
join: ->
|
||||||
super()
|
super()
|
||||||
@wizardRef = @myConnection.child('wizard')
|
@wizardRef = @myConnection.child('wizard')
|
||||||
@wizardRef?.child('targetPos').set(@selfWizardSprite?.targetPos or null)
|
@wizardRef?.child('targetPos').set(@selfWizardLank?.targetPos or null)
|
||||||
@wizardRef?.child('targetSprite').set(@selfWizardSprite?.targetSprite?.thang.id or null)
|
@wizardRef?.child('targetSprite').set(@selfWizardLank?.targetSprite?.thang.id or null)
|
||||||
@wizardRef?.child('wizardColor1').set(me.get('wizardColor1') or 0.0)
|
@wizardRef?.child('wizardColor1').set(me.get('wizardColor1') or 0.0)
|
||||||
|
|
||||||
disconnect: ->
|
disconnect: ->
|
||||||
|
|
|
@ -66,7 +66,7 @@ module.exports = class Dimmer extends CocoClass
|
||||||
@dimMask.graphics.clear()
|
@dimMask.graphics.clear()
|
||||||
for thangID, sprite of @sprites
|
for thangID, sprite of @sprites
|
||||||
continue unless (thangID in @highlightedThangIDs) or sprite.isTalking?() or sprite.thang?.id is 'My Wizard'
|
continue unless (thangID in @highlightedThangIDs) or sprite.isTalking?() or sprite.thang?.id is 'My Wizard'
|
||||||
sup = x: sprite.imageObject.x, y: sprite.imageObject.y
|
sup = x: sprite.sprite.x, y: sprite.sprite.y
|
||||||
cap = @camera.surfaceToCanvas sup
|
cap = @camera.surfaceToCanvas sup
|
||||||
r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size
|
r = 50 * @camera.zoom # TODO: find better way to get the radius based on the sprite's size
|
||||||
@dimMask.graphics.beginRadialGradientFill(['rgba(0,0,0,1)', 'rgba(0,0,0,0)'], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r)
|
@dimMask.graphics.beginRadialGradientFill(['rgba(0,0,0,1)', 'rgba(0,0,0,0)'], [0.5, 1], cap.x, cap.y, 0, cap.x, cap.y, r).drawCircle(cap.x, cap.y, r)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
IndieSprite = require 'lib/surface/IndieSprite'
|
IndieLank = require 'lib/surface/IndieLank'
|
||||||
{me} = require 'lib/auth'
|
{me} = require 'lib/auth'
|
||||||
|
|
||||||
module.exports = class FlagSprite extends IndieSprite
|
module.exports = class FlagLank extends IndieLank
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'surface:mouse-moved': 'onMouseMoved'
|
'surface:mouse-moved': 'onMouseMoved'
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
Thang = require 'lib/world/thang'
|
Thang = require 'lib/world/thang'
|
||||||
CocoSprite = require 'lib/surface/CocoSprite'
|
Lank = require 'lib/surface/Lank'
|
||||||
|
|
||||||
module.exports = IndieSprite = class IndieSprite extends CocoSprite
|
module.exports = IndieLank = class IndieLank extends Lank
|
||||||
notOfThisWorld: true
|
notOfThisWorld: true
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'script:note-group-started': 'onNoteGroupStarted'
|
'script:note-group-started': 'onNoteGroupStarted'
|
|
@ -49,11 +49,11 @@ module.exports = class Label extends CocoClass
|
||||||
update: ->
|
update: ->
|
||||||
return unless @text
|
return unless @text
|
||||||
offset = @sprite.getOffset? (if @style in ['dialogue', 'say'] then 'mouth' else 'aboveHead')
|
offset = @sprite.getOffset? (if @style in ['dialogue', 'say'] then 'mouth' else 'aboveHead')
|
||||||
offset ?= x: 0, y: 0 # temp (if not CocoSprite)
|
offset ?= x: 0, y: 0 # temp (if not Lank)
|
||||||
rotation = @sprite.getRotation()
|
rotation = @sprite.getRotation()
|
||||||
offset.x *= -1 if rotation >= 135 or rotation <= -135
|
offset.x *= -1 if rotation >= 135 or rotation <= -135
|
||||||
@label.x = @background.x = @sprite.imageObject.x + offset.x
|
@label.x = @background.x = @sprite.sprite.x + offset.x
|
||||||
@label.y = @background.y = @sprite.imageObject.y + offset.y
|
@label.y = @background.y = @sprite.sprite.y + offset.y
|
||||||
null
|
null
|
||||||
|
|
||||||
show: ->
|
show: ->
|
||||||
|
@ -122,7 +122,7 @@ module.exports = class Label extends CocoClass
|
||||||
pointerWidth += radius # Convenience value including pointer width and border radius
|
pointerWidth += radius # Convenience value including pointer width and border radius
|
||||||
|
|
||||||
# Figure out the position of the pointer for the bubble
|
# Figure out the position of the pointer for the bubble
|
||||||
sup = x: @sprite.imageObject.x, y: @sprite.imageObject.y # a little more accurate to aim for mouth--how?
|
sup = x: @sprite.sprite.x, y: @sprite.sprite.y # a little more accurate to aim for mouth--how?
|
||||||
cap = @camera.surfaceToCanvas sup
|
cap = @camera.surfaceToCanvas sup
|
||||||
hPos = if cap.x / @camera.canvasWidth > 0.53 then 'right' else 'left'
|
hPos = if cap.x / @camera.canvasWidth > 0.53 then 'right' else 'left'
|
||||||
vPos = if cap.y / @camera.canvasHeight > 0.53 then 'bottom' else 'top'
|
vPos = if cap.y / @camera.canvasHeight > 0.53 then 'bottom' else 'top'
|
||||||
|
|
|
@ -13,10 +13,10 @@ healthColors =
|
||||||
neutral: [64, 212, 128]
|
neutral: [64, 212, 128]
|
||||||
|
|
||||||
# Sprite: EaselJS-based view/controller for Thang model
|
# Sprite: EaselJS-based view/controller for Thang model
|
||||||
module.exports = CocoSprite = class CocoSprite extends CocoClass
|
module.exports = Lank = class Lank extends CocoClass
|
||||||
thangType: null # ThangType instance
|
thangType: null # ThangType instance
|
||||||
|
|
||||||
imageObject: null
|
sprite: null
|
||||||
|
|
||||||
healthBar: null
|
healthBar: null
|
||||||
marks: null
|
marks: null
|
||||||
|
@ -62,12 +62,12 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@options = _.extend($.extend(true, {}, @options), options)
|
@options = _.extend($.extend(true, {}, @options), options)
|
||||||
@setThang @options.thang
|
@setThang @options.thang
|
||||||
if @thang?
|
if @thang?
|
||||||
options = @thang?.getSpriteOptions?()
|
options = @thang?.getLankOptions?()
|
||||||
@options.colorConfig = options.colorConfig if options and options.colorConfig
|
@options.colorConfig = options.colorConfig if options and options.colorConfig
|
||||||
console.error @toString(), 'has no ThangType!' unless @thangType
|
console.error @toString(), 'has no ThangType!' unless @thangType
|
||||||
|
|
||||||
# this is a stub, use @setImageObject to swap it out for something else later
|
# this is a stub, use @setSprite to swap it out for something else later
|
||||||
@imageObject = new createjs.Container
|
@sprite = new createjs.Container
|
||||||
|
|
||||||
@actionQueue = []
|
@actionQueue = []
|
||||||
@marks = {}
|
@marks = {}
|
||||||
|
@ -78,7 +78,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@stillLoading = true
|
@stillLoading = true
|
||||||
if @thangType.isFullyLoaded() then @onThangTypeLoaded() else @listenToOnce(@thangType, 'sync', @onThangTypeLoaded)
|
if @thangType.isFullyLoaded() then @onThangTypeLoaded() else @listenToOnce(@thangType, 'sync', @onThangTypeLoaded)
|
||||||
|
|
||||||
toString: -> "<CocoSprite: #{@thang?.id}>"
|
toString: -> "<Lank: #{@thang?.id}>"
|
||||||
|
|
||||||
onThangTypeLoaded: ->
|
onThangTypeLoaded: ->
|
||||||
@stillLoading = false
|
@stillLoading = false
|
||||||
|
@ -97,22 +97,22 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@scaleFactorY = @thang.scaleFactor if @thang?.scaleFactor?
|
@scaleFactorY = @thang.scaleFactor if @thang?.scaleFactor?
|
||||||
@updateAction() unless @currentAction
|
@updateAction() unless @currentAction
|
||||||
|
|
||||||
setImageObject: (newImageObject) ->
|
setSprite: (newSprite) ->
|
||||||
if @imageObject
|
if @sprite
|
||||||
@imageObject.destroy?()
|
@sprite.destroy?()
|
||||||
if parent = @imageObject.parent
|
if parent = @sprite.parent
|
||||||
parent.removeChild @imageObject
|
parent.removeChild @sprite
|
||||||
parent.addChild newImageObject
|
parent.addChild newSprite
|
||||||
|
|
||||||
# get the cocosprite to update things
|
# get the lank to update things
|
||||||
for prop in ['lastPos', 'currentRootAction']
|
for prop in ['lastPos', 'currentRootAction']
|
||||||
delete @[prop]
|
delete @[prop]
|
||||||
|
|
||||||
@imageObject = newImageObject
|
@sprite = newSprite
|
||||||
@configureMouse()
|
@configureMouse()
|
||||||
@imageObject.on 'animationend', @playNextAction
|
@sprite.on 'animationend', @playNextAction
|
||||||
@playAction(@currentAction) if @currentAction and not @stillLoading
|
@playAction(@currentAction) if @currentAction and not @stillLoading
|
||||||
@trigger 'new-image-object', @imageObject
|
@trigger 'new-sprite', @sprite
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
# QUEUEING AND PLAYING ACTIONS
|
# QUEUEING AND PLAYING ACTIONS
|
||||||
|
@ -141,9 +141,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
return @hide() unless action.animation or action.container or action.relatedActions
|
return @hide() unless action.animation or action.container or action.relatedActions
|
||||||
@show()
|
@show()
|
||||||
return @updateActionDirection() unless action.animation or action.container
|
return @updateActionDirection() unless action.animation or action.container
|
||||||
return if @imageObject.placeholder
|
return if @sprite.placeholder
|
||||||
m = if action.container then 'gotoAndStop' else 'gotoAndPlay'
|
m = if action.container then 'gotoAndStop' else 'gotoAndPlay'
|
||||||
@imageObject[m]?(action.name)
|
@sprite[m]?(action.name)
|
||||||
@updateScale()
|
@updateScale()
|
||||||
@updateRotation()
|
@updateRotation()
|
||||||
|
|
||||||
|
@ -156,12 +156,12 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@updateAlpha()
|
@updateAlpha()
|
||||||
|
|
||||||
stop: ->
|
stop: ->
|
||||||
@imageObject?.stop?()
|
@sprite?.stop?()
|
||||||
mark.stop() for name, mark of @marks
|
mark.stop() for name, mark of @marks
|
||||||
@stopped = true
|
@stopped = true
|
||||||
|
|
||||||
play: ->
|
play: ->
|
||||||
@imageObject?.play?()
|
@sprite?.play?()
|
||||||
mark.play() for name, mark of @marks
|
mark.play() for name, mark of @marks
|
||||||
@stopped = false
|
@stopped = false
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
shadowColor = {humans: '#F00', ogres: '#00F', neutral: '#0F0', common: '#0F0'}[@thang.team] ? '#000'
|
shadowColor = {humans: '#F00', ogres: '#00F', neutral: '#0F0', common: '#0F0'}[@thang.team] ? '#000'
|
||||||
label.shadow = new createjs.Shadow shadowColor, 1, 1, 3
|
label.shadow = new createjs.Shadow shadowColor, 1, 1, 3
|
||||||
offset = @getOffset 'aboveHead'
|
offset = @getOffset 'aboveHead'
|
||||||
[label.x, label.y] = [@imageObject.x + offset.x - label.getMeasuredWidth() / 2, @imageObject.y + offset.y]
|
[label.x, label.y] = [@sprite.x + offset.x - label.getMeasuredWidth() / 2, @sprite.y + offset.y]
|
||||||
@options.textLayer.addChild label
|
@options.textLayer.addChild label
|
||||||
window.labels ?= []
|
window.labels ?= []
|
||||||
window.labels.push label
|
window.labels.push label
|
||||||
|
@ -270,7 +270,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
[p0, p1] = [@lastPos, @thang.pos]
|
[p0, p1] = [@lastPos, @thang.pos]
|
||||||
return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo and not @thang.bobHeight
|
return if p0 and p0.x is p1.x and p0.y is p1.y and p0.z is p1.z and not @options.camera.tweeningZoomTo and not @thang.bobHeight
|
||||||
sup = @options.camera.worldToSurface wop
|
sup = @options.camera.worldToSurface wop
|
||||||
[@imageObject.x, @imageObject.y] = [sup.x, sup.y]
|
[@sprite.x, @sprite.y] = [sup.x, sup.y]
|
||||||
@lastPos = p1.copy?() or _.clone(p1) unless whileLoading
|
@lastPos = p1.copy?() or _.clone(p1) unless whileLoading
|
||||||
@hasMoved = true
|
@hasMoved = true
|
||||||
if @thangType.get('name') is 'Flag' and not @notOfThisWorld
|
if @thangType.get('name') is 'Flag' and not @notOfThisWorld
|
||||||
|
@ -278,19 +278,19 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
_.defer => Backbone.Mediator.publish 'surface:flag-appeared', sprite: @
|
_.defer => Backbone.Mediator.publish 'surface:flag-appeared', sprite: @
|
||||||
|
|
||||||
updateScale: ->
|
updateScale: ->
|
||||||
return unless @imageObject
|
return unless @sprite
|
||||||
if @thangType.get('matchWorldDimensions') and @thang
|
if @thangType.get('matchWorldDimensions') and @thang
|
||||||
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
||||||
bounds = @imageObject.getBounds()
|
bounds = @sprite.getBounds()
|
||||||
return unless bounds
|
return unless bounds
|
||||||
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width
|
@sprite.scaleX = @thang.width * Camera.PPM / bounds.width
|
||||||
@imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height
|
@sprite.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height
|
||||||
@imageObject.regX = bounds.width / 2
|
@sprite.regX = bounds.width / 2
|
||||||
@imageObject.regY = bounds.height / 2
|
@sprite.regY = bounds.height / 2
|
||||||
|
|
||||||
unless @thang.spriteName is 'Beam'
|
unless @thang.spriteName is 'Beam'
|
||||||
@imageObject.scaleX *= @thangType.get('scale') ? 1
|
@sprite.scaleX *= @thangType.get('scale') ? 1
|
||||||
@imageObject.scaleY *= @thangType.get('scale') ? 1
|
@sprite.scaleY *= @thangType.get('scale') ? 1
|
||||||
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -311,8 +311,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
scaleX = 0.5 + 0.5 * (90 - angle) / 90
|
scaleX = 0.5 + 0.5 * (90 - angle) / 90
|
||||||
|
|
||||||
# console.error 'No thang for', @ unless @thang
|
# console.error 'No thang for', @ unless @thang
|
||||||
@imageObject.scaleX = @imageObject.baseScaleX * @scaleFactorX * scaleX
|
@sprite.scaleX = @sprite.baseScaleX * @scaleFactorX * scaleX
|
||||||
@imageObject.scaleY = @imageObject.baseScaleY * @scaleFactorY * scaleY
|
@sprite.scaleY = @sprite.baseScaleY * @scaleFactorY * scaleY
|
||||||
|
|
||||||
newScaleFactorX = @thang?.scaleFactorX ? @thang?.scaleFactor ? 1
|
newScaleFactorX = @thang?.scaleFactorX ? @thang?.scaleFactor ? 1
|
||||||
newScaleFactorY = @thang?.scaleFactorY ? @thang?.scaleFactor ? 1
|
newScaleFactorY = @thang?.scaleFactorY ? @thang?.scaleFactor ? 1
|
||||||
|
@ -323,16 +323,16 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
createjs.Tween.get(@).to({scaleFactorX: @targetScaleFactorX, scaleFactorY: @targetScaleFactorY}, 2000, createjs.Ease.elasticOut)
|
createjs.Tween.get(@).to({scaleFactorX: @targetScaleFactorX, scaleFactorY: @targetScaleFactorY}, 2000, createjs.Ease.elasticOut)
|
||||||
|
|
||||||
updateAlpha: ->
|
updateAlpha: ->
|
||||||
@imageObject.alpha = if @hiding then 0 else 1
|
@sprite.alpha = if @hiding then 0 else 1
|
||||||
return unless @thang?.alpha?
|
return unless @thang?.alpha?
|
||||||
return if @imageObject.alpha is @thang.alpha
|
return if @sprite.alpha is @thang.alpha
|
||||||
@imageObject.alpha = @thang.alpha
|
@sprite.alpha = @thang.alpha
|
||||||
if @options.showInvisible
|
if @options.showInvisible
|
||||||
@imageObject.alpha = Math.max 0.5, @imageObject.alpha
|
@sprite.alpha = Math.max 0.5, @sprite.alpha
|
||||||
mark.updateAlpha @thang.alpha for name, mark of @marks
|
mark.updateAlpha @thang.alpha for name, mark of @marks
|
||||||
@healthBar?.alpha = @thang.alpha
|
@healthBar?.alpha = @thang.alpha
|
||||||
|
|
||||||
updateRotation: (imageObject) ->
|
updateRotation: (sprite) ->
|
||||||
rotationType = @thangType.get('rotationType')
|
rotationType = @thangType.get('rotationType')
|
||||||
return if rotationType is 'fixed'
|
return if rotationType is 'fixed'
|
||||||
rotation = @getRotation()
|
rotation = @getRotation()
|
||||||
|
@ -347,9 +347,9 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
xFactor = Math.cos heading
|
xFactor = Math.cos heading
|
||||||
zFactor = vz / Math.sqrt(vz * vz + vx * vx)
|
zFactor = vz / Math.sqrt(vz * vz + vx * vx)
|
||||||
rotation -= xFactor * zFactor * 45
|
rotation -= xFactor * zFactor * 45
|
||||||
imageObject ?= @imageObject
|
sprite ?= @sprite
|
||||||
return imageObject.rotation = rotation if rotationType is 'free' or not rotationType
|
return sprite.rotation = rotation if rotationType is 'free' or not rotationType
|
||||||
@updateIsometricRotation(rotation, imageObject)
|
@updateIsometricRotation(rotation, sprite)
|
||||||
|
|
||||||
getRotation: ->
|
getRotation: ->
|
||||||
thang = if @possessed then @shadow else @thang
|
thang = if @possessed then @shadow else @thang
|
||||||
|
@ -359,11 +359,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
rotation -= 360 if rotation > 180
|
rotation -= 360 if rotation > 180
|
||||||
rotation
|
rotation
|
||||||
|
|
||||||
updateIsometricRotation: (rotation, imageObject) ->
|
updateIsometricRotation: (rotation, sprite) ->
|
||||||
return unless @currentAction
|
return unless @currentAction
|
||||||
return if _.string.endsWith(@currentAction.name, 'back')
|
return if _.string.endsWith(@currentAction.name, 'back')
|
||||||
return if _.string.endsWith(@currentAction.name, 'fore')
|
return if _.string.endsWith(@currentAction.name, 'fore')
|
||||||
imageObject.scaleX *= -1 if Math.abs(rotation) >= 90
|
sprite.scaleX *= -1 if Math.abs(rotation) >= 90
|
||||||
|
|
||||||
##################################################
|
##################################################
|
||||||
updateAction: ->
|
updateAction: ->
|
||||||
|
@ -455,18 +455,18 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
|
@setNameLabel(if @thang.health <= 0 then '' else @thang.id)
|
||||||
|
|
||||||
configureMouse: ->
|
configureMouse: ->
|
||||||
@imageObject.cursor = 'pointer' if @thang?.isSelectable
|
@sprite.cursor = 'pointer' if @thang?.isSelectable
|
||||||
@imageObject.mouseEnabled = @imageObject.mouseChildren = false unless @thang?.isSelectable or @thang?.isLand
|
@sprite.mouseEnabled = @sprite.mouseChildren = false unless @thang?.isSelectable or @thang?.isLand
|
||||||
if @imageObject.mouseEnabled
|
if @sprite.mouseEnabled
|
||||||
@imageObject.on 'mousedown', @onMouseEvent, @, false, 'sprite:mouse-down'
|
@sprite.on 'mousedown', @onMouseEvent, @, false, 'sprite:mouse-down'
|
||||||
@imageObject.on 'click', @onMouseEvent, @, false, 'sprite:clicked'
|
@sprite.on 'click', @onMouseEvent, @, false, 'sprite:clicked'
|
||||||
@imageObject.on 'dblclick', @onMouseEvent, @, false, 'sprite:double-clicked'
|
@sprite.on 'dblclick', @onMouseEvent, @, false, 'sprite:double-clicked'
|
||||||
@imageObject.on 'pressmove', @onMouseEvent, @, false, 'sprite:dragged'
|
@sprite.on 'pressmove', @onMouseEvent, @, false, 'sprite:dragged'
|
||||||
@imageObject.on 'pressup', @onMouseEvent, @, false, 'sprite:mouse-up'
|
@sprite.on 'pressup', @onMouseEvent, @, false, 'sprite:mouse-up'
|
||||||
|
|
||||||
onMouseEvent: (e, ourEventName) ->
|
onMouseEvent: (e, ourEventName) ->
|
||||||
return if @letterboxOn or not @imageObject
|
return if @letterboxOn or not @sprite
|
||||||
p = @imageObject
|
p = @sprite
|
||||||
p = p.parent while p.parent
|
p = p.parent while p.parent
|
||||||
newEvent = sprite: @, thang: @thang, originalEvent: e, canvas: p.canvas
|
newEvent = sprite: @, thang: @thang, originalEvent: e, canvas: p.canvas
|
||||||
@trigger ourEventName, newEvent
|
@trigger ourEventName, newEvent
|
||||||
|
@ -505,7 +505,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
pos = x: pos.x, y: pos.y
|
pos = x: pos.x, y: pos.y
|
||||||
if not @isRaster
|
if not @isRaster
|
||||||
scale = @getActionProp 'scale', null, 1
|
scale = @getActionProp 'scale', null, 1
|
||||||
scale *= @imageObject.parent.resolutionFactor if prop is 'registration'
|
scale *= @sprite.parent.resolutionFactor if prop is 'registration'
|
||||||
pos.x *= scale
|
pos.x *= scale
|
||||||
pos.y *= scale
|
pos.y *= scale
|
||||||
if @thang and prop isnt 'registration'
|
if @thang and prop isnt 'registration'
|
||||||
|
@ -613,7 +613,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
@labels[name]
|
@labels[name]
|
||||||
|
|
||||||
addMark: (name, layer, thangType=null) ->
|
addMark: (name, layer, thangType=null) ->
|
||||||
@marks[name] ?= new Mark name: name, sprite: @, camera: @options.camera, layer: layer ? @options.groundLayer, thangType: thangType
|
@marks[name] ?= new Mark name: name, lank: @, camera: @options.camera, layer: layer ? @options.groundLayer, thangType: thangType
|
||||||
@marks[name]
|
@marks[name]
|
||||||
|
|
||||||
notifySpeechUpdated: (e) ->
|
notifySpeechUpdated: (e) ->
|
||||||
|
@ -720,7 +720,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
z = @shadow.pos.z
|
z = @shadow.pos.z
|
||||||
@shadow.pos = pos
|
@shadow.pos = pos
|
||||||
@shadow.pos.z = z
|
@shadow.pos.z = z
|
||||||
@imageObject.gotoAndPlay?(endAnimation)
|
@sprite.gotoAndPlay?(endAnimation)
|
||||||
return
|
return
|
||||||
|
|
||||||
@shadow.action = 'move'
|
@shadow.action = 'move'
|
||||||
|
@ -736,7 +736,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
|
|
||||||
endFunc = =>
|
endFunc = =>
|
||||||
@lastTween = null
|
@lastTween = null
|
||||||
@imageObject.gotoAndPlay(endAnimation) unless @stillLoading
|
@sprite.gotoAndPlay(endAnimation) unless @stillLoading
|
||||||
@shadow.action = 'idle'
|
@shadow.action = 'idle'
|
||||||
@update true
|
@update true
|
||||||
@possessed = false
|
@possessed = false
|
||||||
|
@ -762,13 +762,13 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
||||||
return unless @healthBar
|
return unless @healthBar
|
||||||
bounds = @healthBar.getBounds()
|
bounds = @healthBar.getBounds()
|
||||||
offset = @getOffset 'aboveHead'
|
offset = @getOffset 'aboveHead'
|
||||||
@healthBar.x = @imageObject.x - (-offset.x + bounds.width / 2 / @options.floatingLayer.resolutionFactor)
|
@healthBar.x = @sprite.x - (-offset.x + bounds.width / 2 / @options.floatingLayer.resolutionFactor)
|
||||||
@healthBar.y = @imageObject.y - (-offset.y + bounds.height / 2 / @options.floatingLayer.resolutionFactor)
|
@healthBar.y = @sprite.y - (-offset.y + bounds.height / 2 / @options.floatingLayer.resolutionFactor)
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
mark.destroy() for name, mark of @marks
|
mark.destroy() for name, mark of @marks
|
||||||
label.destroy() for name, label of @labels
|
label.destroy() for name, label of @labels
|
||||||
p.removeChild @healthBar if p = @healthBar?.parent
|
p.removeChild @healthBar if p = @healthBar?.parent
|
||||||
@imageObject?.off 'animationend', @playNextAction
|
@sprite?.off 'animationend', @playNextAction
|
||||||
clearInterval @effectInterval if @effectInterval
|
clearInterval @effectInterval if @effectInterval
|
||||||
super()
|
super()
|
391
app/lib/surface/LankBoss.coffee
Normal file
391
app/lib/surface/LankBoss.coffee
Normal file
|
@ -0,0 +1,391 @@
|
||||||
|
CocoClass = require 'lib/CocoClass'
|
||||||
|
{me} = require 'lib/auth'
|
||||||
|
LayerAdapter = require './LayerAdapter'
|
||||||
|
IndieLank = require 'lib/surface/IndieLank'
|
||||||
|
WizardLank = require 'lib/surface/WizardLank'
|
||||||
|
FlagLank = require 'lib/surface/FlagLank'
|
||||||
|
Lank = require 'lib/surface/Lank'
|
||||||
|
Mark = require './Mark'
|
||||||
|
Grid = require 'lib/world/Grid'
|
||||||
|
|
||||||
|
module.exports = class LankBoss extends CocoClass
|
||||||
|
subscriptions:
|
||||||
|
'bus:player-joined': 'onPlayerJoined'
|
||||||
|
'bus:player-left': 'onPlayerLeft'
|
||||||
|
'level:set-debug': 'onSetDebug'
|
||||||
|
'sprite:highlight-sprites': 'onHighlightSprites'
|
||||||
|
'surface:stage-mouse-down': 'onStageMouseDown'
|
||||||
|
'level:select-sprite': 'onSelectSprite'
|
||||||
|
'level:suppress-selection-sounds': 'onSuppressSelectionSounds'
|
||||||
|
'level:lock-select': 'onSetLockSelect'
|
||||||
|
'level:restarted': 'onLevelRestarted'
|
||||||
|
'god:new-world-created': 'onNewWorld'
|
||||||
|
'god:streaming-world-updated': 'onNewWorld'
|
||||||
|
'camera:dragged': 'onCameraDragged'
|
||||||
|
'sprite:loaded': -> @update(true)
|
||||||
|
'level:flag-color-selected': 'onFlagColorSelected'
|
||||||
|
'level:flag-updated': 'onFlagUpdated'
|
||||||
|
'surface:flag-appeared': 'onFlagAppeared'
|
||||||
|
'surface:remove-selected-flag': 'onRemoveSelectedFlag'
|
||||||
|
|
||||||
|
constructor: (@options) ->
|
||||||
|
super()
|
||||||
|
@dragged = 0
|
||||||
|
@options ?= {}
|
||||||
|
@camera = @options.camera
|
||||||
|
@webGLStage = @options.webGLStage
|
||||||
|
@surfaceTextLayer = @options.surfaceTextLayer
|
||||||
|
@world = options.world
|
||||||
|
@options.thangTypes ?= []
|
||||||
|
@lanks = {}
|
||||||
|
@lankArray = [] # Mirror @lanks, but faster for when we just need to iterate
|
||||||
|
@selfWizardLank = null
|
||||||
|
@createLayers()
|
||||||
|
@pendingFlags = []
|
||||||
|
|
||||||
|
destroy: ->
|
||||||
|
@removeLank lank for thangID, lank of @lanks
|
||||||
|
@targetMark?.destroy()
|
||||||
|
@selectionMark?.destroy()
|
||||||
|
super()
|
||||||
|
|
||||||
|
toString: -> "<LankBoss: #{@lankArray.length} lanks>"
|
||||||
|
|
||||||
|
thangTypeFor: (type) ->
|
||||||
|
_.find @options.thangTypes, (m) -> m.get('original') is type or m.get('name') is type
|
||||||
|
|
||||||
|
createLayers: ->
|
||||||
|
@layerAdapters = {}
|
||||||
|
for [name, priority] in [
|
||||||
|
['Land', -40]
|
||||||
|
['Ground', -30]
|
||||||
|
['Obstacle', -20]
|
||||||
|
['Path', -10]
|
||||||
|
['Default', 0]
|
||||||
|
['Floating', 10]
|
||||||
|
]
|
||||||
|
@layerAdapters[name] = new LayerAdapter name: name, webGL: true, layerPriority: priority, transform: LayerAdapter.TRANSFORM_SURFACE, camera: @camera
|
||||||
|
@webGLStage.addChild (lankLayer.container for lankLayer in _.values(@layerAdapters))...
|
||||||
|
|
||||||
|
layerForChild: (child, lank) ->
|
||||||
|
unless child.layerPriority?
|
||||||
|
if thang = lank?.thang
|
||||||
|
child.layerPriority = thang.layerPriority
|
||||||
|
child.layerPriority ?= 0 if thang.isSelectable
|
||||||
|
child.layerPriority ?= -40 if thang.isLand
|
||||||
|
child.layerPriority ?= 0
|
||||||
|
return @layerAdapters['Default'] unless child.layerPriority
|
||||||
|
layer = _.findLast @layerAdapters, (layer, name) ->
|
||||||
|
layer.layerPriority <= child.layerPriority
|
||||||
|
layer ?= @layerAdapters['Land'] if child.layerPriority < -40
|
||||||
|
layer ? @layerAdapters['Default']
|
||||||
|
|
||||||
|
addLank: (lank, id=null, layer=null) ->
|
||||||
|
id ?= lank.thang.id
|
||||||
|
console.error 'Lank collision! Already have:', id if @lanks[id]
|
||||||
|
@lanks[id] = lank
|
||||||
|
@lankArray.push lank
|
||||||
|
layer ?= @layerAdapters['Obstacle'] if lank.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1
|
||||||
|
layer ?= @layerForChild lank.sprite, lank
|
||||||
|
layer.addLank lank
|
||||||
|
layer.updateLayerOrder()
|
||||||
|
lank
|
||||||
|
|
||||||
|
createMarks: ->
|
||||||
|
@targetMark = new Mark name: 'target', camera: @camera, layer: @layerAdapters['Ground'], thangType: 'target'
|
||||||
|
@selectionMark = new Mark name: 'selection', camera: @camera, layer: @layerAdapters['Ground'], thangType: 'selection'
|
||||||
|
|
||||||
|
createLankOptions: (options) ->
|
||||||
|
_.extend options, camera: @camera, resolutionFactor: SPRITE_RESOLUTION_FACTOR, groundLayer: @layerAdapters['Ground'], textLayer: @surfaceTextLayer, floatingLayer: @layerAdapters['Floating'], showInvisible: @options.showInvisible
|
||||||
|
|
||||||
|
createIndieLanks: (indieLanks, withWizards) ->
|
||||||
|
unless @indieLanks
|
||||||
|
@indieLanks = []
|
||||||
|
@indieLanks = (@createIndieLank indieLank for indieLank in indieLanks) if indieLanks
|
||||||
|
if withWizards and not @selfWizardLank
|
||||||
|
@selfWizardLank = @createWizardLank thangID: 'My Wizard', isSelf: true, lanks: @lanks
|
||||||
|
|
||||||
|
createIndieLank: (indieLank) ->
|
||||||
|
unless thangType = @thangTypeFor indieLank.thangType
|
||||||
|
console.warn "Need to convert #{indieLank.id}'s ThangType #{indieLank.thangType} to a ThangType reference. Until then, #{indieLank.id} won't show up."
|
||||||
|
return
|
||||||
|
lank = new IndieLank thangType, @createLankOptions {thangID: indieLank.id, pos: indieLank.pos, lanks: @lanks, team: indieLank.team, teamColors: @world.getTeamColors()}
|
||||||
|
@addLank lank, lank.thang.id
|
||||||
|
|
||||||
|
createOpponentWizard: (opponent) ->
|
||||||
|
# TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
|
||||||
|
lank = @createWizardLank thangID: opponent.id, name: opponent.name, codeLanguage: opponent.codeLanguage
|
||||||
|
if not opponent.levelSlug or opponent.levelSlug is 'brawlwood'
|
||||||
|
lank.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
|
||||||
|
else if opponent.levelSlug in ['dungeon-arena', 'sky-span']
|
||||||
|
lank.targetPos = if opponent.team is 'ogres' then {x: 72, y: 39} else {x: 9, y: 39}
|
||||||
|
else if opponent.levelSlug is 'criss-cross'
|
||||||
|
lank.targetPos = if opponent.team is 'ogres' then {x: 50, y: 12} else {x: 0, y: 40}
|
||||||
|
else
|
||||||
|
lank.targetPos = if opponent.team is 'ogres' then {x: 52, y: 28} else {x: 20, y: 28}
|
||||||
|
|
||||||
|
createWizardLank: (options) ->
|
||||||
|
lank = new WizardLank @thangTypeFor('Wizard'), @createLankOptions(options)
|
||||||
|
@addLank lank, lank.thang.id, @layerAdapters['Floating']
|
||||||
|
|
||||||
|
onPlayerJoined: (e) ->
|
||||||
|
# Create another WizardLank, unless this player is just me
|
||||||
|
pid = e.player.id
|
||||||
|
return if pid is me.id
|
||||||
|
wiz = @createWizardLank thangID: pid, lanks: @lanks
|
||||||
|
wiz.animateIn()
|
||||||
|
state = e.player.wizard or {}
|
||||||
|
wiz.setInitialState(state.targetPos, @lanks[state.targetLank])
|
||||||
|
|
||||||
|
onPlayerLeft: (e) ->
|
||||||
|
pid = e.player.id
|
||||||
|
@lanks[pid]?.animateOut => @removeLank @lanks[pid]
|
||||||
|
|
||||||
|
onSetDebug: (e) ->
|
||||||
|
return if e.debug is @debug
|
||||||
|
@debug = e.debug
|
||||||
|
lank.setDebug @debug for lank in @lankArray
|
||||||
|
|
||||||
|
onHighlightSprites: (e) ->
|
||||||
|
highlightedIDs = e.thangIDs or []
|
||||||
|
for thangID, lank of @lanks
|
||||||
|
lank.setHighlight? thangID in highlightedIDs, e.delay
|
||||||
|
|
||||||
|
addThangToLanks: (thang, layer=null) ->
|
||||||
|
return console.warn 'Tried to add Thang to the surface it already has:', thang.id if @lanks[thang.id]
|
||||||
|
thangType = _.find @options.thangTypes, (m) ->
|
||||||
|
return false unless m.get('actions') or m.get('raster')
|
||||||
|
return m.get('name') is thang.spriteName
|
||||||
|
thangType ?= _.find @options.thangTypes, (m) -> return m.get('name') is thang.spriteName
|
||||||
|
return console.error "Couldn't find ThangType for", thang unless thangType
|
||||||
|
|
||||||
|
options = @createLankOptions thang: thang
|
||||||
|
options.resolutionFactor = if thangType.get('kind') is 'Floor' then 2 else SPRITE_RESOLUTION_FACTOR
|
||||||
|
lank = new Lank thangType, options
|
||||||
|
@listenTo lank, 'sprite:mouse-up', @onLankMouseUp
|
||||||
|
@addLank lank, null, layer
|
||||||
|
lank.setDebug @debug
|
||||||
|
lank
|
||||||
|
|
||||||
|
removeLank: (lank) ->
|
||||||
|
lank.layer.removeLank(lank)
|
||||||
|
thang = lank.thang
|
||||||
|
delete @lanks[lank.thang.id]
|
||||||
|
@lankArray.splice @lankArray.indexOf(lank), 1
|
||||||
|
@stopListening lank
|
||||||
|
lank.destroy()
|
||||||
|
lank.thang = thang # Keep around so that we know which thang the destroyed thang was for
|
||||||
|
|
||||||
|
updateSounds: ->
|
||||||
|
lank.playSounds() for lank in @lankArray # hmm; doesn't work for lanks which we didn't add yet in adjustLankExistence
|
||||||
|
|
||||||
|
update: (frameChanged) ->
|
||||||
|
@adjustLankExistence() if frameChanged
|
||||||
|
lank.update frameChanged for lank in @lankArray
|
||||||
|
@updateSelection()
|
||||||
|
@layerAdapters['Default'].updateLayerOrder()
|
||||||
|
@cacheObstacles()
|
||||||
|
|
||||||
|
adjustLankExistence: ->
|
||||||
|
# Add anything new, remove anything old, update everything current
|
||||||
|
updatedObstacles = []
|
||||||
|
itemsJustEquipped = []
|
||||||
|
for thang in @world.thangs when thang.exists and thang.pos
|
||||||
|
itemsJustEquipped = itemsJustEquipped.concat @equipNewItems thang
|
||||||
|
if lank = @lanks[thang.id]
|
||||||
|
lank.setThang thang # make sure Lank has latest Thang
|
||||||
|
else
|
||||||
|
lank = @addThangToLanks(thang)
|
||||||
|
Backbone.Mediator.publish 'surface:new-thang-added', thang: thang, sprite: lank
|
||||||
|
updatedObstacles.push lank if lank.sprite.parent is @layerAdapters['Obstacle']
|
||||||
|
lank.playSounds()
|
||||||
|
item.modifyStats() for item in itemsJustEquipped
|
||||||
|
for thangID, lank of @lanks
|
||||||
|
missing = not (lank.notOfThisWorld or @world.thangMap[thangID]?.exists)
|
||||||
|
isObstacle = lank.sprite.parent is @layerAdapters['Obstacle']
|
||||||
|
updatedObstacles.push lank if isObstacle and (missing or lank.hasMoved)
|
||||||
|
lank.hasMoved = false
|
||||||
|
@removeLank lank if missing
|
||||||
|
@cacheObstacles updatedObstacles if updatedObstacles.length and @cachedObstacles
|
||||||
|
|
||||||
|
# mainly for handling selecting thangs from session when the thang is not always in existence
|
||||||
|
if @willSelectThang and @lanks[@willSelectThang[0]]
|
||||||
|
@selectThang @willSelectThang...
|
||||||
|
|
||||||
|
equipNewItems: (thang) ->
|
||||||
|
itemsJustEquipped = []
|
||||||
|
if thang.equip and not thang.equipped
|
||||||
|
thang.equip() # Pretty hacky, but needed since initialize may not be called if we're not running Systems.
|
||||||
|
itemsJustEquipped.push thang
|
||||||
|
if thang.inventoryIDs
|
||||||
|
# Even hackier: these items were only created/equipped during simulation, so we reequip here.
|
||||||
|
for slot, itemID of thang.inventoryIDs
|
||||||
|
item = @world.getThangByID itemID
|
||||||
|
unless item.equipped
|
||||||
|
console.log thang.id, 'equipping', item, 'in', thang.slot, 'Surface-side, but it cannot equip?' unless item.equip
|
||||||
|
item.equip()
|
||||||
|
itemsJustEquipped.push item
|
||||||
|
return itemsJustEquipped
|
||||||
|
|
||||||
|
cacheObstacles: (updatedObstacles=null) ->
|
||||||
|
return if @cachedObstacles and not updatedObstacles
|
||||||
|
wallLanks = (lank for lank in @lankArray when lank.thangType?.get('name').search(/(dungeon|indoor).wall/i) isnt -1)
|
||||||
|
return if _.any (s.stillLoading for s in wallLanks)
|
||||||
|
walls = (lank.thang for lank in wallLanks)
|
||||||
|
@world.calculateBounds()
|
||||||
|
wallGrid = new Grid walls, @world.size()...
|
||||||
|
if updatedObstacles
|
||||||
|
possiblyUpdatedWallLanks = (lank for lank in wallLanks when _.find updatedObstacles, (w2) -> lank is w2 or (Math.abs(lank.thang.pos.x - w2.thang.pos.x) + Math.abs(lank.thang.pos.y - w2.thang.pos.y)) <= 16)
|
||||||
|
else
|
||||||
|
possiblyUpdatedWallLanks = wallLanks
|
||||||
|
#console.log 'updating up to', possiblyUpdatedWallLanks.length, 'of', wallLanks.length, 'wall lanks from updatedObstacles', updatedObstacles
|
||||||
|
for wallLank in possiblyUpdatedWallLanks
|
||||||
|
wallLank.updateActionDirection wallGrid
|
||||||
|
wallLank.lockAction()
|
||||||
|
wallLank.updateScale()
|
||||||
|
wallLank.updatePosition()
|
||||||
|
#console.log @wallGrid.toString()
|
||||||
|
@cachedObstacles = true
|
||||||
|
|
||||||
|
lankFor: (thangID) -> @lanks[thangID]
|
||||||
|
|
||||||
|
onNewWorld: (e) ->
|
||||||
|
@world = @options.world = e.world
|
||||||
|
|
||||||
|
play: ->
|
||||||
|
lank.play() for lank in @lankArray
|
||||||
|
@selectionMark?.play()
|
||||||
|
@targetMark?.play()
|
||||||
|
|
||||||
|
stop: ->
|
||||||
|
lank.stop() for lank in @lankArray
|
||||||
|
@selectionMark?.stop()
|
||||||
|
@targetMark?.stop()
|
||||||
|
|
||||||
|
# Selection
|
||||||
|
|
||||||
|
onSuppressSelectionSounds: (e) -> @suppressSelectionSounds = e.suppress
|
||||||
|
onSetLockSelect: (e) -> @selectLocked = e.lock
|
||||||
|
onLevelRestarted: (e) ->
|
||||||
|
@selectLocked = false
|
||||||
|
@selectLank e, null
|
||||||
|
|
||||||
|
onSelectSprite: (e) ->
|
||||||
|
@selectThang e.thangID, e.spellName
|
||||||
|
|
||||||
|
onCameraDragged: ->
|
||||||
|
@dragged += 1
|
||||||
|
|
||||||
|
onLankMouseUp: (e) ->
|
||||||
|
return if key.shift #and @options.choosing
|
||||||
|
return @dragged = 0 if @dragged > 3
|
||||||
|
@dragged = 0
|
||||||
|
lank = if e.sprite?.thang?.isSelectable then e.sprite else null
|
||||||
|
return if @flagCursorLank and lank?.thangType.get('name') is 'Flag'
|
||||||
|
@selectLank e, lank
|
||||||
|
|
||||||
|
onStageMouseDown: (e) ->
|
||||||
|
return if key.shift #and @options.choosing
|
||||||
|
@selectLank e if e.onBackground
|
||||||
|
|
||||||
|
selectThang: (thangID, spellName=null, treemaThangSelected = null) ->
|
||||||
|
return @willSelectThang = [thangID, spellName] unless @lanks[thangID]
|
||||||
|
@selectLank null, @lanks[thangID], spellName, treemaThangSelected
|
||||||
|
|
||||||
|
selectLank: (e, lank=null, spellName=null, treemaThangSelected = null) ->
|
||||||
|
return if e and (@disabled or @selectLocked) # Ignore clicks for selection/panning/wizard movement while disabled or select is locked
|
||||||
|
worldPos = lank?.thang?.pos
|
||||||
|
worldPos ?= @camera.screenToWorld {x: e.originalEvent.rawX, y: e.originalEvent.rawY} if e?.originalEvent
|
||||||
|
if worldPos and (@options.navigateToSelection or not lank or treemaThangSelected) and e?.originalEvent?.nativeEvent?.which isnt 3
|
||||||
|
@camera.zoomTo(lank?.sprite or @camera.worldToSurface(worldPos), @camera.zoom, 1000, true)
|
||||||
|
lank = null if @options.choosing # Don't select lanks while choosing
|
||||||
|
if lank isnt @selectedLank
|
||||||
|
@selectedLank?.selected = false
|
||||||
|
lank?.selected = true
|
||||||
|
@selectedLank = lank
|
||||||
|
alive = lank and not (lank.thang.health < 0)
|
||||||
|
|
||||||
|
Backbone.Mediator.publish 'surface:sprite-selected',
|
||||||
|
thang: if lank then lank.thang else null
|
||||||
|
sprite: lank
|
||||||
|
spellName: spellName ? e?.spellName
|
||||||
|
originalEvent: e
|
||||||
|
worldPos: worldPos
|
||||||
|
|
||||||
|
@willSelectThang = null if lank # Now that we've done a real selection, don't reselect some other Thang later.
|
||||||
|
|
||||||
|
if alive and not @suppressSelectionSounds
|
||||||
|
instance = lank.playSound 'selected'
|
||||||
|
if instance?.playState is 'playSucceeded'
|
||||||
|
Backbone.Mediator.publish 'sprite:thang-began-talking', thang: lank?.thang
|
||||||
|
instance.addEventListener 'complete', ->
|
||||||
|
Backbone.Mediator.publish 'sprite:thang-finished-talking', thang: lank?.thang
|
||||||
|
|
||||||
|
onFlagColorSelected: (e) ->
|
||||||
|
@removeLank @flagCursorLank if @flagCursorLank
|
||||||
|
@flagCursorLank = null
|
||||||
|
for flagLank in @lankArray when flagLank.thangType.get('name') is 'Flag'
|
||||||
|
flagLank.sprite.cursor = if e.color then 'crosshair' else 'pointer'
|
||||||
|
return unless e.color
|
||||||
|
@flagCursorLank = new FlagLank @thangTypeFor('Flag'), @createLankOptions(thangID: 'Flag Cursor', color: e.color, team: me.team, isCursor: true, pos: e.pos)
|
||||||
|
@addLank @flagCursorLank, @flagCursorLank.thang.id, @layerAdapters['Floating']
|
||||||
|
|
||||||
|
onFlagUpdated: (e) ->
|
||||||
|
return unless e.active
|
||||||
|
pendingFlag = new FlagLank @thangTypeFor('Flag'), @createLankOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: e.team, isCursor: false, pos: e.pos)
|
||||||
|
@addLank pendingFlag, pendingFlag.thang.id, @layerAdapters['Floating']
|
||||||
|
@pendingFlags.push pendingFlag
|
||||||
|
|
||||||
|
onFlagAppeared: (e) ->
|
||||||
|
# Remove the pending flag that matches this one's color/team/position, and any color/team matches placed earlier.
|
||||||
|
t1 = e.sprite.thang
|
||||||
|
pending = (@pendingFlags ? []).slice()
|
||||||
|
foundExactMatch = false
|
||||||
|
for i in [pending.length - 1 .. 0] by -1
|
||||||
|
pendingFlag = pending[i]
|
||||||
|
t2 = pendingFlag.thang
|
||||||
|
matchedType = t1.color is t2.color and t1.team is t2.team
|
||||||
|
matched = matchedType and (foundExactMatch or Math.abs(t1.pos.x - t2.pos.x) < 0.00001 and Math.abs(t1.pos.y - t2.pos.y) < 0.00001)
|
||||||
|
if matched
|
||||||
|
foundExactMatch = true
|
||||||
|
@pendingFlags.splice(i, 1)
|
||||||
|
@removeLank pendingFlag
|
||||||
|
e.sprite.sprite.cursor = if @flagCursorLank then 'crosshair' else 'pointer'
|
||||||
|
null
|
||||||
|
|
||||||
|
onRemoveSelectedFlag: (e) ->
|
||||||
|
# Remove the selected lank if it's a flag, or any flag of the given color if a color is given.
|
||||||
|
flagLank = _.find [@selectedLank].concat(@lankArray), (lank) ->
|
||||||
|
lank and lank.thangType.get('name') is 'Flag' and lank.thang.team is me.team and (lank.thang.color is e.color or not e.color) and not lank.notOfThisWorld
|
||||||
|
return unless flagLank
|
||||||
|
Backbone.Mediator.publish 'surface:remove-flag', color: flagLank.thang.color
|
||||||
|
|
||||||
|
# Marks
|
||||||
|
|
||||||
|
updateSelection: ->
|
||||||
|
if @selectedLank?.thang and (not @selectedLank.thang.exists or not @world.getThangByID @selectedLank.thang.id)
|
||||||
|
thangID = @selectedLank.thang.id
|
||||||
|
@selectedLank = null # Don't actually trigger deselection, but remove the selected lank.
|
||||||
|
@selectionMark?.toggle false
|
||||||
|
@willSelectThang = [thangID, null]
|
||||||
|
@updateTarget()
|
||||||
|
return unless @selectionMark
|
||||||
|
@selectedLank = null if @selectedLank and (@selectedLank.destroyed or not @selectedLank.thang)
|
||||||
|
# The selection mark should be on the ground layer, unless we're not a normal lank (like a wall), in which case we'll place it higher so we can see it.
|
||||||
|
if @selectedLank and @selectedLank.sprite.parent isnt @layerAdapters.Default.container
|
||||||
|
@selectionMark.setLayer @layerAdapters.Default
|
||||||
|
else if @selectedLank
|
||||||
|
@selectionMark.setLayer @layerAdapters.Ground
|
||||||
|
@selectionMark.toggle @selectedLank?
|
||||||
|
@selectionMark.setLank @selectedLank
|
||||||
|
@selectionMark.update()
|
||||||
|
|
||||||
|
updateTarget: ->
|
||||||
|
return unless @targetMark
|
||||||
|
thang = @selectedLank?.thang
|
||||||
|
target = thang?.target
|
||||||
|
targetPos = thang?.targetPos
|
||||||
|
targetPos = null if targetPos?.isZero?() # Null targetPos get serialized as (0, 0, 0)
|
||||||
|
@targetMark.setLank if target then @lanks[target.id] else null
|
||||||
|
@targetMark.toggle @targetMark.lank or targetPos
|
||||||
|
@targetMark.update if targetPos then @camera.worldToSurface targetPos else null
|
|
@ -44,7 +44,7 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
resolutionFactor: SPRITE_RESOLUTION_FACTOR
|
resolutionFactor: SPRITE_RESOLUTION_FACTOR
|
||||||
defaultActions: ['idle', 'die', 'move', 'move', 'attack']
|
defaultActions: ['idle', 'die', 'move', 'move', 'attack']
|
||||||
numThingsLoading: 0
|
numThingsLoading: 0
|
||||||
cocoSprites: null
|
lanks: null
|
||||||
spriteSheet: null
|
spriteSheet: null
|
||||||
container: null
|
container: null
|
||||||
customGraphics: null
|
customGraphics: null
|
||||||
|
@ -70,7 +70,7 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
@container = new createjs.SpriteContainer(@spriteSheet)
|
@container = new createjs.SpriteContainer(@spriteSheet)
|
||||||
@actionRenderState = {}
|
@actionRenderState = {}
|
||||||
@toRenderBundles = []
|
@toRenderBundles = []
|
||||||
@cocoSprites = []
|
@lanks = []
|
||||||
@initializing = false
|
@initializing = false
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -91,13 +91,13 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
# TODO: remove this z stuff
|
# TODO: remove this z stuff
|
||||||
az = a.z or 1000
|
az = a.z or 1000
|
||||||
bz = b.z or 1000
|
bz = b.z or 1000
|
||||||
if aSprite = a.sprite
|
if aLank = a.lank
|
||||||
if aThang = aSprite.thang
|
if aThang = aLank.thang
|
||||||
aPos = aThang.pos
|
aPos = aThang.pos
|
||||||
if aThang.health < 0
|
if aThang.health < 0
|
||||||
--az
|
--az
|
||||||
if bSprite = b.sprite
|
if bLank = b.lank
|
||||||
if bThang = bSprite.thang
|
if bThang = bLank.thang
|
||||||
bPos = bThang.pos
|
bPos = bThang.pos
|
||||||
if bThang.health < 0
|
if bThang.health < 0
|
||||||
--bz
|
--bz
|
||||||
|
@ -142,27 +142,27 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
|
|
||||||
#- Adding, removing children for WebGL layers.
|
#- Adding, removing children for WebGL layers.
|
||||||
|
|
||||||
addCocoSprite: (cocoSprite) ->
|
addLank: (lank) ->
|
||||||
# TODO: Move this into the production DB rather than setting it dynamically.
|
# TODO: Move this into the production DB rather than setting it dynamically.
|
||||||
if cocoSprite.thangType?.get('name') is 'Highlight'
|
if lank.thangType?.get('name') is 'Highlight'
|
||||||
cocoSprite.thangType.set('spriteType', 'segmented')
|
lank.thangType.set('spriteType', 'segmented')
|
||||||
cocoSprite.options.resolutionFactor = @resolutionFactor
|
lank.options.resolutionFactor = @resolutionFactor
|
||||||
if cocoSprite.layer
|
if lank.layer
|
||||||
console.warn 'CocoSprite being re-added to a layer?'
|
console.warn 'Lank being re-added to a layer?'
|
||||||
|
|
||||||
cocoSprite.layer = @
|
lank.layer = @
|
||||||
@listenTo(cocoSprite, 'action-needs-render', @onActionNeedsRender)
|
@listenTo(lank, 'action-needs-render', @onActionNeedsRender)
|
||||||
@cocoSprites.push cocoSprite
|
@lanks.push lank
|
||||||
@loadThangType(cocoSprite.thangType)
|
@loadThangType(lank.thangType)
|
||||||
@addDefaultActionsToRender(cocoSprite)
|
@addDefaultActionsToRender(lank)
|
||||||
@setImageObjectToCocoSprite(cocoSprite)
|
@setSpriteToLank(lank)
|
||||||
@updateLayerOrder()
|
@updateLayerOrder()
|
||||||
cocoSprite.addHealthBar()
|
lank.addHealthBar()
|
||||||
|
|
||||||
removeCocoSprite: (cocoSprite) ->
|
removeLank: (lank) ->
|
||||||
@stopListening(cocoSprite)
|
@stopListening(lank)
|
||||||
@container.removeChild cocoSprite.imageObject
|
@container.removeChild lank.sprite
|
||||||
@cocoSprites = _.without @cocoSprites, cocoSprite
|
@lanks = _.without @lanks, lank
|
||||||
|
|
||||||
#- Loading network resources dynamically
|
#- Loading network resources dynamically
|
||||||
|
|
||||||
|
@ -180,24 +180,24 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
somethingLoaded: (thangType) ->
|
somethingLoaded: (thangType) ->
|
||||||
@numThingsLoading--
|
@numThingsLoading--
|
||||||
@loadThangType(thangType) # might need to load the raster image object
|
@loadThangType(thangType) # might need to load the raster image object
|
||||||
for cocoSprite in @cocoSprites
|
for lank in @lanks
|
||||||
if cocoSprite.thangType is thangType
|
if lank.thangType is thangType
|
||||||
@addDefaultActionsToRender(cocoSprite)
|
@addDefaultActionsToRender(lank)
|
||||||
@renderNewSpriteSheet()
|
@renderNewSpriteSheet()
|
||||||
|
|
||||||
#- Adding to the list of things we need to render
|
#- Adding to the list of things we need to render
|
||||||
|
|
||||||
onActionNeedsRender: (cocoSprite, action) ->
|
onActionNeedsRender: (lank, action) ->
|
||||||
@upsertActionToRender(cocoSprite.thangType, action.name, cocoSprite.options.colorConfig)
|
@upsertActionToRender(lank.thangType, action.name, lank.options.colorConfig)
|
||||||
|
|
||||||
addDefaultActionsToRender: (cocoSprite) ->
|
addDefaultActionsToRender: (lank) ->
|
||||||
needToRender = false
|
needToRender = false
|
||||||
if cocoSprite.thangType.get('raster')
|
if lank.thangType.get('raster')
|
||||||
@upsertActionToRender(cocoSprite.thangType)
|
@upsertActionToRender(lank.thangType)
|
||||||
else
|
else
|
||||||
for action in _.values(cocoSprite.thangType.getActions())
|
for action in _.values(lank.thangType.getActions())
|
||||||
continue unless _.any @defaultActions, (prefix) -> action.name.startsWith(prefix)
|
continue unless _.any @defaultActions, (prefix) -> action.name.startsWith(prefix)
|
||||||
@upsertActionToRender(cocoSprite.thangType, action.name, cocoSprite.options.colorConfig)
|
@upsertActionToRender(lank.thangType, action.name, lank.options.colorConfig)
|
||||||
|
|
||||||
upsertActionToRender: (thangType, actionName, colorConfig) ->
|
upsertActionToRender: (thangType, actionName, colorConfig) ->
|
||||||
groupKey = @renderGroupingKey(thangType, actionName, colorConfig)
|
groupKey = @renderGroupingKey(thangType, actionName, colorConfig)
|
||||||
|
@ -279,10 +279,10 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
@spriteSheet.resolutionFactor = @resolutionFactor
|
@spriteSheet.resolutionFactor = @resolutionFactor
|
||||||
oldLayer = @container
|
oldLayer = @container
|
||||||
@container = new createjs.SpriteContainer(@spriteSheet)
|
@container = new createjs.SpriteContainer(@spriteSheet)
|
||||||
for cocoSprite in @cocoSprites
|
for lank in @lanks
|
||||||
console.log 'zombie sprite found on layer', @name if cocoSprite.destroyed
|
console.log 'zombie sprite found on layer', @name if lank.destroyed
|
||||||
continue if cocoSprite.destroyed
|
continue if lank.destroyed
|
||||||
@setImageObjectToCocoSprite(cocoSprite)
|
@setSpriteToLank(lank)
|
||||||
for prop in ['scaleX', 'scaleY', 'regX', 'regY']
|
for prop in ['scaleX', 'scaleY', 'regX', 'regY']
|
||||||
@container[prop] = oldLayer[prop]
|
@container[prop] = oldLayer[prop]
|
||||||
if parent = oldLayer.parent
|
if parent = oldLayer.parent
|
||||||
|
@ -291,12 +291,20 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
parent.addChildAt(@container, index)
|
parent.addChildAt(@container, index)
|
||||||
@camera?.updateZoom(true)
|
@camera?.updateZoom(true)
|
||||||
@updateLayerOrder()
|
@updateLayerOrder()
|
||||||
for cocoSprite in @cocoSprites
|
for lank in @lanks
|
||||||
cocoSprite.options.resolutionFactor = @resolutionFactor
|
lank.options.resolutionFactor = @resolutionFactor
|
||||||
cocoSprite.updateScale()
|
lank.updateScale()
|
||||||
cocoSprite.updateRotation()
|
lank.updateRotation()
|
||||||
@trigger 'new-spritesheet'
|
@trigger 'new-spritesheet'
|
||||||
|
|
||||||
|
resetSpriteSheet: ->
|
||||||
|
@removeLank(lank) for lank in @lanks.slice(0)
|
||||||
|
@toRenderBundles = []
|
||||||
|
@actionRenderState = {}
|
||||||
|
@initializing = true
|
||||||
|
@spriteSheet = @_renderNewSpriteSheet(false) # builds an empty spritesheet
|
||||||
|
@initializing = false
|
||||||
|
|
||||||
#- Placeholder
|
#- Placeholder
|
||||||
|
|
||||||
createPlaceholder: ->
|
createPlaceholder: ->
|
||||||
|
@ -326,6 +334,7 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
#- Rendering containers for segmented thang types
|
#- Rendering containers for segmented thang types
|
||||||
|
|
||||||
renderSegmentedThangType: (thangType, colorConfig, actionNames, spriteSheetBuilder) ->
|
renderSegmentedThangType: (thangType, colorConfig, actionNames, spriteSheetBuilder) ->
|
||||||
|
console.log 'rendering segmented thang type'
|
||||||
containersToRender = {}
|
containersToRender = {}
|
||||||
for actionName in actionNames
|
for actionName in actionNames
|
||||||
action = _.find(thangType.getActions(), {name: actionName})
|
action = _.find(thangType.getActions(), {name: actionName})
|
||||||
|
@ -356,6 +365,7 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
#- Rendering sprite sheets for singular thang types
|
#- Rendering sprite sheets for singular thang types
|
||||||
|
|
||||||
renderSingularThangType: (thangType, colorConfig, actionNames, spriteSheetBuilder) ->
|
renderSingularThangType: (thangType, colorConfig, actionNames, spriteSheetBuilder) ->
|
||||||
|
console.log 'rendering singular thang type'
|
||||||
actionObjects = _.values(thangType.getActions())
|
actionObjects = _.values(thangType.getActions())
|
||||||
animationActions = []
|
animationActions = []
|
||||||
for a in actionObjects
|
for a in actionObjects
|
||||||
|
@ -441,10 +451,10 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
frame = spriteSheetBuilder.addFrame(bm, null, scale)
|
frame = spriteSheetBuilder.addFrame(bm, null, scale)
|
||||||
spriteSheetBuilder.addAnimation(@renderGroupingKey(thangType), [frame], false)
|
spriteSheetBuilder.addAnimation(@renderGroupingKey(thangType), [frame], false)
|
||||||
|
|
||||||
#- Distributing new Segmented/Singular/RasterSprites to CocoSprites
|
#- Distributing new Segmented/Singular/RasterSprites to Lanks
|
||||||
|
|
||||||
setImageObjectToCocoSprite: (cocoSprite) ->
|
setSpriteToLank: (lank) ->
|
||||||
if not cocoSprite.thangType.isFullyLoaded()
|
if not lank.thangType.isFullyLoaded()
|
||||||
# just give a placeholder
|
# just give a placeholder
|
||||||
sprite = new createjs.Sprite(@spriteSheet)
|
sprite = new createjs.Sprite(@spriteSheet)
|
||||||
sprite.gotoAndStop(0)
|
sprite.gotoAndStop(0)
|
||||||
|
@ -453,26 +463,26 @@ module.exports = LayerAdapter = class LayerAdapter extends CocoClass
|
||||||
sprite.regY = @resolutionFactor * SPRITE_PLACEHOLDER_WIDTH
|
sprite.regY = @resolutionFactor * SPRITE_PLACEHOLDER_WIDTH
|
||||||
sprite.baseScaleX = sprite.baseScaleY = sprite.scaleX = sprite.scaleY = 10 / (@resolutionFactor * SPRITE_PLACEHOLDER_WIDTH)
|
sprite.baseScaleX = sprite.baseScaleY = sprite.scaleX = sprite.scaleY = 10 / (@resolutionFactor * SPRITE_PLACEHOLDER_WIDTH)
|
||||||
|
|
||||||
else if cocoSprite.thangType.get('raster')
|
else if lank.thangType.get('raster')
|
||||||
sprite = new createjs.Sprite(@spriteSheet)
|
sprite = new createjs.Sprite(@spriteSheet)
|
||||||
scale = cocoSprite.thangType.get('scale') or 1
|
scale = lank.thangType.get('scale') or 1
|
||||||
reg = cocoSprite.getOffset 'registration'
|
reg = lank.getOffset 'registration'
|
||||||
sprite.regX = -reg.x * scale
|
sprite.regX = -reg.x * scale
|
||||||
sprite.regY = -reg.y * scale
|
sprite.regY = -reg.y * scale
|
||||||
sprite.gotoAndStop(@renderGroupingKey(cocoSprite.thangType))
|
sprite.gotoAndStop(@renderGroupingKey(lank.thangType))
|
||||||
sprite.baseScaleX = sprite.baseScaleY = 1
|
sprite.baseScaleX = sprite.baseScaleY = 1
|
||||||
|
|
||||||
else
|
else
|
||||||
SpriteClass = if (cocoSprite.thangType.get('spriteType') or @defaultSpriteType) is 'segmented' then SegmentedSprite else SingularSprite
|
SpriteClass = if (lank.thangType.get('spriteType') or @defaultSpriteType) is 'segmented' then SegmentedSprite else SingularSprite
|
||||||
prefix = @renderGroupingKey(cocoSprite.thangType, null, cocoSprite.options.colorConfig) + '.'
|
prefix = @renderGroupingKey(lank.thangType, null, lank.options.colorConfig) + '.'
|
||||||
sprite = new SpriteClass(@spriteSheet, cocoSprite.thangType, prefix, @resolutionFactor)
|
sprite = new SpriteClass(@spriteSheet, lank.thangType, prefix, @resolutionFactor)
|
||||||
|
|
||||||
sprite.sprite = cocoSprite
|
sprite.lank = lank
|
||||||
sprite.camera = @camera
|
sprite.camera = @camera
|
||||||
sprite.layerPriority = cocoSprite.thang?.layerPriority ? cocoSprite.thangType.get 'layerPriority'
|
sprite.layerPriority = lank.thang?.layerPriority ? lank.thangType.get 'layerPriority'
|
||||||
sprite.name = cocoSprite.thang?.spriteName or cocoSprite.thangType.get 'name'
|
sprite.name = lank.thang?.spriteName or lank.thangType.get 'name'
|
||||||
cocoSprite.setImageObject(sprite)
|
lank.setSprite(sprite)
|
||||||
cocoSprite.update(true)
|
lank.update(true)
|
||||||
@container.addChild(sprite)
|
@container.addChild(sprite)
|
||||||
|
|
||||||
renderGroupingKey: (thangType, grouping, colorConfig) ->
|
renderGroupingKey: (thangType, grouping, colorConfig) ->
|
||||||
|
|
|
@ -11,7 +11,7 @@ module.exports = class Mark extends CocoClass
|
||||||
super()
|
super()
|
||||||
options ?= {}
|
options ?= {}
|
||||||
@name = options.name
|
@name = options.name
|
||||||
@sprite = options.sprite
|
@lank = options.lank
|
||||||
@camera = options.camera
|
@camera = options.camera
|
||||||
@layer = options.layer
|
@layer = options.layer
|
||||||
@thangType = options.thangType
|
@thangType = options.thangType
|
||||||
|
@ -22,46 +22,46 @@ module.exports = class Mark extends CocoClass
|
||||||
@build()
|
@build()
|
||||||
|
|
||||||
destroy: ->
|
destroy: ->
|
||||||
createjs.Tween.removeTweens @mark if @mark
|
createjs.Tween.removeTweens @sprite if @sprite
|
||||||
@mark?.parent?.removeChild @mark
|
@sprite?.parent?.removeChild @sprite
|
||||||
if @markSprite
|
if @markLank
|
||||||
@layer.removeCocoSprite(@markSprite)
|
@layer.removeLank(@markLank)
|
||||||
@markSprite.destroy()
|
@markLank.destroy()
|
||||||
@sprite = null
|
@lank = null
|
||||||
super()
|
super()
|
||||||
|
|
||||||
toString: -> "<Mark #{@name}: Sprite #{@sprite?.thang?.id ? 'None'}>"
|
toString: -> "<Mark #{@name}: Sprite #{@lank?.thang?.id ? 'None'}>"
|
||||||
|
|
||||||
onLayerMadeSpriteSheet: ->
|
onLayerMadeSpriteSheet: ->
|
||||||
return unless @mark
|
return unless @sprite
|
||||||
return @update() if @markSprite
|
return @update() if @markLank
|
||||||
# need to update the mark display object manually...
|
# need to update the mark display object manually...
|
||||||
@mark = null
|
@sprite = null
|
||||||
@build()
|
@build()
|
||||||
@layer.addChild @mark
|
@layer.addChild @sprite
|
||||||
@layer.updateLayerOrder()
|
@layer.updateLayerOrder()
|
||||||
|
|
||||||
toggle: (to) ->
|
toggle: (to) ->
|
||||||
to = !!to
|
to = !!to
|
||||||
return @ if to is @on
|
return @ if to is @on
|
||||||
return @toggleTo = to unless @mark
|
return @toggleTo = to unless @sprite
|
||||||
@on = to
|
@on = to
|
||||||
delete @toggleTo
|
delete @toggleTo
|
||||||
if @on
|
if @on
|
||||||
if @markSprite
|
if @markLank
|
||||||
@layer.addCocoSprite(@markSprite)
|
@layer.addLank(@markLank)
|
||||||
else
|
else
|
||||||
@layer.addChild @mark
|
@layer.addChild @sprite
|
||||||
@layer.updateLayerOrder()
|
@layer.updateLayerOrder()
|
||||||
else
|
else
|
||||||
if @markSprite
|
if @markLank
|
||||||
@layer.removeCocoSprite(@markSprite)
|
@layer.removeLank(@markLank)
|
||||||
else
|
else
|
||||||
@layer.removeChild @mark
|
@layer.removeChild @sprite
|
||||||
if @highlightTween
|
if @highlightTween
|
||||||
@highlightDelay = @highlightTween = null
|
@highlightDelay = @highlightTween = null
|
||||||
createjs.Tween.removeTweens @mark
|
createjs.Tween.removeTweens @sprite
|
||||||
@mark.visible = true
|
@sprite.visible = true
|
||||||
@
|
@
|
||||||
|
|
||||||
setLayer: (layer) ->
|
setLayer: (layer) ->
|
||||||
|
@ -71,34 +71,34 @@ module.exports = class Mark extends CocoClass
|
||||||
@layer = layer
|
@layer = layer
|
||||||
@toggle true if wasOn
|
@toggle true if wasOn
|
||||||
|
|
||||||
setSprite: (sprite) ->
|
setLank: (lank) ->
|
||||||
return if sprite is @sprite
|
return if lank is @lank
|
||||||
@sprite = sprite
|
@lank = lank
|
||||||
@build()
|
@build()
|
||||||
@
|
@
|
||||||
|
|
||||||
build: ->
|
build: ->
|
||||||
unless @mark
|
unless @sprite
|
||||||
if @name is 'bounds' then @buildBounds()
|
if @name is 'bounds' then @buildBounds()
|
||||||
else if @name is 'shadow' then @buildShadow()
|
else if @name is 'shadow' then @buildShadow()
|
||||||
else if @name is 'debug' then @buildDebug()
|
else if @name is 'debug' then @buildDebug()
|
||||||
else if @name.match(/.+(Range|Distance|Radius)$/) then @buildRadius(@name)
|
else if @name.match(/.+(Range|Distance|Radius)$/) then @buildRadius(@name)
|
||||||
else if @thangType then @buildSprite()
|
else if @thangType then @buildSprite()
|
||||||
else console.error 'Don\'t know how to build mark for', @name
|
else console.error 'Don\'t know how to build mark for', @name
|
||||||
@mark?.mouseEnabled = false
|
@sprite?.mouseEnabled = false
|
||||||
@
|
@
|
||||||
|
|
||||||
buildBounds: ->
|
buildBounds: ->
|
||||||
@mark = new createjs.Container()
|
@sprite = new createjs.Container()
|
||||||
@mark.mouseChildren = false
|
@sprite.mouseChildren = false
|
||||||
style = @sprite.thang.drawsBoundsStyle
|
style = @lank.thang.drawsBoundsStyle
|
||||||
@drawsBoundsIndex = @sprite.thang.drawsBoundsIndex
|
@drawsBoundsIndex = @lank.thang.drawsBoundsIndex
|
||||||
return if style is 'corner-text' and @sprite.thang.world.age is 0
|
return if style is 'corner-text' and @lank.thang.world.age is 0
|
||||||
|
|
||||||
# Confusingly make some semi-random colors that'll be consistent based on the drawsBoundsIndex
|
# Confusingly make some semi-random colors that'll be consistent based on the drawsBoundsIndex
|
||||||
colors = (128 + Math.floor(('0.'+Math.sin(3 * @drawsBoundsIndex + i).toString().substr(6)) * 128) for i in [1 ... 4])
|
colors = (128 + Math.floor(('0.'+Math.sin(3 * @drawsBoundsIndex + i).toString().substr(6)) * 128) for i in [1 ... 4])
|
||||||
color = "rgba(#{colors[0]}, #{colors[1]}, #{colors[2]}, 0.5)"
|
color = "rgba(#{colors[0]}, #{colors[1]}, #{colors[2]}, 0.5)"
|
||||||
[w, h] = [@sprite.thang.width * Camera.PPM, @sprite.thang.height * Camera.PPM * @camera.y2x]
|
[w, h] = [@lank.thang.width * Camera.PPM, @lank.thang.height * Camera.PPM * @camera.y2x]
|
||||||
|
|
||||||
if style in ['border-text', 'corner-text']
|
if style in ['border-text', 'corner-text']
|
||||||
@drawsBoundsBorderShape = shape = new createjs.Shape()
|
@drawsBoundsBorderShape = shape = new createjs.Shape()
|
||||||
|
@ -108,37 +108,37 @@ module.exports = class Mark extends CocoClass
|
||||||
shape.graphics.beginFill color.replace('0.5', '0.25')
|
shape.graphics.beginFill color.replace('0.5', '0.25')
|
||||||
else
|
else
|
||||||
shape.graphics.beginFill color
|
shape.graphics.beginFill color
|
||||||
if @sprite.thang.shape in ['ellipsoid', 'disc']
|
if @lank.thang.shape in ['ellipsoid', 'disc']
|
||||||
shape.drawEllipse 0, 0, w, h
|
shape.drawEllipse 0, 0, w, h
|
||||||
else
|
else
|
||||||
shape.graphics.drawRect -w / 2, -h / 2, w, h
|
shape.graphics.drawRect -w / 2, -h / 2, w, h
|
||||||
shape.graphics.endStroke()
|
shape.graphics.endStroke()
|
||||||
shape.graphics.endFill()
|
shape.graphics.endFill()
|
||||||
@mark.addChild shape
|
@sprite.addChild shape
|
||||||
|
|
||||||
if style is 'border-text'
|
if style is 'border-text'
|
||||||
text = new createjs.Text '' + @drawsBoundsIndex, '20px Arial', color.replace('0.5', '1')
|
text = new createjs.Text '' + @drawsBoundsIndex, '20px Arial', color.replace('0.5', '1')
|
||||||
text.regX = text.getMeasuredWidth() / 2
|
text.regX = text.getMeasuredWidth() / 2
|
||||||
text.regY = text.getMeasuredHeight() / 2
|
text.regY = text.getMeasuredHeight() / 2
|
||||||
text.shadow = new createjs.Shadow('#000000', 1, 1, 0)
|
text.shadow = new createjs.Shadow('#000000', 1, 1, 0)
|
||||||
@mark.addChild text
|
@sprite.addChild text
|
||||||
else if style is 'corner-text'
|
else if style is 'corner-text'
|
||||||
return if @sprite.thang.world.age is 0
|
return if @lank.thang.world.age is 0
|
||||||
letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[@drawsBoundsIndex % 26]
|
letter = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[@drawsBoundsIndex % 26]
|
||||||
text = new createjs.Text letter, '14px Arial', '#333333' # color.replace('0.5', '1')
|
text = new createjs.Text letter, '14px Arial', '#333333' # color.replace('0.5', '1')
|
||||||
text.x = -w / 2 + 2
|
text.x = -w / 2 + 2
|
||||||
text.y = -h / 2 + 2
|
text.y = -h / 2 + 2
|
||||||
@mark.addChild text
|
@sprite.addChild text
|
||||||
else
|
else
|
||||||
console.warn @sprite.thang.id, 'didn\'t know how to draw bounds style:', style
|
console.warn @lank.thang.id, 'didn\'t know how to draw bounds style:', style
|
||||||
|
|
||||||
if w > 0 and h > 0 and style is 'border-text'
|
if w > 0 and h > 0 and style is 'border-text'
|
||||||
@mark.cache -w / 2, -h / 2, w, h, 2
|
@sprite.cache -w / 2, -h / 2, w, h, 2
|
||||||
@lastWidth = @sprite.thang.width
|
@lastWidth = @lank.thang.width
|
||||||
@lastHeight = @sprite.thang.height
|
@lastHeight = @lank.thang.height
|
||||||
|
|
||||||
buildShadow: ->
|
buildShadow: ->
|
||||||
shapeName = if @sprite.thang.shape in ['ellipsoid', 'disc'] then 'ellipse' else 'rect'
|
shapeName = if @lank.thang.shape in ['ellipsoid', 'disc'] then 'ellipse' else 'rect'
|
||||||
key = "#{shapeName}-shadow"
|
key = "#{shapeName}-shadow"
|
||||||
SHADOW_SIZE = 10
|
SHADOW_SIZE = 10
|
||||||
unless key in @layer.spriteSheet.getAnimations()
|
unless key in @layer.spriteSheet.getAnimations()
|
||||||
|
@ -151,21 +151,21 @@ module.exports = class Mark extends CocoClass
|
||||||
shape.graphics.drawRect bounds...
|
shape.graphics.drawRect bounds...
|
||||||
shape.graphics.endFill()
|
shape.graphics.endFill()
|
||||||
@layer.addCustomGraphic(key, shape, bounds)
|
@layer.addCustomGraphic(key, shape, bounds)
|
||||||
alpha = @sprite.thang?.alpha ? 1
|
alpha = @lank.thang?.alpha ? 1
|
||||||
width = (@sprite.thang?.width ? 0) + 0.5
|
width = (@lank.thang?.width ? 0) + 0.5
|
||||||
height = (@sprite.thang?.height ? 0) + 0.5
|
height = (@lank.thang?.height ? 0) + 0.5
|
||||||
longest = Math.max width, height
|
longest = Math.max width, height
|
||||||
actualLongest = @sprite.thangType.get('shadow') ? longest
|
actualLongest = @lank.thangType.get('shadow') ? longest
|
||||||
width = width * actualLongest / longest
|
width = width * actualLongest / longest
|
||||||
height = height * actualLongest / longest
|
height = height * actualLongest / longest
|
||||||
width *= Camera.PPM
|
width *= Camera.PPM
|
||||||
height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation
|
height *= Camera.PPM * @camera.y2x # TODO: doesn't work with rotation
|
||||||
@mark = new createjs.Sprite(@layer.spriteSheet)
|
@sprite = new createjs.Sprite(@layer.spriteSheet)
|
||||||
@mark.gotoAndStop(key)
|
@sprite.gotoAndStop(key)
|
||||||
@mark.mouseEnabled = false
|
@sprite.mouseEnabled = false
|
||||||
@mark.alpha = alpha
|
@sprite.alpha = alpha
|
||||||
@baseScaleX = @mark.scaleX = width / (@layer.resolutionFactor * SHADOW_SIZE)
|
@baseScaleX = @sprite.scaleX = width / (@layer.resolutionFactor * SHADOW_SIZE)
|
||||||
@baseScaleY = @mark.scaleY = height / (@layer.resolutionFactor * SHADOW_SIZE)
|
@baseScaleY = @sprite.scaleY = height / (@layer.resolutionFactor * SHADOW_SIZE)
|
||||||
|
|
||||||
buildRadius: (range) ->
|
buildRadius: (range) ->
|
||||||
alpha = 0.15
|
alpha = 0.15
|
||||||
|
@ -183,36 +183,36 @@ module.exports = class Mark extends CocoClass
|
||||||
]
|
]
|
||||||
|
|
||||||
# Find the index of this range, to find the next-smallest radius
|
# Find the index of this range, to find the next-smallest radius
|
||||||
rangeNames = @sprite.ranges.map((range, index) ->
|
rangeNames = @lank.ranges.map((range, index) ->
|
||||||
range['name']
|
range['name']
|
||||||
)
|
)
|
||||||
i = rangeNames.indexOf(range)
|
i = rangeNames.indexOf(range)
|
||||||
|
|
||||||
@mark = new createjs.Shape()
|
@sprite = new createjs.Shape()
|
||||||
|
|
||||||
fillColor = colors[range] ? extraColors[i]
|
fillColor = colors[range] ? extraColors[i]
|
||||||
@mark.graphics.beginFill fillColor
|
@sprite.graphics.beginFill fillColor
|
||||||
|
|
||||||
# Draw the outer circle
|
# Draw the outer circle
|
||||||
@mark.graphics.drawCircle 0, 0, @sprite.thang[range] * Camera.PPM
|
@sprite.graphics.drawCircle 0, 0, @lank.thang[range] * Camera.PPM
|
||||||
|
|
||||||
# Cut out the hollow part if necessary
|
# Cut out the hollow part if necessary
|
||||||
if i+1 < @sprite.ranges.length
|
if i+1 < @lank.ranges.length
|
||||||
@mark.graphics.arc 0, 0, @sprite.ranges[i+1]['radius'], Math.PI*2, 0, true
|
@sprite.graphics.arc 0, 0, @lank.ranges[i+1]['radius'], Math.PI*2, 0, true
|
||||||
|
|
||||||
@mark.graphics.endFill()
|
@sprite.graphics.endFill()
|
||||||
|
|
||||||
strokeColor = fillColor.replace '' + alpha, '0.75'
|
strokeColor = fillColor.replace '' + alpha, '0.75'
|
||||||
@mark.graphics.setStrokeStyle 2
|
@sprite.graphics.setStrokeStyle 2
|
||||||
@mark.graphics.beginStroke strokeColor
|
@sprite.graphics.beginStroke strokeColor
|
||||||
@mark.graphics.arc 0, 0, @sprite.thang[range] * Camera.PPM, Math.PI*2, 0, true
|
@sprite.graphics.arc 0, 0, @lank.thang[range] * Camera.PPM, Math.PI*2, 0, true
|
||||||
@mark.graphics.endStroke()
|
@sprite.graphics.endStroke()
|
||||||
|
|
||||||
# Add perspective
|
# Add perspective
|
||||||
@mark.scaleY *= @camera.y2x
|
@sprite.scaleY *= @camera.y2x
|
||||||
|
|
||||||
buildDebug: ->
|
buildDebug: ->
|
||||||
shapeName = if @sprite.thang.shape in ['ellipsoid', 'disc'] then 'ellipse' else 'rect'
|
shapeName = if @lank.thang.shape in ['ellipsoid', 'disc'] then 'ellipse' else 'rect'
|
||||||
key = "#{shapeName}-debug"
|
key = "#{shapeName}-debug"
|
||||||
DEBUG_SIZE = 10
|
DEBUG_SIZE = 10
|
||||||
unless key in @layer.spriteSheet.getAnimations()
|
unless key in @layer.spriteSheet.getAnimations()
|
||||||
|
@ -226,12 +226,12 @@ module.exports = class Mark extends CocoClass
|
||||||
shape.graphics.endFill()
|
shape.graphics.endFill()
|
||||||
@layer.addCustomGraphic(key, shape, bounds)
|
@layer.addCustomGraphic(key, shape, bounds)
|
||||||
|
|
||||||
@mark = new createjs.Sprite(@layer.spriteSheet)
|
@sprite = new createjs.Sprite(@layer.spriteSheet)
|
||||||
@mark.gotoAndStop(key)
|
@sprite.gotoAndStop(key)
|
||||||
PX = 3
|
PX = 3
|
||||||
[w, h] = [Math.max(PX, @sprite.thang.width * Camera.PPM), Math.max(PX, @sprite.thang.height * Camera.PPM) * @camera.y2x] # TODO: doesn't work with rotation
|
[w, h] = [Math.max(PX, @lank.thang.width * Camera.PPM), Math.max(PX, @lank.thang.height * Camera.PPM) * @camera.y2x] # TODO: doesn't work with rotation
|
||||||
@mark.scaleX = w / (@layer.resolutionFactor * DEBUG_SIZE)
|
@sprite.scaleX = w / (@layer.resolutionFactor * DEBUG_SIZE)
|
||||||
@mark.scaleY = h / (@layer.resolutionFactor * DEBUG_SIZE)
|
@sprite.scaleY = h / (@layer.resolutionFactor * DEBUG_SIZE)
|
||||||
|
|
||||||
buildSprite: ->
|
buildSprite: ->
|
||||||
if _.isString @thangType
|
if _.isString @thangType
|
||||||
|
@ -240,13 +240,13 @@ module.exports = class Mark extends CocoClass
|
||||||
@thangType = thangType
|
@thangType = thangType
|
||||||
|
|
||||||
return @listenToOnce(@thangType, 'sync', @onLoadedThangType) if not @thangType.loaded
|
return @listenToOnce(@thangType, 'sync', @onLoadedThangType) if not @thangType.loaded
|
||||||
CocoSprite = require './CocoSprite'
|
Lank = require './Lank'
|
||||||
# don't bother with making these render async for now, but maybe later for fun and more complexity of code
|
# don't bother with making these render async for now, but maybe later for fun and more complexity of code
|
||||||
markSprite = new CocoSprite @thangType
|
markLank = new Lank @thangType
|
||||||
markSprite.queueAction 'idle'
|
markLank.queueAction 'idle'
|
||||||
@mark = markSprite.imageObject
|
@sprite = markLank.sprite
|
||||||
@markSprite = markSprite
|
@markLank = markLank
|
||||||
@listenTo @markSprite, 'new-image-object', (@mark) ->
|
@listenTo @markLank, 'new-sprite', (@sprite) ->
|
||||||
|
|
||||||
loadThangType: ->
|
loadThangType: ->
|
||||||
name = @thangType
|
name = @thangType
|
||||||
|
@ -262,83 +262,83 @@ module.exports = class Mark extends CocoClass
|
||||||
Backbone.Mediator.publish 'sprite:loaded', {sprite: @}
|
Backbone.Mediator.publish 'sprite:loaded', {sprite: @}
|
||||||
|
|
||||||
update: (pos=null) ->
|
update: (pos=null) ->
|
||||||
return false unless @on and @mark
|
return false unless @on and @sprite
|
||||||
return false if @sprite? and not @sprite.thangType.isFullyLoaded()
|
return false if @lank? and not @lank.thangType.isFullyLoaded()
|
||||||
@mark.visible = not @hidden
|
@sprite.visible = not @hidden
|
||||||
@updatePosition pos
|
@updatePosition pos
|
||||||
@updateRotation()
|
@updateRotation()
|
||||||
@updateScale()
|
@updateScale()
|
||||||
if @name is 'highlight' and @highlightDelay and not @highlightTween
|
if @name is 'highlight' and @highlightDelay and not @highlightTween
|
||||||
@mark.visible = false
|
@sprite.visible = false
|
||||||
@highlightTween = createjs.Tween.get(@mark).to({}, @highlightDelay).call =>
|
@highlightTween = createjs.Tween.get(@sprite).to({}, @highlightDelay).call =>
|
||||||
@mark.visible = true
|
@sprite.visible = true
|
||||||
@highlightDelay = @highlightTween = null
|
@highlightDelay = @highlightTween = null
|
||||||
@updateAlpha @alpha if @name in ['shadow', 'bounds']
|
@updateAlpha @alpha if @name in ['shadow', 'bounds']
|
||||||
true
|
true
|
||||||
|
|
||||||
updatePosition: (pos) ->
|
updatePosition: (pos) ->
|
||||||
if @sprite?.thang and @name in ['shadow', 'debug', 'target', 'selection', 'repair']
|
if @lank?.thang and @name in ['shadow', 'debug', 'target', 'selection', 'repair']
|
||||||
pos = @camera.worldToSurface x: @sprite.thang.pos.x, y: @sprite.thang.pos.y
|
pos = @camera.worldToSurface x: @lank.thang.pos.x, y: @lank.thang.pos.y
|
||||||
else
|
else
|
||||||
pos ?= @sprite?.imageObject
|
pos ?= @lank?.sprite
|
||||||
return unless pos
|
return unless pos
|
||||||
@mark.x = pos.x
|
@sprite.x = pos.x
|
||||||
@mark.y = pos.y
|
@sprite.y = pos.y
|
||||||
if @statusEffect or @name is 'highlight'
|
if @statusEffect or @name is 'highlight'
|
||||||
offset = @sprite.getOffset 'aboveHead'
|
offset = @lank.getOffset 'aboveHead'
|
||||||
@mark.x += offset.x
|
@sprite.x += offset.x
|
||||||
@mark.y += offset.y
|
@sprite.y += offset.y
|
||||||
@mark.y -= 3 if @statusEffect
|
@sprite.y -= 3 if @statusEffect
|
||||||
|
|
||||||
updateAlpha: (@alpha) ->
|
updateAlpha: (@alpha) ->
|
||||||
return if not @mark or @name is 'debug'
|
return if not @sprite or @name is 'debug'
|
||||||
if @name is 'shadow'
|
if @name is 'shadow'
|
||||||
worldZ = @sprite.thang.pos.z - @sprite.thang.depth / 2 + @sprite.getBobOffset()
|
worldZ = @lank.thang.pos.z - @lank.thang.depth / 2 + @lank.getBobOffset()
|
||||||
@mark.alpha = @alpha * 0.451 / Math.sqrt(worldZ / 2 + 1)
|
@sprite.alpha = @alpha * 0.451 / Math.sqrt(worldZ / 2 + 1)
|
||||||
else if @name is 'bounds'
|
else if @name is 'bounds'
|
||||||
@drawsBoundsBorderShape?.alpha = Math.floor @sprite.thang.alpha # Stop drawing bounds as soon as alpha is reduced at all
|
@drawsBoundsBorderShape?.alpha = Math.floor @lank.thang.alpha # Stop drawing bounds as soon as alpha is reduced at all
|
||||||
else
|
else
|
||||||
@mark.alpha = @alpha
|
@sprite.alpha = @alpha
|
||||||
|
|
||||||
updateRotation: ->
|
updateRotation: ->
|
||||||
if @name is 'debug' or (@name is 'shadow' and @sprite.thang?.shape in ['rectangle', 'box'])
|
if @name is 'debug' or (@name is 'shadow' and @lank.thang?.shape in ['rectangle', 'box'])
|
||||||
@mark.rotation = -@sprite.thang.rotation * 180 / Math.PI
|
@sprite.rotation = -@lank.thang.rotation * 180 / Math.PI
|
||||||
|
|
||||||
updateScale: ->
|
updateScale: ->
|
||||||
if @name is 'bounds' and ((@sprite.thang.width isnt @lastWidth or @sprite.thang.height isnt @lastHeight) or (@sprite.thang.drawsBoundsIndex isnt @drawsBoundsIndex))
|
if @name is 'bounds' and ((@lank.thang.width isnt @lastWidth or @lank.thang.height isnt @lastHeight) or (@lank.thang.drawsBoundsIndex isnt @drawsBoundsIndex))
|
||||||
oldMark = @mark
|
oldMark = @sprite
|
||||||
@buildBounds()
|
@buildBounds()
|
||||||
oldMark.parent.addChild @mark
|
oldMark.parent.addChild @sprite
|
||||||
oldMark.parent.swapChildren oldMark, @mark
|
oldMark.parent.swapChildren oldMark, @sprite
|
||||||
oldMark.parent.removeChild oldMark
|
oldMark.parent.removeChild oldMark
|
||||||
|
|
||||||
if @markSprite?
|
if @markLank?
|
||||||
@markSprite.scaleFactor = 1.2
|
@markLank.scaleFactor = 1.2
|
||||||
@markSprite.updateScale()
|
@markLank.updateScale()
|
||||||
|
|
||||||
if @name is 'shadow' and thang = @sprite.thang
|
if @name is 'shadow' and thang = @lank.thang
|
||||||
@mark.scaleX = @baseScaleX * (thang.scaleFactor ? thang.scaleFactorX ? 1)
|
@sprite.scaleX = @baseScaleX * (thang.scaleFactor ? thang.scaleFactorX ? 1)
|
||||||
@mark.scaleY = @baseScaleY * (thang.scaleFactor ? thang.scaleFactorY ? 1)
|
@sprite.scaleY = @baseScaleY * (thang.scaleFactor ? thang.scaleFactorY ? 1)
|
||||||
|
|
||||||
return unless @name in ['selection', 'target', 'repair', 'highlight']
|
return unless @name in ['selection', 'target', 'repair', 'highlight']
|
||||||
|
|
||||||
# scale these marks to 10m (100px). Adjust based on sprite size.
|
# scale these marks to 10m (100px). Adjust based on lank size.
|
||||||
factor = 0.3 # default size: 3m width, most commonly for target when pointing to a location
|
factor = 0.3 # default size: 3m width, most commonly for target when pointing to a location
|
||||||
|
|
||||||
if @sprite?.imageObject
|
if @lank?.sprite
|
||||||
width = @sprite.imageObject.getBounds()?.width or 0
|
width = @lank.sprite.getBounds()?.width or 0
|
||||||
width /= @sprite.options.resolutionFactor
|
width /= @lank.options.resolutionFactor
|
||||||
# all targets should be set to have a width of 100px, and then be scaled accordingly
|
# all targets should be set to have a width of 100px, and then be scaled accordingly
|
||||||
factor = width / 100 # normalize
|
factor = width / 100 # normalize
|
||||||
factor *= 1.1 # add margin
|
factor *= 1.1 # add margin
|
||||||
factor = Math.max(factor, 0.3) # lower bound
|
factor = Math.max(factor, 0.3) # lower bound
|
||||||
@mark.scaleX *= factor
|
@sprite.scaleX *= factor
|
||||||
@mark.scaleY *= factor
|
@sprite.scaleY *= factor
|
||||||
|
|
||||||
if @name in ['selection', 'target', 'repair']
|
if @name in ['selection', 'target', 'repair']
|
||||||
@mark.scaleY *= @camera.y2x # code applies perspective
|
@sprite.scaleY *= @camera.y2x # code applies perspective
|
||||||
|
|
||||||
stop: -> @markSprite?.stop()
|
stop: -> @markLank?.stop()
|
||||||
play: -> @markSprite?.play()
|
play: -> @markLank?.play()
|
||||||
hide: -> @hidden = true
|
hide: -> @hidden = true
|
||||||
show: -> @hidden = false
|
show: -> @hidden = false
|
||||||
|
|
|
@ -1,391 +0,0 @@
|
||||||
CocoClass = require 'lib/CocoClass'
|
|
||||||
{me} = require 'lib/auth'
|
|
||||||
LayerAdapter = require './LayerAdapter'
|
|
||||||
IndieSprite = require 'lib/surface/IndieSprite'
|
|
||||||
WizardSprite = require 'lib/surface/WizardSprite'
|
|
||||||
FlagSprite = require 'lib/surface/FlagSprite'
|
|
||||||
CocoSprite = require 'lib/surface/CocoSprite'
|
|
||||||
Mark = require './Mark'
|
|
||||||
Grid = require 'lib/world/Grid'
|
|
||||||
|
|
||||||
module.exports = class SpriteBoss extends CocoClass
|
|
||||||
subscriptions:
|
|
||||||
'bus:player-joined': 'onPlayerJoined'
|
|
||||||
'bus:player-left': 'onPlayerLeft'
|
|
||||||
'level:set-debug': 'onSetDebug'
|
|
||||||
'sprite:highlight-sprites': 'onHighlightSprites'
|
|
||||||
'surface:stage-mouse-down': 'onStageMouseDown'
|
|
||||||
'level:select-sprite': 'onSelectSprite'
|
|
||||||
'level:suppress-selection-sounds': 'onSuppressSelectionSounds'
|
|
||||||
'level:lock-select': 'onSetLockSelect'
|
|
||||||
'level:restarted': 'onLevelRestarted'
|
|
||||||
'god:new-world-created': 'onNewWorld'
|
|
||||||
'god:streaming-world-updated': 'onNewWorld'
|
|
||||||
'camera:dragged': 'onCameraDragged'
|
|
||||||
'sprite:loaded': -> @update(true)
|
|
||||||
'level:flag-color-selected': 'onFlagColorSelected'
|
|
||||||
'level:flag-updated': 'onFlagUpdated'
|
|
||||||
'surface:flag-appeared': 'onFlagAppeared'
|
|
||||||
'surface:remove-selected-flag': 'onRemoveSelectedFlag'
|
|
||||||
|
|
||||||
constructor: (@options) ->
|
|
||||||
super()
|
|
||||||
@dragged = 0
|
|
||||||
@options ?= {}
|
|
||||||
@camera = @options.camera
|
|
||||||
@webGLStage = @options.webGLStage
|
|
||||||
@surfaceTextLayer = @options.surfaceTextLayer
|
|
||||||
@world = options.world
|
|
||||||
@options.thangTypes ?= []
|
|
||||||
@sprites = {}
|
|
||||||
@spriteArray = [] # Mirror @sprites, but faster for when we just need to iterate
|
|
||||||
@selfWizardSprite = null
|
|
||||||
@createLayers()
|
|
||||||
@pendingFlags = []
|
|
||||||
|
|
||||||
destroy: ->
|
|
||||||
@removeSprite sprite for thangID, sprite of @sprites
|
|
||||||
@targetMark?.destroy()
|
|
||||||
@selectionMark?.destroy()
|
|
||||||
super()
|
|
||||||
|
|
||||||
toString: -> "<SpriteBoss: #{@spriteArray.length} sprites>"
|
|
||||||
|
|
||||||
thangTypeFor: (type) ->
|
|
||||||
_.find @options.thangTypes, (m) -> m.get('original') is type or m.get('name') is type
|
|
||||||
|
|
||||||
createLayers: ->
|
|
||||||
@spriteLayers = {}
|
|
||||||
for [name, priority] in [
|
|
||||||
['Land', -40]
|
|
||||||
['Ground', -30]
|
|
||||||
['Obstacle', -20]
|
|
||||||
['Path', -10]
|
|
||||||
['Default', 0]
|
|
||||||
['Floating', 10]
|
|
||||||
]
|
|
||||||
@spriteLayers[name] = new LayerAdapter name: name, webGL: true, layerPriority: priority, transform: LayerAdapter.TRANSFORM_SURFACE, camera: @camera
|
|
||||||
@webGLStage.addChild (spriteLayer.container for spriteLayer in _.values(@spriteLayers))...
|
|
||||||
|
|
||||||
layerForChild: (child, sprite) ->
|
|
||||||
unless child.layerPriority?
|
|
||||||
if thang = sprite?.thang
|
|
||||||
child.layerPriority = thang.layerPriority
|
|
||||||
child.layerPriority ?= 0 if thang.isSelectable
|
|
||||||
child.layerPriority ?= -40 if thang.isLand
|
|
||||||
child.layerPriority ?= 0
|
|
||||||
return @spriteLayers['Default'] unless child.layerPriority
|
|
||||||
layer = _.findLast @spriteLayers, (layer, name) ->
|
|
||||||
layer.layerPriority <= child.layerPriority
|
|
||||||
layer ?= @spriteLayers['Land'] if child.layerPriority < -40
|
|
||||||
layer ? @spriteLayers['Default']
|
|
||||||
|
|
||||||
addSprite: (sprite, id=null, layer=null) ->
|
|
||||||
id ?= sprite.thang.id
|
|
||||||
console.error 'Sprite collision! Already have:', id if @sprites[id]
|
|
||||||
@sprites[id] = sprite
|
|
||||||
@spriteArray.push sprite
|
|
||||||
layer ?= @spriteLayers['Obstacle'] if sprite.thang?.spriteName.search(/(dungeon|indoor).wall/i) isnt -1
|
|
||||||
layer ?= @layerForChild sprite.imageObject, sprite
|
|
||||||
layer.addCocoSprite sprite
|
|
||||||
layer.updateLayerOrder()
|
|
||||||
sprite
|
|
||||||
|
|
||||||
createMarks: ->
|
|
||||||
@targetMark = new Mark name: 'target', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'target'
|
|
||||||
@selectionMark = new Mark name: 'selection', camera: @camera, layer: @spriteLayers['Ground'], thangType: 'selection'
|
|
||||||
|
|
||||||
createSpriteOptions: (options) ->
|
|
||||||
_.extend options, camera: @camera, resolutionFactor: SPRITE_RESOLUTION_FACTOR, groundLayer: @spriteLayers['Ground'], textLayer: @surfaceTextLayer, floatingLayer: @spriteLayers['Floating'], showInvisible: @options.showInvisible
|
|
||||||
|
|
||||||
createIndieSprites: (indieSprites, withWizards) ->
|
|
||||||
unless @indieSprites
|
|
||||||
@indieSprites = []
|
|
||||||
@indieSprites = (@createIndieSprite indieSprite for indieSprite in indieSprites) if indieSprites
|
|
||||||
if withWizards and not @selfWizardSprite
|
|
||||||
@selfWizardSprite = @createWizardSprite thangID: 'My Wizard', isSelf: true, sprites: @sprites
|
|
||||||
|
|
||||||
createIndieSprite: (indieSprite) ->
|
|
||||||
unless thangType = @thangTypeFor indieSprite.thangType
|
|
||||||
console.warn "Need to convert #{indieSprite.id}'s ThangType #{indieSprite.thangType} to a ThangType reference. Until then, #{indieSprite.id} won't show up."
|
|
||||||
return
|
|
||||||
sprite = new IndieSprite thangType, @createSpriteOptions {thangID: indieSprite.id, pos: indieSprite.pos, sprites: @sprites, team: indieSprite.team, teamColors: @world.getTeamColors()}
|
|
||||||
@addSprite sprite, sprite.thang.id
|
|
||||||
|
|
||||||
createOpponentWizard: (opponent) ->
|
|
||||||
# TODO: colorize name and cloud by team, colorize wizard by user's color config, level-specific wizard spawn points
|
|
||||||
sprite = @createWizardSprite thangID: opponent.id, name: opponent.name, codeLanguage: opponent.codeLanguage
|
|
||||||
if not opponent.levelSlug or opponent.levelSlug is 'brawlwood'
|
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 52} else {x: 28, y: 28}
|
|
||||||
else if opponent.levelSlug in ['dungeon-arena', 'sky-span']
|
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x: 72, y: 39} else {x: 9, y: 39}
|
|
||||||
else if opponent.levelSlug is 'criss-cross'
|
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x: 50, y: 12} else {x: 0, y: 40}
|
|
||||||
else
|
|
||||||
sprite.targetPos = if opponent.team is 'ogres' then {x: 52, y: 28} else {x: 20, y: 28}
|
|
||||||
|
|
||||||
createWizardSprite: (options) ->
|
|
||||||
sprite = new WizardSprite @thangTypeFor('Wizard'), @createSpriteOptions(options)
|
|
||||||
@addSprite sprite, sprite.thang.id, @spriteLayers['Floating']
|
|
||||||
|
|
||||||
onPlayerJoined: (e) ->
|
|
||||||
# Create another WizardSprite, unless this player is just me
|
|
||||||
pid = e.player.id
|
|
||||||
return if pid is me.id
|
|
||||||
wiz = @createWizardSprite thangID: pid, sprites: @sprites
|
|
||||||
wiz.animateIn()
|
|
||||||
state = e.player.wizard or {}
|
|
||||||
wiz.setInitialState(state.targetPos, @sprites[state.targetSprite])
|
|
||||||
|
|
||||||
onPlayerLeft: (e) ->
|
|
||||||
pid = e.player.id
|
|
||||||
@sprites[pid]?.animateOut => @removeSprite @sprites[pid]
|
|
||||||
|
|
||||||
onSetDebug: (e) ->
|
|
||||||
return if e.debug is @debug
|
|
||||||
@debug = e.debug
|
|
||||||
sprite.setDebug @debug for sprite in @spriteArray
|
|
||||||
|
|
||||||
onHighlightSprites: (e) ->
|
|
||||||
highlightedIDs = e.thangIDs or []
|
|
||||||
for thangID, sprite of @sprites
|
|
||||||
sprite.setHighlight? thangID in highlightedIDs, e.delay
|
|
||||||
|
|
||||||
addThangToSprites: (thang, layer=null) ->
|
|
||||||
return console.warn 'Tried to add Thang to the surface it already has:', thang.id if @sprites[thang.id]
|
|
||||||
thangType = _.find @options.thangTypes, (m) ->
|
|
||||||
return false unless m.get('actions') or m.get('raster')
|
|
||||||
return m.get('name') is thang.spriteName
|
|
||||||
thangType ?= _.find @options.thangTypes, (m) -> return m.get('name') is thang.spriteName
|
|
||||||
return console.error "Couldn't find ThangType for", thang unless thangType
|
|
||||||
|
|
||||||
options = @createSpriteOptions thang: thang
|
|
||||||
options.resolutionFactor = if thangType.get('kind') is 'Floor' then 2 else SPRITE_RESOLUTION_FACTOR
|
|
||||||
sprite = new CocoSprite thangType, options
|
|
||||||
@listenTo sprite, 'sprite:mouse-up', @onSpriteMouseUp
|
|
||||||
@addSprite sprite, null, layer
|
|
||||||
sprite.setDebug @debug
|
|
||||||
sprite
|
|
||||||
|
|
||||||
removeSprite: (sprite) ->
|
|
||||||
sprite.layer.removeCocoSprite(sprite)
|
|
||||||
thang = sprite.thang
|
|
||||||
delete @sprites[sprite.thang.id]
|
|
||||||
@spriteArray.splice @spriteArray.indexOf(sprite), 1
|
|
||||||
@stopListening sprite
|
|
||||||
sprite.destroy()
|
|
||||||
sprite.thang = thang # Keep around so that we know which thang the destroyed thang was for
|
|
||||||
|
|
||||||
updateSounds: ->
|
|
||||||
sprite.playSounds() for sprite in @spriteArray # hmm; doesn't work for sprites which we didn't add yet in adjustSpriteExistence
|
|
||||||
|
|
||||||
update: (frameChanged) ->
|
|
||||||
@adjustSpriteExistence() if frameChanged
|
|
||||||
sprite.update frameChanged for sprite in @spriteArray
|
|
||||||
@updateSelection()
|
|
||||||
@spriteLayers['Default'].updateLayerOrder()
|
|
||||||
@cacheObstacles()
|
|
||||||
|
|
||||||
adjustSpriteExistence: ->
|
|
||||||
# Add anything new, remove anything old, update everything current
|
|
||||||
updatedObstacles = []
|
|
||||||
itemsJustEquipped = []
|
|
||||||
for thang in @world.thangs when thang.exists and thang.pos
|
|
||||||
itemsJustEquipped = itemsJustEquipped.concat @equipNewItems thang
|
|
||||||
if sprite = @sprites[thang.id]
|
|
||||||
sprite.setThang thang # make sure Sprite has latest Thang
|
|
||||||
else
|
|
||||||
sprite = @addThangToSprites(thang)
|
|
||||||
Backbone.Mediator.publish 'surface:new-thang-added', thang: thang, sprite: sprite
|
|
||||||
updatedObstacles.push sprite if sprite.imageObject.parent is @spriteLayers['Obstacle']
|
|
||||||
sprite.playSounds()
|
|
||||||
item.modifyStats() for item in itemsJustEquipped
|
|
||||||
for thangID, sprite of @sprites
|
|
||||||
missing = not (sprite.notOfThisWorld or @world.thangMap[thangID]?.exists)
|
|
||||||
isObstacle = sprite.imageObject.parent is @spriteLayers['Obstacle']
|
|
||||||
updatedObstacles.push sprite if isObstacle and (missing or sprite.hasMoved)
|
|
||||||
sprite.hasMoved = false
|
|
||||||
@removeSprite sprite if missing
|
|
||||||
@cacheObstacles updatedObstacles if updatedObstacles.length and @cachedObstacles
|
|
||||||
|
|
||||||
# mainly for handling selecting thangs from session when the thang is not always in existence
|
|
||||||
if @willSelectThang and @sprites[@willSelectThang[0]]
|
|
||||||
@selectThang @willSelectThang...
|
|
||||||
|
|
||||||
equipNewItems: (thang) ->
|
|
||||||
itemsJustEquipped = []
|
|
||||||
if thang.equip and not thang.equipped
|
|
||||||
thang.equip() # Pretty hacky, but needed since initialize may not be called if we're not running Systems.
|
|
||||||
itemsJustEquipped.push thang
|
|
||||||
if thang.inventoryIDs
|
|
||||||
# Even hackier: these items were only created/equipped during simulation, so we reequip here.
|
|
||||||
for slot, itemID of thang.inventoryIDs
|
|
||||||
item = @world.getThangByID itemID
|
|
||||||
unless item.equipped
|
|
||||||
console.log thang.id, 'equipping', item, 'in', thang.slot, 'Surface-side, but it cannot equip?' unless item.equip
|
|
||||||
item.equip()
|
|
||||||
itemsJustEquipped.push item
|
|
||||||
return itemsJustEquipped
|
|
||||||
|
|
||||||
cacheObstacles: (updatedObstacles=null) ->
|
|
||||||
return if @cachedObstacles and not updatedObstacles
|
|
||||||
wallSprites = (sprite for sprite in @spriteArray when sprite.thangType?.get('name').search(/(dungeon|indoor).wall/i) isnt -1)
|
|
||||||
return if _.any (s.stillLoading for s in wallSprites)
|
|
||||||
walls = (sprite.thang for sprite in wallSprites)
|
|
||||||
@world.calculateBounds()
|
|
||||||
wallGrid = new Grid walls, @world.size()...
|
|
||||||
if updatedObstacles
|
|
||||||
possiblyUpdatedWallSprites = (sprite for sprite in wallSprites when _.find updatedObstacles, (w2) -> sprite is w2 or (Math.abs(sprite.thang.pos.x - w2.thang.pos.x) + Math.abs(sprite.thang.pos.y - w2.thang.pos.y)) <= 16)
|
|
||||||
else
|
|
||||||
possiblyUpdatedWallSprites = wallSprites
|
|
||||||
#console.log 'updating up to', possiblyUpdatedWallSprites.length, 'of', wallSprites.length, 'wall sprites from updatedObstacles', updatedObstacles
|
|
||||||
for wallSprite in possiblyUpdatedWallSprites
|
|
||||||
wallSprite.updateActionDirection wallGrid
|
|
||||||
wallSprite.lockAction()
|
|
||||||
wallSprite.updateScale()
|
|
||||||
wallSprite.updatePosition()
|
|
||||||
#console.log @wallGrid.toString()
|
|
||||||
@cachedObstacles = true
|
|
||||||
|
|
||||||
spriteFor: (thangID) -> @sprites[thangID]
|
|
||||||
|
|
||||||
onNewWorld: (e) ->
|
|
||||||
@world = @options.world = e.world
|
|
||||||
|
|
||||||
play: ->
|
|
||||||
sprite.play() for sprite in @spriteArray
|
|
||||||
@selectionMark?.play()
|
|
||||||
@targetMark?.play()
|
|
||||||
|
|
||||||
stop: ->
|
|
||||||
sprite.stop() for sprite in @spriteArray
|
|
||||||
@selectionMark?.stop()
|
|
||||||
@targetMark?.stop()
|
|
||||||
|
|
||||||
# Selection
|
|
||||||
|
|
||||||
onSuppressSelectionSounds: (e) -> @suppressSelectionSounds = e.suppress
|
|
||||||
onSetLockSelect: (e) -> @selectLocked = e.lock
|
|
||||||
onLevelRestarted: (e) ->
|
|
||||||
@selectLocked = false
|
|
||||||
@selectSprite e, null
|
|
||||||
|
|
||||||
onSelectSprite: (e) ->
|
|
||||||
@selectThang e.thangID, e.spellName
|
|
||||||
|
|
||||||
onCameraDragged: ->
|
|
||||||
@dragged += 1
|
|
||||||
|
|
||||||
onSpriteMouseUp: (e) ->
|
|
||||||
return if key.shift #and @options.choosing
|
|
||||||
return @dragged = 0 if @dragged > 3
|
|
||||||
@dragged = 0
|
|
||||||
sprite = if e.sprite?.thang?.isSelectable then e.sprite else null
|
|
||||||
return if @flagCursorSprite and sprite?.thangType.get('name') is 'Flag'
|
|
||||||
@selectSprite e, sprite
|
|
||||||
|
|
||||||
onStageMouseDown: (e) ->
|
|
||||||
return if key.shift #and @options.choosing
|
|
||||||
@selectSprite e if e.onBackground
|
|
||||||
|
|
||||||
selectThang: (thangID, spellName=null, treemaThangSelected = null) ->
|
|
||||||
return @willSelectThang = [thangID, spellName] unless @sprites[thangID]
|
|
||||||
@selectSprite null, @sprites[thangID], spellName, treemaThangSelected
|
|
||||||
|
|
||||||
selectSprite: (e, sprite=null, spellName=null, treemaThangSelected = null) ->
|
|
||||||
return if e and (@disabled or @selectLocked) # Ignore clicks for selection/panning/wizard movement while disabled or select is locked
|
|
||||||
worldPos = sprite?.thang?.pos
|
|
||||||
worldPos ?= @camera.screenToWorld {x: e.originalEvent.rawX, y: e.originalEvent.rawY} if e?.originalEvent
|
|
||||||
if worldPos and (@options.navigateToSelection or not sprite or treemaThangSelected) and e?.originalEvent?.nativeEvent?.which isnt 3
|
|
||||||
@camera.zoomTo(sprite?.imageObject or @camera.worldToSurface(worldPos), @camera.zoom, 1000, true)
|
|
||||||
sprite = null if @options.choosing # Don't select sprites while choosing
|
|
||||||
if sprite isnt @selectedSprite
|
|
||||||
@selectedSprite?.selected = false
|
|
||||||
sprite?.selected = true
|
|
||||||
@selectedSprite = sprite
|
|
||||||
alive = sprite and not (sprite.thang.health < 0)
|
|
||||||
|
|
||||||
Backbone.Mediator.publish 'surface:sprite-selected',
|
|
||||||
thang: if sprite then sprite.thang else null
|
|
||||||
sprite: sprite
|
|
||||||
spellName: spellName ? e?.spellName
|
|
||||||
originalEvent: e
|
|
||||||
worldPos: worldPos
|
|
||||||
|
|
||||||
@willSelectThang = null if sprite # Now that we've done a real selection, don't reselect some other Thang later.
|
|
||||||
|
|
||||||
if alive and not @suppressSelectionSounds
|
|
||||||
instance = sprite.playSound 'selected'
|
|
||||||
if instance?.playState is 'playSucceeded'
|
|
||||||
Backbone.Mediator.publish 'sprite:thang-began-talking', thang: sprite?.thang
|
|
||||||
instance.addEventListener 'complete', ->
|
|
||||||
Backbone.Mediator.publish 'sprite:thang-finished-talking', thang: sprite?.thang
|
|
||||||
|
|
||||||
onFlagColorSelected: (e) ->
|
|
||||||
@removeSprite @flagCursorSprite if @flagCursorSprite
|
|
||||||
@flagCursorSprite = null
|
|
||||||
for flagSprite in @spriteArray when flagSprite.thangType.get('name') is 'Flag'
|
|
||||||
flagSprite.imageObject.cursor = if e.color then 'crosshair' else 'pointer'
|
|
||||||
return unless e.color
|
|
||||||
@flagCursorSprite = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Flag Cursor', color: e.color, team: me.team, isCursor: true, pos: e.pos)
|
|
||||||
@addSprite @flagCursorSprite, @flagCursorSprite.thang.id, @spriteLayers['Floating']
|
|
||||||
|
|
||||||
onFlagUpdated: (e) ->
|
|
||||||
return unless e.active
|
|
||||||
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: e.team, isCursor: false, pos: e.pos)
|
|
||||||
@addSprite pendingFlag, pendingFlag.thang.id, @spriteLayers['Floating']
|
|
||||||
@pendingFlags.push pendingFlag
|
|
||||||
|
|
||||||
onFlagAppeared: (e) ->
|
|
||||||
# Remove the pending flag that matches this one's color/team/position, and any color/team matches placed earlier.
|
|
||||||
t1 = e.sprite.thang
|
|
||||||
pending = (@pendingFlags ? []).slice()
|
|
||||||
foundExactMatch = false
|
|
||||||
for i in [pending.length - 1 .. 0] by -1
|
|
||||||
pendingFlag = pending[i]
|
|
||||||
t2 = pendingFlag.thang
|
|
||||||
matchedType = t1.color is t2.color and t1.team is t2.team
|
|
||||||
matched = matchedType and (foundExactMatch or Math.abs(t1.pos.x - t2.pos.x) < 0.00001 and Math.abs(t1.pos.y - t2.pos.y) < 0.00001)
|
|
||||||
if matched
|
|
||||||
foundExactMatch = true
|
|
||||||
@pendingFlags.splice(i, 1)
|
|
||||||
@removeSprite pendingFlag
|
|
||||||
e.sprite.imageObject.cursor = if @flagCursorSprite then 'crosshair' else 'pointer'
|
|
||||||
null
|
|
||||||
|
|
||||||
onRemoveSelectedFlag: (e) ->
|
|
||||||
# Remove the selected sprite if it's a flag, or any flag of the given color if a color is given.
|
|
||||||
flagSprite = _.find [@selectedSprite].concat(@spriteArray), (sprite) ->
|
|
||||||
sprite and sprite.thangType.get('name') is 'Flag' and sprite.thang.team is me.team and (sprite.thang.color is e.color or not e.color) and not sprite.notOfThisWorld
|
|
||||||
return unless flagSprite
|
|
||||||
Backbone.Mediator.publish 'surface:remove-flag', color: flagSprite.thang.color
|
|
||||||
|
|
||||||
# Marks
|
|
||||||
|
|
||||||
updateSelection: ->
|
|
||||||
if @selectedSprite?.thang and (not @selectedSprite.thang.exists or not @world.getThangByID @selectedSprite.thang.id)
|
|
||||||
thangID = @selectedSprite.thang.id
|
|
||||||
@selectedSprite = null # Don't actually trigger deselection, but remove the selected sprite.
|
|
||||||
@selectionMark?.toggle false
|
|
||||||
@willSelectThang = [thangID, null]
|
|
||||||
@updateTarget()
|
|
||||||
return unless @selectionMark
|
|
||||||
@selectedSprite = null if @selectedSprite and (@selectedSprite.destroyed or not @selectedSprite.thang)
|
|
||||||
# The selection mark should be on the ground layer, unless we're not a normal sprite (like a wall), in which case we'll place it higher so we can see it.
|
|
||||||
if @selectedSprite and @selectedSprite.imageObject.parent isnt @spriteLayers.Default.container
|
|
||||||
@selectionMark.setLayer @spriteLayers.Default
|
|
||||||
else if @selectedSprite
|
|
||||||
@selectionMark.setLayer @spriteLayers.Ground
|
|
||||||
@selectionMark.toggle @selectedSprite?
|
|
||||||
@selectionMark.setSprite @selectedSprite
|
|
||||||
@selectionMark.update()
|
|
||||||
|
|
||||||
updateTarget: ->
|
|
||||||
return unless @targetMark
|
|
||||||
thang = @selectedSprite?.thang
|
|
||||||
target = thang?.target
|
|
||||||
targetPos = thang?.targetPos
|
|
||||||
targetPos = null if targetPos?.isZero?() # Null targetPos get serialized as (0, 0, 0)
|
|
||||||
@targetMark.setSprite if target then @sprites[target.id] else null
|
|
||||||
@targetMark.toggle @targetMark.sprite or targetPos
|
|
||||||
@targetMark.update if targetPos then @camera.worldToSurface targetPos else null
|
|
|
@ -14,7 +14,7 @@ WaitingScreen = require './WaitingScreen'
|
||||||
DebugDisplay = require './DebugDisplay'
|
DebugDisplay = require './DebugDisplay'
|
||||||
CoordinateDisplay = require './CoordinateDisplay'
|
CoordinateDisplay = require './CoordinateDisplay'
|
||||||
CoordinateGrid = require './CoordinateGrid'
|
CoordinateGrid = require './CoordinateGrid'
|
||||||
SpriteBoss = require './SpriteBoss'
|
LankBoss = require './LankBoss'
|
||||||
PointChooser = require './PointChooser'
|
PointChooser = require './PointChooser'
|
||||||
RegionChooser = require './RegionChooser'
|
RegionChooser = require './RegionChooser'
|
||||||
MusicPlayer = require './MusicPlayer'
|
MusicPlayer = require './MusicPlayer'
|
||||||
|
@ -30,7 +30,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
screenLayer: null
|
screenLayer: null
|
||||||
gridLayer: null
|
gridLayer: null
|
||||||
|
|
||||||
spriteBoss: null
|
lankBoss: null
|
||||||
|
|
||||||
debugDisplay: null
|
debugDisplay: null
|
||||||
currentFrame: 0
|
currentFrame: 0
|
||||||
|
@ -111,7 +111,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
canvasHeight = parseInt @normalCanvas.attr('height'), 10
|
canvasHeight = parseInt @normalCanvas.attr('height'), 10
|
||||||
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
||||||
|
|
||||||
@spriteBoss = new SpriteBoss camera: @camera, webGLStage: @webGLStage, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
@lankBoss = new LankBoss camera: @camera, webGLStage: @webGLStage, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
||||||
@countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer
|
@countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer
|
||||||
@playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer
|
@playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer
|
||||||
@waitingScreen = new WaitingScreen camera: @camera, layer: @screenLayer
|
@waitingScreen = new WaitingScreen camera: @camera, layer: @screenLayer
|
||||||
|
@ -146,7 +146,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
setWorld: (@world) ->
|
setWorld: (@world) ->
|
||||||
@worldLoaded = true
|
@worldLoaded = true
|
||||||
@spriteBoss.world = @world
|
@lankBoss.world = @world
|
||||||
@restoreWorldState() unless @options.choosing
|
@restoreWorldState() unless @options.choosing
|
||||||
@showLevel()
|
@showLevel()
|
||||||
@updateState true if @loaded
|
@updateState true if @loaded
|
||||||
|
@ -156,15 +156,15 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if @destroyed
|
return if @destroyed
|
||||||
return if @loaded
|
return if @loaded
|
||||||
@loaded = true
|
@loaded = true
|
||||||
@spriteBoss.createMarks()
|
@lankBoss.createMarks()
|
||||||
@spriteBoss.createIndieSprites @world.indieSprites, @options.wizards
|
@lankBoss.createIndieLanks @world.indieSprites, @options.wizards
|
||||||
@updateState true
|
@updateState true
|
||||||
@drawCurrentFrame()
|
@drawCurrentFrame()
|
||||||
createjs.Ticker.addEventListener 'tick', @tick
|
createjs.Ticker.addEventListener 'tick', @tick
|
||||||
Backbone.Mediator.publish 'level:started', {}
|
Backbone.Mediator.publish 'level:started', {}
|
||||||
|
|
||||||
createOpponentWizard: (opponent) ->
|
createOpponentWizard: (opponent) ->
|
||||||
@spriteBoss.createOpponentWizard opponent
|
@lankBoss.createOpponentWizard opponent
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -224,15 +224,15 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
ratio = current % 1
|
ratio = current % 1
|
||||||
@world.frames[next].restorePartialState ratio if next > 1
|
@world.frames[next].restorePartialState ratio if next > 1
|
||||||
frame.clearEvents() if parseInt(@currentFrame) is parseInt(@lastFrame)
|
frame.clearEvents() if parseInt(@currentFrame) is parseInt(@lastFrame)
|
||||||
@spriteBoss.updateSounds() if parseInt(@currentFrame) isnt parseInt(@lastFrame)
|
@lankBoss.updateSounds() if parseInt(@currentFrame) isnt parseInt(@lastFrame)
|
||||||
|
|
||||||
updateState: (frameChanged) ->
|
updateState: (frameChanged) ->
|
||||||
# world state must have been restored in @restoreWorldState
|
# world state must have been restored in @restoreWorldState
|
||||||
if @playing and @heroSprite and not @mouseIsDown and @camera.newTarget isnt @heroSprite.imageObject and @camera.target isnt @heroSprite.imageObject
|
if @playing and @heroSprite and not @mouseIsDown and @camera.newTarget isnt @heroSprite.sprite and @camera.target isnt @heroSprite.sprite
|
||||||
@camera.zoomTo @heroSprite.imageObject, @camera.zoom, 750
|
@camera.zoomTo @heroSprite.sprite, @camera.zoom, 750
|
||||||
@camera.updateZoom()
|
@camera.updateZoom()
|
||||||
@spriteBoss.update frameChanged
|
@lankBoss.update frameChanged
|
||||||
@dimmer?.setSprites @spriteBoss.sprites
|
@dimmer?.setSprites @lankBoss.sprites
|
||||||
|
|
||||||
drawCurrentFrame: (e) ->
|
drawCurrentFrame: (e) ->
|
||||||
++@totalFramesDrawn
|
++@totalFramesDrawn
|
||||||
|
@ -288,12 +288,12 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
frame = @world.getFrame(@getCurrentFrame())
|
frame = @world.getFrame(@getCurrentFrame())
|
||||||
frame.restoreState()
|
frame.restoreState()
|
||||||
volume = Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
|
volume = Math.max(0.05, Math.min(1, 1 / @scrubbingPlaybackSpeed))
|
||||||
sprite.playSounds false, volume for sprite in @spriteBoss.spriteArray
|
sprite.playSounds false, volume for sprite in @lankBoss.spriteArray
|
||||||
tempFrame += if rising then 1 else -1
|
tempFrame += if rising then 1 else -1
|
||||||
@currentFrame = actualCurrentFrame
|
@currentFrame = actualCurrentFrame
|
||||||
|
|
||||||
@restoreWorldState()
|
@restoreWorldState()
|
||||||
@spriteBoss.update true
|
@lankBoss.update true
|
||||||
@onFrameChanged()
|
@onFrameChanged()
|
||||||
|
|
||||||
getCurrentFrame: ->
|
getCurrentFrame: ->
|
||||||
|
@ -310,11 +310,11 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@surfacePauseTimeout = @surfaceZoomPauseTimeout = null
|
@surfacePauseTimeout = @surfaceZoomPauseTimeout = null
|
||||||
if paused
|
if paused
|
||||||
@surfacePauseTimeout = _.delay performToggle, 2000
|
@surfacePauseTimeout = _.delay performToggle, 2000
|
||||||
@spriteBoss.stop()
|
@lankBoss.stop()
|
||||||
@playbackOverScreen.show()
|
@playbackOverScreen.show()
|
||||||
else
|
else
|
||||||
performToggle()
|
performToggle()
|
||||||
@spriteBoss.play()
|
@lankBoss.play()
|
||||||
@playbackOverScreen.hide()
|
@playbackOverScreen.hide()
|
||||||
|
|
||||||
|
|
||||||
|
@ -327,7 +327,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if @currentFrame is @lastFrame and not force
|
return if @currentFrame is @lastFrame and not force
|
||||||
progress = @getProgress()
|
progress = @getProgress()
|
||||||
Backbone.Mediator.publish('surface:frame-changed',
|
Backbone.Mediator.publish('surface:frame-changed',
|
||||||
selectedThang: @spriteBoss.selectedSprite?.thang
|
selectedThang: @lankBoss.selectedSprite?.thang
|
||||||
progress: progress
|
progress: progress
|
||||||
frame: @currentFrame
|
frame: @currentFrame
|
||||||
world: @world
|
world: @world
|
||||||
|
@ -365,7 +365,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
onSetCamera: (e) ->
|
onSetCamera: (e) ->
|
||||||
if e.thangID
|
if e.thangID
|
||||||
return unless target = @spriteBoss.spriteFor(e.thangID)?.imageObject
|
return unless target = @lankBoss.spriteFor(e.thangID)?.sprite
|
||||||
else if e.pos
|
else if e.pos
|
||||||
target = @camera.worldToSurface e.pos
|
target = @camera.worldToSurface e.pos
|
||||||
else
|
else
|
||||||
|
@ -383,7 +383,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if e.controls and not ('surface' in e.controls)
|
return if e.controls and not ('surface' in e.controls)
|
||||||
@setDisabled true
|
@setDisabled true
|
||||||
@dimmer ?= new Dimmer camera: @camera, layer: @screenLayer
|
@dimmer ?= new Dimmer camera: @camera, layer: @screenLayer
|
||||||
@dimmer.setSprites @spriteBoss.sprites
|
@dimmer.setSprites @lankBoss.sprites
|
||||||
|
|
||||||
onEnableControls: (e) ->
|
onEnableControls: (e) ->
|
||||||
return if e.controls and not ('surface' in e.controls)
|
return if e.controls and not ('surface' in e.controls)
|
||||||
|
@ -393,7 +393,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
@setDisabled e.on
|
@setDisabled e.on
|
||||||
|
|
||||||
setDisabled: (@disabled) ->
|
setDisabled: (@disabled) ->
|
||||||
@spriteBoss.disabled = @disabled
|
@lankBoss.disabled = @disabled
|
||||||
|
|
||||||
onSetPlaying: (e) ->
|
onSetPlaying: (e) ->
|
||||||
@playing = (e ? {}).playing ? true
|
@playing = (e ? {}).playing ? true
|
||||||
|
@ -433,7 +433,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
onStreamingWorldUpdated: (event) ->
|
onStreamingWorldUpdated: (event) ->
|
||||||
@casting = false
|
@casting = false
|
||||||
@spriteBoss.play()
|
@lankBoss.play()
|
||||||
|
|
||||||
# This has a tendency to break scripts that are waiting for playback to change when the level is loaded
|
# 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.
|
# so only run it after the first world is created.
|
||||||
|
@ -535,7 +535,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
#- Camera focus on hero
|
#- Camera focus on hero
|
||||||
focusOnHero: ->
|
focusOnHero: ->
|
||||||
@heroSprite = @spriteBoss.spriteFor 'Hero Placeholder'
|
@heroSprite = @lankBoss.spriteFor 'Hero Placeholder'
|
||||||
|
|
||||||
|
|
||||||
#- Real-time playback
|
#- Real-time playback
|
||||||
|
@ -547,18 +547,18 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
return if @realTime
|
return if @realTime
|
||||||
@realTime = true
|
@realTime = true
|
||||||
@onResize()
|
@onResize()
|
||||||
@spriteBoss.selfWizardSprite?.toggle false
|
@lankBoss.selfWizardLank?.toggle false
|
||||||
@playing = false # Will start when countdown is done.
|
@playing = false # Will start when countdown is done.
|
||||||
if @heroSprite
|
if @heroSprite
|
||||||
@previousCameraZoom = @camera.zoom
|
@previousCameraZoom = @camera.zoom
|
||||||
@camera.zoomTo @heroSprite.imageObject, 4, 3000
|
@camera.zoomTo @heroSprite.sprite, 4, 3000
|
||||||
|
|
||||||
onRealTimePlaybackEnded: (e) ->
|
onRealTimePlaybackEnded: (e) ->
|
||||||
return unless @realTime
|
return unless @realTime
|
||||||
@realTime = false
|
@realTime = false
|
||||||
@onResize()
|
@onResize()
|
||||||
_.delay @onResize, resizeDelay + 100 # Do it again just to be double sure that we don't stay zoomed in due to timing problems.
|
_.delay @onResize, resizeDelay + 100 # Do it again just to be double sure that we don't stay zoomed in due to timing problems.
|
||||||
@spriteBoss.selfWizardSprite?.toggle true
|
@lankBoss.selfWizardLank?.toggle true
|
||||||
@normalCanvas.add(@webGLCanvas).removeClass 'flag-color-selected'
|
@normalCanvas.add(@webGLCanvas).removeClass 'flag-color-selected'
|
||||||
if @previousCameraZoom
|
if @previousCameraZoom
|
||||||
@camera.zoomTo @camera.newTarget or @camera.target, @previousCameraZoom, 3000
|
@camera.zoomTo @camera.newTarget or @camera.target, @previousCameraZoom, 3000
|
||||||
|
@ -569,22 +569,22 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#- Paths - TODO: move to SpriteBoss? but only update on frame drawing instead of on every frame update?
|
#- Paths - TODO: move to LankBoss? but only update on frame drawing instead of on every frame update?
|
||||||
|
|
||||||
updatePaths: ->
|
updatePaths: ->
|
||||||
return # TODO: Get paths working again with WebGL
|
return # TODO: Get paths working again with WebGL
|
||||||
return unless @options.paths
|
return unless @options.paths
|
||||||
return if @casting
|
return if @casting
|
||||||
@hidePaths()
|
@hidePaths()
|
||||||
selectedThang = @spriteBoss.selectedSprite?.thang
|
selectedThang = @lankBoss.selectedSprite?.thang
|
||||||
return if @world.showPaths is 'never'
|
return if @world.showPaths is 'never'
|
||||||
return if @world.showPaths is 'paused' and @playing
|
return if @world.showPaths is 'paused' and @playing
|
||||||
return if @world.showPaths is 'selected' and not selectedThang
|
return if @world.showPaths is 'selected' and not selectedThang
|
||||||
@trailmaster ?= new path.Trailmaster @camera
|
@trailmaster ?= new path.Trailmaster @camera
|
||||||
selectedOnly = @playing and @world.showPaths is 'selected'
|
selectedOnly = @playing and @world.showPaths is 'selected'
|
||||||
@paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @spriteBoss.sprites, selectedOnly
|
@paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @lankBoss.sprites, selectedOnly
|
||||||
@paths.name = 'paths'
|
@paths.name = 'paths'
|
||||||
@spriteBoss.spriteLayers['Path'].addChild @paths
|
@lankBoss.layerAdapters['Path'].addChild @paths
|
||||||
|
|
||||||
hidePaths: ->
|
hidePaths: ->
|
||||||
return if not @paths
|
return if not @paths
|
||||||
|
@ -681,7 +681,7 @@ module.exports = Surface = class Surface extends CocoClass
|
||||||
createjs.Ticker.removeEventListener('tick', @tick)
|
createjs.Ticker.removeEventListener('tick', @tick)
|
||||||
createjs.Sound.stop()
|
createjs.Sound.stop()
|
||||||
layer.destroy() for layer in @normalLayers
|
layer.destroy() for layer in @normalLayers
|
||||||
@spriteBoss.destroy()
|
@lankBoss.destroy()
|
||||||
@chooser?.destroy()
|
@chooser?.destroy()
|
||||||
@dimmer?.destroy()
|
@dimmer?.destroy()
|
||||||
@countdownScreen?.destroy()
|
@countdownScreen?.destroy()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
IndieSprite = require 'lib/surface/IndieSprite'
|
IndieLank = require 'lib/surface/IndieLank'
|
||||||
{me} = require 'lib/auth'
|
{me} = require 'lib/auth'
|
||||||
|
|
||||||
module.exports = class WizardSprite extends IndieSprite
|
module.exports = class WizardLank extends IndieLank
|
||||||
# Wizard targets are constantly changing, so a simple tween doesn't work.
|
# Wizard targets are constantly changing, so a simple tween doesn't work.
|
||||||
# Instead, the wizard stores its origin point and the (possibly) moving target.
|
# Instead, the wizard stores its origin point and the (possibly) moving target.
|
||||||
# Then it figures out its current position based on tween percentage and
|
# Then it figures out its current position based on tween percentage and
|
||||||
|
@ -9,7 +9,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
tweenPercentage: 1.0
|
tweenPercentage: 1.0
|
||||||
originPos: null
|
originPos: null
|
||||||
targetPos: null
|
targetPos: null
|
||||||
targetSprite: null
|
targetLank: null
|
||||||
reachedTarget: true
|
reachedTarget: true
|
||||||
spriteXOffset: 4 # meters from target sprite
|
spriteXOffset: 4 # meters from target sprite
|
||||||
spriteYOffset: 0 # meters from target sprite
|
spriteYOffset: 0 # meters from target sprite
|
||||||
|
@ -17,8 +17,8 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
subscriptions:
|
subscriptions:
|
||||||
'bus:player-states-changed': 'onPlayerStatesChanged'
|
'bus:player-states-changed': 'onPlayerStatesChanged'
|
||||||
'auth:me-synced': 'onMeSynced'
|
'auth:me-synced': 'onMeSynced'
|
||||||
'surface:sprite-selected': 'onSpriteSelected'
|
'surface:sprite-selected': 'onLankSelected'
|
||||||
'sprite:echo-all-wizard-sprites': 'onEchoAllWizardSprites'
|
'sprite:echo-all-wizard-sprites': 'onEchoAllWizardLanks'
|
||||||
|
|
||||||
shortcuts:
|
shortcuts:
|
||||||
'up': 'onMoveKey'
|
'up': 'onMoveKey'
|
||||||
|
@ -57,7 +57,7 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
super name
|
super name
|
||||||
|
|
||||||
toggle: (to) ->
|
toggle: (to) ->
|
||||||
@imageObject?.visible = to
|
@sprite?.visible = to
|
||||||
label[if to then 'show' else 'hide']() for name, label of @labels
|
label[if to then 'show' else 'hide']() for name, label of @labels
|
||||||
mark.mark?.visible = to for name, mark of @marks
|
mark.mark?.visible = to for name, mark of @marks
|
||||||
|
|
||||||
|
@ -65,37 +65,37 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
for playerID, state of e.states
|
for playerID, state of e.states
|
||||||
continue unless playerID is @thang.id
|
continue unless playerID is @thang.id
|
||||||
@setEditing state.wizard?.editing
|
@setEditing state.wizard?.editing
|
||||||
continue if playerID is me.id # ignore changes for self wizard sprite
|
continue if playerID is me.id # ignore changes for self wizard lank
|
||||||
@setNameLabel state.name
|
@setNameLabel state.name
|
||||||
continue unless state.wizard?
|
continue unless state.wizard?
|
||||||
if targetID = state.wizard.targetSprite
|
if targetID = state.wizard.targetLank
|
||||||
return console.warn 'Wizard Sprite couldn\'t find target sprite', targetID unless targetID of @options.sprites
|
return console.warn 'Wizard Lank couldn\'t find target lank', targetID unless targetID of @options.lanks
|
||||||
@setTarget @options.sprites[targetID]
|
@setTarget @options.lanks[targetID]
|
||||||
else
|
else
|
||||||
@setTarget state.wizard.targetPos
|
@setTarget state.wizard.targetPos
|
||||||
|
|
||||||
onMeSynced: (e) ->
|
onMeSynced: (e) ->
|
||||||
return unless @isSelf
|
return unless @isSelf
|
||||||
@setNameLabel me.displayName() if @imageObject.visible # not if we hid the wiz
|
@setNameLabel me.displayName() if @sprite.visible # not if we hid the wiz
|
||||||
newColorConfig = me.get('wizard')?.colorConfig or {}
|
newColorConfig = me.get('wizard')?.colorConfig or {}
|
||||||
shouldUpdate = not _.isEqual(newColorConfig, @options.colorConfig)
|
shouldUpdate = not _.isEqual(newColorConfig, @options.colorConfig)
|
||||||
@options.colorConfig = $.extend(true, {}, newColorConfig)
|
@options.colorConfig = $.extend(true, {}, newColorConfig)
|
||||||
if shouldUpdate
|
if shouldUpdate
|
||||||
@setUpSprite()
|
@setUpLank()
|
||||||
@playAction(@currentAction) if @currentAction
|
@playAction(@currentAction) if @currentAction
|
||||||
|
|
||||||
onSpriteSelected: (e) ->
|
onLankSelected: (e) ->
|
||||||
return unless @isSelf
|
return unless @isSelf
|
||||||
@setTarget e.sprite or e.worldPos
|
@setTarget e.sprite or e.worldPos
|
||||||
|
|
||||||
animateIn: ->
|
animateIn: ->
|
||||||
@imageObject.scaleX = @imageObject.scaleY = @imageObject.alpha = 0
|
@sprite.scaleX = @sprite.scaleY = @sprite.alpha = 0
|
||||||
createjs.Tween.get(@imageObject)
|
createjs.Tween.get(@sprite)
|
||||||
.to({scaleX: 1, scaleY: 1, alpha: 1}, 1000, createjs.Ease.getPowInOut(2.2))
|
.to({scaleX: 1, scaleY: 1, alpha: 1}, 1000, createjs.Ease.getPowInOut(2.2))
|
||||||
@labels.name?.show()
|
@labels.name?.show()
|
||||||
|
|
||||||
animateOut: (callback) ->
|
animateOut: (callback) ->
|
||||||
tween = createjs.Tween.get(@imageObject)
|
tween = createjs.Tween.get(@sprite)
|
||||||
.to({scaleX: 0, scaleY: 0, alpha: 0}, 1000, createjs.Ease.getPowInOut(2.2))
|
.to({scaleX: 0, scaleY: 0, alpha: 0}, 1000, createjs.Ease.getPowInOut(2.2))
|
||||||
tween.call(callback) if callback
|
tween.call(callback) if callback
|
||||||
@labels.name?.hide()
|
@labels.name?.hide()
|
||||||
|
@ -107,11 +107,11 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
else
|
else
|
||||||
@thang.action = 'idle' if @thang.action is 'cast'
|
@thang.action = 'idle' if @thang.action is 'cast'
|
||||||
|
|
||||||
setInitialState: (targetPos, @targetSprite) ->
|
setInitialState: (targetPos, @targetLank) ->
|
||||||
@targetPos = @getPosFromTarget(@targetSprite or targetPos)
|
@targetPos = @getPosFromTarget(@targetLank or targetPos)
|
||||||
@endMoveTween()
|
@endMoveTween()
|
||||||
|
|
||||||
onEchoAllWizardSprites: (e) -> e.payload.push @
|
onEchoAllWizardLanks: (e) -> e.payload.push @
|
||||||
defaultPos: -> x: 35, y: 24, z: @thang.depth / 2 + @thang.bobHeight
|
defaultPos: -> x: 35, y: 24, z: @thang.depth / 2 + @thang.bobHeight
|
||||||
move: (pos, duration) -> @setTarget(pos, duration)
|
move: (pos, duration) -> @setTarget(pos, duration)
|
||||||
|
|
||||||
|
@ -121,12 +121,12 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
return if @targetPos and @targetPos.x is targetPos.x and @targetPos.y is targetPos.y
|
return if @targetPos and @targetPos.x is targetPos.x and @targetPos.y is targetPos.y
|
||||||
|
|
||||||
# ignore selecting sprites you can't control
|
# ignore selecting sprites you can't control
|
||||||
isSprite = newTarget?.thang?
|
isLank = newTarget?.thang?
|
||||||
return if isSprite and not newTarget.thang.isProgrammable
|
return if isLank and not newTarget.thang.isProgrammable
|
||||||
return if isSprite and newTarget is @targetSprite
|
return if isLank and newTarget is @targetLank
|
||||||
|
|
||||||
@shoveOtherWizards(true) if @targetSprite
|
@shoveOtherWizards(true) if @targetLank
|
||||||
@targetSprite = if isSprite then newTarget else null
|
@targetLank = if isLank then newTarget else null
|
||||||
@targetPos = @boundWizard targetPos
|
@targetPos = @boundWizard targetPos
|
||||||
@beginMoveTween(duration, isLinear)
|
@beginMoveTween(duration, isLinear)
|
||||||
@shoveOtherWizards()
|
@shoveOtherWizards()
|
||||||
|
@ -175,10 +175,10 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
@update true
|
@update true
|
||||||
|
|
||||||
shoveOtherWizards: (removeMe) ->
|
shoveOtherWizards: (removeMe) ->
|
||||||
return unless @targetSprite
|
return unless @targetLank
|
||||||
allWizards = []
|
allWizards = []
|
||||||
Backbone.Mediator.publish 'sprite:echo-all-wizard-sprites', payload: allWizards
|
Backbone.Mediator.publish 'sprite:echo-all-wizard-sprites', payload: allWizards
|
||||||
allOfUs = (wizard for wizard in allWizards when wizard.targetSprite is @targetSprite)
|
allOfUs = (wizard for wizard in allWizards when wizard.targetLank is @targetLank)
|
||||||
allOfUs = (wizard for wizard in allOfUs when wizard isnt @) if removeMe
|
allOfUs = (wizard for wizard in allOfUs when wizard isnt @) if removeMe
|
||||||
|
|
||||||
# diagonal lineup pattern
|
# diagonal lineup pattern
|
||||||
|
@ -210,18 +210,18 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
@thang.pos = @getCurrentPosition()
|
@thang.pos = @getCurrentPosition()
|
||||||
@faceTarget()
|
@faceTarget()
|
||||||
sup = @options.camera.worldToSurface x: @thang.pos.x, y: @thang.pos.y, z: @thang.pos.z - @thang.depth / 2
|
sup = @options.camera.worldToSurface x: @thang.pos.x, y: @thang.pos.y, z: @thang.pos.z - @thang.depth / 2
|
||||||
@imageObject.x = sup.x
|
@sprite.x = sup.x
|
||||||
@imageObject.y = sup.y
|
@sprite.y = sup.y
|
||||||
|
|
||||||
getCurrentPosition: ->
|
getCurrentPosition: ->
|
||||||
"""
|
"""
|
||||||
Takes into account whether the wizard is in transit or not, and the bobbing up and down.
|
Takes into account whether the wizard is in transit or not, and the bobbing up and down.
|
||||||
Eventually will also adjust based on where other wizards are.
|
Eventually will also adjust based on where other wizards are.
|
||||||
"""
|
"""
|
||||||
@targetPos = @targetSprite.thang.pos if @targetSprite?.thang
|
@targetPos = @targetLank.thang.pos if @targetLank?.thang
|
||||||
pos = _.clone(@targetPos)
|
pos = _.clone(@targetPos)
|
||||||
pos.z = @defaultPos().z + @getBobOffset()
|
pos.z = @defaultPos().z + @getBobOffset()
|
||||||
@adjustPositionToSideOfTarget(pos) if @targetSprite # be off to the side depending on placement in world
|
@adjustPositionToSideOfTarget(pos) if @targetLank # be off to the side depending on placement in world
|
||||||
return pos if @reachedTarget # stick like glue
|
return pos if @reachedTarget # stick like glue
|
||||||
|
|
||||||
# if here, then the wizard is in transit. Calculate the diff!
|
# if here, then the wizard is in transit. Calculate the diff!
|
||||||
|
@ -248,11 +248,11 @@ module.exports = class WizardSprite extends IndieSprite
|
||||||
targetPos.y += @spriteYOffset
|
targetPos.y += @spriteYOffset
|
||||||
|
|
||||||
faceTarget: ->
|
faceTarget: ->
|
||||||
if @targetSprite?.thang
|
if @targetLank?.thang
|
||||||
@pointToward(@targetSprite.thang.pos)
|
@pointToward(@targetLank.thang.pos)
|
||||||
|
|
||||||
updateMarks: ->
|
updateMarks: ->
|
||||||
super() if @imageObject.visible # not if we hid the wiz
|
super() if @sprite.visible # not if we hid the wiz
|
||||||
|
|
||||||
onMoveKey: (e) ->
|
onMoveKey: (e) ->
|
||||||
return unless @isSelf
|
return unless @isSelf
|
|
@ -144,7 +144,7 @@ module.exports.Trailmaster = class Trailmaster
|
||||||
sprites = []
|
sprites = []
|
||||||
sprite = @sprites[thang.id]
|
sprite = @sprites[thang.id]
|
||||||
return sprites unless sprite?.actions
|
return sprites unless sprite?.actions
|
||||||
lastPos = @camera.surfaceToWorld x: sprite.imageObject.x, y: sprite.imageObject.y
|
lastPos = @camera.surfaceToWorld x: sprite.sprite.x, y: sprite.sprite.y
|
||||||
minDistance = Math.pow(CLONE_INTERVAL * Camera.MPP, 2)
|
minDistance = Math.pow(CLONE_INTERVAL * Camera.MPP, 2)
|
||||||
actions = @world.actionsForThang(thang.id)
|
actions = @world.actionsForThang(thang.id)
|
||||||
lastAction = null
|
lastAction = null
|
||||||
|
@ -159,7 +159,7 @@ module.exports.Trailmaster = class Trailmaster
|
||||||
diff += Math.pow(lastPos.y - thang.pos.y, 2)
|
diff += Math.pow(lastPos.y - thang.pos.y, 2)
|
||||||
continue if diff < minDistance and action.name is lastAction
|
continue if diff < minDistance and action.name is lastAction
|
||||||
|
|
||||||
clone = sprite.imageObject.clone()
|
clone = sprite.sprite.clone()
|
||||||
clonePos = @camera.worldToSurface thang.pos
|
clonePos = @camera.worldToSurface thang.pos
|
||||||
clone.x = clonePos.x
|
clone.x = clonePos.x
|
||||||
clone.y = clonePos.y
|
clone.y = clonePos.y
|
||||||
|
|
|
@ -166,7 +166,7 @@ module.exports = class Thang
|
||||||
serializeForAether: ->
|
serializeForAether: ->
|
||||||
{CN: @constructor.className, id: @id}
|
{CN: @constructor.className, id: @id}
|
||||||
|
|
||||||
getSpriteOptions: ->
|
getLankOptions: ->
|
||||||
colorConfigs = @teamColors or @world?.getTeamColors() or {}
|
colorConfigs = @teamColors or @world?.getTeamColors() or {}
|
||||||
options = {colorConfig: {}}
|
options = {colorConfig: {}}
|
||||||
if @team and teamColor = colorConfigs[@team]
|
if @team and teamColor = colorConfigs[@team]
|
||||||
|
|
|
@ -66,7 +66,7 @@ class CocoModel extends Backbone.Model
|
||||||
inFlux = @loading or not @loaded
|
inFlux = @loading or not @loaded
|
||||||
@markToRevert() unless inFlux or @_revertAttributes or @project or options?.fromMerge
|
@markToRevert() unless inFlux or @_revertAttributes or @project or options?.fromMerge
|
||||||
res = super attributes, options
|
res = super attributes, options
|
||||||
@saveBackup() if @saveBackups and (not inFlux) and @hasLocalChanges()
|
@saveBackup() if @saveBackups and (not inFlux)
|
||||||
res
|
res
|
||||||
|
|
||||||
buildAttributesWithDefaults: ->
|
buildAttributesWithDefaults: ->
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
RootView = require 'views/kinds/RootView'
|
RootView = require 'views/kinds/RootView'
|
||||||
template = require 'templates/home'
|
template = require 'templates/home'
|
||||||
WizardSprite = require 'lib/surface/WizardSprite'
|
WizardLank = require 'lib/surface/WizardLank'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
Simulator = require 'lib/simulator/Simulator'
|
Simulator = require 'lib/simulator/Simulator'
|
||||||
{me} = require '/lib/auth'
|
{me} = require '/lib/auth'
|
||||||
|
|
|
@ -359,9 +359,9 @@ module.exports = class ThangsTabView extends CocoView
|
||||||
@addThangType = type
|
@addThangType = type
|
||||||
if @addThangType
|
if @addThangType
|
||||||
thang = @createAddThang()
|
thang = @createAddThang()
|
||||||
@addThangSprite = @surface.spriteBoss.addThangToSprites thang, @surface.spriteBoss.spriteLayers['Floating']
|
@addThangSprite = @surface.spriteBoss.addThangToSprites thang, @surface.spriteBoss.layerAdapters['Floating']
|
||||||
@addThangSprite.notOfThisWorld = true
|
@addThangSprite.notOfThisWorld = true
|
||||||
@addThangSprite.imageObject.alpha = 0.75
|
@addThangSprite.sprite.alpha = 0.75
|
||||||
@addThangSprite.playSound? 'selected'
|
@addThangSprite.playSound? 'selected'
|
||||||
pos ?= x: Math.round(@world.width / 2), y: Math.round(@world.height / 2)
|
pos ?= x: Math.round(@world.width / 2), y: Math.round(@world.height / 2)
|
||||||
@adjustThangPos @addThangSprite, thang, pos
|
@adjustThangPos @addThangSprite, thang, pos
|
||||||
|
@ -420,11 +420,11 @@ module.exports = class ThangsTabView extends CocoView
|
||||||
|
|
||||||
onSurfaceMouseOver: (e) ->
|
onSurfaceMouseOver: (e) ->
|
||||||
return unless @addThangSprite
|
return unless @addThangSprite
|
||||||
@addThangSprite.imageObject.visible = true
|
@addThangSprite.sprite.visible = true
|
||||||
|
|
||||||
onSurfaceMouseOut: (e) ->
|
onSurfaceMouseOut: (e) ->
|
||||||
return unless @addThangSprite
|
return unless @addThangSprite
|
||||||
@addThangSprite.imageObject.visible = false
|
@addThangSprite.sprite.visible = false
|
||||||
|
|
||||||
calculateMovement: (pctX, pctY, widthHeightRatio) ->
|
calculateMovement: (pctX, pctY, widthHeightRatio) ->
|
||||||
MOVE_TOP_MARGIN = 1.0 - MOVE_MARGIN
|
MOVE_TOP_MARGIN = 1.0 - MOVE_MARGIN
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
SpriteParser = require 'lib/sprites/SpriteParser'
|
SpriteParser = require 'lib/sprites/SpriteParser'
|
||||||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||||
CocoSprite = require 'lib/surface/CocoSprite'
|
Lank = require 'lib/surface/Lank'
|
||||||
|
LayerAdapter = require 'lib/surface/LayerAdapter'
|
||||||
Camera = require 'lib/surface/Camera'
|
Camera = require 'lib/surface/Camera'
|
||||||
DocumentFiles = require 'collections/DocumentFiles'
|
DocumentFiles = require 'collections/DocumentFiles'
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
@listenToOnce @thangType, 'sync', ->
|
@listenToOnce @thangType, 'sync', ->
|
||||||
@files = @supermodel.loadCollection(new DocumentFiles(@thangType), 'files').model
|
@files = @supermodel.loadCollection(new DocumentFiles(@thangType), 'files').model
|
||||||
@updateFileSize()
|
@updateFileSize()
|
||||||
@refreshAnimation = _.debounce @refreshAnimation, 500
|
# @refreshAnimation = _.debounce @refreshAnimation, 500
|
||||||
|
|
||||||
showLoading: ($el) ->
|
showLoading: ($el) ->
|
||||||
$el ?= @$el.find('.outer-content')
|
$el ?= @$el.find('.outer-content')
|
||||||
|
@ -74,7 +75,8 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
context
|
context
|
||||||
|
|
||||||
getAnimationNames: ->
|
getAnimationNames: ->
|
||||||
raw = _.keys(@thangType.get('raw', true).animations)
|
raw = _.keys((@thangType.get('raw') or {}).animations)
|
||||||
|
return [] unless raw
|
||||||
raw = ("raw:#{name}" for name in raw)
|
raw = ("raw:#{name}" for name in raw)
|
||||||
main = _.keys(@thangType.get('actions') or {})
|
main = _.keys(@thangType.get('actions') or {})
|
||||||
main.concat(raw)
|
main.concat(raw)
|
||||||
|
@ -119,6 +121,8 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
initStage: ->
|
initStage: ->
|
||||||
canvas = @$el.find('#canvas')
|
canvas = @$el.find('#canvas')
|
||||||
@stage = new createjs.Stage(canvas[0])
|
@stage = new createjs.Stage(canvas[0])
|
||||||
|
@layerAdapter = new LayerAdapter({name:'Default', webGL: true})
|
||||||
|
@stage.addChild(@layerAdapter.container)
|
||||||
@camera?.destroy()
|
@camera?.destroy()
|
||||||
@camera = new Camera canvas
|
@camera = new Camera canvas
|
||||||
|
|
||||||
|
@ -128,7 +132,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
@groundDot = @makeDot('red')
|
@groundDot = @makeDot('red')
|
||||||
@stage.addChild(@groundDot, @torsoDot, @mouthDot, @aboveHeadDot)
|
@stage.addChild(@groundDot, @torsoDot, @mouthDot, @aboveHeadDot)
|
||||||
@updateGrid()
|
@updateGrid()
|
||||||
@refreshAnimation()
|
_.defer @refreshAnimation
|
||||||
|
|
||||||
createjs.Ticker.setFPS(30)
|
createjs.Ticker.setFPS(30)
|
||||||
createjs.Ticker.addEventListener('tick', @stage)
|
createjs.Ticker.addEventListener('tick', @stage)
|
||||||
|
@ -139,11 +143,11 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
|
|
||||||
updateDots: ->
|
updateDots: ->
|
||||||
@stage.removeChild(@torsoDot, @mouthDot, @aboveHeadDot, @groundDot)
|
@stage.removeChild(@torsoDot, @mouthDot, @aboveHeadDot, @groundDot)
|
||||||
return unless @currentSprite
|
return unless @currentLank
|
||||||
return unless @showDots
|
return unless @showDots
|
||||||
torso = @currentSprite.getOffset 'torso'
|
torso = @currentLank.getOffset 'torso'
|
||||||
mouth = @currentSprite.getOffset 'mouth'
|
mouth = @currentLank.getOffset 'mouth'
|
||||||
aboveHead = @currentSprite.getOffset 'aboveHead'
|
aboveHead = @currentLank.getOffset 'aboveHead'
|
||||||
@torsoDot.x = CENTER.x + torso.x * @scale
|
@torsoDot.x = CENTER.x + torso.x * @scale
|
||||||
@torsoDot.y = CENTER.y + torso.y * @scale
|
@torsoDot.y = CENTER.y + torso.y * @scale
|
||||||
@mouthDot.x = CENTER.x + mouth.x * @scale
|
@mouthDot.x = CENTER.x + mouth.x * @scale
|
||||||
|
@ -153,7 +157,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
@stage.addChild(@groundDot, @torsoDot, @mouthDot, @aboveHeadDot)
|
@stage.addChild(@groundDot, @torsoDot, @mouthDot, @aboveHeadDot)
|
||||||
|
|
||||||
endAnimation: ->
|
endAnimation: ->
|
||||||
@currentSprite?.queueAction('idle')
|
@currentLank?.queueAction('idle')
|
||||||
|
|
||||||
updateGrid: ->
|
updateGrid: ->
|
||||||
grid = new createjs.Container()
|
grid = new createjs.Container()
|
||||||
|
@ -223,23 +227,24 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
|
|
||||||
# animation select
|
# animation select
|
||||||
|
|
||||||
refreshAnimation: ->
|
refreshAnimation: =>
|
||||||
return @showRasterImage() if @thangType.get('raster')
|
return @showRasterImage() if @thangType.get('raster')
|
||||||
options = @getSpriteOptions()
|
options = @getLankOptions()
|
||||||
@thangType.resetSpriteSheetCache()
|
console.log 'refresh animation....'
|
||||||
spriteSheet = @thangType.buildSpriteSheet(options)
|
# @thangType.resetSpriteSheetCache()
|
||||||
$('#spritesheets').empty()
|
# spriteSheet = @thangType.buildSpriteSheet(options)
|
||||||
return unless spriteSheet
|
# $('#spritesheets').empty()
|
||||||
for image in spriteSheet._images
|
# return unless spriteSheet
|
||||||
$('#spritesheets').append(image)
|
# for image in spriteSheet._images
|
||||||
|
# $('#spritesheets').append(image)
|
||||||
@showAnimation()
|
@showAnimation()
|
||||||
@updatePortrait()
|
@updatePortrait()
|
||||||
|
|
||||||
showRasterImage: ->
|
showRasterImage: ->
|
||||||
sprite = new CocoSprite(@thangType, @getSpriteOptions())
|
sprite = new Lank(@thangType, @getLankOptions())
|
||||||
@currentSprite?.destroy()
|
@currentLank?.destroy()
|
||||||
@currentSprite = sprite
|
@currentLank = sprite
|
||||||
@showImageObject(sprite.imageObject)
|
@showSprite(sprite.sprite)
|
||||||
@updateScale()
|
@updateScale()
|
||||||
|
|
||||||
showAnimation: (animationName) ->
|
showAnimation: (animationName) ->
|
||||||
|
@ -249,7 +254,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
animationName = animationName[4...]
|
animationName = animationName[4...]
|
||||||
@showMovieClip(animationName)
|
@showMovieClip(animationName)
|
||||||
else
|
else
|
||||||
@showSprite(animationName)
|
@showAction(animationName)
|
||||||
@updateRotation()
|
@updateRotation()
|
||||||
@updateScale() # must happen after update rotation, because updateRotation calls the sprite update() method.
|
@updateScale() # must happen after update rotation, because updateRotation calls the sprite update() method.
|
||||||
|
|
||||||
|
@ -261,37 +266,52 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
if reg
|
if reg
|
||||||
movieClip.regX = -reg.x
|
movieClip.regX = -reg.x
|
||||||
movieClip.regY = -reg.y
|
movieClip.regY = -reg.y
|
||||||
@showImageObject(movieClip)
|
@showSprite(movieClip)
|
||||||
|
|
||||||
getSpriteOptions: -> {resolutionFactor: @resolution, thang: @mockThang}
|
getLankOptions: -> {resolutionFactor: @resolution, thang: @mockThang}
|
||||||
|
|
||||||
showSprite: (actionName) ->
|
showAction: (actionName) ->
|
||||||
options = @getSpriteOptions()
|
options = @getLankOptions()
|
||||||
sprite = new CocoSprite(@thangType, options)
|
lank = new Lank(@thangType, options)
|
||||||
sprite.queueAction(actionName)
|
@showLank(lank)
|
||||||
@currentSprite?.destroy()
|
lank.queueAction(actionName)
|
||||||
@currentSprite = sprite
|
|
||||||
@showImageObject(sprite.imageObject)
|
|
||||||
|
|
||||||
updatePortrait: ->
|
updatePortrait: ->
|
||||||
options = @getSpriteOptions()
|
options = @getLankOptions()
|
||||||
portrait = @thangType.getPortraitImage(options)
|
portrait = @thangType.getPortraitImage(options)
|
||||||
return unless portrait
|
return unless portrait
|
||||||
portrait?.attr('id', 'portrait').addClass('img-thumbnail')
|
portrait?.attr('id', 'portrait').addClass('img-thumbnail')
|
||||||
portrait.addClass 'img-thumbnail'
|
portrait.addClass 'img-thumbnail'
|
||||||
$('#portrait').replaceWith(portrait)
|
$('#portrait').replaceWith(portrait)
|
||||||
|
|
||||||
showImageObject: (imageObject) ->
|
showLank: (lank) ->
|
||||||
@clearDisplayObject()
|
@clearDisplayObject()
|
||||||
imageObject.x = CENTER.x
|
@clearLank()
|
||||||
imageObject.y = CENTER.y
|
@layerAdapter.resetSpriteSheet()
|
||||||
@stage.addChildAt(imageObject, 1)
|
@layerAdapter.addLank(lank)
|
||||||
@currentObject = imageObject
|
@currentLank = lank
|
||||||
|
lank.sprite.x = CENTER.x
|
||||||
|
lank.sprite.y = CENTER.y
|
||||||
|
lank.on 'new-sprite', ->
|
||||||
|
lank.sprite.x = CENTER.x
|
||||||
|
lank.sprite.y = CENTER.y
|
||||||
|
|
||||||
|
showSprite: (sprite) ->
|
||||||
|
@clearDisplayObject()
|
||||||
|
@clearLank()
|
||||||
|
sprite.x = CENTER.x
|
||||||
|
sprite.y = CENTER.y
|
||||||
|
@stage.addChildAt(sprite, 1)
|
||||||
|
@currentObject = sprite
|
||||||
@updateDots()
|
@updateDots()
|
||||||
|
|
||||||
clearDisplayObject: ->
|
clearDisplayObject: ->
|
||||||
@stage.removeChild(@currentObject) if @currentObject?
|
@stage.removeChild(@currentObject) if @currentObject?
|
||||||
|
|
||||||
|
clearLank: ->
|
||||||
|
@layerAdapter.removeLank(@currentLank) if @currentLank
|
||||||
|
@currentLank?.destroy()
|
||||||
|
|
||||||
# sliders
|
# sliders
|
||||||
|
|
||||||
initSliders: ->
|
initSliders: ->
|
||||||
|
@ -303,9 +323,9 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
updateRotation: =>
|
updateRotation: =>
|
||||||
value = parseInt(180 * (@rotationSlider.slider('value') - 50) / 50)
|
value = parseInt(180 * (@rotationSlider.slider('value') - 50) / 50)
|
||||||
@$el.find('.rotation-label').text " #{value}° "
|
@$el.find('.rotation-label').text " #{value}° "
|
||||||
if @currentSprite
|
if @currentLank
|
||||||
@currentSprite.rotation = value
|
@currentLank.rotation = value
|
||||||
@currentSprite.update(true)
|
@currentLank.update(true)
|
||||||
|
|
||||||
updateScale: =>
|
updateScale: =>
|
||||||
resValue = (@resolutionSlider.slider('value') + 1) / 10
|
resValue = (@resolutionSlider.slider('value') + 1) / 10
|
||||||
|
@ -313,9 +333,9 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
fixed = scaleValue.toFixed(1)
|
fixed = scaleValue.toFixed(1)
|
||||||
@scale = scaleValue
|
@scale = scaleValue
|
||||||
@$el.find('.scale-label').text " #{fixed}x "
|
@$el.find('.scale-label').text " #{fixed}x "
|
||||||
if @currentSprite
|
if @currentLank
|
||||||
@currentSprite.scaleFactorX = @currentSprite.scaleFactorY = scaleValue
|
@currentLank.scaleFactorX = @currentLank.scaleFactorY = scaleValue
|
||||||
@currentSprite.updateScale()
|
@currentLank.updateScale()
|
||||||
else if @currentObject?
|
else if @currentObject?
|
||||||
@currentObject.scaleX = @currentObject.scaleY = scaleValue / resValue
|
@currentObject.scaleX = @currentObject.scaleY = scaleValue / resValue
|
||||||
@updateGrid()
|
@updateGrid()
|
||||||
|
@ -332,7 +352,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
value = parseInt((@healthSlider.slider('value')) / 10)
|
value = parseInt((@healthSlider.slider('value')) / 10)
|
||||||
@$el.find('.health-label').text " #{value}hp "
|
@$el.find('.health-label').text " #{value}hp "
|
||||||
@mockThang.health = value
|
@mockThang.health = value
|
||||||
@currentSprite?.update()
|
@currentLank?.update()
|
||||||
|
|
||||||
# save
|
# save
|
||||||
|
|
||||||
|
@ -352,7 +372,7 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
url = "/editor/thang/#{newThangType.get('slug') or newThangType.id}"
|
url = "/editor/thang/#{newThangType.get('slug') or newThangType.id}"
|
||||||
portraitSource = null
|
portraitSource = null
|
||||||
if @thangType.get('raster')
|
if @thangType.get('raster')
|
||||||
image = @currentSprite.imageObject.image
|
image = @currentLank.sprite.image
|
||||||
portraitSource = imageToPortrait image
|
portraitSource = imageToPortrait image
|
||||||
# bit of a hacky way to get that portrait
|
# bit of a hacky way to get that portrait
|
||||||
success = =>
|
success = =>
|
||||||
|
@ -422,11 +442,11 @@ module.exports = class ThangTypeEditView extends RootView
|
||||||
bounds = obj.frameBounds[0]
|
bounds = obj.frameBounds[0]
|
||||||
obj.regX = bounds.x + bounds.width / 2
|
obj.regX = bounds.x + bounds.width / 2
|
||||||
obj.regY = bounds.y + bounds.height / 2
|
obj.regY = bounds.y + bounds.height / 2
|
||||||
@showImageObject(obj) if obj
|
@showSprite(obj) if obj
|
||||||
obj.y = 200 if obj # truly center the container
|
obj.y = 200 if obj # truly center the container
|
||||||
@showingSelectedNode = true
|
@showingSelectedNode = true
|
||||||
@currentSprite?.destroy()
|
@currentLank?.destroy()
|
||||||
@currentSprite = null
|
@currentLank = null
|
||||||
@updateScale()
|
@updateScale()
|
||||||
@grid.alpha = 0.0
|
@grid.alpha = 0.0
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
ModalView = require 'views/kinds/ModalView'
|
ModalView = require 'views/kinds/ModalView'
|
||||||
template = require 'templates/modal/wizard_settings'
|
template = require 'templates/modal/wizard_settings'
|
||||||
WizardSprite = require 'lib/surface/WizardSprite'
|
WizardLank = require 'lib/surface/WizardLank'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
{me} = require 'lib/auth'
|
{me} = require 'lib/auth'
|
||||||
forms = require 'lib/forms'
|
forms = require 'lib/forms'
|
||||||
|
|
|
@ -118,7 +118,7 @@ module.exports = class LevelHUDView extends CocoView
|
||||||
@listeningToCreateAvatar = true
|
@listeningToCreateAvatar = true
|
||||||
return
|
return
|
||||||
@listeningToCreateAvatar = false
|
@listeningToCreateAvatar = false
|
||||||
options = thang.getSpriteOptions() or {}
|
options = thang.getLankOptions() or {}
|
||||||
options.async = false
|
options.async = false
|
||||||
options.colorConfig = colorConfig if colorConfig
|
options.colorConfig = colorConfig if colorConfig
|
||||||
wrapper = @$el.find '.thang-canvas-wrapper'
|
wrapper = @$el.find '.thang-canvas-wrapper'
|
||||||
|
|
|
@ -36,7 +36,7 @@ module.exports = class ThangAvatarView extends CocoView
|
||||||
getRenderData: (context={}) ->
|
getRenderData: (context={}) ->
|
||||||
context = super context
|
context = super context
|
||||||
context.thang = @thang
|
context.thang = @thang
|
||||||
options = @thang?.getSpriteOptions() or {}
|
options = @thang?.getLankOptions() or {}
|
||||||
options.async = true
|
options.async = true
|
||||||
context.avatarURL = @thangType.getPortraitSource(options) unless @thangType.loading
|
context.avatarURL = @thangType.getPortraitSource(options) unless @thangType.loading
|
||||||
context.includeName = @includeName
|
context.includeName = @includeName
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
SpriteBoss = require 'lib/surface/SpriteBoss'
|
LankBoss = require 'lib/surface/LankBoss'
|
||||||
Camera = require 'lib/surface/Camera'
|
Camera = require 'lib/surface/Camera'
|
||||||
World = require 'lib/world/world'
|
World = require 'lib/world/world'
|
||||||
ThangType = require 'models/ThangType'
|
ThangType = require 'models/ThangType'
|
||||||
|
@ -8,8 +8,8 @@ munchkinData = require 'test/app/fixtures/ogre-munchkin-m.thang.type'
|
||||||
fangriderData = require 'test/app/fixtures/ogre-fangrider.thang.type'
|
fangriderData = require 'test/app/fixtures/ogre-fangrider.thang.type'
|
||||||
curseData = require 'test/app/fixtures/curse.thang.type'
|
curseData = require 'test/app/fixtures/curse.thang.type'
|
||||||
|
|
||||||
describe 'SpriteBoss', ->
|
describe 'LankBoss', ->
|
||||||
spriteBoss = null
|
lankBoss = null
|
||||||
canvas = null
|
canvas = null
|
||||||
stage = null
|
stage = null
|
||||||
midRenderExpectations = [] # bit of a hack to move tests which happen mid-initialization into a separate test
|
midRenderExpectations = [] # bit of a hack to move tests which happen mid-initialization into a separate test
|
||||||
|
@ -18,7 +18,7 @@ describe 'SpriteBoss', ->
|
||||||
# check the resulting data for the whole thing, without changing anything.
|
# check the resulting data for the whole thing, without changing anything.
|
||||||
|
|
||||||
init = (done) ->
|
init = (done) ->
|
||||||
return done() if spriteBoss
|
return done() if lankBoss
|
||||||
t = new Date()
|
t = new Date()
|
||||||
canvas = $('<canvas width="800" height="600"></canvas>')
|
canvas = $('<canvas width="800" height="600"></canvas>')
|
||||||
camera = new Camera(canvas)
|
camera = new Camera(canvas)
|
||||||
|
@ -45,7 +45,7 @@ describe 'SpriteBoss', ->
|
||||||
|
|
||||||
thangTypes = [fangrider, segmentedMunchkin, singularMunchkin, segmentedTree, singularTree]
|
thangTypes = [fangrider, segmentedMunchkin, singularMunchkin, segmentedTree, singularTree]
|
||||||
|
|
||||||
# Build the Stage and SpriteBoss.
|
# Build the Stage and LankBoss.
|
||||||
window.stage = stage = new createjs.SpriteStage(canvas[0])
|
window.stage = stage = new createjs.SpriteStage(canvas[0])
|
||||||
options = {
|
options = {
|
||||||
camera: camera
|
camera: camera
|
||||||
|
@ -55,9 +55,9 @@ describe 'SpriteBoss', ->
|
||||||
thangTypes: thangTypes
|
thangTypes: thangTypes
|
||||||
}
|
}
|
||||||
|
|
||||||
window.spriteBoss = spriteBoss = new SpriteBoss(options)
|
window.lankBoss = lankBoss = new LankBoss(options)
|
||||||
|
|
||||||
defaultLayer = spriteBoss.spriteLayers.Default
|
defaultLayer = lankBoss.layerAdapters.Default
|
||||||
defaultLayer.buildAsync = false # cause faster
|
defaultLayer.buildAsync = false # cause faster
|
||||||
|
|
||||||
# Sort of an implicit test. By default, all the default actions are always rendered,
|
# Sort of an implicit test. By default, all the default actions are always rendered,
|
||||||
|
@ -66,14 +66,14 @@ describe 'SpriteBoss', ->
|
||||||
defaultLayer.defaultActions = ['idle']
|
defaultLayer.defaultActions = ['idle']
|
||||||
|
|
||||||
# Render the simple world with just trees
|
# Render the simple world with just trees
|
||||||
spriteBoss.update(true)
|
lankBoss.update(true)
|
||||||
|
|
||||||
# Test that the unrendered, static sprites aren't showing anything
|
# Test that the unrendered, static sprites aren't showing anything
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Segmented Tree'].imageObject.children.length,1,'static segmented action'])
|
midRenderExpectations.push([lankBoss.lanks['Segmented Tree'].imageObject.children.length,1,'static segmented action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Segmented Tree'].imageObject.children[0].currentFrame,0,'static segmented action'])
|
midRenderExpectations.push([lankBoss.lanks['Segmented Tree'].imageObject.children[0].currentFrame,0,'static segmented action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Segmented Tree'].imageObject.children[0].paused,true,'static segmented action'])
|
midRenderExpectations.push([lankBoss.lanks['Segmented Tree'].imageObject.children[0].paused,true,'static segmented action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Singular Tree'].imageObject.currentFrame,0,'static singular action'])
|
midRenderExpectations.push([lankBoss.lanks['Singular Tree'].imageObject.currentFrame,0,'static singular action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Singular Tree'].imageObject.paused,true,'static singular action'])
|
midRenderExpectations.push([lankBoss.lanks['Singular Tree'].imageObject.paused,true,'static singular action'])
|
||||||
|
|
||||||
defaultLayer.once 'new-spritesheet', ->
|
defaultLayer.once 'new-spritesheet', ->
|
||||||
|
|
||||||
|
@ -101,15 +101,15 @@ describe 'SpriteBoss', ->
|
||||||
|
|
||||||
_.find(world.thangs, {id: 'Disappearing Tree'}).exists = false
|
_.find(world.thangs, {id: 'Disappearing Tree'}).exists = false
|
||||||
world.thangMap[thang.id] = thang for thang in world.thangs
|
world.thangMap[thang.id] = thang for thang in world.thangs
|
||||||
spriteBoss.update(true)
|
lankBoss.update(true)
|
||||||
jasmine.Ajax.requests.sendResponses({'/db/thang.type/curse': curseData})
|
jasmine.Ajax.requests.sendResponses({'/db/thang.type/curse': curseData})
|
||||||
|
|
||||||
# Test that the unrendered, animated sprites aren't showing anything
|
# Test that the unrendered, animated sprites aren't showing anything
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Segmented Ogre'].imageObject.children.length,10,'animated segmented action'])
|
midRenderExpectations.push([lankBoss.lanks['Segmented Ogre'].imageObject.children.length,10,'animated segmented action'])
|
||||||
for child in spriteBoss.sprites['Segmented Ogre'].imageObject.children
|
for child in lankBoss.lanks['Segmented Ogre'].imageObject.children
|
||||||
midRenderExpectations.push([child.children[0].currentFrame, 0, 'animated segmented action'])
|
midRenderExpectations.push([child.children[0].currentFrame, 0, 'animated segmented action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Singular Ogre'].imageObject.currentFrame,0,'animated singular action'])
|
midRenderExpectations.push([lankBoss.lanks['Singular Ogre'].imageObject.currentFrame,0,'animated singular action'])
|
||||||
midRenderExpectations.push([spriteBoss.sprites['Singular Ogre'].imageObject.paused,true,'animated singular action'])
|
midRenderExpectations.push([lankBoss.lanks['Singular Ogre'].imageObject.paused,true,'animated singular action'])
|
||||||
|
|
||||||
defaultLayer.once 'new-spritesheet', ->
|
defaultLayer.once 'new-spritesheet', ->
|
||||||
# showMe() # Uncomment to display this world when you run any of these tests.
|
# showMe() # Uncomment to display this world when you run any of these tests.
|
||||||
|
@ -127,7 +127,7 @@ describe 'SpriteBoss', ->
|
||||||
return if ticks >= 100
|
return if ticks >= 100
|
||||||
ticks += 1
|
ticks += 1
|
||||||
if ticks % 20 is 0
|
if ticks % 20 is 0
|
||||||
spriteBoss.update(true)
|
lankBoss.update(true)
|
||||||
stage.update()
|
stage.update()
|
||||||
}
|
}
|
||||||
createjs.Ticker.addEventListener "tick", listener
|
createjs.Ticker.addEventListener "tick", listener
|
||||||
|
@ -140,43 +140,43 @@ describe 'SpriteBoss', ->
|
||||||
expect(expectation[0]).toBe(expectation[1])
|
expect(expectation[0]).toBe(expectation[1])
|
||||||
|
|
||||||
it 'rotates and animates sprites according to thang rotation', ->
|
it 'rotates and animates sprites according to thang rotation', ->
|
||||||
expect(spriteBoss.sprites['Ogre N'].imageObject.currentAnimation).toBe('move_fore')
|
expect(lankBoss.lanks['Ogre N'].imageObject.currentAnimation).toBe('move_fore')
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.currentAnimation).toBe('move_side')
|
expect(lankBoss.lanks['Ogre E'].imageObject.currentAnimation).toBe('move_side')
|
||||||
expect(spriteBoss.sprites['Ogre W'].imageObject.currentAnimation).toBe('move_side')
|
expect(lankBoss.lanks['Ogre W'].imageObject.currentAnimation).toBe('move_side')
|
||||||
expect(spriteBoss.sprites['Ogre S'].imageObject.currentAnimation).toBe('move_back')
|
expect(lankBoss.lanks['Ogre S'].imageObject.currentAnimation).toBe('move_back')
|
||||||
|
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.scaleX).toBeLessThan(0)
|
expect(lankBoss.lanks['Ogre E'].imageObject.scaleX).toBeLessThan(0)
|
||||||
expect(spriteBoss.sprites['Ogre W'].imageObject.scaleX).toBeGreaterThan(0)
|
expect(lankBoss.lanks['Ogre W'].imageObject.scaleX).toBeGreaterThan(0)
|
||||||
|
|
||||||
it 'positions sprites according to thang pos', ->
|
it 'positions sprites according to thang pos', ->
|
||||||
expect(spriteBoss.sprites['Ogre N'].imageObject.x).toBe(0)
|
expect(lankBoss.lanks['Ogre N'].imageObject.x).toBe(0)
|
||||||
expect(spriteBoss.sprites['Ogre N'].imageObject.y).toBeCloseTo(-60)
|
expect(lankBoss.lanks['Ogre N'].imageObject.y).toBeCloseTo(-60)
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.x).toBeCloseTo(80)
|
expect(lankBoss.lanks['Ogre E'].imageObject.x).toBeCloseTo(80)
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.y).toBe(0)
|
expect(lankBoss.lanks['Ogre E'].imageObject.y).toBe(0)
|
||||||
expect(spriteBoss.sprites['Ogre W'].imageObject.x).toBe(-80)
|
expect(lankBoss.lanks['Ogre W'].imageObject.x).toBe(-80)
|
||||||
expect(spriteBoss.sprites['Ogre W'].imageObject.y).toBeCloseTo(0)
|
expect(lankBoss.lanks['Ogre W'].imageObject.y).toBeCloseTo(0)
|
||||||
expect(spriteBoss.sprites['Ogre S'].imageObject.x).toBe(0)
|
expect(lankBoss.lanks['Ogre S'].imageObject.x).toBe(0)
|
||||||
expect(spriteBoss.sprites['Ogre S'].imageObject.y).toBeCloseTo(60)
|
expect(lankBoss.lanks['Ogre S'].imageObject.y).toBeCloseTo(60)
|
||||||
|
|
||||||
it 'scales sprites according to thang scaleFactorX and scaleFactorY', ->
|
it 'scales sprites according to thang scaleFactorX and scaleFactorY', ->
|
||||||
expect(spriteBoss.sprites['Ogre N'].imageObject.scaleX).toBe(spriteBoss.sprites['Ogre N'].imageObject.baseScaleX * 1.5)
|
expect(lankBoss.lanks['Ogre N'].imageObject.scaleX).toBe(lankBoss.lanks['Ogre N'].imageObject.baseScaleX * 1.5)
|
||||||
expect(spriteBoss.sprites['Ogre W'].imageObject.scaleY).toBe(spriteBoss.sprites['Ogre N'].imageObject.baseScaleY * 1.5)
|
expect(lankBoss.lanks['Ogre W'].imageObject.scaleY).toBe(lankBoss.lanks['Ogre N'].imageObject.baseScaleY * 1.5)
|
||||||
|
|
||||||
it 'sets alpha based on thang alpha', ->
|
it 'sets alpha based on thang alpha', ->
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.alpha).toBe(0.5)
|
expect(lankBoss.lanks['Ogre E'].imageObject.alpha).toBe(0.5)
|
||||||
|
|
||||||
it 'orders sprites in the layer based on thang pos.y\'s', ->
|
it 'orders sprites in the layer based on thang pos.y\'s', ->
|
||||||
container = spriteBoss.spriteLayers.Default.container
|
container = lankBoss.layerAdapters.Default.container
|
||||||
l = container.children
|
l = container.children
|
||||||
i1 = container.getChildIndex(_.find(container.children, (c) -> c.sprite.thang.id is 'Dying Ogre 1'))
|
i1 = container.getChildIndex(_.find(container.children, (c) -> c.lank.thang.id is 'Dying Ogre 1'))
|
||||||
i2 = container.getChildIndex(_.find(container.children, (c) -> c.sprite.thang.id is 'Dying Ogre 2'))
|
i2 = container.getChildIndex(_.find(container.children, (c) -> c.lank.thang.id is 'Dying Ogre 2'))
|
||||||
i3 = container.getChildIndex(_.find(container.children, (c) -> c.sprite.thang.id is 'Dying Ogre 3'))
|
i3 = container.getChildIndex(_.find(container.children, (c) -> c.lank.thang.id is 'Dying Ogre 3'))
|
||||||
i4 = container.getChildIndex(_.find(container.children, (c) -> c.sprite.thang.id is 'Dying Ogre 4'))
|
i4 = container.getChildIndex(_.find(container.children, (c) -> c.lank.thang.id is 'Dying Ogre 4'))
|
||||||
expect(i1).toBeGreaterThan(i2)
|
expect(i1).toBeGreaterThan(i2)
|
||||||
expect(i2).toBeGreaterThan(i3)
|
expect(i2).toBeGreaterThan(i3)
|
||||||
expect(i3).toBeGreaterThan(i4)
|
expect(i3).toBeGreaterThan(i4)
|
||||||
|
|
||||||
it 'only contains children Sprites and SpriteContainers whose spritesheet matches the Layer', ->
|
it 'only contains children Sprites and SpriteContainers whose spritesheet matches the Layer', ->
|
||||||
defaultLayerContainer = spriteBoss.spriteLayers.Default.container
|
defaultLayerContainer = lankBoss.layerAdapters.Default.container
|
||||||
for c in defaultLayerContainer.children
|
for c in defaultLayerContainer.children
|
||||||
expect(c.spriteSheet).toBe(defaultLayerContainer.spriteSheet)
|
expect(c.spriteSheet).toBe(defaultLayerContainer.spriteSheet)
|
Loading…
Reference in a new issue