2014-09-19 17:59:29 -04:00
|
|
|
LayerAdapter = require 'lib/surface/LayerAdapter'
|
2014-09-19 17:56:40 -04:00
|
|
|
SegmentedSprite = require 'lib/surface/SegmentedSprite'
|
|
|
|
CocoSprite = require 'lib/surface/CocoSprite'
|
|
|
|
ThangType = require 'models/ThangType'
|
2014-09-23 14:37:05 -04:00
|
|
|
SpriteBuilder = require 'lib/sprites/SpriteBuilder'
|
2014-09-19 17:56:40 -04:00
|
|
|
ogreMunchkinThangType = new ThangType(require 'test/app/fixtures/ogre-munchkin-m.thang.type')
|
|
|
|
ogreFangriderThangType = new ThangType(require 'test/app/fixtures/ogre-fangrider.thang.type')
|
2014-09-23 15:08:50 -04:00
|
|
|
treeThangType = new ThangType(require 'test/app/fixtures/tree1.thang.type')
|
2014-09-24 19:53:38 -04:00
|
|
|
scaleTestUtils = require './scale-testing-utils'
|
2014-09-19 17:56:40 -04:00
|
|
|
|
|
|
|
describe 'SegmentedSprite', ->
|
|
|
|
segmentedSprite = null
|
2014-09-23 14:37:05 -04:00
|
|
|
stage = null
|
2014-09-19 17:56:40 -04:00
|
|
|
|
|
|
|
showMe = ->
|
|
|
|
canvas = $('<canvas width="600" height="400"></canvas>').css('position', 'absolute').css('index', 1000).css('background', 'white')
|
|
|
|
$('body').append(canvas)
|
2014-09-23 14:37:05 -04:00
|
|
|
stage = new createjs.Stage(canvas[0]) # this is not a SpriteStage because some tests require adding MovieClips
|
2014-09-19 17:56:40 -04:00
|
|
|
stage.addChild(segmentedSprite)
|
2014-09-24 19:53:38 -04:00
|
|
|
scale = 3
|
|
|
|
stage.scaleX = stage.scaleY = scale
|
|
|
|
stage.regX = -300 / scale
|
|
|
|
stage.regY = -200 / scale
|
2014-09-23 14:37:05 -04:00
|
|
|
window.stage = stage
|
2014-09-19 17:56:40 -04:00
|
|
|
|
|
|
|
ticks = 0
|
|
|
|
listener = {
|
|
|
|
handleEvent: ->
|
|
|
|
return if ticks >= 100
|
|
|
|
ticks += 1
|
|
|
|
segmentedSprite.tick(arguments[0].delta)
|
|
|
|
stage.update()
|
|
|
|
}
|
|
|
|
createjs.Ticker.addEventListener "tick", listener
|
|
|
|
|
2014-09-23 15:08:50 -04:00
|
|
|
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)
|
|
|
|
|
|
|
|
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')
|
2014-09-24 19:53:38 -04:00
|
|
|
container.scaleX = container.scaleY = 0.3
|
2014-09-23 15:08:50 -04:00
|
|
|
container.regX = 59
|
|
|
|
container.regY = 100
|
|
|
|
showMe()
|
|
|
|
stage.addChild(container)
|
|
|
|
stage.update()
|
2014-09-24 19:53:38 -04:00
|
|
|
hitRate = scaleTestUtils.hitTest(stage, new createjs.Rectangle(-15, -30, 35, 40))
|
|
|
|
expect(hitRate).toBeGreaterThan(0.92)
|
|
|
|
$('canvas').remove()
|
2014-09-23 15:08:50 -04:00
|
|
|
|
|
|
|
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')
|
2014-09-24 19:53:38 -04:00
|
|
|
container.scaleX = container.scaleY = 0.3
|
2014-09-23 15:08:50 -04:00
|
|
|
container.regX = 59
|
|
|
|
container.regY = 100
|
|
|
|
showMe()
|
|
|
|
stage.addChild(container)
|
|
|
|
stage.update()
|
2014-09-24 19:53:38 -04:00
|
|
|
hitRate = scaleTestUtils.hitTest(stage, new createjs.Rectangle(-15, -30, 35, 40))
|
|
|
|
expect(hitRate).toBeGreaterThan(0.73)
|
2014-09-23 15:08:50 -04:00
|
|
|
$('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)
|
|
|
|
|
2014-09-19 17:56:40 -04:00
|
|
|
describe 'with Ogre Munchkin ThangType', ->
|
|
|
|
beforeEach ->
|
2014-09-19 18:46:02 -04:00
|
|
|
layer = new LayerAdapter({webGL:true})
|
2014-09-19 17:56:40 -04:00
|
|
|
layer.buildAutomatically = false
|
|
|
|
layer.buildAsync = false
|
|
|
|
ogreMunchkinThangType.markToRevert()
|
|
|
|
ogreMunchkinThangType.set('spriteType', 'segmented')
|
|
|
|
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}
|
2014-09-23 14:37:05 -04:00
|
|
|
actions.head = {container:'head'}
|
2014-09-19 17:56:40 -04:00
|
|
|
|
|
|
|
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.segmentedSprite = segmentedSprite = new SegmentedSprite(sheet, ogreMunchkinThangType, prefix)
|
|
|
|
|
|
|
|
afterEach ->
|
|
|
|
ogreMunchkinThangType.revert()
|
|
|
|
|
|
|
|
it 'has gotoAndPlay, gotoAndStop, currentAnimation, and paused like a MovieClip or Sprite', ->
|
|
|
|
segmentedSprite.gotoAndPlay('move_fore')
|
|
|
|
expect(segmentedSprite.baseMovieClip).toBeDefined()
|
|
|
|
expect(segmentedSprite.paused).toBe(false)
|
|
|
|
segmentedSprite.gotoAndStop('move_fore')
|
|
|
|
expect(segmentedSprite.paused).toBe(true)
|
|
|
|
expect(segmentedSprite.currentAnimation).toBe('move_fore')
|
|
|
|
|
|
|
|
it 'has a tick function which moves the animation forward', ->
|
|
|
|
segmentedSprite.gotoAndPlay('attack')
|
|
|
|
segmentedSprite.tick(100) # one hundred milliseconds
|
|
|
|
expect(segmentedSprite.baseMovieClip.currentFrame).toBe(segmentedSprite.framerate*100/1000)
|
|
|
|
|
|
|
|
it 'will interpolate between frames of a custom frame set', ->
|
|
|
|
segmentedSprite.gotoAndPlay('littledance')
|
|
|
|
segmentedSprite.tick(1000)
|
|
|
|
expect(segmentedSprite.baseMovieClip.currentFrame).toBe(6)
|
|
|
|
segmentedSprite.tick(1000)
|
|
|
|
expect(segmentedSprite.baseMovieClip.currentFrame).toBe(2)
|
|
|
|
segmentedSprite.tick(500)
|
|
|
|
expect(segmentedSprite.baseMovieClip.currentFrame).toBe(4)
|
|
|
|
segmentedSprite.tick(500)
|
|
|
|
expect(segmentedSprite.baseMovieClip.currentFrame).toBe(6)
|
|
|
|
|
|
|
|
it 'emits animationend for animations where loops is false and there is no goesTo', ->
|
|
|
|
fired = false
|
|
|
|
segmentedSprite.gotoAndPlay('onestep')
|
|
|
|
segmentedSprite.on('animationend', -> fired = true)
|
|
|
|
segmentedSprite.tick(1000)
|
|
|
|
expect(fired).toBe(true)
|
|
|
|
|
2014-09-23 14:37:05 -04:00
|
|
|
it 'scales rendered animations like a MovieClip', ->
|
|
|
|
# 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(ogreMunchkinThangType)
|
|
|
|
movieClip = builder.buildMovieClip('enemy_small_move_side')
|
2014-09-24 19:53:38 -04:00
|
|
|
movieClip.scaleX = movieClip.scaleY = 0.3
|
2014-09-23 14:37:05 -04:00
|
|
|
movieClip.regX = 285
|
|
|
|
movieClip.regY = 300
|
|
|
|
movieClip.stop()
|
|
|
|
showMe()
|
|
|
|
stage.addChild(movieClip)
|
2014-09-24 19:53:38 -04:00
|
|
|
|
2014-09-23 14:37:05 -04:00
|
|
|
stage.update()
|
2014-09-24 19:53:38 -04:00
|
|
|
hitRate = scaleTestUtils.hitTest(stage, new createjs.Rectangle(-10, -30, 25, 35))
|
|
|
|
expect(hitRate).toBeGreaterThan(0.91)
|
2014-09-23 14:37:05 -04:00
|
|
|
expect(segmentedSprite.baseScaleX).toBe(0.3)
|
|
|
|
expect(segmentedSprite.baseScaleY).toBe(0.3)
|
|
|
|
$('canvas').remove()
|
|
|
|
|
|
|
|
it 'scales placeholder animations like a MovieClip', ->
|
|
|
|
segmentedSprite.usePlaceholders = true
|
|
|
|
segmentedSprite.gotoAndStop('idle')
|
|
|
|
builder = new SpriteBuilder(ogreMunchkinThangType)
|
|
|
|
movieClip = builder.buildMovieClip('enemy_small_move_side')
|
2014-09-24 19:53:38 -04:00
|
|
|
movieClip.scaleX = movieClip.scaleY = 0.3
|
2014-09-23 14:37:05 -04:00
|
|
|
movieClip.regX = 285
|
|
|
|
movieClip.regY = 300
|
|
|
|
movieClip.stop()
|
|
|
|
showMe()
|
|
|
|
stage.addChild(movieClip)
|
|
|
|
stage.update()
|
2014-09-24 19:53:38 -04:00
|
|
|
hitRate = scaleTestUtils.hitTest(stage, new createjs.Rectangle(-10, -30, 25, 35))
|
|
|
|
expect(hitRate).toBeGreaterThan(0.96)
|
2014-09-23 14:37:05 -04:00
|
|
|
$('canvas').remove()
|
|
|
|
|
|
|
|
it 'propagates events from the segments through the segmented sprite', ->
|
|
|
|
fired = {}
|
|
|
|
segmentedSprite.on('click', -> fired.didIt = true)
|
|
|
|
segmentedSprite.gotoAndStop('idle')
|
|
|
|
segmentedSprite.children[0].children[0].dispatchEvent('click')
|
|
|
|
expect(fired.didIt).toBe(true)
|
|
|
|
|
2014-09-19 17:56:40 -04:00
|
|
|
describe 'with Ogre Fangrider ThangType', ->
|
|
|
|
beforeEach ->
|
2014-09-19 18:46:02 -04:00
|
|
|
layer = new LayerAdapter({webGL:true})
|
2014-09-19 17:56:40 -04:00
|
|
|
layer.buildAutomatically = false
|
|
|
|
layer.buildAsync = false
|
|
|
|
ogreFangriderThangType.markToRevert()
|
|
|
|
ogreFangriderThangType.set('spriteType', 'segmented')
|
|
|
|
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
|
|
|
sprite = new CocoSprite(ogreFangriderThangType, {colorConfig: colorConfig})
|
|
|
|
layer.addCocoSprite(sprite)
|
|
|
|
sheet = layer.renderNewSpriteSheet()
|
|
|
|
prefix = layer.renderGroupingKey(ogreFangriderThangType, null, colorConfig) + '.'
|
|
|
|
window.segmentedSprite = segmentedSprite = new SegmentedSprite(sheet, ogreFangriderThangType, prefix)
|
|
|
|
|
|
|
|
afterEach ->
|
|
|
|
ogreFangriderThangType.revert()
|
|
|
|
|
|
|
|
it 'synchronizes animations with child movie clips properly', ->
|
|
|
|
segmentedSprite.gotoAndPlay('die')
|
|
|
|
segmentedSprite.tick(100) # one hundred milliseconds
|
|
|
|
expectedFrame = segmentedSprite.framerate*100/1000
|
|
|
|
expect(segmentedSprite.currentFrame).toBe(expectedFrame)
|
|
|
|
for movieClip in segmentedSprite.childMovieClips
|
|
|
|
expect(movieClip.currentFrame).toBe(expectedFrame)
|
|
|
|
|
|
|
|
it 'does not include shapes from the original animation', ->
|
|
|
|
segmentedSprite.gotoAndPlay('attack')
|
|
|
|
segmentedSprite.tick(230)
|
|
|
|
for child in segmentedSprite.children
|
|
|
|
expect(_.isString(child)).toBe(false)
|
|
|
|
|
|
|
|
it 'maintains the right number of shapes', ->
|
|
|
|
segmentedSprite.gotoAndPlay('idle')
|
|
|
|
lengths = []
|
|
|
|
for i in _.range(10)
|
|
|
|
segmentedSprite.tick(10)
|
|
|
|
expect(segmentedSprite.children.length).toBe(20)
|