mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-30 10:56:53 -05:00
WebGLSprites of all types no longer display anything at all if their required data hasn't been rendered.
This commit is contained in:
parent
7db73a5ddf
commit
0404b94e5e
3 changed files with 52 additions and 12 deletions
|
@ -103,6 +103,13 @@ module.exports = class WebGLLayer extends CocoClass
|
||||||
async ?= @buildAsync
|
async ?= @buildAsync
|
||||||
builder = new createjs.SpriteSheetBuilder()
|
builder = new createjs.SpriteSheetBuilder()
|
||||||
groups = _.groupBy(@toRenderBundles, ((bundle) -> @renderGroupingKey(bundle.thangType, '', bundle.colorConfig)), @)
|
groups = _.groupBy(@toRenderBundles, ((bundle) -> @renderGroupingKey(bundle.thangType, '', bundle.colorConfig)), @)
|
||||||
|
|
||||||
|
# Always have an empty frame be the first frame.
|
||||||
|
# Then if you go to a frame that DNE, it doesn't show up.
|
||||||
|
emptiness = new createjs.Container()
|
||||||
|
emptiness.setBounds(0, 0, 1, 1)
|
||||||
|
builder.addFrame(emptiness)
|
||||||
|
|
||||||
for bundleGrouping in _.values(groups)
|
for bundleGrouping in _.values(groups)
|
||||||
thangType = bundleGrouping[0].thangType
|
thangType = bundleGrouping[0].thangType
|
||||||
colorConfig = bundleGrouping[0].colorConfig
|
colorConfig = bundleGrouping[0].colorConfig
|
||||||
|
@ -116,11 +123,6 @@ module.exports = class WebGLLayer extends CocoClass
|
||||||
else
|
else
|
||||||
@renderRasterImage(thangType, builder)
|
@renderRasterImage(thangType, builder)
|
||||||
|
|
||||||
if not _.size(groups)
|
|
||||||
emptiness = new createjs.Container()
|
|
||||||
emptiness.setBounds(0, 0, 1, 1)
|
|
||||||
builder.addFrame(emptiness)
|
|
||||||
|
|
||||||
if async
|
if async
|
||||||
builder.buildAsync()
|
builder.buildAsync()
|
||||||
builder.on 'complete', @onBuildSpriteSheetComplete, @, true, builder
|
builder.on 'complete', @onBuildSpriteSheetComplete, @, true, builder
|
||||||
|
|
|
@ -47,6 +47,9 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
@regY = -reg.y * scale
|
@regY = -reg.y * scale
|
||||||
func = if @paused then 'gotoAndStop' else 'gotoAndPlay'
|
func = if @paused then 'gotoAndStop' else 'gotoAndPlay'
|
||||||
animationName = @spriteSheetPrefix + actionName
|
animationName = @spriteSheetPrefix + actionName
|
||||||
|
if not (animationName in @spriteSheet.getAnimations())
|
||||||
|
@singleChildSprite.gotoAndStop(0)
|
||||||
|
return
|
||||||
@singleChildSprite[func](animationName)
|
@singleChildSprite[func](animationName)
|
||||||
@singleChildSprite.framerate = action.framerate or 20
|
@singleChildSprite.framerate = action.framerate or 20
|
||||||
|
|
||||||
|
@ -58,6 +61,9 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
@regY = -reg.y
|
@regY = -reg.y
|
||||||
@childMovieClips = []
|
@childMovieClips = []
|
||||||
@baseMovieClip = @buildMovieClip(action.animation)
|
@baseMovieClip = @buildMovieClip(action.animation)
|
||||||
|
if not @baseMovieClip
|
||||||
|
@children = []
|
||||||
|
return
|
||||||
@children = @baseMovieClip.children
|
@children = @baseMovieClip.children
|
||||||
@frames = action.frames
|
@frames = action.frames
|
||||||
@frames = (parseInt(f) for f in @frames.split(',')) if @frames
|
@frames = (parseInt(f) for f in @frames.split(',')) if @frames
|
||||||
|
@ -73,6 +79,9 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
@regX = -reg.x * scale
|
@regX = -reg.x * scale
|
||||||
@regY = -reg.y * scale
|
@regY = -reg.y * scale
|
||||||
animationName = @spriteSheetPrefix + actionName
|
animationName = @spriteSheetPrefix + actionName
|
||||||
|
if not (animationName in @spriteSheet.getAnimations())
|
||||||
|
@singleChildSprite.gotoAndStop(0)
|
||||||
|
return
|
||||||
@singleChildSprite.gotoAndStop(animationName)
|
@singleChildSprite.gotoAndStop(animationName)
|
||||||
|
|
||||||
else
|
else
|
||||||
|
@ -80,6 +89,9 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
@regY = -reg.y
|
@regY = -reg.y
|
||||||
@childMovieClips = []
|
@childMovieClips = []
|
||||||
containerName = @spriteSheetPrefix + action.container
|
containerName = @spriteSheetPrefix + action.container
|
||||||
|
if not (containerName in @spriteSheet.getAnimations())
|
||||||
|
@children = []
|
||||||
|
return
|
||||||
sprite = new createjs.Sprite(@spriteSheet)
|
sprite = new createjs.Sprite(@spriteSheet)
|
||||||
sprite.gotoAndStop(containerName)
|
sprite.gotoAndStop(containerName)
|
||||||
sprite.scaleX = sprite.scaleY = 1 / @resolutionFactor
|
sprite.scaleX = sprite.scaleY = 1 / @resolutionFactor
|
||||||
|
@ -93,8 +105,10 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
movieClip = new createjs.MovieClip()
|
movieClip = new createjs.MovieClip()
|
||||||
|
|
||||||
locals = {}
|
locals = {}
|
||||||
_.extend locals, @buildMovieClipContainers(animData.containers)
|
_.extend locals, containers = @buildMovieClipContainers(animData.containers)
|
||||||
_.extend locals, @buildMovieClipAnimations(animData.animations)
|
return false if not containers
|
||||||
|
_.extend locals, animations = @buildMovieClipAnimations(animData.animations)
|
||||||
|
return false if not animations
|
||||||
|
|
||||||
toSkip = {}
|
toSkip = {}
|
||||||
toSkip[shape.bn] = true for shape in animData.shapes
|
toSkip[shape.bn] = true for shape in animData.shapes
|
||||||
|
@ -127,7 +141,9 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
outerContainer = new createjs.SpriteContainer(@spriteSheet)
|
outerContainer = new createjs.SpriteContainer(@spriteSheet)
|
||||||
innerContainer = new createjs.Sprite(@spriteSheet)
|
innerContainer = new createjs.Sprite(@spriteSheet)
|
||||||
innerContainer.scaleX = innerContainer.scaleY = 1 / @resolutionFactor
|
innerContainer.scaleX = innerContainer.scaleY = 1 / @resolutionFactor
|
||||||
innerContainer.gotoAndStop(@spriteSheetPrefix + localContainer.gn)
|
animationName = @spriteSheetPrefix + localContainer.gn
|
||||||
|
return false if not (animationName in @spriteSheet.getAnimations())
|
||||||
|
innerContainer.gotoAndStop(animationName)
|
||||||
outerContainer.addChild(innerContainer)
|
outerContainer.addChild(innerContainer)
|
||||||
outerContainer.setTransform(localContainer.t...)
|
outerContainer.setTransform(localContainer.t...)
|
||||||
outerContainer._off = localContainer.o if localContainer.o?
|
outerContainer._off = localContainer.o if localContainer.o?
|
||||||
|
@ -139,6 +155,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
|
||||||
map = {}
|
map = {}
|
||||||
for localAnimation in localAnimations
|
for localAnimation in localAnimations
|
||||||
animation = @buildMovieClip(localAnimation.gn, localAnimation.a...)
|
animation = @buildMovieClip(localAnimation.gn, localAnimation.a...)
|
||||||
|
return false if not animation
|
||||||
animation.setTransform(localAnimation.t...)
|
animation.setTransform(localAnimation.t...)
|
||||||
map[localAnimation.bn] = animation
|
map[localAnimation.bn] = animation
|
||||||
@childMovieClips.push(animation)
|
@childMovieClips.push(animation)
|
||||||
|
|
|
@ -11,6 +11,7 @@ describe 'SpriteBoss', ->
|
||||||
spriteBoss = null
|
spriteBoss = 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
|
||||||
|
|
||||||
# This suite just creates and renders the stage once, and then has each of the tests
|
# This suite just creates and renders the stage once, and then has each of the tests
|
||||||
# check the resulting data for the whole thing, without changing anything.
|
# check the resulting data for the whole thing, without changing anything.
|
||||||
|
@ -61,10 +62,16 @@ describe 'SpriteBoss', ->
|
||||||
|
|
||||||
# Don't have the layer automatically draw for move_fore, instead have it notified from WebGLSprites that
|
# Don't have the layer automatically draw for move_fore, instead have it notified from WebGLSprites that
|
||||||
# this animation or its containers are needed.
|
# this animation or its containers are needed.
|
||||||
# defaultLayer.setDefaultActions(_.without defaultLayer.defaultActions, 'move_fore')
|
defaultLayer.setDefaultActions(_.without defaultLayer.defaultActions, 'move_fore')
|
||||||
|
|
||||||
# Render the simple world with just trees
|
# Render the simple world with just trees
|
||||||
spriteBoss.update(true)
|
spriteBoss.update(true)
|
||||||
|
|
||||||
|
# Test that the unrendered, static sprites aren't showing anything
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['Tree 1'].imageObject.children.length,0,'static container action'])
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['Tree 2'].imageObject.children[0].currentFrame,0,'static spriteSheet action'])
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['Tree 2'].imageObject.children[0].paused,true,'static spriteSheet action'])
|
||||||
|
|
||||||
defaultLayer.once 'new-spritesheet', ->
|
defaultLayer.once 'new-spritesheet', ->
|
||||||
|
|
||||||
# Now make the world a little more complicated.
|
# Now make the world a little more complicated.
|
||||||
|
@ -76,8 +83,8 @@ describe 'SpriteBoss', ->
|
||||||
{id: 'Ogre S', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:0, y:-8}, action: 'move', health: 5, maxHealth: 10, rotation: Math.PI/2, acts: true }
|
{id: 'Ogre S', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:0, y:-8}, action: 'move', health: 5, maxHealth: 10, rotation: Math.PI/2, acts: true }
|
||||||
|
|
||||||
# Set ogres side by side with different render strategies
|
# Set ogres side by side with different render strategies
|
||||||
{id: 'FROgre', spriteName: 'Full Render Ogre', exists: true, pos: {x:-10, y:-8}, action: 'idle', health: 10, maxHealth: 10, rotation: 0, acts: true, alpha: 0.5 }
|
{id: 'FROgre', spriteName: 'Full Render Ogre', exists: true, pos: {x:-10, y:-8}, action: 'move', health: 10, maxHealth: 10, rotation: -Math.PI/2, acts: true, alpha: 0.5 }
|
||||||
{id: 'NotFROgre', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:-8, y:-8}, action: 'idle', health: 10, maxHealth: 10, rotation: 0, acts: true }
|
{id: 'NotFROgre', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:-8, y:-8}, action: 'move', health: 10, maxHealth: 10, rotation: -Math.PI/2, acts: true }
|
||||||
|
|
||||||
# A line of ogres overlapping to test child ordering
|
# A line of ogres overlapping to test child ordering
|
||||||
{id: 'Ogre 1', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:-14, y:0}, action: 'die', health: 5, maxHealth: 10, rotation: 0, acts: true }
|
{id: 'Ogre 1', spriteName: 'Ogre Munchkin M', exists: true, pos: {x:-14, y:0}, action: 'die', health: 5, maxHealth: 10, rotation: 0, acts: true }
|
||||||
|
@ -89,10 +96,18 @@ describe 'SpriteBoss', ->
|
||||||
{id: 'Fangrider 1', spriteName: 'Ogre Fangrider', exists: true, pos: {x:8, y:8}, action: 'move', health: 20, maxHealth: 20, rotation: 0, acts: true }
|
{id: 'Fangrider 1', spriteName: 'Ogre Fangrider', exists: true, pos: {x:8, y:8}, action: 'move', health: 20, maxHealth: 20, rotation: 0, acts: true }
|
||||||
]
|
]
|
||||||
|
|
||||||
_.find(world.thangs, {id: 'Tree Will Disappear'}).exists = false
|
_.find(world.thangs, {id: 'Tree Will Disappear'}).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)
|
spriteBoss.update(true)
|
||||||
|
|
||||||
|
# Test that the unrendered, animated sprites aren't showing anything
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['NotFROgre'].imageObject.children.length,0,'animated container action'])
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['FROgre'].imageObject.children[0].currentFrame,0,'animated spriteSheet action'])
|
||||||
|
midRenderExpectations.push([spriteBoss.sprites['FROgre'].imageObject.children[0].paused,true,'animated spriteSheet action'])
|
||||||
|
|
||||||
defaultLayer.once 'new-spritesheet', ->
|
defaultLayer.once 'new-spritesheet', ->
|
||||||
|
expect(spriteBoss.sprites['Ogre 1'].imageObject.children.length).toBeGreaterThan(0)
|
||||||
|
# expect(spriteBoss.sprites['FROgre'].imageObject.children[0].currentFrame).toBeGreaterThan(0)
|
||||||
done()
|
done()
|
||||||
# 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.
|
||||||
|
|
||||||
|
@ -113,6 +128,12 @@ describe 'SpriteBoss', ->
|
||||||
createjs.Ticker.addEventListener "tick", listener
|
createjs.Ticker.addEventListener "tick", listener
|
||||||
$('body').append($('<div style="position: absolute; top: 295px; left: 395px; height: 10px; width: 10px; background: red;"></div>'))
|
$('body').append($('<div style="position: absolute; top: 295px; left: 395px; height: 10px; width: 10px; background: red;"></div>'))
|
||||||
|
|
||||||
|
it 'does not display anything for sprites whose animations or containers have not been rendered yet', ->
|
||||||
|
for expectation in midRenderExpectations
|
||||||
|
if expectation[0] isnt expectation[1]
|
||||||
|
console.error('This type of action display failed:', expectation[2])
|
||||||
|
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(spriteBoss.sprites['Ogre N'].imageObject.currentAnimation).toBe('move_fore')
|
||||||
expect(spriteBoss.sprites['Ogre E'].imageObject.currentAnimation).toBe('move_side')
|
expect(spriteBoss.sprites['Ogre E'].imageObject.currentAnimation).toBe('move_side')
|
||||||
|
|
Loading…
Reference in a new issue