From 16cb596a123c02b05626001c2834aa1c291c9fd6 Mon Sep 17 00:00:00 2001 From: Scott Erickson Date: Tue, 23 Sep 2014 12:08:50 -0700 Subject: [PATCH] Set up scaling and mouse events for segmented sprites with container actions. --- app/lib/sprites/SpriteBuilder.coffee | 2 +- app/lib/surface/SegmentedSprite.coffee | 16 +-- .../lib/surface/SegmentedSprite.spec.coffee | 102 ++++++++++++++++++ 3 files changed, 113 insertions(+), 7 deletions(-) diff --git a/app/lib/sprites/SpriteBuilder.coffee b/app/lib/sprites/SpriteBuilder.coffee index e34e7d901..527c263a8 100644 --- a/app/lib/sprites/SpriteBuilder.coffee +++ b/app/lib/sprites/SpriteBuilder.coffee @@ -107,7 +107,7 @@ module.exports = class SpriteBuilder shape buildContainerFromStore: (containerKey) -> - console.error 'Yo we don\'t have no', containerKey unless containerKey + console.error 'Yo we don\'t have no containerKey' unless containerKey contData = @containerStore[containerKey] cont = new createjs.Container() cont.initialize() diff --git a/app/lib/surface/SegmentedSprite.coffee b/app/lib/surface/SegmentedSprite.coffee index 54aca06d1..85a6be2f8 100644 --- a/app/lib/surface/SegmentedSprite.coffee +++ b/app/lib/surface/SegmentedSprite.coffee @@ -19,6 +19,7 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer gotoAndStop: (actionName) -> @goto(actionName, true) goto: (actionName, @paused=true) -> + @removeAllChildren() @currentAnimation = actionName @baseMovieClip = @framerate = null @actionNotSupported = false @@ -31,10 +32,10 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer reg = action.positions?.registration or @thangType.get('positions')?.registration or {x:0, y:0} @regX = -reg.x @regY = -reg.y + @baseScaleY = @baseScaleX = action.scale ? @thangType.get('scale') ? 1 if action.animation @framerate = (action.framerate ? 20) * (action.speed ? 1) - @baseScaleY = @baseScaleX = action.scale ? @thangType.get('scale') ? 1 @childMovieClips = [] @baseMovieClip = @buildMovieClip(action.animation) @children = @baseMovieClip.children @@ -54,16 +55,19 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer containerName = @spriteSheetPrefix + action.container sprite = new createjs.Sprite(@spriteSheet) sprite.gotoAndStop(containerName) - if sprite.currentFrame is 0 + @listenToEventsFor(sprite) + if sprite.currentFrame is 0 or @usePlaceholders + sprite.gotoAndStop(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) + sprite.scaleX = bounds[2] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2) + sprite.scaleY = bounds[3] / (SPRITE_PLACEHOLDER_RADIUS * @resolutionFactor * 2) else sprite.scaleX = sprite.scaleY = 1 / scale - @children = [sprite] + @children = [] + @addChild(sprite) return @@ -168,7 +172,7 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer @lastTimeStamp = e.timeStamp tick: (delta) -> - return if @paused + return if @paused or not @baseMovieClip newFrame = @currentFrame + @framerate * delta / 1000 if newFrame > @animLength diff --git a/test/app/lib/surface/SegmentedSprite.spec.coffee b/test/app/lib/surface/SegmentedSprite.spec.coffee index 03a98615c..465155b14 100644 --- a/test/app/lib/surface/SegmentedSprite.spec.coffee +++ b/test/app/lib/surface/SegmentedSprite.spec.coffee @@ -5,6 +5,7 @@ ThangType = require 'models/ThangType' SpriteBuilder = require 'lib/sprites/SpriteBuilder' ogreMunchkinThangType = new ThangType(require 'test/app/fixtures/ogre-munchkin-m.thang.type') ogreFangriderThangType = new ThangType(require 'test/app/fixtures/ogre-fangrider.thang.type') +treeThangType = new ThangType(require 'test/app/fixtures/tree1.thang.type') describe 'SegmentedSprite', -> segmentedSprite = null @@ -27,6 +28,107 @@ describe 'SegmentedSprite', -> } createjs.Ticker.addEventListener "tick", listener + describe 'with Tree ThangType', -> + beforeEach -> + layer = new LayerAdapter({webGL:true}) + layer.buildAutomatically = false + layer.buildAsync = false + treeThangType.markToRevert() + treeThangType.set('spriteType', 'segmented') + sprite = new CocoSprite(treeThangType) + layer.addCocoSprite(sprite) + sheet = layer.renderNewSpriteSheet() + prefix = layer.renderGroupingKey(treeThangType) + '.' + window.segmentedSprite = segmentedSprite = new SegmentedSprite(sheet, treeThangType, prefix) + segmentedSprite.x = 100 + segmentedSprite.y = 200 + + it 'scales rendered containers to the size of the source container', -> + # build a movie clip, put it on top of the segmented sprite and make sure + # they both 'hit' at the same time. + + segmentedSprite.gotoAndStop('idle') + builder = new SpriteBuilder(treeThangType) + container = builder.buildContainerFromStore('Tree_4') + container.x = 100 + container.y = 200 + container.regX = 59 + container.regY = 100 + showMe() + stage.addChild(container) + stage.update() + t = new Date() + tests = hits = 0 + for x in _.range(30, 190, 20) + for y in _.range(90, 250, 20) + tests += 1 + objects = stage.getObjectsUnderPoint(x, y) + if objects.length + hasSprite = _.any objects, (o) -> o instanceof createjs.Sprite + hasShape = _.any objects, (o) -> o instanceof createjs.Shape + hits+= 1 if hasSprite and hasShape + g = new createjs.Graphics() + g.beginFill(createjs.Graphics.getRGB(64,64,64,0.7)) + g.drawCircle(0, 0, 2) + s = new createjs.Shape(g) + s.x = x + s.y = y + stage.addChild(s) + else + hits += 1 + + expect(hits / tests).toBeGreaterThan(0.98) # not perfect, but pretty close. + expect(segmentedSprite.baseScaleX).toBe(0.3) + expect(segmentedSprite.baseScaleY).toBe(0.3) +# $('canvas').remove() + + it 'scales placeholder containers to the size of the source container', -> + # build a movie clip, put it on top of the segmented sprite and make sure + # they both 'hit' at the same time. + + segmentedSprite.usePlaceholders = true + segmentedSprite.gotoAndStop('idle') + builder = new SpriteBuilder(treeThangType) + container = builder.buildContainerFromStore('Tree_4') + container.x = 100 + container.y = 200 + container.regX = 59 + container.regY = 100 + showMe() + stage.addChild(container) + stage.update() + t = new Date() + tests = hits = 0 + for x in _.range(30, 190, 20) + for y in _.range(90, 250, 20) + tests += 1 + objects = stage.getObjectsUnderPoint(x, y) + if objects.length + hasSprite = _.any objects, (o) -> o instanceof createjs.Sprite + hasShape = _.any objects, (o) -> o instanceof createjs.Shape + hits+= 1 if hasSprite and hasShape + g = new createjs.Graphics() + g.beginFill(createjs.Graphics.getRGB(64,64,64,0.7)) + g.drawCircle(0, 0, 2) + s = new createjs.Shape(g) + s.x = x + s.y = y + stage.addChild(s) + else + hits += 1 + + expect(hits / tests).toBeGreaterThan(0.84) # the circle is rather out of the tree bounds, so accuracy is low + expect(segmentedSprite.baseScaleX).toBe(0.3) + expect(segmentedSprite.baseScaleY).toBe(0.3) + $('canvas').remove() + + it 'propagates events from the single segment through the segmented sprite', -> + fired = {} + segmentedSprite.on('click', -> fired.didIt = true) + segmentedSprite.gotoAndStop('idle') + segmentedSprite.children[0].dispatchEvent('click') + expect(fired.didIt).toBe(true) + describe 'with Ogre Munchkin ThangType', -> beforeEach -> layer = new LayerAdapter({webGL:true})