Set up placeholders for when WebGLSprites don't have their raw data built yet. Not finished yet because of scaling, but will come back to it... Got some refactoring to do first.

This commit is contained in:
Scott Erickson 2014-09-19 13:50:14 -07:00
parent a99cdfb957
commit 3c9b40e8f4
5 changed files with 74 additions and 36 deletions

View file

@ -11,6 +11,7 @@ marked.setOptions {gfm: true, sanitize: true, smartLists: true, breaks: false}
# TODO, add C-style macro constants like this? # TODO, add C-style macro constants like this?
window.SPRITE_RESOLUTION_FACTOR = 3 window.SPRITE_RESOLUTION_FACTOR = 3
window.SPRITE_PLACEHOLDER_RADIUS = 30
# Prevent Ctrl/Cmd + [ / ], P, S # Prevent Ctrl/Cmd + [ / ], P, S
ctrlDefaultPrevented = [219, 221, 80, 83] ctrlDefaultPrevented = [219, 221, 80, 83]

View file

@ -3,6 +3,8 @@ CocoClass = require 'lib/CocoClass'
WebGLSprite = require './WebGLSprite' WebGLSprite = require './WebGLSprite'
{SpriteContainerLayer} = require 'lib/surface/Layer' {SpriteContainerLayer} = require 'lib/surface/Layer'
NEVER_RENDER_ANYTHING = true # set to true to test placeholders
module.exports = class WebGLLayer extends CocoClass module.exports = class WebGLLayer extends CocoClass
_.extend(WebGLLayer.prototype, Backbone.Events) _.extend(WebGLLayer.prototype, Backbone.Events)
@ -109,12 +111,13 @@ module.exports = class WebGLLayer extends CocoClass
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. # The first frame is always the 'loading', ie placeholder, image.
# Then if you go to a frame that DNE, it doesn't show up. placeholder = @createPlaceholder()
emptiness = new createjs.Container() dimension = @resolutionFactor*SPRITE_PLACEHOLDER_RADIUS*2
emptiness.setBounds(0, 0, 1, 1) placeholder.setBounds(0, 0, dimension, dimension)
builder.addFrame(emptiness) builder.addFrame(placeholder)
groups = {} if NEVER_RENDER_ANYTHING
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
@ -136,6 +139,17 @@ module.exports = class WebGLLayer extends CocoClass
@onBuildSpriteSheetComplete(null, builder) @onBuildSpriteSheetComplete(null, builder)
return sheet return sheet
createPlaceholder: ->
# TODO: Experiment with this. Perhaps have rectangles if default layer is obstacle or floor,
# and different colors for different layers.
g = new createjs.Graphics()
g.setStrokeStyle(5)
g.beginStroke(createjs.Graphics.getRGB(64,64,64))
g.beginFill(createjs.Graphics.getRGB(64,64,64,0.7))
radius = @resolutionFactor*SPRITE_PLACEHOLDER_RADIUS
g.drawCircle(radius, radius, radius)
new createjs.Shape(g)
onBuildSpriteSheetComplete: (e, builder) -> onBuildSpriteSheetComplete: (e, builder) ->
return if @initializing return if @initializing

View file

