mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-14 07:00:01 -04:00
Working on SegmentedSprite mouse events, hit tests and scaling.
This commit is contained in:
parent
39b6b9ef84
commit
5de5d5658e
2 changed files with 95 additions and 7 deletions
|
@ -25,12 +25,16 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
|
||||
action = @thangType.getActions()[actionName]
|
||||
randomStart = actionName.startsWith('move')
|
||||
|
||||
# because the resulting segmented image is set to the size of the movie clip, you can use
|
||||
# the raw registration data without scaling it.
|
||||
reg = action.positions?.registration or @thangType.get('positions')?.registration or {x:0, y:0}
|
||||
@regX = -reg.x
|
||||
@regY = -reg.y
|
||||
|
||||
if action.animation
|
||||
@framerate = (action.framerate ? 20) * (action.speed ? 1)
|
||||
@regX = -reg.x
|
||||
@regY = -reg.y
|
||||
@baseScaleY = @baseScaleX = action.scale ? @thangType.get('scale') ? 1
|
||||
@childMovieClips = []
|
||||
@baseMovieClip = @buildMovieClip(action.animation)
|
||||
@children = @baseMovieClip.children
|
||||
|
@ -42,11 +46,10 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
@loop = action.loops isnt false
|
||||
@goesTo = action.goesTo
|
||||
@notifyActionNeedsRender(action) if @actionNotSupported
|
||||
@updateBaseMovieClip()
|
||||
|
||||
else if action.container
|
||||
scale = @resolutionFactor * (action.scale ? @thangType.get('scale') ? 1)
|
||||
@regX = -reg.x
|
||||
@regY = -reg.y
|
||||
@childMovieClips = []
|
||||
containerName = @spriteSheetPrefix + action.container
|
||||
sprite = new createjs.Sprite(@spriteSheet)
|
||||
|
@ -63,6 +66,10 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
@children = [sprite]
|
||||
|
||||
return
|
||||
|
||||
updateBaseMovieClip: ->
|
||||
return unless @baseMovieClip
|
||||
@baseMovieClip[prop] = @[prop] for prop in ['x', 'y', 'regX', 'regY']
|
||||
|
||||
notifyActionNeedsRender: (action) ->
|
||||
@sprite?.trigger('action-needs-render', @sprite, action)
|
||||
|
@ -107,7 +114,9 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
outerContainer = new createjs.SpriteContainer(@spriteSheet)
|
||||
innerContainer = new createjs.Sprite(@spriteSheet)
|
||||
innerContainer.gotoAndStop(@spriteSheetPrefix + localContainer.gn)
|
||||
if innerContainer.currentFrame is 0
|
||||
@listenToEventsFor(innerContainer)
|
||||
if innerContainer.currentFrame is 0 or @usePlaceholders
|
||||
innerContainer.gotoAndStop(0)
|
||||
@actionNotSupported = true
|
||||
bounds = @thangType.get('raw').containers[localContainer.gn].b
|
||||
innerContainer.x = bounds[0]
|
||||
|
@ -123,6 +132,12 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
map[localContainer.bn] = outerContainer
|
||||
return map
|
||||
|
||||
listenToEventsFor: (displayObject) ->
|
||||
for event in ['mousedown', 'click', 'dblclick', 'pressmove', 'pressup']
|
||||
displayObject.on event, @onMouseEvent, @
|
||||
|
||||
onMouseEvent: (e) -> @dispatchEvent(e)
|
||||
|
||||
buildMovieClipAnimations: (localAnimations) ->
|
||||
map = {}
|
||||
for localAnimation in localAnimations
|
||||
|
|
|
@ -2,17 +2,20 @@ LayerAdapter = require 'lib/surface/LayerAdapter'
|
|||
SegmentedSprite = require 'lib/surface/SegmentedSprite'
|
||||
CocoSprite = require 'lib/surface/CocoSprite'
|
||||
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')
|
||||
|
||||
describe 'SegmentedSprite', ->
|
||||
segmentedSprite = null
|
||||
stage = null
|
||||
|
||||
showMe = ->
|
||||
canvas = $('<canvas width="600" height="400"></canvas>').css('position', 'absolute').css('index', 1000).css('background', 'white')
|
||||
$('body').append(canvas)
|
||||
stage = new createjs.SpriteStage(canvas[0])
|
||||
stage = new createjs.Stage(canvas[0]) # this is not a SpriteStage because some tests require adding MovieClips
|
||||
stage.addChild(segmentedSprite)
|
||||
window.stage = stage
|
||||
|
||||
ticks = 0
|
||||
listener = {
|
||||
|
@ -36,6 +39,7 @@ describe 'SegmentedSprite', ->
|
|||
# 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}
|
||||
actions.head = {container:'head'}
|
||||
|
||||
colorConfig = {team: {hue: 0, saturation: 1, lightness: 0.5}}
|
||||
sprite = new CocoSprite(ogreMunchkinThangType, {colorConfig: colorConfig})
|
||||
|
@ -43,7 +47,7 @@ describe 'SegmentedSprite', ->
|
|||
sheet = layer.renderNewSpriteSheet()
|
||||
prefix = layer.renderGroupingKey(ogreMunchkinThangType, null, colorConfig) + '.'
|
||||
window.segmentedSprite = segmentedSprite = new SegmentedSprite(sheet, ogreMunchkinThangType, prefix)
|
||||
segmentedSprite.x = 200
|
||||
segmentedSprite.x = 100
|
||||
segmentedSprite.y = 200
|
||||
|
||||
afterEach ->
|
||||
|
@ -80,6 +84,75 @@ describe 'SegmentedSprite', ->
|
|||
segmentedSprite.tick(1000)
|
||||
expect(fired).toBe(true)
|
||||
|
||||
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')
|
||||
movieClip.x = 100
|
||||
movieClip.y = 200
|
||||
movieClip.regX = 285
|
||||
movieClip.regY = 300
|
||||
movieClip.stop()
|
||||
showMe()
|
||||
stage.addChild(movieClip)
|
||||
stage.update()
|
||||
t = new Date()
|
||||
tests = hits = 0
|
||||
for x in _.range(50, 160, 20)
|
||||
for y in _.range(50, 220, 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
|
||||
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 animations like a MovieClip', ->
|
||||
segmentedSprite.usePlaceholders = true
|
||||
segmentedSprite.gotoAndStop('idle')
|
||||
builder = new SpriteBuilder(ogreMunchkinThangType)
|
||||
movieClip = builder.buildMovieClip('enemy_small_move_side')
|
||||
movieClip.x = 100
|
||||
movieClip.y = 200
|
||||
movieClip.regX = 285
|
||||
movieClip.regY = 300
|
||||
movieClip.stop()
|
||||
showMe()
|
||||
stage.addChild(movieClip)
|
||||
stage.update()
|
||||
t = new Date()
|
||||
tests = hits = 0
|
||||
for x in _.range(50, 160, 20)
|
||||
for y in _.range(50, 220, 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
|
||||
else
|
||||
hits += 1
|
||||
|
||||
expect(hits / tests).toBeGreaterThan(0.96) # not as perfect, but still, close!
|
||||
$('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)
|
||||
|
||||
describe 'with Ogre Fangrider ThangType', ->
|
||||
beforeEach ->
|
||||
layer = new LayerAdapter({webGL:true})
|
||||
|
|
Loading…
Reference in a new issue