mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Integrated WebGLLayer and WebGLSprite with CocoSprite.
Disabled some features in CocoSprite that'll have to be added back later. Moved more logic from CocoSprite, like determining registration points for a given animation, to WebGLSprite. WebGLSprite can now display either rendering containers or SpriteSheets.
This commit is contained in:
parent
9343d1e645
commit
1ef3d150a8
6 changed files with 377 additions and 229 deletions
|
@ -28,7 +28,6 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
groundLayer: null
|
||||
textLayer: null
|
||||
floatingLayer: null
|
||||
frameRateFactor: 1 # TODO: use or lose?
|
||||
thang: null
|
||||
camera: null
|
||||
spriteSheetCache: null
|
||||
|
@ -79,110 +78,60 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@handledDisplayEvents = {}
|
||||
@age = 0
|
||||
@stillLoading = true
|
||||
# if @thangType.isFullyLoaded()
|
||||
# @setUpSprite()
|
||||
# else
|
||||
# @thangType.setProjection null
|
||||
# @thangType.fetch() unless @thangType.loading
|
||||
# @listenToOnce(@thangType, 'sync', @setUpSprite)
|
||||
# @setUpPlaceholder()
|
||||
if @thangType.isFullyLoaded() then @onThangTypeLoaded() else @listenToOnce(@thangType, 'sync', @onThangTypeLoaded)
|
||||
|
||||
setUpSprite: ->
|
||||
toString: -> "<CocoSprite: #{@thang?.id}>"
|
||||
|
||||
onThangTypeLoaded: ->
|
||||
@stillLoading = false
|
||||
for trigger, sounds of @thangType.get('soundTriggers') or {} when trigger isnt 'say'
|
||||
AudioPlayer.preloadSoundReference sound for sound in sounds
|
||||
if @thangType.get('raster')
|
||||
@stillLoading = false
|
||||
@actions = {}
|
||||
@isRaster = true
|
||||
@setUpRasterImage()
|
||||
else
|
||||
result = @buildSpriteSheet()
|
||||
if _.isString result # async build
|
||||
@listenToOnce @thangType, 'build-complete', @setUpSprite
|
||||
@setUpPlaceholder()
|
||||
else
|
||||
@stillLoading = false
|
||||
@actions = @thangType.getActions()
|
||||
@buildFromSpriteSheet result
|
||||
@createMarks()
|
||||
@queueAction 'idle'
|
||||
@actions = @thangType.getActions()
|
||||
@createMarks()
|
||||
@queueAction 'idle'
|
||||
|
||||
finishSetup: ->
|
||||
@placeholder = null
|
||||
@updateBaseScale()
|
||||
@scaleFactorX = @thang.scaleFactorX if @thang?.scaleFactorX?
|
||||
@scaleFactorX = @thang.scaleFactor if @thang?.scaleFactor?
|
||||
@scaleFactorY = @thang.scaleFactorY if @thang?.scaleFactorY?
|
||||
@scaleFactorY = @thang.scaleFactor if @thang?.scaleFactor?
|
||||
@update true # Reflect initial scale and other state
|
||||
|
||||
setUpRasterImage: ->
|
||||
raster = @thangType.get('raster')
|
||||
image = new createjs.Bitmap('/file/'+raster)
|
||||
@setImageObject image
|
||||
$(image.image).one 'load', => @updateScale?()
|
||||
@configureMouse()
|
||||
@imageObject.sprite = @
|
||||
@imageObject.layerPriority = @thang?.layerPriority ? @thangType.get 'layerPriority'
|
||||
@imageObject.name = @thang?.spriteName or @thangType.get 'name'
|
||||
reg = @getOffset 'registration'
|
||||
@imageObject.regX = -reg.x
|
||||
@imageObject.regY = -reg.y
|
||||
@finishSetup()
|
||||
|
||||
setUpPlaceholder: ->
|
||||
return if @placeholder or not @thang
|
||||
shape = new createjs.Shape()
|
||||
width = @thang.width * Camera.PPM
|
||||
height = @thang.height * Camera.PPM * @options.camera.y2x
|
||||
depth = @thang.depth * Camera.PPM * @options.camera.z2y * @options.camera.y2x
|
||||
brightnessFuzzFactor = 1 + 0.1 * (Math.random() - 0.5)
|
||||
makeColor = (brightnessFactor) => (Math.round(c * brightnessFuzzFactor * brightnessFactor) for c in (healthColors[@thang.team] ? [180, 180, 180]))
|
||||
topColor = "rgba(#{makeColor(0.85).join(', ')},1)"
|
||||
mainColor = "rgba(#{makeColor(0.75).join(', ')},1)"
|
||||
ellipse = @thang.shape in ['ellipsoid', 'disc']
|
||||
fn = if ellipse then 'drawEllipse' else 'drawRect'
|
||||
shape.graphics.beginFill(mainColor)[fn](-width / 2, -height / 2, width, height).endFill()
|
||||
if ellipse
|
||||
shape.graphics.moveTo(-width / 2, 0).beginFill(mainColor).lineTo(-width / 2, -depth).lineTo(width / 2, -depth).lineTo(width / 2, 0).lineTo(-width / 2, 0).endFill()
|
||||
else
|
||||
shape.graphics.moveTo(-width / 2, 0).beginFill(mainColor).lineTo(-width / 2, -depth).lineTo(width / 2, -depth).lineTo(width / 2, 0).lineTo(-width / 2, 0).endFill()
|
||||
shape.graphics.beginFill(topColor)[fn](-width / 2, -height / 2 - depth, width, height).endFill()
|
||||
shape.layerPriority = @thang?.layerPriority ? @thangType.get 'layerPriority'
|
||||
@setImageObject shape
|
||||
@updatePosition true
|
||||
@placeholder = shape
|
||||
|
||||
toString: -> "<CocoSprite: #{@thang?.id}>"
|
||||
|
||||
buildSpriteSheet: ->
|
||||
options = _.extend @options, @thang?.getSpriteOptions?() ? {}
|
||||
options.colorConfig = @options.colorConfig if @options.colorConfig
|
||||
options.async = @options.async
|
||||
@thangType.getSpriteSheet options
|
||||
|
||||
setImageObject: (newImageObject) ->
|
||||
if parent = @imageObject?.parent
|
||||
parent.removeChild @imageObject
|
||||
parent.addChild newImageObject
|
||||
parent.updateLayerOrder()
|
||||
if @imageObject
|
||||
@imageObject.removeAllEventListeners()
|
||||
if parent = @imageObject.parent
|
||||
parent.removeChild @imageObject
|
||||
parent.addChild newImageObject
|
||||
parent.updateLayerOrder()
|
||||
@imageObject = newImageObject
|
||||
|
||||
buildFromSpriteSheet: (spriteSheet) ->
|
||||
if spriteSheet
|
||||
sprite = new createjs.Sprite(spriteSheet)
|
||||
else
|
||||
sprite = new createjs.Shape()
|
||||
|
||||
@setImageObject sprite
|
||||
@addHealthBar()
|
||||
@configureMouse()
|
||||
# TODO: generalize this later?
|
||||
@imageObject.sprite = @
|
||||
@imageObject.layerPriority = @thang?.layerPriority ? @thangType.get 'layerPriority'
|
||||
@imageObject.name = @thang?.spriteName or @thangType.get 'name'
|
||||
@imageObject.on 'animationend', @playNextAction
|
||||
@finishSetup()
|
||||
|
||||
|
||||
# TODO: figure out how to do placeholders again
|
||||
# setUpPlaceholder: ->
|
||||
# return if @placeholder or not @thang
|
||||
# shape = new createjs.Shape()
|
||||
# width = @thang.width * Camera.PPM
|
||||
# height = @thang.height * Camera.PPM * @options.camera.y2x
|
||||
# depth = @thang.depth * Camera.PPM * @options.camera.z2y * @options.camera.y2x
|
||||
# brightnessFuzzFactor = 1 + 0.1 * (Math.random() - 0.5)
|
||||
# makeColor = (brightnessFactor) => (Math.round(c * brightnessFuzzFactor * brightnessFactor) for c in (healthColors[@thang.team] ? [180, 180, 180]))
|
||||
# topColor = "rgba(#{makeColor(0.85).join(', ')},1)"
|
||||
# mainColor = "rgba(#{makeColor(0.75).join(', ')},1)"
|
||||
# ellipse = @thang.shape in ['ellipsoid', 'disc']
|
||||
# fn = if ellipse then 'drawEllipse' else 'drawRect'
|
||||
# shape.graphics.beginFill(mainColor)[fn](-width / 2, -height / 2, width, height).endFill()
|
||||
# shape.graphics.moveTo(-width / 2, 0).beginFill(mainColor).lineTo(-width / 2, -depth).lineTo(width / 2, -depth).lineTo(width / 2, 0).lineTo(-width / 2, 0).endFill()
|
||||
# shape.graphics.beginFill(topColor)[fn](-width / 2, -height / 2 - depth, width, height).endFill()
|
||||
# shape.layerPriority = @thang?.layerPriority ? @thangType.get 'layerPriority'
|
||||
# @setImageObject shape
|
||||
# @updatePosition true
|
||||
# @placeholder = shape
|
||||
|
||||
##################################################
|
||||
# QUEUEING AND PLAYING ACTIONS
|
||||
|
@ -214,14 +163,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@updateBaseScale()
|
||||
return @updateActionDirection() unless action.animation or action.container
|
||||
m = if action.container then 'gotoAndStop' else 'gotoAndPlay'
|
||||
@imageObject.framerate = action.framerate or 20
|
||||
@imageObject[m] action.name
|
||||
reg = @getOffset 'registration'
|
||||
@imageObject.regX = -reg.x
|
||||
@imageObject.regY = -reg.y
|
||||
if @currentRootAction.name is 'move' and action.frames
|
||||
start = Math.floor(Math.random() * action.frames.length)
|
||||
@imageObject.currentAnimationFrame = start
|
||||
@imageObject[m]?(action.name)
|
||||
|
||||
hide: ->
|
||||
@hiding = true
|
||||
|
@ -261,66 +203,69 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@updateLabels()
|
||||
|
||||
showAreaOfEffects: ->
|
||||
return unless @thang?.currentEvents
|
||||
for event in @thang.currentEvents
|
||||
continue unless event.startsWith 'aoe-'
|
||||
continue if @handledDisplayEvents[event]
|
||||
|
||||
@handledDisplayEvents[event] = true
|
||||
args = JSON.parse(event[4...])
|
||||
pos = @options.camera.worldToSurface {x: args[0], y: args[1]}
|
||||
circle = new createjs.Shape()
|
||||
radius = args[2] * Camera.PPM
|
||||
if args.length is 4
|
||||
circle.graphics.beginFill(args[3]).drawCircle(0, 0, radius)
|
||||
else
|
||||
startAngle = args[4]
|
||||
endAngle = args[5]
|
||||
circle.graphics.beginFill(args[3])
|
||||
.lineTo(0, 0)
|
||||
.lineTo(radius * Math.cos(startAngle), radius * Math.sin(startAngle))
|
||||
.arc(0, 0, radius, startAngle, endAngle)
|
||||
.lineTo(0, 0)
|
||||
circle.x = pos.x
|
||||
circle.y = pos.y
|
||||
circle.scaleY = @options.camera.y2x * 0.7
|
||||
circle.scaleX = 0.7
|
||||
circle.alpha = 0.2
|
||||
circle
|
||||
@options.groundLayer.addChild circle
|
||||
createjs.Tween.get(circle)
|
||||
.to({alpha: 0.6, scaleY: @options.camera.y2x, scaleX: 1}, 100, createjs.Ease.circOut)
|
||||
.to({alpha: 0, scaleY: 0, scaleX: 0}, 700, createjs.Ease.circIn)
|
||||
.call =>
|
||||
return if @destroyed
|
||||
@options.groundLayer.removeChild circle
|
||||
delete @handledDisplayEvents[event]
|
||||
# TODO: add back area of effects
|
||||
# return unless @thang?.currentEvents
|
||||
# for event in @thang.currentEvents
|
||||
# continue unless event.startsWith 'aoe-'
|
||||
# continue if @handledDisplayEvents[event]
|
||||
#
|
||||
# @handledDisplayEvents[event] = true
|
||||
# args = JSON.parse(event[4...])
|
||||
# pos = @options.camera.worldToSurface {x: args[0], y: args[1]}
|
||||
# circle = new createjs.Shape()
|
||||
# radius = args[2] * Camera.PPM
|
||||
# if args.length is 4
|
||||
# circle.graphics.beginFill(args[3]).drawCircle(0, 0, radius)
|
||||
# else
|
||||
# startAngle = args[4]
|
||||
# endAngle = args[5]
|
||||
# circle.graphics.beginFill(args[3])
|
||||
# .lineTo(0, 0)
|
||||
# .lineTo(radius * Math.cos(startAngle), radius * Math.sin(startAngle))
|
||||
# .arc(0, 0, radius, startAngle, endAngle)
|
||||
# .lineTo(0, 0)
|
||||
# circle.x = pos.x
|
||||
# circle.y = pos.y
|
||||
# circle.scaleY = @options.camera.y2x * 0.7
|
||||
# circle.scaleX = 0.7
|
||||
# circle.alpha = 0.2
|
||||
# circle
|
||||
# @options.groundLayer.addChild circle
|
||||
# createjs.Tween.get(circle)
|
||||
# .to({alpha: 0.6, scaleY: @options.camera.y2x, scaleX: 1}, 100, createjs.Ease.circOut)
|
||||
# .to({alpha: 0, scaleY: 0, scaleX: 0}, 700, createjs.Ease.circIn)
|
||||
# .call =>
|
||||
# return if @destroyed
|
||||
# @options.groundLayer.removeChild circle
|
||||
# delete @handledDisplayEvents[event]
|
||||
|
||||
showTextEvents: ->
|
||||
return unless @thang?.currentEvents
|
||||
for event in @thang.currentEvents
|
||||
continue unless event.startsWith 'text-'
|
||||
continue if @handledDisplayEvents[event]
|
||||
@handledDisplayEvents[event] = true
|
||||
options = JSON.parse(event[5...])
|
||||
label = new createjs.Text options.text, "bold #{options.size or 16}px Arial", options.color or '#FFF'
|
||||
shadowColor = {humans: '#F00', ogres: '#00F', neutral: '#0F0', common: '#0F0'}[@thang.team] ? '#000'
|
||||
label.shadow = new createjs.Shadow shadowColor, 1, 1, 3
|
||||
offset = @getOffset 'aboveHead'
|
||||
[label.x, label.y] = [@imageObject.x + offset.x - label.getMeasuredWidth() / 2, @imageObject.y + offset.y]
|
||||
@options.floatingLayer.addChild label
|
||||
window.labels ?= []
|
||||
window.labels.push label
|
||||
label.alpha = 0
|
||||
createjs.Tween.get(label)
|
||||
.to({y: label.y-2, alpha: 1}, 200, createjs.Ease.linear)
|
||||
.to({y: label.y-12}, 1000, createjs.Ease.linear)
|
||||
.to({y: label.y-22, alpha: 0}, 1000, createjs.Ease.linear)
|
||||
.call =>
|
||||
return if @destroyed
|
||||
@options.floatingLayer.removeChild label
|
||||
# TODO: Add back text events
|
||||
# return unless @thang?.currentEvents
|
||||
# for event in @thang.currentEvents
|
||||
# continue unless event.startsWith 'text-'
|
||||
# continue if @handledDisplayEvents[event]
|
||||
# @handledDisplayEvents[event] = true
|
||||
# options = JSON.parse(event[5...])
|
||||
# label = new createjs.Text options.text, "bold #{options.size or 16}px Arial", options.color or '#FFF'
|
||||
# shadowColor = {humans: '#F00', ogres: '#00F', neutral: '#0F0', common: '#0F0'}[@thang.team] ? '#000'
|
||||
# label.shadow = new createjs.Shadow shadowColor, 1, 1, 3
|
||||
# offset = @getOffset 'aboveHead'
|
||||
# [label.x, label.y] = [@imageObject.x + offset.x - label.getMeasuredWidth() / 2, @imageObject.y + offset.y]
|
||||
# @options.floatingLayer.addChild label
|
||||
# window.labels ?= []
|
||||
# window.labels.push label
|
||||
# label.alpha = 0
|
||||
# createjs.Tween.get(label)
|
||||
# .to({y: label.y-2, alpha: 1}, 200, createjs.Ease.linear)
|
||||
# .to({y: label.y-12}, 1000, createjs.Ease.linear)
|
||||
# .to({y: label.y-22, alpha: 0}, 1000, createjs.Ease.linear)
|
||||
# .call =>
|
||||
# return if @destroyed
|
||||
# @options.floatingLayer.removeChild label
|
||||
|
||||
cache: ->
|
||||
return # TODO: get rid of caching
|
||||
bounds = @imageObject.getBounds()
|
||||
@imageObject.cache 0, 0, bounds.width, bounds.height
|
||||
#console.log 'just cached', @thang.id, 'which was at', @imageObject.x, @imageObject.y, bounds.width, bounds.height, 'with scale', Math.max(@imageObject.scaleX, @imageObject.scaleY)
|
||||
|
@ -554,14 +499,15 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
Backbone.Mediator.publish ourEventName, newEvent
|
||||
|
||||
addHealthBar: ->
|
||||
return unless @thang?.health? and 'health' in (@thang?.hudProperties ? []) and @options.floatingLayer
|
||||
healthColor = healthColors[@thang?.team] ? healthColors['neutral']
|
||||
healthOffset = @getOffset 'aboveHead'
|
||||
bar = @healthBar = createProgressBar(healthColor, healthOffset)
|
||||
bar.name = 'health bar'
|
||||
bar.cache 0, -bar.height * bar.baseScale / 2, bar.width * bar.baseScale, bar.height * bar.baseScale
|
||||
@options.floatingLayer.addChild bar
|
||||
@updateHealthBar()
|
||||
# TODO: Put back in health bars
|
||||
# return unless @thang?.health? and 'health' in (@thang?.hudProperties ? []) and @options.floatingLayer
|
||||
# healthColor = healthColors[@thang?.team] ? healthColors['neutral']
|
||||
# healthOffset = @getOffset 'aboveHead'
|
||||
# bar = @healthBar = createProgressBar(healthColor, healthOffset)
|
||||
# bar.name = 'health bar'
|
||||
# bar.cache 0, -bar.height * bar.baseScale / 2, bar.width * bar.baseScale, bar.height * bar.baseScale
|
||||
# @options.floatingLayer.addChild bar
|
||||
# @updateHealthBar()
|
||||
|
||||
getActionProp: (prop, subProp, def=null) ->
|
||||
# Get a property or sub-property from an action, falling back to ThangType
|
||||
|
@ -629,29 +575,30 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@updateEffectMarks() if @thang?.effectNames?.length or @previousEffectNames?.length
|
||||
|
||||
updateEffectMarks: ->
|
||||
return if _.isEqual @thang.effectNames, @previousEffectNames
|
||||
return if @stopped
|
||||
for effect in @thang.effectNames
|
||||
mark = @addMark effect, @options.floatingLayer, effect
|
||||
mark.statusEffect = true
|
||||
mark.toggle 'on'
|
||||
mark.show()
|
||||
|
||||
if @previousEffectNames
|
||||
for effect in @previousEffectNames
|
||||
continue if effect in @thang.effectNames
|
||||
mark = @marks[effect]
|
||||
mark.toggle false
|
||||
|
||||
if @thang.effectNames.length > 1 and not @effectInterval
|
||||
@rotateEffect()
|
||||
@effectInterval = setInterval @rotateEffect, 1500
|
||||
|
||||
else if @effectInterval and @thang.effectNames.length <= 1
|
||||
clearInterval @effectInterval
|
||||
@effectInterval = null
|
||||
|
||||
@previousEffectNames = @thang.effectNames
|
||||
# TODO: get effect marks working again
|
||||
# return if _.isEqual @thang.effectNames, @previousEffectNames
|
||||
# return if @stopped
|
||||
# for effect in @thang.effectNames
|
||||
# mark = @addMark effect, @options.floatingLayer, effect
|
||||
# mark.statusEffect = true
|
||||
# mark.toggle 'on'
|
||||
# mark.show()
|
||||
#
|
||||
# if @previousEffectNames
|
||||
# for effect in @previousEffectNames
|
||||
# continue if effect in @thang.effectNames
|
||||
# mark = @marks[effect]
|
||||
# mark.toggle false
|
||||
#
|
||||
# if @thang.effectNames.length > 1 and not @effectInterval
|
||||
# @rotateEffect()
|
||||
# @effectInterval = setInterval @rotateEffect, 1500
|
||||
#
|
||||
# else if @effectInterval and @thang.effectNames.length <= 1
|
||||
# clearInterval @effectInterval
|
||||
# @effectInterval = null
|
||||
#
|
||||
# @previousEffectNames = @thang.effectNames
|
||||
|
||||
rotateEffect: =>
|
||||
effects = (m.name for m in _.values(@marks) when m.on and m.statusEffect and m.mark)
|
||||
|
@ -663,9 +610,10 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@marks[effects[@effectIndex]].show()
|
||||
|
||||
setHighlight: (to, delay) ->
|
||||
@addMark 'highlight', @options.floatingLayer, 'highlight' if to
|
||||
@marks.highlight?.highlightDelay = delay
|
||||
@marks.highlight?.toggle to and not @dimmed
|
||||
# TODO: get highlights working again
|
||||
# @addMark 'highlight', @options.floatingLayer, 'highlight' if to
|
||||
# @marks.highlight?.highlightDelay = delay
|
||||
# @marks.highlight?.toggle to and not @dimmed
|
||||
|
||||
setDimmed: (@dimmed) ->
|
||||
@marks.highlight?.toggle @marks.highlight.on and not @dimmed
|
||||
|
@ -674,15 +622,17 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@options.thang = @thang
|
||||
|
||||
setDebug: (debug) ->
|
||||
return unless @thang?.collides and @options.camera?
|
||||
@addMark 'debug', @options.floatingLayer if debug
|
||||
@marks.debug?.toggle debug
|
||||
# TODO: get debugging shapes working again
|
||||
# return unless @thang?.collides and @options.camera?
|
||||
# @addMark 'debug', @options.floatingLayer if debug
|
||||
# @marks.debug?.toggle debug
|
||||
|
||||
addLabel: (name, style) ->
|
||||
@labels[name] ?= new Label sprite: @, camera: @options.camera, layer: @options.textLayer, style: style
|
||||
@labels[name]
|
||||
|
||||
addMark: (name, layer, thangType=null) ->
|
||||
return # TODO: figure out how to recreate marks
|
||||
@marks[name] ?= new Mark name: name, sprite: @, camera: @options.camera, layer: layer ? @options.groundLayer, thangType: thangType
|
||||
@marks[name]
|
||||
|
||||
|
|
|
@ -1,19 +1,31 @@
|
|||
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
||||
CocoClass = require 'lib/CocoClass'
|
||||
WebGLSprite = require './WebGLSprite'
|
||||
|
||||
module.exports = class WebGLLayer extends CocoClass # createjs.SpriteContainer
|
||||
|
||||
_.extend(WebGLLayer.prototype, Backbone.Events)
|
||||
|
||||
module.exports = class WebGLLayer extends createjs.SpriteContainer
|
||||
|
||||
actionRenderState: null
|
||||
needToRerender: false
|
||||
toRenderBundles: null
|
||||
willRender: false
|
||||
buildAutomatically: true
|
||||
buildAsync: true
|
||||
resolutionFactor: SPRITE_RESOLUTION_FACTOR
|
||||
defaultActions: ['idle', 'die', 'move', 'move_back', 'move_side', 'move_fore', 'attack']
|
||||
numThingsLoading: 0
|
||||
cocoSprites: null
|
||||
spriteSheet: null
|
||||
spriteContainer: null
|
||||
|
||||
constructor: ->
|
||||
super(arguments...)
|
||||
@spriteSheet = @_renderNewSpriteSheet(false) # builds an empty spritesheet
|
||||
@spriteContainer = new createjs.SpriteContainer(@spriteSheet)
|
||||
@actionRenderState = {}
|
||||
@toRenderBundles = []
|
||||
@initialize(arguments...)
|
||||
@cocoSprites = []
|
||||
|
||||
setDefaultActions: (@defaultActions) ->
|
||||
|
||||
|
@ -25,24 +37,54 @@ module.exports = class WebGLLayer extends createjs.SpriteContainer
|
|||
key
|
||||
|
||||
addCocoSprite: (cocoSprite) ->
|
||||
# build the animations for it
|
||||
@cocoSprites.push cocoSprite
|
||||
@loadThangType(cocoSprite.thangType)
|
||||
@addDefaultActionsToRender(cocoSprite)
|
||||
@setImageObjectToCocoSprite(cocoSprite)
|
||||
# TODO: actually add it as a child
|
||||
|
||||
loadThangType: (thangType) ->
|
||||
if not thangType.isFullyLoaded()
|
||||
thangType.setProjection null
|
||||
thangType.fetch() unless thangType.loading
|
||||
@numThingsLoading++
|
||||
@listenToOnce(thangType, 'sync', @somethingLoaded)
|
||||
else if thangType.get('raster') and not thangType.loadedRaster
|
||||
thangType.loadRasterImage()
|
||||
@listenToOnce(thangType, 'raster-image-loaded', @somethingLoaded)
|
||||
@numThingsLoading++
|
||||
|
||||
somethingLoaded: (thangType) ->
|
||||
@numThingsLoading--
|
||||
@loadThangType(thangType) # might need to load the raster image object
|
||||
for cocoSprite in @cocoSprites
|
||||
if cocoSprite.thangType is thangType
|
||||
@addDefaultActionsToRender(cocoSprite)
|
||||
@renderNewSpriteSheet()
|
||||
|
||||
addDefaultActionsToRender: (cocoSprite) ->
|
||||
if cocoSprite.thangType.get('raster')
|
||||
@upsertActionToRender(cocoSprite.thangType)
|
||||
else
|
||||
for action in _.values(cocoSprite.thangType.getActions())
|
||||
continue unless action.name in @defaultActions
|
||||
@upsertActionToRender(cocoSprite.thangType, action.name, cocoSprite.options.colorConfig)
|
||||
|
||||
|
||||
upsertActionToRender: (thangType, actionName, colorConfig) ->
|
||||
groupKey = @renderGroupingKey(thangType, actionName, colorConfig)
|
||||
return if @actionRenderState[groupKey] isnt undefined
|
||||
@actionRenderState[groupKey] = 'need-to-render'
|
||||
@toRenderBundles.push({thangType: thangType, actionName: actionName, colorConfig: colorConfig})
|
||||
return if @willRender
|
||||
# @willRender = _.defer => @renderNewSpriteSheet()
|
||||
return if @willRender or not @buildAutomatically
|
||||
@willRender = _.defer => @renderNewSpriteSheet()
|
||||
|
||||
renderNewSpriteSheet: ->
|
||||
@willRender = false
|
||||
return if @numThingsLoading
|
||||
@_renderNewSpriteSheet()
|
||||
|
||||
_renderNewSpriteSheet: (async) ->
|
||||
async ?= @buildAsync
|
||||
builder = new createjs.SpriteSheetBuilder()
|
||||
groups = _.groupBy(@toRenderBundles, ((bundle) -> @renderGroupingKey(bundle.thangType, '', bundle.colorConfig)), @)
|
||||
for bundleGrouping in _.values(groups)
|
||||
|
@ -57,7 +99,20 @@ module.exports = class WebGLLayer extends createjs.SpriteContainer
|
|||
@renderSpriteSheet(args...)
|
||||
else
|
||||
@renderRasterImage(thangType, builder)
|
||||
builder.build()
|
||||
|
||||
if not _.size(groups)
|
||||
emptiness = new createjs.Container()
|
||||
emptiness.setBounds(0, 0, 1, 1)
|
||||
builder.addFrame(emptiness)
|
||||
|
||||
if async
|
||||
builder.buildAsync()
|
||||
builder.on 'complete', @onBuildSpriteSheetComplete, @, true, builder
|
||||
else
|
||||
builder.build()
|
||||
|
||||
onBuildSpriteSheetComplete: (e, builder) ->
|
||||
console.log 'done?', builder.spriteSheet
|
||||
|
||||
renderContainers: (thangType, colorConfig, actionNames, spriteSheetBuilder) ->
|
||||
containersToRender = {}
|
||||
|
@ -146,4 +201,26 @@ module.exports = class WebGLLayer extends createjs.SpriteContainer
|
|||
bm = new createjs.Bitmap(thangType.rasterImage[0])
|
||||
scale = thangType.get('scale') or 1
|
||||
frame = spriteSheetBuilder.addFrame(bm, null, scale)
|
||||
spriteSheetBuilder.addAnimation(@renderGroupingKey(thangType), [frame], false)
|
||||
spriteSheetBuilder.addAnimation(@renderGroupingKey(thangType), [frame], false)
|
||||
|
||||
setImageObjectToCocoSprite: (cocoSprite) ->
|
||||
if not cocoSprite.thangType.isFullyLoaded()
|
||||
# just give a placeholder
|
||||
sprite = new createjs.Sprite(@spriteSheet)
|
||||
|
||||
else if cocoSprite.thangType.get('raster')
|
||||
sprite = new createjs.Sprite(@spriteSheet)
|
||||
reg = cocoSprite.getOffset 'registration'
|
||||
sprite.regX = -reg.x
|
||||
sprite.regY = -reg.y
|
||||
sprite.gotoAndStop(@renderGroupingKey(cocoSprite.thangType))
|
||||
|
||||
else
|
||||
prefix = @renderGroupingKey(cocoSprite.thangType, null, cocoSprite.colorConfig) + '.'
|
||||
sprite = new WebGLSprite(@spriteSheet, cocoSprite.thangType, prefix)
|
||||
|
||||
sprite.sprite = cocoSprite
|
||||
sprite.layerPriority = cocoSprite.thang?.layerPriority ? cocoSprite.thangType.get 'layerPriority'
|
||||
sprite.name = cocoSprite.thang?.spriteName or cocoSprite.thangType.get 'name'
|
||||
cocoSprite.addHealthBar()
|
||||
cocoSprite.setImageObject(sprite)
|
|
@ -5,30 +5,63 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
|
||||
constructor: (@spriteSheet, @thangType, @spriteSheetPrefix) ->
|
||||
@initialize(@spriteSheet)
|
||||
if @thangType.get('renderStrategy') isnt 'container'
|
||||
@singleChildSprite = new createjs.Sprite(@spriteSheet)
|
||||
@addChild(@singleChildSprite)
|
||||
|
||||
play: ->
|
||||
@singleChildSprite?.play()
|
||||
@paused = false
|
||||
|
||||
stop: ->
|
||||
@singleChildSprite?.stop()
|
||||
@paused = true
|
||||
|
||||
gotoAndPlay: (actionName) -> @goto(actionName, false)
|
||||
gotoAndStop: (actionName) -> @goto(actionName, true)
|
||||
|
||||
goto: (actionName, @paused=true) ->
|
||||
@currentAnimation = actionName
|
||||
action = @thangType.getActions()[actionName]
|
||||
randomStart = actionName.startsWith('move')
|
||||
if action.animation
|
||||
@childSpriteContainers = []
|
||||
@baseMovieClip = @buildMovieClip(action.animation)
|
||||
@mirrorMovieClip(@baseMovieClip, @)
|
||||
@framerate = (action.framerate ? 20) * (action.speed ? 1)
|
||||
@frames = action.frames
|
||||
@currentFrame = 0
|
||||
if @frames
|
||||
@frames = (parseInt(f) for f in @frames.split(','))
|
||||
|
||||
if @frames and @frames.length is 1
|
||||
@baseMovieClip.gotoAndStop(@frames[0])
|
||||
@paused = true
|
||||
@loop = action.loops isnt false
|
||||
@goesTo = action.goesTo
|
||||
@animLength = if @frames then @frames.length else @baseMovieClip.frameBounds.length
|
||||
|
||||
reg = action.positions?.registration or @thangType.get('positions')?.registration or {x:0, y:0}
|
||||
|
||||
if @singleChildSprite
|
||||
scale = SPRITE_RESOLUTION_FACTOR * (action.scale ? @thangType.get('scale') ? 1)
|
||||
@regX = -reg.x * scale
|
||||
@regY = -reg.y * scale
|
||||
func = if @paused then 'gotoAndStop' else 'gotoAndPlay'
|
||||
animationName = @spriteSheetPrefix + actionName
|
||||
@singleChildSprite[func](animationName)
|
||||
@singleChildSprite.framerate = action.framerate or 20
|
||||
|
||||
if randomStart and frames = @spriteSheet.getAnimation(animationName)?.frames
|
||||
start = Math.floor(Math.random() * frames.length)
|
||||
@singleChildSprite.currentAnimationFrame = start
|
||||
|
||||
else
|
||||
@childSpriteContainers = []
|
||||
@baseMovieClip = @buildMovieClip(action.animation)
|
||||
@mirrorMovieClip(@baseMovieClip, @)
|
||||
@frames = action.frames
|
||||
@currentFrame = 0
|
||||
if @frames
|
||||
@frames = (parseInt(f) for f in @frames.split(','))
|
||||
|
||||
if @frames and @frames.length is 1
|
||||
@baseMovieClip.gotoAndStop(@frames[0])
|
||||
@paused = true
|
||||
@loop = action.loops isnt false
|
||||
@goesTo = action.goesTo
|
||||
@animLength = if @frames then @frames.length else @baseMovieClip.frameBounds.length
|
||||
@regX = -reg.x
|
||||
@regY = -reg.y
|
||||
|
||||
if randomStart
|
||||
@currentFrame = Math.floor(Math.random() * @animLength)
|
||||
|
||||
return
|
||||
|
||||
mirrorMovieClip: (movieClip, spriteContainer) ->
|
||||
|
@ -42,6 +75,10 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
locals = {}
|
||||
_.extend locals, @buildMovieClipContainers(animData.containers)
|
||||
_.extend locals, @buildMovieClipAnimations(animData.animations)
|
||||
|
||||
toSkip = {}
|
||||
toSkip[shape.bn] for shape in animData.shapes
|
||||
toSkip[graphic.bn] for graphic in animData.graphics
|
||||
|
||||
anim = new createjs.MovieClip()
|
||||
anim.initialize(mode ? createjs.MovieClip.INDEPENDENT, startPosition ? 0, loops ? true)
|
||||
|
@ -51,7 +88,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
tween = createjs.Tween
|
||||
for func in tweenData
|
||||
args = $.extend(true, [], (func.a))
|
||||
if @dereferenceArgs(args, locals) is false
|
||||
if @dereferenceArgs(args, locals, toSkip) is false
|
||||
console.log 'could not dereference args', args
|
||||
stopped = true
|
||||
break
|
||||
|
@ -87,7 +124,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
@childSpriteContainers.push(childSpriteContainer)
|
||||
return map
|
||||
|
||||
dereferenceArgs: (args, locals) ->
|
||||
dereferenceArgs: (args, locals, toSkip) ->
|
||||
for key, val of args
|
||||
if locals[val]
|
||||
args[key] = locals[val]
|
||||
|
@ -96,14 +133,15 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
else if _.isString(val) and val.indexOf('createjs.') is 0
|
||||
args[key] = eval(val) # TODO: Security risk
|
||||
else if _.isObject(val) or _.isArray(val)
|
||||
res = @dereferenceArgs(val, locals)
|
||||
res = @dereferenceArgs(val, locals, toSkip)
|
||||
return res if res is false
|
||||
else if _.isString(val)
|
||||
else if _.isString(val) and toSkip[val]
|
||||
return false
|
||||
return args
|
||||
|
||||
tick: (delta) ->
|
||||
return unless @framerate and not @paused
|
||||
return if @singleChildSprite # this gets moved forward automatically
|
||||
newFrame = @currentFrame + @framerate * delta / 1000
|
||||
|
||||
if newFrame > @animLength
|
||||
|
@ -137,6 +175,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
|||
if @childSpriteContainers
|
||||
for childSpriteContainer in @childSpriteContainers
|
||||
movieClip = childSpriteContainer.movieClip
|
||||
continue unless movieClip.parent
|
||||
index = movieClip.parent.getChildIndex(movieClip)
|
||||
movieClip.gotoAndStop(newFrame)
|
||||
movieClip.parent[index] = childSpriteContainer
|
||||
|
|
|
@ -35,9 +35,14 @@ module.exports = class ThangType extends CocoModel
|
|||
return @get('actions') or @get('raster') # needs one of these two things
|
||||
|
||||
loadRasterImage: ->
|
||||
return if @loadingRaster or @loadedRaster
|
||||
return unless raster = @get('raster')
|
||||
@rasterImage = $("<img src='/file/#{raster}' />")
|
||||
@rasterImage.on('load', => @trigger('raster-image-loaded'))
|
||||
@loadingRaster = true
|
||||
@rasterImage.one('load', =>
|
||||
@loadingRaster = false
|
||||
@loadedRaster = true
|
||||
@trigger('raster-image-loaded', @))
|
||||
|
||||
getActions: ->
|
||||
return {} unless @isFullyLoaded()
|
||||
|
|
|
@ -5,8 +5,13 @@ treeThangType = new ThangType(require 'test/app/fixtures/tree1.thang.type')
|
|||
ogreMunchkinThangType = new ThangType(require 'test/app/fixtures/ogre-munchkin-m.thang.type')
|
||||
|
||||
describe 'WebGLLayer', ->
|
||||
it 'creates containers for animated actions if set to renderStrategy=container', ->
|
||||
layer = null
|
||||
beforeEach ->
|
||||
layer = new WebGLLayer()
|
||||
layer.buildAutomatically = false
|
||||
layer.buildAsync = false
|
||||
|
||||
it 'creates containers for animated actions if set to renderStrategy=container', ->
|
||||
ogreMunchkinThangType.set('renderStrategy', 'container')
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
sprite = new CocoSprite(ogreMunchkinThangType, {colorConfig: colorConfig})
|
||||
|
@ -16,7 +21,6 @@ describe 'WebGLLayer', ->
|
|||
expect(key in sheet.getAnimations()).toBe(true)
|
||||
|
||||
it 'creates the container for static actions if set to renderStrategy=container', ->
|
||||
layer = new WebGLLayer()
|
||||
treeThangType.set('renderStrategy', 'container')
|
||||
sprite = new CocoSprite(treeThangType)
|
||||
layer.addCocoSprite(sprite)
|
||||
|
@ -25,7 +29,6 @@ describe 'WebGLLayer', ->
|
|||
expect(key in sheet.getAnimations()).toBe(true)
|
||||
|
||||
it 'creates animations for animated actions if set to renderStrategy=spriteSheet', ->
|
||||
layer = new WebGLLayer()
|
||||
ogreMunchkinThangType.set('renderStrategy', 'spriteSheet')
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
sprite = new CocoSprite(ogreMunchkinThangType, {colorConfig: colorConfig})
|
||||
|
@ -35,7 +38,6 @@ describe 'WebGLLayer', ->
|
|||
expect(key in sheet.getAnimations()).toBe(true)
|
||||
|
||||
it 'creates animations for static actions if set to renderStrategy=spriteSheet', ->
|
||||
layer = new WebGLLayer()
|
||||
treeThangType.set('renderStrategy', 'spriteSheet')
|
||||
sprite = new CocoSprite(treeThangType)
|
||||
layer.addCocoSprite(sprite)
|
||||
|
@ -44,7 +46,6 @@ describe 'WebGLLayer', ->
|
|||
expect(key in sheet.getAnimations()).toBe(true)
|
||||
|
||||
it 'only renders frames used by actions when renderStrategy=spriteSheet', ->
|
||||
layer = new WebGLLayer()
|
||||
layer.setDefaultActions(['idle']) # uses the move side animation
|
||||
ogreMunchkinThangType.set('renderStrategy', 'spriteSheet')
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
|
@ -61,7 +62,6 @@ describe 'WebGLLayer', ->
|
|||
bootsThangType = new ThangType(require 'test/app/fixtures/leather-boots.thang.type')
|
||||
bootsThangType.loadRasterImage()
|
||||
bootsThangType.once('raster-image-loaded', ->
|
||||
layer = new WebGLLayer()
|
||||
sprite = new CocoSprite(bootsThangType)
|
||||
layer.addCocoSprite(sprite)
|
||||
sheet = layer.renderNewSpriteSheet()
|
||||
|
@ -69,4 +69,44 @@ describe 'WebGLLayer', ->
|
|||
expect(key in sheet.getAnimations()).toBe(true)
|
||||
done()
|
||||
#$('body').attr('class', '').empty().css('background', 'white').append($(sheet._images))
|
||||
)
|
||||
)
|
||||
|
||||
it 'loads ThangTypes for CocoSprites that are added to it and need to be loaded', ->
|
||||
thangType = new ThangType({_id: 1})
|
||||
sprite = new CocoSprite(thangType)
|
||||
layer.addCocoSprite(sprite)
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
expect(jasmine.Ajax.requests.count()).toBe(1)
|
||||
|
||||
it 'loads raster images for ThangType', (done) ->
|
||||
bootsThangTypeData = require 'test/app/fixtures/leather-boots.thang.type'
|
||||
thangType = new ThangType({_id: 1})
|
||||
sprite = new CocoSprite(thangType)
|
||||
layer.addCocoSprite(sprite)
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
jasmine.Ajax.requests.sendResponses({'/db/thang.type/1': bootsThangTypeData})
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
thangType.once('raster-image-loaded', ->
|
||||
expect(layer.numThingsLoading).toBe(0)
|
||||
done()
|
||||
)
|
||||
|
||||
it 'renders a new SpriteSheet only once everything has loaded', (done) ->
|
||||
bootsThangTypeData = require 'test/app/fixtures/leather-boots.thang.type'
|
||||
thangType1 = new ThangType({_id: 1})
|
||||
thangType2 = new ThangType({_id: 2})
|
||||
layer.addCocoSprite(new CocoSprite(thangType1))
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
layer.addCocoSprite(new CocoSprite(thangType2))
|
||||
expect(layer.numThingsLoading).toBe(2)
|
||||
spyOn layer, '_renderNewSpriteSheet'
|
||||
jasmine.Ajax.requests.sendResponses({'/db/thang.type/1': ogreMunchkinThangType.attributes})
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
jasmine.Ajax.requests.sendResponses({'/db/thang.type/2': bootsThangTypeData})
|
||||
expect(layer.numThingsLoading).toBe(1)
|
||||
expect(layer._renderNewSpriteSheet).not.toHaveBeenCalled()
|
||||
thangType2.once('raster-image-loaded', ->
|
||||
expect(layer.numThingsLoading).toBe(0)
|
||||
expect(layer._renderNewSpriteSheet).toHaveBeenCalled()
|
||||
done()
|
||||
)
|
||||
|
|
|
@ -18,7 +18,7 @@ describe 'WebGLSprite', ->
|
|||
ticks = 0
|
||||
listener = {
|
||||
handleEvent: ->
|
||||
# return if ticks >= 100
|
||||
return if ticks >= 100
|
||||
webGLSprite.tick(arguments[0].delta)
|
||||
stage.update()
|
||||
ticks += 1
|
||||
|
@ -28,6 +28,8 @@ describe 'WebGLSprite', ->
|
|||
describe 'with Ogre Munchkin ThangType', ->
|
||||
beforeEach ->
|
||||
layer = new WebGLLayer()
|
||||
layer.buildAutomatically = false
|
||||
layer.buildAsync = false
|
||||
ogreMunchkinThangType.markToRevert()
|
||||
ogreMunchkinThangType.set('renderStrategy', 'container')
|
||||
actions = ogreMunchkinThangType.getActions()
|
||||
|
@ -42,6 +44,8 @@ describe 'WebGLSprite', ->
|
|||
sheet = layer.renderNewSpriteSheet()
|
||||
prefix = layer.renderGroupingKey(ogreMunchkinThangType, null, colorConfig) + '.'
|
||||
window.webGLSprite = webGLSprite = new WebGLSprite(sheet, ogreMunchkinThangType, prefix)
|
||||
webGLSprite.x = 200
|
||||
webGLSprite.y = 200
|
||||
|
||||
afterEach ->
|
||||
ogreMunchkinThangType.revert()
|
||||
|
@ -58,7 +62,7 @@ describe 'WebGLSprite', ->
|
|||
expect(webGLSprite.paused).toBe(true)
|
||||
|
||||
it 'has a tick function which moves the animation forward', ->
|
||||
webGLSprite.gotoAndPlay('move_fore')
|
||||
webGLSprite.gotoAndPlay('attack')
|
||||
webGLSprite.tick(100) # one hundred milliseconds
|
||||
expect(webGLSprite.baseMovieClip.currentFrame).toBe(webGLSprite.framerate*100/1000)
|
||||
|
||||
|
@ -83,6 +87,8 @@ describe 'WebGLSprite', ->
|
|||
describe 'with Ogre Fangrider ThangType', ->
|
||||
beforeEach ->
|
||||
layer = new WebGLLayer()
|
||||
layer.buildAutomatically = false
|
||||
layer.buildAsync = false
|
||||
ogreFangriderThangType.markToRevert()
|
||||
ogreFangriderThangType.set('renderStrategy', 'container')
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
|
@ -91,15 +97,46 @@ describe 'WebGLSprite', ->
|
|||
sheet = layer.renderNewSpriteSheet()
|
||||
prefix = layer.renderGroupingKey(ogreFangriderThangType, null, colorConfig) + '.'
|
||||
window.webGLSprite = webGLSprite = new WebGLSprite(sheet, ogreFangriderThangType, prefix)
|
||||
webGLSprite.x = 300
|
||||
webGLSprite.y = 300
|
||||
|
||||
afterEach ->
|
||||
ogreFangriderThangType.revert()
|
||||
|
||||
it 'has gotoAndPlay, gotoAndStop, and paused like a MovieClip or Sprite', ->
|
||||
webGLSprite.gotoAndPlay('move_fore')
|
||||
it 'synchronizes animations with child movie clips properly', ->
|
||||
webGLSprite.gotoAndPlay('die')
|
||||
webGLSprite.tick(100) # one hundred milliseconds
|
||||
expectedFrame = webGLSprite.framerate*100/1000
|
||||
expect(webGLSprite.baseMovieClip.currentFrame).toBe(expectedFrame)
|
||||
expect(webGLSprite.currentFrame).toBe(expectedFrame)
|
||||
for child in webGLSprite.childSpriteContainers
|
||||
expect(child.movieClip.currentFrame).toBe(expectedFrame)
|
||||
|
||||
describe 'with Ogre Munchkin ThangType and renderStrategy=spriteSheet', ->
|
||||
beforeEach ->
|
||||
layer = new WebGLLayer()
|
||||
layer.buildAutomatically = false
|
||||
layer.buildAsync = false
|
||||
ogreMunchkinThangType.markToRevert()
|
||||
ogreMunchkinThangType.set('renderStrategy', 'spriteSheet')
|
||||
actions = ogreMunchkinThangType.getActions()
|
||||
|
||||
# couple extra actions for doing some tests
|
||||
actions.littledance = {animation:'enemy_small_move_side',framerate:1, frames:'0,6,2,6,2,8,0'}
|
||||
actions.onestep = {animation:'enemy_small_move_side', loops: false}
|
||||
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
sprite = new CocoSprite(ogreMunchkinThangType, {colorConfig: colorConfig})
|
||||
layer.addCocoSprite(sprite)
|
||||
sheet = layer.renderNewSpriteSheet()
|
||||
prefix = layer.renderGroupingKey(ogreMunchkinThangType, null, colorConfig) + '.'
|
||||
window.webGLSprite = webGLSprite = new WebGLSprite(sheet, ogreMunchkinThangType, prefix)
|
||||
webGLSprite.x = 200
|
||||
webGLSprite.y = 200
|
||||
|
||||
afterEach ->
|
||||
ogreMunchkinThangType.revert()
|
||||
|
||||
it 'has the same interface as for when the ThangType uses the container renderStrategy', ->
|
||||
webGLSprite.gotoAndPlay('move_fore')
|
||||
webGLSprite.gotoAndStop('attack')
|
||||
showMe()
|
||||
|
|
Loading…
Reference in a new issue