mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-03-24 11:50:58 -04:00
Most of the way there with the raster images. Just need to figure out loading with PreloadJS and the SuperModel.
This commit is contained in:
parent
eacbf571c6
commit
aee90c72bb
8 changed files with 104 additions and 37 deletions
app
lib
models
schemas/models
views
server/levels/thangs
|
@ -168,6 +168,10 @@ module.exports = class LevelLoader extends CocoClass
|
|||
# Building sprite sheets
|
||||
|
||||
buildSpriteSheetsForThangType: (thangType) ->
|
||||
# TODO: Finish making sure the supermodel loads the raster image before triggering load complete, and that the cocosprite has access to the asset.
|
||||
# if f = thangType.get('raster')
|
||||
# queue = new createjs.LoadQueue()
|
||||
# queue.loadFile('/file/'+f)
|
||||
@grabThangTypeTeams() unless @thangTypeTeams
|
||||
for team in @thangTypeTeams[thangType.get('original')] ? [null]
|
||||
spriteOptions = {resolutionFactor: 4, async: false}
|
||||
|
|
|
@ -70,7 +70,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@age = 0
|
||||
@scaleFactor = @targetScaleFactor = 1
|
||||
@displayObject = new createjs.Container()
|
||||
if @thangType.get('actions')
|
||||
if @thangType.get('actions') or @thangType.get('raster')
|
||||
@setupSprite()
|
||||
else
|
||||
@stillLoading = true
|
||||
|
@ -79,9 +79,29 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
|
||||
setupSprite: ->
|
||||
@stillLoading = false
|
||||
@actions = @thangType.getActions()
|
||||
@buildFromSpriteSheet @buildSpriteSheet()
|
||||
@createMarks()
|
||||
if @thangType.get('raster')
|
||||
@isRaster = true
|
||||
@setUpRasterImage()
|
||||
@actions = {}
|
||||
else
|
||||
@actions = @thangType.getActions()
|
||||
@buildFromSpriteSheet @buildSpriteSheet()
|
||||
@createMarks()
|
||||
|
||||
setUpRasterImage: ->
|
||||
raster = @thangType.get('raster')
|
||||
sprite = @imageObject = new createjs.Bitmap('/file/'+raster)
|
||||
@displayObject.addChild(sprite)
|
||||
@configureMouse()
|
||||
@originalScaleX = sprite.scaleX
|
||||
@originalScaleY = sprite.scaleY
|
||||
@displayObject.sprite = @
|
||||
@displayObject.layerPriority = @thangType.get 'layerPriority'
|
||||
@displayObject.name = @thang?.spriteName or @thangType.get 'name'
|
||||
reg = @getOffset 'registration'
|
||||
@imageObject.regX = -reg.x
|
||||
@imageObject.regY = -reg.y
|
||||
@updateScale()
|
||||
|
||||
destroy: ->
|
||||
mark.destroy() for name, mark of @marks
|
||||
|
@ -143,6 +163,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
@playAction(@actionQueue.splice(0,1)[0]) if @actionQueue.length
|
||||
|
||||
playAction: (action) ->
|
||||
return if @isRaster
|
||||
@currentAction = action
|
||||
return @hide() unless action.animation or action.container or action.relatedActions
|
||||
@show()
|
||||
|
@ -244,13 +265,14 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
updateScale: ->
|
||||
if @thangType.get('matchWorldDimensions') and @thang
|
||||
if @thang.width isnt @lastThangWidth or @thang.height isnt @lastThangHeight
|
||||
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
||||
bounds = @imageObject.getBounds()
|
||||
return unless bounds # TODO: remove this because it's a bandaid over the image sometimes not being loaded
|
||||
@imageObject.scaleX = @thang.width * Camera.PPM / bounds.width
|
||||
@imageObject.scaleY = @thang.height * Camera.PPM * @options.camera.y2x / bounds.height
|
||||
unless @thang.spriteName is 'Beam'
|
||||
@imageObject.scaleX *= @thangType.get('scale') ? 1
|
||||
@imageObject.scaleY *= @thangType.get('scale') ? 1
|
||||
[@lastThangWidth, @lastThangHeight] = [@thang.width, @thang.height]
|
||||
return
|
||||
scaleX = if @getActionProp 'flipX' then -1 else 1
|
||||
scaleY = if @getActionProp 'flipY' then -1 else 1
|
||||
|
@ -267,6 +289,12 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
angle = -angle if angle < 0
|
||||
angle = 180 - angle if angle > 90
|
||||
scaleX = 0.5 + 0.5 * (90 - angle) / 90
|
||||
|
||||
if @isRaster # scale is worked into building the sprite sheet for animations
|
||||
scale = @thangType.get('scale') or 1
|
||||
scaleX *= scale
|
||||
scaleY *= scale
|
||||
|
||||
scaleFactorX = @thang.scaleFactorX ? @scaleFactor
|
||||
scaleFactorY = @thang.scaleFactorY ? @scaleFactor
|
||||
@imageObject.scaleX = @originalScaleX * scaleX * scaleFactorX
|
||||
|
@ -319,6 +347,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
|
||||
##################################################
|
||||
updateAction: ->
|
||||
return if @isRaster
|
||||
action = @determineAction()
|
||||
isDifferent = action isnt @currentRootAction or action is null
|
||||
if not action and @thang?.actionActivated and not @stopLogging
|
||||
|
@ -440,10 +469,11 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
def = x: 0, y: {registration: 0, torso: -50, mouth: -60, aboveHead: -100}[prop]
|
||||
pos = @getActionProp 'positions', prop, def
|
||||
pos = x: pos.x, y: pos.y
|
||||
scale = @getActionProp 'scale', null, 1
|
||||
scale *= @options.resolutionFactor if prop is 'registration'
|
||||
pos.x *= scale
|
||||
pos.y *= scale
|
||||
if not @isRaster
|
||||
scale = @getActionProp 'scale', null, 1
|
||||
scale *= @options.resolutionFactor if prop is 'registration'
|
||||
pos.x *= scale
|
||||
pos.y *= scale
|
||||
if @thang and prop isnt 'registration'
|
||||
scaleFactor = @thang.scaleFactor ? 1
|
||||
pos.x *= @thang.scaleFactorX ? scaleFactor
|
||||
|
@ -654,7 +684,7 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
z = @shadow.pos.z
|
||||
@shadow.pos = pos
|
||||
@shadow.pos.z = z
|
||||
@imageObject.gotoAndPlay(endAnimation)
|
||||
@imageObject.gotoAndPlay?(endAnimation)
|
||||
return
|
||||
|
||||
@shadow.action = 'move'
|
||||
|
|
|
@ -145,7 +145,11 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
|
||||
addThangToSprites: (thang, layer=null) ->
|
||||
return console.warn 'Tried to add Thang to the surface it already has:', thang.id if @sprites[thang.id]
|
||||
thangType = _.find @options.thangTypes, (m) -> m.get('actions') and m.get('name') is thang.spriteName
|
||||
thangType = _.find @options.thangTypes, (m) ->
|
||||
return false unless m.get('actions') or m.get('raster')
|
||||
return m.get('name') is thang.spriteName
|
||||
thangType ?= _.find @options.thangTypes, (m) -> return m.get('name') is thang.spriteName
|
||||
|
||||
options = @createSpriteOptions thang: thang
|
||||
options.resolutionFactor = if thangType.get('kind') is 'Floor' then 2 else 4
|
||||
sprite = new CocoSprite thangType, options
|
||||
|
@ -221,12 +225,12 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
onCastSpells: -> @stop()
|
||||
|
||||
play: ->
|
||||
sprite.imageObject.play() for sprite in @spriteArray
|
||||
sprite.imageObject.play?() for sprite in @spriteArray
|
||||
@selectionMark?.play()
|
||||
@targetMark?.play()
|
||||
|
||||
stop: ->
|
||||
sprite.imageObject.stop() for sprite in @spriteArray
|
||||
sprite.imageObject.stop?() for sprite in @spriteArray
|
||||
@selectionMark?.stop()
|
||||
@targetMark?.stop()
|
||||
|
||||
|
|
|
@ -210,8 +210,8 @@ module.exports = class ThangType extends CocoModel
|
|||
@tick = null
|
||||
stage
|
||||
|
||||
uploadGenericPortrait: (callback) ->
|
||||
src = @getPortraitSource()
|
||||
uploadGenericPortrait: (callback, src) ->
|
||||
src ?= @getPortraitSource()
|
||||
return callback?() unless src
|
||||
src = src.replace('data:image/png;base64,', '').replace(/\ /g, '+')
|
||||
body =
|
||||
|
|
|
@ -123,6 +123,7 @@ _.extend ThangTypeSchema.properties,
|
|||
title: 'Scale'
|
||||
type: 'number'
|
||||
positions: PositionsSchema
|
||||
raster: { type: 'string', format: 'image-file', title: 'Raster Image' }
|
||||
colorGroups: c.object
|
||||
title: 'Color Groups'
|
||||
additionalProperties:
|
||||
|
|
|
@ -197,6 +197,7 @@ module.exports = class ThangTypeEditView extends View
|
|||
# animation select
|
||||
|
||||
refreshAnimation: ->
|
||||
return @showRasterImage() if @thangType.get('raster')
|
||||
options = @getSpriteOptions()
|
||||
@thangType.resetSpriteSheetCache()
|
||||
spriteSheet = @thangType.buildSpriteSheet(options)
|
||||
|
@ -207,6 +208,13 @@ module.exports = class ThangTypeEditView extends View
|
|||
@showAnimation()
|
||||
@updatePortrait()
|
||||
|
||||
showRasterImage: ->
|
||||
sprite = new CocoSprite(@thangType, @getSpriteOptions())
|
||||
@currentSprite?.destroy()
|
||||
@currentSprite = sprite
|
||||
@showDisplayObject(sprite.displayObject)
|
||||
@updateScale()
|
||||
|
||||
showAnimation: (animationName) ->
|
||||
animationName = @$el.find('#animations-select').val() unless _.isString animationName
|
||||
return unless animationName
|
||||
|
@ -310,8 +318,13 @@ module.exports = class ThangTypeEditView extends View
|
|||
|
||||
res.success =>
|
||||
url = "/editor/thang/#{newThangType.get('slug') or newThangType.id}"
|
||||
newThangType.uploadGenericPortrait ->
|
||||
document.location.href = url
|
||||
portraitSource = null
|
||||
if @thangType.get('raster')
|
||||
image = @currentSprite.imageObject.image
|
||||
portraitSource = imageToPortrait image
|
||||
# bit of a hacky way to get that portrait
|
||||
success = -> document.location.href = url
|
||||
newThangType.uploadGenericPortrait success, portraitSource
|
||||
|
||||
clearRawData: ->
|
||||
@thangType.resetRawData()
|
||||
|
@ -393,3 +406,14 @@ module.exports = class ThangTypeEditView extends View
|
|||
destroy: ->
|
||||
@camera?.destroy()
|
||||
super()
|
||||
|
||||
imageToPortrait = (img) ->
|
||||
canvas = document.createElement("canvas")
|
||||
canvas.width = 100
|
||||
canvas.height = 100
|
||||
ctx = canvas.getContext("2d")
|
||||
scaleX = 100 / img.width
|
||||
scaleY = 100 / img.height
|
||||
ctx.scale scaleX, scaleY
|
||||
ctx.drawImage img, 0, 0
|
||||
canvas.toDataURL("image/png")
|
|
@ -112,16 +112,19 @@ module.exports = class HUDView extends View
|
|||
options = thang.getSpriteOptions() or {}
|
||||
options.async = false
|
||||
options.colorConfig = colorConfig if colorConfig
|
||||
stage = thangType.getPortraitStage options
|
||||
wrapper = @$el.find '.thang-canvas-wrapper'
|
||||
newCanvas = $(stage.canvas).addClass('thang-canvas')
|
||||
wrapper.empty().append(newCanvas)
|
||||
team = @thang?.team or @speakerSprite?.thang?.team
|
||||
wrapper.removeClass (i, css) -> (css.match(/\bteam-\S+/g) or []).join ' '
|
||||
wrapper.addClass "team-#{team}"
|
||||
stage.update()
|
||||
@stage?.stopTalking()
|
||||
@stage = stage
|
||||
if thangType.get('raster')
|
||||
wrapper.empty().append($('<img />').attr('src', '/file/'+thangType.get('raster')))
|
||||
else
|
||||
stage = thangType.getPortraitStage options
|
||||
newCanvas = $(stage.canvas).addClass('thang-canvas')
|
||||
wrapper.empty().append(newCanvas)
|
||||
stage.update()
|
||||
@stage?.stopTalking()
|
||||
@stage = stage
|
||||
|
||||
onThangBeganTalking: (e) ->
|
||||
return unless @stage and @thang is e.thang
|
||||
|
|
|
@ -5,21 +5,22 @@ ThangTypeHandler = class ThangTypeHandler extends Handler
|
|||
modelClass: ThangType
|
||||
jsonSchema: require '../../../app/schemas/models/thang_type'
|
||||
editableProperties: [
|
||||
'name',
|
||||
'raw',
|
||||
'actions',
|
||||
'soundTriggers',
|
||||
'rotationType',
|
||||
'matchWorldDimensions',
|
||||
'shadow',
|
||||
'layerPriority',
|
||||
'staticImage',
|
||||
'scale',
|
||||
'positions',
|
||||
'snap',
|
||||
'components',
|
||||
'colorGroups',
|
||||
'name'
|
||||
'raw'
|
||||
'actions'
|
||||
'soundTriggers'
|
||||
'rotationType'
|
||||
'matchWorldDimensions'
|
||||
'shadow'
|
||||
'layerPriority'
|
||||
'staticImage'
|
||||
'scale'
|
||||
'positions'
|
||||
'snap'
|
||||
'components'
|
||||
'colorGroups'
|
||||
'kind'
|
||||
'raster'
|
||||
]
|
||||
|
||||
hasAccess: (req) ->
|
||||
|
|
Loading…
Add table
Reference in a new issue