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?
window.SPRITE_RESOLUTION_FACTOR = 3
window.SPRITE_PLACEHOLDER_RADIUS = 30
# Prevent Ctrl/Cmd + [ / ], P, S
ctrlDefaultPrevented = [219, 221, 80, 83]

View file

@ -3,6 +3,8 @@ CocoClass = require 'lib/CocoClass'
WebGLSprite = require './WebGLSprite'
{SpriteContainerLayer} = require 'lib/surface/Layer'
NEVER_RENDER_ANYTHING = true # set to true to test placeholders
module.exports = class WebGLLayer extends CocoClass
_.extend(WebGLLayer.prototype, Backbone.Events)
@ -109,12 +111,13 @@ module.exports = class WebGLLayer extends CocoClass
builder = new createjs.SpriteSheetBuilder()
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)
# The first frame is always the 'loading', ie placeholder, image.
placeholder = @createPlaceholder()
dimension = @resolutionFactor*SPRITE_PLACEHOLDER_RADIUS*2
placeholder.setBounds(0, 0, dimension, dimension)
builder.addFrame(placeholder)
groups = {} if NEVER_RENDER_ANYTHING
for bundleGrouping in _.values(groups)
thangType = bundleGrouping[0].thangType
colorConfig = bundleGrouping[0].colorConfig
@ -135,6 +138,17 @@ module.exports = class WebGLLayer extends CocoClass
sheet = builder.build()
@onBuildSpriteSheetComplete(null, builder)
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) ->
return if @initializing

View file

@ -33,6 +33,7 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
goto: (actionName, @paused=true) ->
@currentAnimation = actionName
@baseMovieClip = @framerate = null
@actionNotSupported = false
action = @thangType.getActions()[actionName]
randomStart = actionName.startsWith('move')
@ -47,13 +48,21 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
@regY = -reg.y * scale
func = if @paused then 'gotoAndStop' else 'gotoAndPlay'
animationName = @spriteSheetPrefix + actionName
if not (animationName in @spriteSheet.getAnimations())
@singleChildSprite.gotoAndStop(0)
@notifyActionNeedsRender(action)
return
@singleChildSprite[func](animationName)
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
@singleChildSprite.currentAnimationFrame = Math.floor(Math.random() * frames.length)
@ -62,10 +71,6 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
@regY = -reg.y
@childMovieClips = []
@baseMovieClip = @buildMovieClip(action.animation)
if not @baseMovieClip
@children = []
@notifyActionNeedsRender(action)
return
@children = @baseMovieClip.children
@frames = action.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)
@loop = action.loops isnt false
@goesTo = action.goesTo
@notifyActionNeedsRender(action) if @actionNotSupported
if action.container
scale = @resolutionFactor * (action.scale ? @thangType.get('scale') ? 1)
if @singleChildSprite
scale = @resolutionFactor * (action.scale ? @thangType.get('scale') ? 1)
@regX = -reg.x * scale
@regY = -reg.y * scale
animationName = @spriteSheetPrefix + actionName
if not (animationName in @spriteSheet.getAnimations())
@singleChildSprite.gotoAndStop(0)
@notifyActionNeedsRender(action)
return
@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
@regX = -reg.x
@regY = -reg.y
@childMovieClips = []
containerName = @spriteSheetPrefix + action.container
if not (containerName in @spriteSheet.getAnimations())
@children = []
@notifyActionNeedsRender(action)
return
sprite = new createjs.Sprite(@spriteSheet)
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]
return
@ -112,10 +127,8 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
movieClip = new createjs.MovieClip()
locals = {}
_.extend locals, containers = @buildMovieClipContainers(animData.containers)
return false if not containers
_.extend locals, animations = @buildMovieClipAnimations(animData.animations)
return false if not animations
_.extend locals, @buildMovieClipContainers(animData.containers)
_.extend locals, @buildMovieClipAnimations(animData.animations)
toSkip = {}
toSkip[shape.bn] = true for shape in animData.shapes
@ -147,10 +160,16 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
for localContainer in localContainers
outerContainer = new createjs.SpriteContainer(@spriteSheet)
innerContainer = new createjs.Sprite(@spriteSheet)
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)
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))
outerContainer.addChild(innerContainer)
outerContainer.setTransform(localContainer.t...)
outerContainer._off = localContainer.o if localContainer.o?
@ -162,7 +181,6 @@ module.exports = class WebGLSprite extends createjs.SpriteContainer
map = {}
for localAnimation in localAnimations
animation = @buildMovieClip(localAnimation.gn, localAnimation.a...)
return false if not animation
animation.setTransform(localAnimation.t...)
map[localAnimation.bn] = animation
@childMovieClips.push(animation)

View file

@ -69,7 +69,9 @@ describe 'SpriteBoss', ->
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 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].paused,true,'static spriteSheet action'])
@ -102,13 +104,15 @@ describe 'SpriteBoss', ->
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['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].paused,true,'animated spriteSheet action'])
defaultLayer.once 'new-spritesheet', ->
showMe() # Uncomment to display this world when you run any of these tests.
done()
# showMe() # Uncomment to display this world when you run any of these tests.
beforeEach (done) -> init(done)

View file

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