@ -33,6 +33,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
goto: (actionName, @paused=true) -> goto: (actionName, @paused=true) ->
@currentAnimation = actionName @currentAnimation = actionName
@baseMovieClip = @framerate = null @baseMovieClip = @framerate = null
@actionNotSupported = false
action = @thangType.getActions()[actionName] action = @thangType.getActions()[actionName]
randomStart = actionName.startsWith('move') randomStart = actionName.startsWith('move')
@ -47,13 +48,21 @@ 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)
@notifyActionNeedsRender(action)
return
@singleChildSprite[func](animationName) @singleChildSprite[func](animationName)
@singleChildSprite.framerate = action.framerate or 20 if @singleChildSprite.currentFrame is 0
@regX = -reg.x
@regY = -reg.y
@singleChildSprite.stop()
@notifyActionNeedsRender(action)
bounds = @thangType.get('raw').animations[action.animation].bounds
@singleChildSprite.x = bounds[0]
@singleChildSprite.y = bounds[1]
console.log 'bounds?', bounds
@singleChildSprite.scaleX = bounds[2] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2)
@singleChildSprite.scaleY = bounds[3] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2)
return
@singleChildSprite.framerate = action.framerate or 20
if randomStart and frames = @spriteSheet.getAnimation(animationName)?.frames if randomStart and frames = @spriteSheet.getAnimation(animationName)?.frames
@singleChildSprite.currentAnimationFrame = Math.floor(Math.random() * frames.length) @singleChildSprite.currentAnimationFrame = Math.floor(Math.random() * frames.length)
@ -62,10 +71,6 @@ 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 = []
@notifyActionNeedsRender(action)
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
@ -74,31 +79,41 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
@baseMovieClip.gotoAndStop(@currentFrame) @baseMovieClip.gotoAndStop(@currentFrame)
@loop = action.loops isnt false @loop = action.loops isnt false
@goesTo = action.goesTo @goesTo = action.goesTo
@notifyActionNeedsRender(action) if @actionNotSupported
if action.container if action.container
if @singleChildSprite
scale = @resolutionFactor * (action.scale ? @thangType.get('scale') ? 1) scale = @resolutionFactor * (action.scale ? @thangType.get('scale') ? 1)
if @singleChildSprite
@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)
@notifyActionNeedsRender(action)
return
@singleChildSprite.gotoAndStop(animationName) @singleChildSprite.gotoAndStop(animationName)
if @singleChildSprite.currentFrame is 0
@notifyActionNeedsRender(action)
bounds = @thangType.get('raw').containers[action.container].b
@singleChildSprite.x = bounds[0]
@singleChildSprite.y = bounds[1]
@singleChildSprite.scaleX = bounds[2] / (SPRITE_PLACEHOLDER_RADIUS * 2)
@singleChildSprite.scaleY = bounds[3] / (SPRITE_PLACEHOLDER_RADIUS * 2)
return
else else
@regX = -reg.x @regX = -reg.x
@regY = -reg.y @regY = -reg.y
@childMovieClips = [] @childMovieClips = []
containerName = @spriteSheetPrefix + action.container containerName = @spriteSheetPrefix + action.container
if not (containerName in @spriteSheet.getAnimations())
@children = []
@notifyActionNeedsRender(action)
return
sprite = new createjs.Sprite(@spriteSheet) sprite = new createjs.Sprite(@spriteSheet)
sprite.gotoAndStop(containerName) sprite.gotoAndStop(containerName)
sprite.scaleX = sprite.scaleY = 1 / @resolutionFactor if sprite.currentFrame is 0
@notifyActionNeedsRender(action)
bounds = @thangType.get('raw').containers[action.container].b
sprite.x = bounds[0]
sprite.y = bounds[1]
sprite.scaleX = bounds[2] / (SPRITE_PLACEHOLDER_RADIUS * 2 * scale)
sprite.scaleY = bounds[3] / (SPRITE_PLACEHOLDER_RADIUS * 2 * scale)
else
sprite.scaleX = sprite.scaleY = 1 / scale
@children = [sprite] @children = [sprite]
return return
@ -112,10 +127,8 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
movieClip = new createjs.MovieClip() movieClip = new createjs.MovieClip()
locals = {} locals = {}
_.extend locals, containers = @buildMovieClipContainers(animData.containers) _.extend locals, @buildMovieClipContainers(animData.containers)
return false if not containers _.extend locals, @buildMovieClipAnimations(animData.animations)
_.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
@ -147,10 +160,16 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
for localContainer in localContainers for localContainer in localContainers
outerContainer = new createjs.SpriteContainer(@spriteSheet) outerContainer = new createjs.SpriteContainer(@spriteSheet)
innerContainer = new createjs.Sprite(@spriteSheet) innerContainer = new createjs.Sprite(@spriteSheet)
innerContainer.gotoAndStop(@spriteSheetPrefix + localContainer.gn)
if innerContainer.currentFrame is 0
@actionNotSupported = true
bounds = @thangType.get('raw').containers[localContainer.gn].b
innerContainer.x = bounds[0]
innerContainer.y = bounds[1]
innerContainer.scaleX = bounds[2] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2)
innerContainer.scaleY = bounds[3] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2)
else
innerContainer.scaleX = innerContainer.scaleY = 1 / (@resolutionFactor * (@thangType.get('scale') or 1)) innerContainer.scaleX = innerContainer.scaleY = 1 / (@resolutionFactor * (@thangType.get('scale') or 1))
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?
@ -162,7 +181,6 @@ 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)

View file

@ -69,7 +69,9 @@ describe 'SpriteBoss', ->
spriteBoss.update(true) spriteBoss.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['Tree 1'].imageObject.children.length,0,'static container action']) midRenderExpectations.push([spriteBoss.sprites['Tree 1'].imageObject.children.length,1,'static container action'])
midRenderExpectations.push([spriteBoss.sprites['Tree 1'].imageObject.children[0].currentFrame,0,'static container action'])
midRenderExpectations.push([spriteBoss.sprites['Tree 1'].imageObject.children[0].paused,true,'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].currentFrame,0,'static spriteSheet action'])
midRenderExpectations.push([spriteBoss.sprites['Tree 2'].imageObject.children[0].paused,true,'static spriteSheet action']) midRenderExpectations.push([spriteBoss.sprites['Tree 2'].imageObject.children[0].paused,true,'static spriteSheet action'])
@ -102,13 +104,15 @@ describe 'SpriteBoss', ->
spriteBoss.update(true) spriteBoss.update(true)
# Test that the unrendered, animated sprites aren't showing anything # 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['NotFROgre'].imageObject.children.length,10,'animated container action'])
for child in spriteBoss.sprites['NotFROgre'].imageObject.children
midRenderExpectations.push([child.children[0].currentFrame, 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].currentFrame,0,'animated spriteSheet action'])
midRenderExpectations.push([spriteBoss.sprites['FROgre'].imageObject.children[0].paused,true,'animated spriteSheet action']) midRenderExpectations.push([spriteBoss.sprites['FROgre'].imageObject.children[0].paused,true,'animated spriteSheet action'])
defaultLayer.once 'new-spritesheet', -> defaultLayer.once 'new-spritesheet', ->
showMe() # Uncomment to display this world when you run any of these tests.
done() done()
# showMe() # Uncomment to display this world when you run any of these tests.
beforeEach (done) -> init(done) beforeEach (done) -> init(done)

View file

@ -56,6 +56,7 @@ describe 'WebGLSprite', ->
expect(webGLSprite.paused).toBe(false) expect(webGLSprite.paused).toBe(false)
webGLSprite.gotoAndStop('move_fore') webGLSprite.gotoAndStop('move_fore')
expect(webGLSprite.paused).toBe(true) expect(webGLSprite.paused).toBe(true)
showMe()
it 'has a tick function which moves the animation forward', -> it 'has a tick function which moves the animation forward', ->
webGLSprite.gotoAndPlay('attack') webGLSprite.gotoAndPlay('attack')