mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-11-23 23:58:02 -05:00
Merge branch 'master' of github.com:codecombat/codecombat
This commit is contained in:
commit
43f56c7ff7
55 changed files with 7031 additions and 7101 deletions
Binary file not shown.
Before Width: | Height: | Size: 65 KiB After Width: | Height: | Size: 64 KiB |
BIN
app/assets/images/pages/play/modal/k-means.gif
Normal file
BIN
app/assets/images/pages/play/modal/k-means.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 MiB |
|
@ -130,7 +130,7 @@ module.exports = class Angel extends CocoClass
|
|||
eventType = if finished then 'god:new-world-created' else 'god:streaming-world-updated'
|
||||
if finished
|
||||
@shared.world = world
|
||||
Backbone.Mediator.publish eventType, world: world, firstWorld: @shared.firstWorld, goalStates: goalStates, team: me.team, firstChangedFrame: firstChangedFrame
|
||||
Backbone.Mediator.publish eventType, world: world, firstWorld: @shared.firstWorld, goalStates: goalStates, team: me.team, firstChangedFrame: firstChangedFrame, finished: finished
|
||||
if finished
|
||||
for scriptNote in @shared.world.scriptNotes
|
||||
Backbone.Mediator.publish scriptNote.channel, scriptNote.event
|
||||
|
|
|
@ -123,7 +123,7 @@ class AudioPlayer extends CocoClass
|
|||
return if filename of cache
|
||||
name ?= filename
|
||||
# SoundJS flips out if you try to register the same file twice
|
||||
createjs.Sound.registerSound(filename, name, 1, true) # 1: 1 channel, true: should preload
|
||||
result = createjs.Sound.registerSound(filename, name, 1) # 1: 1 channel
|
||||
cache[filename] = new Media(name)
|
||||
|
||||
# PROGRESS CALLBACKS
|
||||
|
|
|
@ -211,10 +211,12 @@ module.exports = class LevelBus extends Bus
|
|||
@changedSessionProperties.state = true
|
||||
@reallySaveSession() # Make sure it saves right away; don't debounce it.
|
||||
|
||||
onNewGoalStates: ({goalStates}) ->
|
||||
onNewGoalStates: (e) ->
|
||||
# TODO: this log doesn't capture when null-status goals are being set during world streaming. Where can they be coming from?
|
||||
goalStates = e.goalStates
|
||||
return console.error("Somehow trying to save null goal states!", newGoalStates) if _.find(newGoalStates, (gs) -> not gs.status)
|
||||
|
||||
return unless e.overallStatus is 'success'
|
||||
newGoalStates = goalStates
|
||||
state = @session.get('state')
|
||||
oldGoalStates = state.goalStates or {}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
module.exports = LevelOptions =
|
||||
'dungeons-of-kithgard':
|
||||
disableSpaces: true
|
||||
hidesSubmitUntilRun: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
|
@ -10,6 +11,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots'}
|
||||
restrictedGear: {feet: 'leather-boots'}
|
||||
'gems-in-the-deep':
|
||||
disableSpaces: true
|
||||
hidesSubmitUntilRun: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
|
@ -20,6 +22,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots'}
|
||||
restrictedGear: {feet: 'leather-boots'}
|
||||
'shadow-guard':
|
||||
disableSpaces: true
|
||||
hidesSubmitUntilRun: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
|
@ -30,6 +33,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots'}
|
||||
restrictedGear: {feet: 'leather-boots', 'right-hand': 'simple-sword'}
|
||||
'kounter-kithwise':
|
||||
disableSpaces: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
hidesHUD: true
|
||||
|
@ -48,6 +52,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots'}
|
||||
restrictedGear: {feet: 'leather-boots', 'right-hand': 'simple-sword', 'programming-book': 'programmaticon-i'}
|
||||
'forgetful-gemsmith':
|
||||
disableSpaces: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
hidesHUD: true
|
||||
|
@ -57,6 +62,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots'}
|
||||
restrictedGear: {feet: 'leather-boots', 'programming-book': 'programmaticon-i'}
|
||||
'true-names':
|
||||
disableSpaces: true
|
||||
hidesPlayButton: true
|
||||
hidesRunShortcut: true
|
||||
hidesHUD: true
|
||||
|
@ -66,6 +72,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword', waist: 'leather-belt'}
|
||||
restrictedGear: {feet: 'leather-boots'}
|
||||
'favorable-odds':
|
||||
disableSpaces: true
|
||||
hidesRunShortcut: true
|
||||
hidesHUD: true
|
||||
hidesSay: true
|
||||
|
@ -74,6 +81,7 @@ module.exports = LevelOptions =
|
|||
requiredGear: {feet: 'simple-boots', 'right-hand': 'simple-sword'}
|
||||
restrictedGear: {feet: 'leather-boots'}
|
||||
'the-raised-sword':
|
||||
disableSpaces: true
|
||||
hidesRunShortcut: true
|
||||
hidesHUD: true
|
||||
hidesSay: true
|
||||
|
|
|
@ -25,6 +25,7 @@ module.exports = class MusicPlayer extends CocoClass
|
|||
@onPlayMusic(@standingBy) if @standingBy
|
||||
|
||||
onPlayMusic: (e) ->
|
||||
return if application.isIPadApp # Hard to measure, but just guessing this will save memory.
|
||||
src = e.file
|
||||
src = "/file#{e.file}#{AudioPlayer.ext}"
|
||||
if (not e.file) or src is @currentMusic?.src
|
||||
|
|
|
@ -13,7 +13,7 @@ module.exports = class SegmentedSprite extends createjs.SpriteContainer
|
|||
|
||||
constructor: (@spriteSheet, @thangType, @spriteSheetPrefix, @resolutionFactor=SPRITE_RESOLUTION_FACTOR) ->
|
||||
@spriteSheet.mcPool ?= {}
|
||||
@initialize(@spriteSheet)
|
||||
super(@spriteSheet)
|
||||
@addEventListener 'tick', @handleTick
|
||||
|
||||
destroy: ->
|
||||
|
|
|
@ -6,7 +6,7 @@ module.exports = class SingularSprite extends createjs.Sprite
|
|||
childMovieClips: null
|
||||
|
||||
constructor: (@spriteSheet, @thangType, @spriteSheetPrefix, @resolutionFactor=SPRITE_RESOLUTION_FACTOR) ->
|
||||
@initialize(@spriteSheet)
|
||||
super(@spriteSheet)
|
||||
|
||||
destroy: ->
|
||||
@removeAllEventListeners()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
CocoClass = require 'lib/CocoClass'
|
||||
path = require './path'
|
||||
TrailMaster = require './TrailMaster'
|
||||
Dropper = require './Dropper'
|
||||
AudioPlayer = require 'lib/AudioPlayer'
|
||||
{me} = require 'lib/auth'
|
||||
|
@ -181,7 +181,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
framesDropped = 0
|
||||
while true
|
||||
Dropper.tick()
|
||||
@trailmaster.tick() if @trailmaster
|
||||
# Skip some frame updates unless we're playing and not at end (or we haven't drawn much yet)
|
||||
frameAdvanced = (@playing and @currentFrame < lastFrame) or @totalFramesDrawn < 2
|
||||
if frameAdvanced and @playing
|
||||
|
@ -210,7 +209,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@updateState @currentFrame isnt oldFrame
|
||||
@drawCurrentFrame e
|
||||
@onFrameChanged()
|
||||
@updatePaths() if (@totalFramesDrawn % 4) is 0 or createjs.Ticker.getMeasuredFPS() > createjs.Ticker.getFPS() - 5
|
||||
Backbone.Mediator.publish('surface:ticked', {dt: 1 / @options.frameRate})
|
||||
mib = @webGLStage.mouseInBounds
|
||||
if @mouseInBounds isnt mib
|
||||
|
@ -314,10 +312,12 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
if paused
|
||||
@surfacePauseTimeout = _.delay performToggle, 2000
|
||||
@lankBoss.stop()
|
||||
@trailmaster?.stop()
|
||||
@playbackOverScreen.show()
|
||||
else
|
||||
performToggle()
|
||||
@lankBoss.play()
|
||||
@trailmaster?.play()
|
||||
@playbackOverScreen.hide()
|
||||
|
||||
|
||||
|
@ -456,7 +456,11 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@fastForwardingSpeed = lag / intendedLag
|
||||
else
|
||||
@fastForwardingToFrame = @fastForwardingSpeed = null
|
||||
#console.log "on new world, lag", lag, "intended lag", intendedLag, "fastForwardingToFrame", @fastForwardingToFrame, "speed", @fastForwardingSpeed, "cause we are at", @world.age, "of", @world.frames.length * @world.dt
|
||||
# console.log "on new world, lag", lag, "intended lag", intendedLag, "fastForwardingToFrame", @fastForwardingToFrame, "speed", @fastForwardingSpeed, "cause we are at", @world.age, "of", @world.frames.length * @world.dt
|
||||
if event.finished
|
||||
@updatePaths()
|
||||
else
|
||||
@hidePaths()
|
||||
|
||||
onIdleChanged: (e) ->
|
||||
@setPaused e.idle unless @ended
|
||||
|
@ -540,10 +544,12 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
#- Camera focus on hero
|
||||
focusOnHero: ->
|
||||
hadHero = @heroLank
|
||||
@heroLank = @lankBoss.lankFor 'Hero Placeholder'
|
||||
if me.team is 'ogres'
|
||||
# TODO: do this for real
|
||||
@heroLank = @lankBoss.lankFor 'Hero Placeholder 1'
|
||||
@updatePaths() if not hadHero
|
||||
|
||||
#- Real-time playback
|
||||
|
||||
|
@ -576,22 +582,16 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
|
||||
|
||||
#- Paths - TODO: move to LankBoss? but only update on frame drawing instead of on every frame update?
|
||||
|
||||
updatePaths: ->
|
||||
return # TODO: Get paths working again with WebGL
|
||||
return unless @options.paths
|
||||
return if @casting
|
||||
return unless @options.paths and @heroLank
|
||||
return unless me.isAdmin() # TODO: Fix world thang points, targets, then remove this
|
||||
@hidePaths()
|
||||
selectedThang = @lankBoss.selectedLank?.thang
|
||||
return if @world.showPaths is 'never'
|
||||
return if @world.showPaths is 'paused' and @playing
|
||||
return if @world.showPaths is 'selected' and not selectedThang
|
||||
@trailmaster ?= new path.Trailmaster @camera
|
||||
selectedOnly = @playing and @world.showPaths is 'selected'
|
||||
@paths = @trailmaster.generatePaths @world, @getCurrentFrame(), selectedThang, @lankBoss.lanks, selectedOnly
|
||||
layerAdapter = @lankBoss.layerAdapters['Path']
|
||||
@trailmaster ?= new TrailMaster @camera, layerAdapter
|
||||
@paths = @trailmaster.generatePaths @world, @heroLank.thang
|
||||
@paths.name = 'paths'
|
||||
@lankBoss.layerAdapters['Path'].addChild @paths
|
||||
layerAdapter.addChild @paths
|
||||
|
||||
hidePaths: ->
|
||||
return if not @paths
|
||||
|
@ -699,6 +699,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@normalStage.clear()
|
||||
@webGLStage.clear()
|
||||
@musicPlayer?.destroy()
|
||||
@trailmaster?.destroy()
|
||||
@normalStage.removeAllChildren()
|
||||
@webGLStage.removeAllChildren()
|
||||
@webGLStage.removeEventListener 'stagemousemove', @onMouseMove
|
||||
|
|
122
app/lib/surface/TrailMaster.coffee
Normal file
122
app/lib/surface/TrailMaster.coffee
Normal file
|
@ -0,0 +1,122 @@
|
|||
PAST_PATH_ALPHA = 0.75
|
||||
PAST_PATH_WIDTH = 5
|
||||
FUTURE_PATH_ALPHA = 0.75
|
||||
FUTURE_PATH_WIDTH = 4
|
||||
TARGET_ALPHA = 1
|
||||
TARGET_WIDTH = 10
|
||||
FUTURE_PATH_INTERVAL_DIVISOR = 4
|
||||
PAST_PATH_INTERVAL_DIVISOR = 2
|
||||
|
||||
Camera = require './Camera'
|
||||
CocoClass = require 'lib/CocoClass'
|
||||
|
||||
module.exports = class TrailMaster extends CocoClass
|
||||
world: null
|
||||
|
||||
constructor: (@camera, @layerAdapter) ->
|
||||
super()
|
||||
@tweenedSprites = []
|
||||
@tweens = []
|
||||
@listenTo @layerAdapter, 'new-spritesheet', -> @generatePaths(@world, @thang)
|
||||
|
||||
generatePaths: (@world, @thang) ->
|
||||
return if @generatingPaths
|
||||
@generatingPaths = true
|
||||
@cleanUp()
|
||||
@createGraphics()
|
||||
pathDisplayObject = new createjs.SpriteContainer(@layerAdapter.spriteSheet)
|
||||
pathDisplayObject.mouseEnabled = pathDisplayObject.mouseChildren = false
|
||||
pathDisplayObject.addChild @createFuturePath()
|
||||
# pathDisplayObject.addChild @createPastPath() # Just made the animated path the full path... do we want to have past and future look different again?
|
||||
pathDisplayObject.addChild @createTargets()
|
||||
@generatingPaths = false
|
||||
return pathDisplayObject
|
||||
|
||||
cleanUp: ->
|
||||
createjs.Tween.removeTweens(sprite) for sprite in @tweenedSprites
|
||||
@tweenedSprites = []
|
||||
@tweens = []
|
||||
|
||||
createGraphics: ->
|
||||
@targetDotKey = @cachePathDot(TARGET_WIDTH, @colorForThang(@thang.team, TARGET_ALPHA), [0, 0, 0, 1])
|
||||
@pastDotKey = @cachePathDot(PAST_PATH_WIDTH, @colorForThang(@thang.team, PAST_PATH_ALPHA), [0, 0, 0, 1])
|
||||
@futureDotKey = @cachePathDot(FUTURE_PATH_WIDTH, [255, 255, 255, FUTURE_PATH_ALPHA], @colorForThang(@thang.team, 1))
|
||||
|
||||
cachePathDot: (width, fillColor, strokeColor) ->
|
||||
key = "path-dot-#{width}-#{fillColor}-#{strokeColor}"
|
||||
fillColor = createjs.Graphics.getRGB(fillColor...)
|
||||
strokeColor = createjs.Graphics.getRGB(strokeColor...)
|
||||
unless key in @layerAdapter.spriteSheet.getAnimations()
|
||||
circle = new createjs.Shape()
|
||||
radius = width/2
|
||||
circle.graphics.setStrokeStyle(width/5).beginFill(fillColor).beginStroke(strokeColor).drawCircle(0, 0, radius)
|
||||
@layerAdapter.addCustomGraphic(key, circle, [-radius*1.5, -radius*1.5, radius*3, radius*3])
|
||||
return key
|
||||
|
||||
colorForThang: (team, alpha=1.0) ->
|
||||
rgb = [0, 255, 0]
|
||||
rgb = [255, 0, 0] if team is 'humans'
|
||||
rgb = [0, 0, 255] if team is 'ogres'
|
||||
rgb.push(alpha)
|
||||
return rgb
|
||||
|
||||
createPastPath: ->
|
||||
return unless points = @world.pointsForThang @thang.id, @camera
|
||||
interval = Math.max(1, parseInt(@world.frameRate / PAST_PATH_INTERVAL_DIVISOR))
|
||||
params = { interval: interval, frameKey: @pastDotKey }
|
||||
return @createPath(points, params)
|
||||
|
||||
createFuturePath: ->
|
||||
return unless points = @world.pointsForThang @thang.id, @camera
|
||||
interval = Math.max(1, parseInt(@world.frameRate / FUTURE_PATH_INTERVAL_DIVISOR))
|
||||
params = { interval: interval, animate: true, frameKey: @futureDotKey }
|
||||
return @createPath(points, params)
|
||||
|
||||
createTargets: ->
|
||||
return unless @thang.allTargets
|
||||
container = new createjs.SpriteContainer(@layerAdapter.spriteSheet)
|
||||
for x, i in @thang.allTargets by 2
|
||||
y = @thang.allTargets[i + 1]
|
||||
sup = @camera.worldToSurface x: x, y: y
|
||||
sprite = new createjs.Sprite(@layerAdapter.spriteSheet)
|
||||
sprite.scaleX = sprite.scaleY = 1 / @layerAdapter.resolutionFactor
|
||||
sprite.scaleY *= @camera.y2x
|
||||
sprite.gotoAndStop(@targetDotKey)
|
||||
sprite.x = sup.x
|
||||
sprite.y = sup.y
|
||||
container.addChild(sprite)
|
||||
return container
|
||||
|
||||
createPath: (points, options={}) ->
|
||||
options = options or {}
|
||||
interval = options.interval or 8
|
||||
key = options.frameKey or @pastDotKey
|
||||
container = new createjs.SpriteContainer(@layerAdapter.spriteSheet)
|
||||
|
||||
for x, i in points by interval * 2
|
||||
y = points[i + 1]
|
||||
sprite = new createjs.Sprite(@layerAdapter.spriteSheet)
|
||||
sprite.scaleX = sprite.scaleY = 1 / @layerAdapter.resolutionFactor
|
||||
sprite.scaleY *= @camera.y2x
|
||||
sprite.gotoAndStop(key)
|
||||
sprite.x = x
|
||||
sprite.y = y
|
||||
container.addChild(sprite)
|
||||
if lastSprite and options.animate
|
||||
tween = createjs.Tween.get(lastSprite, {loop: true}).to({x:x, y:y}, 1000)
|
||||
@tweenedSprites.push lastSprite
|
||||
@tweens.push tween
|
||||
lastSprite = sprite
|
||||
|
||||
@logged = true
|
||||
container
|
||||
|
||||
play: ->
|
||||
tween.setPaused(false) for tween in @tweens
|
||||
|
||||
stop: ->
|
||||
tween.setPaused(true) for tween in @tweens
|
||||
|
||||
destroy: ->
|
||||
@cleanUp()
|
||||
super()
|
|
@ -1,289 +0,0 @@
|
|||
# paths before the current state taper out,
|
||||
# and have a different color than the future
|
||||
PAST_PATH_TAIL_BRIGHTNESS = 150
|
||||
PAST_PATH_TAIL_ALPHA = 0.3
|
||||
PAST_PATH_HEAD_BRIGHTNESS = 200
|
||||
PAST_PATH_HEAD_ALPHA = 0.75
|
||||
|
||||
PAST_PATH_HEAD_LENGTH = 50
|
||||
PAST_PATH_TAIL_WIDTH = 2
|
||||
PAST_PATH_HEAD_WIDTH = 2
|
||||
PAST_PATH_MAX_LENGTH = 200
|
||||
|
||||
# paths in the future are single color dotted lines
|
||||
FUT_PATH_BRIGHTNESS = 153
|
||||
FUT_PATH_ALPHA = 0.8
|
||||
FUT_PATH_HEAD_LENGTH = 0
|
||||
FUT_PATH_WIDTH = 1
|
||||
FUT_PATH_MAX_LENGTH = 2000
|
||||
|
||||
# selected paths are single color, and larger, more prominent
|
||||
# most other properties are the same as non-selected
|
||||
SELECTED_PATH_TAIL_BRIGHTNESS = 146
|
||||
SELECTED_PATH_TAIL_ALPHA = 0.5
|
||||
SELECTED_PATH_HEAD_BRIGHTNESS = 200
|
||||
SELECTED_PATH_HEAD_ALPHA = 1.0
|
||||
SELECTED_PAST_PATH_MAX_LENGTH = 2000
|
||||
|
||||
FUT_SELECTED_PATH_WIDTH = 3
|
||||
|
||||
# for sprites along the path
|
||||
CLONE_INTERVAL = 250 # distance between them, ignored for new actions
|
||||
CLONE_SCALE = 1.0
|
||||
CLONE_ALPHA = 0.4
|
||||
|
||||
# path defaults
|
||||
PATH_DOT_LENGTH = 3
|
||||
PATH_SEGMENT_LENGTH = 15 # should be > PATH_DOT_LENGTH
|
||||
|
||||
Camera = require './Camera'
|
||||
|
||||
module.exports.Trailmaster = class Trailmaster
|
||||
paths: null # dictionary of thang ids to containers for their paths
|
||||
selectedPath: null # container of path selected
|
||||
pathDisplayObject: null
|
||||
world: null
|
||||
clock: 0
|
||||
|
||||
constructor: (@camera) ->
|
||||
|
||||
tick: ->
|
||||
@clock += 1
|
||||
|
||||
generatePaths: (@world, @currentFrame, @selectedThang, @sprites, @selectedOnly) ->
|
||||
@paths = {}
|
||||
@pathDisplayObject = new createjs.Container()
|
||||
@pathDisplayObject.mouseEnabled = @pathDisplayObject.mouseChildren = false
|
||||
for thang in world.thangs
|
||||
continue unless thang.isSelectable
|
||||
continue unless thang.isMovable
|
||||
continue if @selectedOnly and thang isnt @selectedThang
|
||||
path = @createPathForThang thang
|
||||
continue if not path
|
||||
@pathDisplayObject.addChild path
|
||||
@paths[thang.id] = path
|
||||
@pathDisplayObject
|
||||
|
||||
createPathForThang: (thang) ->
|
||||
container = new createjs.Container()
|
||||
|
||||
path = @createPastPathForThang(thang)
|
||||
container.addChild(path) if path
|
||||
|
||||
path = @createFuturePathForThang(thang)
|
||||
container.addChild(path) if path
|
||||
|
||||
targets = @createTargetsForThang(thang)
|
||||
container.addChild(targets) if targets
|
||||
|
||||
if thang is @selectedThang
|
||||
sprites = @spritesForThang(thang)
|
||||
for sprite in sprites
|
||||
container.addChild(sprite)
|
||||
|
||||
container
|
||||
|
||||
createPastPathForThang: (thang) ->
|
||||
maxLength = if thang is @selectedThang then SELECTED_PAST_PATH_MAX_LENGTH else PAST_PATH_MAX_LENGTH
|
||||
start = Math.max(@currentFrame - maxLength, 0)
|
||||
start = 0 if thang isnt @selectedThang
|
||||
resolution = if thang is @selectedThang then 4 else 12
|
||||
return unless points = @world.pointsForThang thang.id, start, @currentFrame, @camera, resolution
|
||||
params =
|
||||
tailWidth: PAST_PATH_TAIL_WIDTH
|
||||
headWidth: PAST_PATH_HEAD_WIDTH
|
||||
headLength: PAST_PATH_HEAD_LENGTH
|
||||
if thang is @selectedThang
|
||||
params['tailColor'] = colorForThang(thang.team, SELECTED_PATH_TAIL_BRIGHTNESS, SELECTED_PATH_TAIL_ALPHA)
|
||||
params['headColor'] = colorForThang(thang.team, SELECTED_PATH_HEAD_BRIGHTNESS, SELECTED_PATH_HEAD_ALPHA)
|
||||
else
|
||||
params['tailColor'] = colorForThang(thang.team, PAST_PATH_TAIL_BRIGHTNESS, PAST_PATH_TAIL_ALPHA)
|
||||
params['headColor'] = colorForThang(thang.team, PAST_PATH_HEAD_BRIGHTNESS, PAST_PATH_HEAD_ALPHA)
|
||||
return createPath(points, params)
|
||||
|
||||
|
||||
createFuturePathForThang: (thang) ->
|
||||
resolution = 8
|
||||
return unless points = @world.pointsForThang thang.id, @currentFrame, @currentFrame + FUT_PATH_MAX_LENGTH, @camera, resolution
|
||||
if thang is @selectedThang
|
||||
color = colorForThang(thang.team, SELECTED_PATH_HEAD_BRIGHTNESS, SELECTED_PATH_HEAD_ALPHA)
|
||||
else
|
||||
color = colorForThang(thang.team, FUT_PATH_BRIGHTNESS, FUT_PATH_ALPHA)
|
||||
return createPath(points,
|
||||
tailColor: color
|
||||
tailWidth: if thang is @selectedThang then FUT_SELECTED_PATH_WIDTH else FUT_PATH_WIDTH
|
||||
headLength: FUT_PATH_HEAD_LENGTH
|
||||
dotted: true
|
||||
dotOffset: @clock
|
||||
)
|
||||
|
||||
createTargetsForThang: (thang) ->
|
||||
return unless thang.allTargets
|
||||
g = new createjs.Graphics()
|
||||
g.setStrokeStyle(0.5)
|
||||
g.beginStroke(createjs.Graphics.getRGB(0, 0, 0))
|
||||
color = colorForThang(thang.team)
|
||||
|
||||
i = 0
|
||||
while i < thang.allTargets.length
|
||||
g.beginStroke(createjs.Graphics.getRGB(0, 0, 0))
|
||||
g.beginFill(createjs.Graphics.getRGB(color...))
|
||||
sup = @camera.worldToSurface x: thang.allTargets[i], y: thang.allTargets[i + 1]
|
||||
g.drawEllipse(sup.x - 5, sup.y - 3, 10, 6)
|
||||
g.endStroke()
|
||||
|
||||
i += 2
|
||||
|
||||
s = new createjs.Shape(g)
|
||||
s.x = 0
|
||||
s.y = 0
|
||||
s
|
||||
|
||||
spritesForThang: (thang) ->
|
||||
i = 0
|
||||
sprites = []
|
||||
sprite = @sprites[thang.id]
|
||||
return sprites unless sprite?.actions
|
||||
lastPos = @camera.surfaceToWorld x: sprite.sprite.x, y: sprite.sprite.y
|
||||
minDistance = Math.pow(CLONE_INTERVAL * Camera.MPP, 2)
|
||||
actions = @world.actionsForThang(thang.id)
|
||||
lastAction = null
|
||||
|
||||
for action in actions
|
||||
continue if action.name in ['idle', 'move']
|
||||
frame = @world.frames[action.frame]
|
||||
frame.restoreStateForThang(thang)
|
||||
|
||||
if lastPos
|
||||
diff = Math.pow(lastPos.x - thang.pos.x, 2)
|
||||
diff += Math.pow(lastPos.y - thang.pos.y, 2)
|
||||
continue if diff < minDistance and action.name is lastAction
|
||||
|
||||
clone = sprite.sprite.clone()
|
||||
clonePos = @camera.worldToSurface thang.pos
|
||||
clone.x = clonePos.x
|
||||
clone.y = clonePos.y
|
||||
clone.alpha = CLONE_ALPHA
|
||||
clone.scaleX *= CLONE_SCALE
|
||||
clone.scaleY *= CLONE_SCALE
|
||||
if sprite.expandActions # old Sprite
|
||||
sprite.updateRotation(clone, sprite.data)
|
||||
animActions = sprite.expandActions(if thang.acts then thang.getActionName() else 'idle')
|
||||
sprite.applyActionsToSprites(animActions, [clone], true)
|
||||
animation = clone.spriteSheet.getAnimation(clone.currentAnimation)
|
||||
clone.currentAnimationFrame = Math.min(@clock % (animation.frames.length * 3), animation.frames.length - 1)
|
||||
else
|
||||
continue unless animation = sprite.actions[action.name]
|
||||
sprite.updateRotation clone
|
||||
animation = sprite.getActionDirection(animation) ? animation # no idea if this ever works
|
||||
clone.gotoAndStop animation.name
|
||||
# TODO: use action-specific framerate here?
|
||||
# clone.currentAnimationFrame = Math.min(@clock % (animation.frames.length * 3), animation.frames.length - 1)
|
||||
sprites.push(clone)
|
||||
lastPos = x: thang.pos.x, y: thang.pos.y
|
||||
lastAction = action.name
|
||||
|
||||
@world.frames[@currentFrame].restoreStateForThang(thang)
|
||||
sprites
|
||||
|
||||
createPath = (points, options={}, g=null) ->
|
||||
options = options or {}
|
||||
tailColor = options.tailColor ? options.headColor
|
||||
headColor = options.headColor ? options.tailColor
|
||||
oneColor = true
|
||||
oneColor = oneColor and headColor[i] is tailColor[i] for i in [0..4]
|
||||
maxLength = options.maxLength or 0
|
||||
tailWidth = options.tailWidth
|
||||
headWidth = options.headWidth
|
||||
oneWidth = headWidth is tailWidth
|
||||
headLength = options.headLength
|
||||
dotted = options.dotted
|
||||
dotOffset = if options.dotOffset? then options.dotOffset else 0
|
||||
|
||||
points = points.slice(-maxLength * 2) if maxLength isnt 0
|
||||
points = points.slice(((points.length / 2 + dotOffset) % PATH_SEGMENT_LENGTH) * 2) if dotOffset
|
||||
g = new createjs.Graphics() unless g
|
||||
return new createjs.Shape(g) if not points
|
||||
|
||||
g.setStrokeStyle(tailWidth)
|
||||
g.beginStroke(createjs.Graphics.getRGB(tailColor...))
|
||||
g.moveTo(points[0], points[1])
|
||||
|
||||
headStart = points.length - headLength
|
||||
[lastX, lastY] = [points[0], points[1]]
|
||||
|
||||
for x, i in points by 2
|
||||
continue if i is 0
|
||||
y = points[i + 1]
|
||||
if i >= headStart and not (oneColor and oneWidth)
|
||||
diff = (i - headStart) / headLength
|
||||
style = transition(tailWidth, headWidth, diff)
|
||||
color = colorTransition(tailColor, headColor, diff)
|
||||
g.setStrokeStyle(style)
|
||||
g.beginStroke(createjs.Graphics.getRGB(color...))
|
||||
g.moveTo(lastX, lastY) if lastX?
|
||||
|
||||
else if dotted
|
||||
|
||||
if false and i < 2
|
||||
# Test: footprints
|
||||
g.beginFill(createjs.Graphics.getRGB(tailColor...))
|
||||
xofs = x - lastX
|
||||
yofs = y - lastY
|
||||
theta = Math.atan2(yofs, xofs)
|
||||
[fdist, fwidth] = [4, 2]
|
||||
fside = if (i + dotOffset) % 4 is 0 then -1 else 1
|
||||
fx = [lastX + fside * fdist * (Math.cos(theta) * xofs - Math.sin(theta) * yofs)]
|
||||
fy = [lastY + fside * fdist * (Math.sin(theta) * xofs - Math.cos(theta) * yofs)]
|
||||
g.drawCircle(fx, fy, 2)
|
||||
|
||||
offset = ((i / 2) % PATH_SEGMENT_LENGTH)
|
||||
if offset >= PATH_DOT_LENGTH
|
||||
if offset is PATH_DOT_LENGTH
|
||||
g.endStroke()
|
||||
lastX = x
|
||||
lastY = y
|
||||
continue
|
||||
|
||||
else
|
||||
if offset is 0
|
||||
g.beginStroke(createjs.Graphics.getRGB(tailColor...))
|
||||
g.moveTo(lastX, lastY) if lastX?
|
||||
|
||||
g.lineTo(x, y)
|
||||
lastX = x
|
||||
lastY = y
|
||||
|
||||
g.endStroke()
|
||||
|
||||
s = new createjs.Shape(g)
|
||||
return s
|
||||
|
||||
colorTransition = (color1, color2, pct) ->
|
||||
return color1 if pct <= 0
|
||||
return color2 if pct >= 1
|
||||
|
||||
i = 0
|
||||
color = []
|
||||
while i < 4
|
||||
val = transition(color1[i], color2[i], pct)
|
||||
val = Math.floor(val) if i isnt 3
|
||||
color.push(val)
|
||||
i += 1
|
||||
color
|
||||
|
||||
transition = (num1, num2, pct) ->
|
||||
return num1 if pct <= 0
|
||||
return num2 if pct >= 1
|
||||
num1 + (num2 - num1) * pct
|
||||
|
||||
colorForThang = (team, brightness=100, alpha=1.0) =>
|
||||
# multipliers should sum to 3.0
|
||||
multipliers = [2.0, 0.5, 0.5] if team is 'humans'
|
||||
multipliers = [0.5, 0.5, 2.0] if team is 'ogres'
|
||||
multipliers = [2.0, 0.5, 0.5] if not multipliers
|
||||
color = _.map(multipliers, (m) -> return parseInt(m * brightness))
|
||||
color.push(alpha)
|
||||
return color
|
||||
|
||||
module.exports.createPath = createPath
|
|
@ -472,9 +472,13 @@ module.exports = class World
|
|||
|
||||
perf.t1 = now()
|
||||
if w.thangs.length
|
||||
for thangConfig in o.thangs when not w.thangMap[thangConfig.id]
|
||||
w.thangs.push thang = Thang.deserialize(thangConfig, w, classMap, level.levelComponents)
|
||||
w.setThang thang
|
||||
for thangConfig in o.thangs
|
||||
if thang = w.thangMap[thangConfig.id]
|
||||
for prop, val of thangConfig.finalState
|
||||
thang[prop] = val
|
||||
else
|
||||
w.thangs.push thang = Thang.deserialize(thangConfig, w, classMap, level.levelComponents)
|
||||
w.setThang thang
|
||||
else
|
||||
w.thangs = (Thang.deserialize(thang, w, classMap, level.levelComponents) for thang in o.thangs)
|
||||
w.setThang thang for thang in w.thangs
|
||||
|
@ -551,7 +555,7 @@ module.exports = class World
|
|||
freeMemoryAfterEachSerialization: ->
|
||||
@frames[i] = null for frame, i in @frames when i < @frames.length - 1
|
||||
|
||||
pointsForThang: (thangID, frameStart=0, frameEnd=null, camera=null, resolution=4) ->
|
||||
pointsForThang: (thangID, camera=null) ->
|
||||
# Optimized
|
||||
@pointsForThangCache ?= {}
|
||||
cacheKey = thangID
|
||||
|
@ -570,16 +574,7 @@ module.exports = class World
|
|||
allPoints.reverse()
|
||||
@pointsForThangCache[cacheKey] = allPoints
|
||||
|
||||
points = []
|
||||
[lastX, lastY] = [null, null]
|
||||
for frameIndex in [Math.floor(frameStart / resolution) ... Math.ceil(frameEnd / resolution)]
|
||||
x = allPoints[frameIndex * 2 * resolution]
|
||||
y = allPoints[frameIndex * 2 * resolution + 1]
|
||||
continue if x is lastX and y is lastY
|
||||
lastX = x
|
||||
lastY = y
|
||||
points.push x, y
|
||||
points
|
||||
return allPoints
|
||||
|
||||
actionsForThang: (thangID, keepIdle=false) ->
|
||||
# Optimized
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
module.exports = nativeDescription: "български език", englishDescription: "Bulgarian", translation:
|
||||
home:
|
||||
slogan: "Научи се да програмираш, докато играеш игра "
|
||||
no_ie: "CodeCombat не работи под Internet Explorer 8 или по-стар. Съжалявам!" # Warning that only shows up in IE8 and older
|
||||
no_ie: "CodeCombat не работи под Internet Explorer 8 или по-стари версии. Съжалявам!" # Warning that only shows up in IE8 and older
|
||||
no_mobile: "CodeCombat не е направен за мобилни устройства и може да не работи!" # Warning that shows up on mobile devices
|
||||
play: "Играй" # The big play button that just starts playing a level
|
||||
# old_browser: "Uh oh, your browser is too old to run CodeCombat. Sorry!" # Warning that shows up on really old Firefox/Chrome/Safari
|
||||
# old_browser_suffix: "You can try anyway, but it probably won't work."
|
||||
old_browser: "О, не! Браузърът ти е твърде стар за CodeCombat. Съжалявам!" #"Uh oh, your browser is too old to run CodeCombat. Sorry!" # Warning that shows up on really old Firefox/Chrome/Safari
|
||||
old_browser_suffix: "Все пак можеш да опиваш, но най-вероятно няма да проработи." # "You can try anyway, but it probably won't work."
|
||||
# campaign: "Campaign"
|
||||
# for_beginners: "For Beginners"
|
||||
for_beginners: "За начинаещи" # "For Beginners"
|
||||
# multiplayer: "Multiplayer" # Not currently shown on home page
|
||||
# for_developers: "For Developers" # Not currently shown on home page.
|
||||
for_developers: "За разработчици" # "For Developers" # Not currently shown on home page.
|
||||
|
||||
nav:
|
||||
play: "Нива" # The top nav bar entry where players choose which levels to play
|
||||
|
@ -19,16 +19,16 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
forum: "Форум"
|
||||
account: "Сметката"
|
||||
profile: "Профил"
|
||||
# stats: "Stats"
|
||||
stats: "Статистики"
|
||||
# code: "Code"
|
||||
# admin: "Admin" # Only shows up when you are an admin
|
||||
home: "Начало"
|
||||
# contribute: "Contribute"
|
||||
contribute: "Допринеси" # "Contribute"
|
||||
# legal: "Legal"
|
||||
about: "За нас"
|
||||
contact: "Контакти"
|
||||
# twitter_follow: "Follow"
|
||||
# teachers: "Teachers"
|
||||
twitter_follow: "Започни да следиш" # "Follow"
|
||||
teachers: "Учители" # "Teachers"
|
||||
|
||||
modal:
|
||||
close: "Затвори"
|
||||
|
@ -38,23 +38,23 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
page_not_found: "Страницата не е намерена"
|
||||
|
||||
diplomat_suggestion:
|
||||
title: "Дай да помогни да преводи CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
|
||||
# sub_heading: "We need your language skills."
|
||||
title: "Помогни да преведем CodeCombat!" # This shows up when a player switches to a non-English language using the language selector.
|
||||
sub_heading: "Имаме нужда от твоите езикови познания!" # "We need your language skills."
|
||||
pitch_body: "We develop CodeCombat in English, but we already have players all over the world. Many of them want to play in Bulgarian but don't speak English, so if you can speak both, please consider signing up to be a Diplomat and help translate both the CodeCombat website and all the levels into Bulgarian."
|
||||
missing_translations: "Until we can translate everything into Bulgarian, you'll see English when Bulgarian isn't available."
|
||||
learn_more: "Научи повече за ставане Дипломат"
|
||||
# subscribe_as_diplomat: "Subscribe as a Diplomat"
|
||||
learn_more: "Научи повече за това как да станеш Дипломат"
|
||||
subscribe_as_diplomat: "Стани дипломат" # "Subscribe as a Diplomat"
|
||||
|
||||
play:
|
||||
# play_as: "Play As" # Ladder page
|
||||
# spectate: "Spectate" # Ladder page
|
||||
# players: "players" # Hover over a level on /play
|
||||
# hours_played: "hours played" # Hover over a level on /play
|
||||
# items: "Items" # Tooltip on item shop button from /play
|
||||
# unlock: "Unlock" # For purchasing items and heroes
|
||||
# confirm: "Confirm"
|
||||
items: "Предмети" # "Items" # Tooltip on item shop button from /play
|
||||
unlock: "Отключи" # "Unlock" # For purchasing items and heroes
|
||||
confirm: "Потвърди"
|
||||
# owned: "Owned" # For items you own
|
||||
# locked: "Locked"
|
||||
locked: "Заключено"
|
||||
# available: "Available"
|
||||
# skills_granted: "Skills Granted" # Property documentation details
|
||||
# heroes: "Heroes" # Tooltip on hero shop button from /play
|
||||
|
@ -64,27 +64,27 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
# next: "Next" # Go from choose hero to choose inventory before playing a level
|
||||
# change_hero: "Change Hero" # Go back from choose inventory to choose hero
|
||||
# choose_inventory: "Equip Items"
|
||||
# buy_gems: "Buy Gems"
|
||||
# older_campaigns: "Older Campaigns"
|
||||
# anonymous: "Anonymous Player"
|
||||
# level_difficulty: "Difficulty: "
|
||||
# campaign_beginner: "Beginner Campaign"
|
||||
buy_gems: "Купи скъпоценни камъни" # "Buy Gems"
|
||||
older_campaigns: "Предишни капмании" # "Older Campaigns"
|
||||
anonymous: "Анонимен играч" # "Anonymous Player"
|
||||
level_difficulty: "Трудност" # "Difficulty: "
|
||||
campaign_beginner: "Кампания за начинаещи" # "Beginner Campaign"
|
||||
# awaiting_levels_adventurer_prefix: "We release five levels per week."
|
||||
# awaiting_levels_adventurer: "Sign up as an Adventurer"
|
||||
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
|
||||
awaiting_levels_adventurer: "Стани Приключенец" # "Sign up as an Adventurer"
|
||||
awaiting_levels_adventurer_suffix: "за да бъдеш първият, който играе нови нива." # "to be the first to play new levels."
|
||||
choose_your_level: "Избери своето ниво" # The rest of this section is the old play view at /play-old and isn't very important.
|
||||
# adventurer_prefix: "You can jump to any level below, or discuss the levels on "
|
||||
# adventurer_forum: "the Adventurer forum"
|
||||
adventurer_forum: "Приключенският форум" # "the Adventurer forum"
|
||||
# adventurer_suffix: "."
|
||||
# campaign_old_beginner: "Old Beginner Campaign"
|
||||
campaign_old_beginner: "Предишни кампании за начинаещи" # "Old Beginner Campaign"
|
||||
# campaign_old_beginner_description: "... in which you learn the wizardry of programming."
|
||||
# campaign_dev: "Random Harder Levels"
|
||||
campaign_dev: "Случайни трудни нива" # "Random Harder Levels"
|
||||
# campaign_dev_description: "... in which you learn the interface while doing something a little harder."
|
||||
# campaign_multiplayer: "Multiplayer Arenas"
|
||||
# campaign_multiplayer_description: "... in which you code head-to-head against other players."
|
||||
# campaign_player_created: "Player-Created"
|
||||
# campaign_player_created_description: "... in which you battle against the creativity of your fellow <a href=\"/contribute#artisan\">Artisan Wizards</a>."
|
||||
# campaign_classic_algorithms: "Classic Algorithms"
|
||||
campaign_classic_algorithms: "Класически алгоритми" # "Classic Algorithms"
|
||||
# campaign_classic_algorithms_description: "... in which you learn the most popular algorithms in Computer Science."
|
||||
# campaign_forest: "Forest Campaign"
|
||||
# campaign_dungeon: "Dungeon Campaign"
|
||||
|
@ -101,27 +101,27 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
# finishing: "Finishing"
|
||||
|
||||
signup:
|
||||
create_account_title: "Создавай нов сметката за да записва прогрес"
|
||||
create_account_title: "Създавай нов акаунт, за да запазиш прогреса си"
|
||||
description: "Е безплатен. Само ще трабва неколко неща и ти ще си готов:"
|
||||
email_announcements: "Получава анонци през имейл"
|
||||
email_announcements: "Получава анонси по имейл"
|
||||
# coppa: "13+ or non-USA "
|
||||
coppa_why: "(Защо?)"
|
||||
creating: "Създаване на профил..."
|
||||
sign_up: "Регистриране"
|
||||
log_in: "Вход с парола"
|
||||
social_signup: "Или, можеш да зарегистрираваш през Facebook или G+:"
|
||||
required: "Трабва да влезиш преди можеш да ходиш на там."
|
||||
social_signup: "Или, можеш да се регистрираш през Facebook или G+:"
|
||||
required: "Трабва да влезеш преди можеш да ходиш на там."
|
||||
|
||||
recover:
|
||||
recover_account_title: "Възстанови Акаунт"
|
||||
send_password: "Изпрати парола за възстановяване"
|
||||
# recovery_sent: "Recovery email sent."
|
||||
recovery_sent: "Писмото за възстановяване на парола е изпратено." # "Recovery email sent."
|
||||
|
||||
# items:
|
||||
# primary: "Primary"
|
||||
# secondary: "Secondary"
|
||||
# armor: "Armor"
|
||||
# accessories: "Accessories"
|
||||
accessories: "Аксесоари" # "Accessories"
|
||||
# misc: "Misc"
|
||||
# books: "Books"
|
||||
|
||||
|
@ -132,8 +132,8 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
send: "Изпрати"
|
||||
cancel: "Отказ"
|
||||
save: "Запис"
|
||||
publish: "Публикирай"
|
||||
create: "Создавай"
|
||||
publish: "Публикувай"
|
||||
create: "Създай"
|
||||
# manual: "Manual"
|
||||
# fork: "Fork"
|
||||
# play: "Play" # When used as an action verb, like "Play next level"
|
||||
|
@ -145,11 +145,11 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
general:
|
||||
and: "и"
|
||||
name: "Име"
|
||||
# date: "Date"
|
||||
date: "Дата" # "Date"
|
||||
# body: "Body"
|
||||
version: "Версия"
|
||||
# commit_msg: "Commit Message"
|
||||
# version_history: "Version History"
|
||||
version_history: "Предишни версии" # "Version History"
|
||||
# version_history_for: "Version History for: "
|
||||
# result: "Result"
|
||||
results: "Резултати"
|
||||
|
@ -157,7 +157,7 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
or: "или"
|
||||
# subject: "Subject"
|
||||
email: "Email"
|
||||
# password: "Password"
|
||||
password: "Парола" # "Password"
|
||||
message: "Съобщение"
|
||||
# code: "Code"
|
||||
# ladder: "Ladder"
|
||||
|
@ -405,10 +405,10 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
# cla_prefix: "To save changes, first you must agree to our"
|
||||
# cla_url: "CLA"
|
||||
# cla_suffix: "."
|
||||
# cla_agree: "I AGREE"
|
||||
cla_agree: "СЪГЛАСЕН СЪМ" # "I AGREE"
|
||||
|
||||
# contact:
|
||||
# contact_us: "Contact CodeCombat"
|
||||
contact_us: "Свържи се с CodeCombat" # "Contact CodeCombat"
|
||||
# welcome: "Good to hear from you! Use this form to send us email. "
|
||||
# contribute_prefix: "If you're interested in contributing, check out our "
|
||||
# contribute_page: "contribute page"
|
||||
|
@ -430,17 +430,17 @@ module.exports = nativeDescription: "български език", englishDescri
|
|||
# password_tab: "Password"
|
||||
# emails_tab: "Emails"
|
||||
# admin: "Admin"
|
||||
# new_password: "New Password"
|
||||
new_password: "Нова парола" # "New Password"
|
||||
# new_password_verify: "Verify"
|
||||
# email_subscriptions: "Email Subscriptions"
|
||||
# email_subscriptions_none: "No Email Subscriptions."
|
||||
# email_announcements: "Announcements"
|
||||
email_announcements: "Съобщения" # "Announcements"
|
||||
# email_announcements_description: "Get emails on the latest news and developments at CodeCombat."
|
||||
# email_notifications: "Notifications"
|
||||
email_notifications: "Известия" # "Notifications"
|
||||
# email_notifications_summary: "Controls for personalized, automatic email notifications related to your CodeCombat activity."
|
||||
# email_any_notes: "Any Notifications"
|
||||
# email_any_notes_description: "Disable to stop all activity notification emails."
|
||||
# email_news: "News"
|
||||
email_news: "Новини" # "News"
|
||||
# email_recruit_notes: "Job Opportunities"
|
||||
# email_recruit_notes_description: "If you play really well, we may contact you about getting you a (better) job."
|
||||
# contributor_emails: "Contributor Class Emails"
|
||||
|
|
|
@ -64,14 +64,14 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
next: "Nächster" # Go from choose hero to choose inventory before playing a level
|
||||
change_hero: "Held wechseln" # Go back from choose inventory to choose hero
|
||||
choose_inventory: "Gegenstände ausrüsten"
|
||||
# buy_gems: "Buy Gems"
|
||||
buy_gems: "Edelsteine kaufen"
|
||||
older_campaigns: "Ältere Kampagne"
|
||||
anonymous: "Anonymer Spieler"
|
||||
level_difficulty: "Schwierigkeit: "
|
||||
campaign_beginner: "Anfängerkampagne"
|
||||
# awaiting_levels_adventurer_prefix: "We release five levels per week."
|
||||
# awaiting_levels_adventurer: "Sign up as an Adventurer"
|
||||
# awaiting_levels_adventurer_suffix: "to be the first to play new levels."
|
||||
awaiting_levels_adventurer_prefix: "Wir veröffentlichen fünf Levels pro Woche."
|
||||
awaiting_levels_adventurer: "Registriere dich als ein Abenteurer"
|
||||
awaiting_levels_adventurer_suffix: "sei der Erste, der neue Levels spielt."
|
||||
choose_your_level: "Wähle dein Level" # The rest of this section is the old play view at /play-old and isn't very important.
|
||||
adventurer_prefix: "Du kannst zu jedem Level springen oder diskutiere die Level "
|
||||
adventurer_forum: "im Abenteurerforum"
|
||||
|
@ -95,10 +95,10 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
logging_in: "Logge ein"
|
||||
log_out: "Ausloggen"
|
||||
recover: "Account wiederherstellen"
|
||||
# authenticate_gplus: "Authenticate G+"
|
||||
# load_profile: "Load G+ Profile"
|
||||
# load_email: "Load G+ Email"
|
||||
# finishing: "Finishing"
|
||||
authenticate_gplus: "Authentifiziere G+"
|
||||
load_profile: "Lade G+ Profil"
|
||||
load_email: "Lade G+ Email"
|
||||
finishing: "Fertigstellen"
|
||||
|
||||
signup:
|
||||
create_account_title: "Account anlegen, um Fortschritt zu speichern"
|
||||
|
@ -172,7 +172,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
medium: "Mittel"
|
||||
hard: "Schwer"
|
||||
player: "Spieler"
|
||||
# player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
|
||||
player_level: "Level" # Like player level 5, not like level: Dungeons of Kithgard
|
||||
|
||||
units:
|
||||
second: "Sekunde"
|
||||
|
@ -307,25 +307,25 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
choose_inventory: "Gegenstände ausrüsten"
|
||||
equipped_item: "Hinzugefügt"
|
||||
available_item: "Verfügbar"
|
||||
# restricted_title: "Restricted"
|
||||
restricted_title: "Eingeschränkt"
|
||||
should_equip: "(Doppelklick zum Hinzufügen)"
|
||||
equipped: "(hinzugefügt)"
|
||||
locked: "(gesperrt)"
|
||||
restricted: "(benötigt für dieses Level)"
|
||||
# equip: "Equip"
|
||||
# unequip: "Unequip"
|
||||
equip: "Ausrüsten"
|
||||
unequip: "Abrüsten"
|
||||
|
||||
# buy_gems:
|
||||
# few_gems: "A few gems"
|
||||
# pile_gems: "Pile of gems"
|
||||
# chest_gems: "Chest of gems"
|
||||
buy_gems:
|
||||
few_gems: "Ein paar Edelsteine"
|
||||
pile_gems: "Stapel von Edelsteinen"
|
||||
chest_gems: "Kiste von Edelsteinen"
|
||||
|
||||
choose_hero:
|
||||
choose_hero: "Wähle deinen Helden"
|
||||
programming_language: "Programmiersprache"
|
||||
programming_language_description: "Welche Programmiersprache möchtest du verwenden?"
|
||||
# default: "Default"
|
||||
# experimental: "Experimental"
|
||||
default: "Standard"
|
||||
experimental: "Experimentell"
|
||||
python_blurb: "Einfach jedoch leistungsfähig, Python ist eine gute Allzweck-Programmiersprache."
|
||||
javascript_blurb: "Die Sprache des Web."
|
||||
coffeescript_blurb: "Schönere JavaScript Syntax."
|
||||
|
@ -466,7 +466,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
enter: "Eingabetaste"
|
||||
escape: "Escape"
|
||||
shift: "Umschalttaste"
|
||||
# run_code: "Run current code."
|
||||
run_code: "Starte aktuellen Code."
|
||||
run_real_time: "Führe in Echtzeit aus."
|
||||
continue_script: "Setze nach aktuellenm Skript fort."
|
||||
skip_scripts: "Überspringe alle überspringbaren Skripte."
|
||||
|
@ -544,7 +544,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
level_tab_thangs_add: "Thangs hinzufügen"
|
||||
delete: "Löschen"
|
||||
duplicate: "Duplizieren"
|
||||
# rotate: "Rotate"
|
||||
rotate: "Drehen"
|
||||
level_settings_title: "Einstellungen"
|
||||
level_component_tab_title: "Aktuelle Komponenten"
|
||||
level_component_btn_new: "neue Komponente erstellen"
|
||||
|
@ -688,14 +688,14 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
summary_your: "Deine "
|
||||
summary_matches: "Matches - "
|
||||
summary_wins: " Siege, "
|
||||
# summary_losses: " Losses"
|
||||
summary_losses: " Verluste"
|
||||
# rank_no_code: "No New Code to Rank"
|
||||
# rank_my_game: "Rank My Game!"
|
||||
# rank_submitting: "Submitting..."
|
||||
rank_submitting: "Übermitteln..."
|
||||
# rank_submitted: "Submitted for Ranking"
|
||||
# rank_failed: "Failed to Rank"
|
||||
# rank_being_ranked: "Game Being Ranked"
|
||||
# rank_last_submitted: "submitted "
|
||||
rank_last_submitted: "übermittelt "
|
||||
help_simulate: "Hilf Spiele zu simulieren?"
|
||||
# code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
|
||||
# no_ranked_matches_pre: "No ranked matches for the "
|
||||
|
@ -744,16 +744,16 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
# last_earned: "Last Earned"
|
||||
amount_achieved: "Anzahl"
|
||||
achievement: "Achievement"
|
||||
# category_contributor: "Contributor"
|
||||
category_contributor: "Mitwirkender"
|
||||
category_miscellaneous: "Sonstiges"
|
||||
category_levels: "Level"
|
||||
category_undefined: "ohne Kategorie"
|
||||
# current_xp_prefix: ""
|
||||
# current_xp_postfix: " in total"
|
||||
current_xp_postfix: " Gesamt"
|
||||
# new_xp_prefix: ""
|
||||
# new_xp_postfix: " earned"
|
||||
# left_xp_prefix: ""
|
||||
# left_xp_infix: " until level "
|
||||
left_xp_infix: " bis Level "
|
||||
# left_xp_postfix: ""
|
||||
|
||||
account:
|
||||
|
@ -877,7 +877,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
mit_license_url: "MIT Lizenz"
|
||||
code_description_suffix: "Dies beihnhaltet all den Code in Systemen und Komponenten der für die Erstellung von Levels durch CodeCombat zu Verfügung gestellt wird."
|
||||
art_title: "Grafiken/Musik - Creative Commons "
|
||||
# art_description_prefix: "All common content is available under the"
|
||||
art_description_prefix: "Gemeinsamer Inhalt ist verfügbar unter"
|
||||
cc_license_url: "Creative Commons Attribution 4.0 International License"
|
||||
# art_description_suffix: "Common content is anything made generally available by CodeCombat for the purpose of creating Levels. This includes:"
|
||||
art_music: "Musik"
|
||||
|
@ -915,8 +915,8 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
in_cash: "in Bar"
|
||||
custom_wizard: "Benutzerdefinierter CodeCombat Zauberer"
|
||||
custom_avatar: "Benutzerdefinierter CodeCombat Avatar"
|
||||
# heap: "for six months of \"Startup\" access"
|
||||
# credits: "credits"
|
||||
heap: "für sechs Monate \"Startup\" Zugriff"
|
||||
credits: "Guthaben"
|
||||
one_month_coupon: "Gutschein: Wähle entweder Rails oder HTML"
|
||||
one_month_discount: "30% Rabatt: Wähle entweder Rails oder HTML"
|
||||
license: "Lizenz"
|
||||
|
@ -952,7 +952,7 @@ module.exports = nativeDescription: "Deutsch (Deutschland)", englishDescription:
|
|||
active: "Suche jetzt nach Interview-Angeboten"
|
||||
inactive: "Suche momentan nicht nach Angeboten"
|
||||
complete: "komplett"
|
||||
# next: "Next"
|
||||
next: "Nächstes"
|
||||
next_city: "Stadt?"
|
||||
next_country: "Wähle dein Land."
|
||||
next_name: "Name?"
|
||||
|
|
|
@ -207,6 +207,8 @@
|
|||
failing: "Failing"
|
||||
action_timeline: "Action Timeline"
|
||||
click_to_select: "Click on a unit to select it."
|
||||
control_bar_multiplayer: "Multiplayer"
|
||||
control_bar_join_game: "Join Game"
|
||||
reload: "Reload"
|
||||
reload_title: "Reload All Code?"
|
||||
reload_really: "Are you sure you want to reload this level back to the beginning?"
|
||||
|
|
|
@ -69,7 +69,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
anonymous: "匿名玩家"
|
||||
level_difficulty: "难度:"
|
||||
campaign_beginner: "新手作战"
|
||||
awaiting_levels_adventurer_prefix: "我们每周发布 5 个关卡。"#"We release five levels per week."
|
||||
awaiting_levels_adventurer_prefix: "我们每周开放五个关卡"
|
||||
awaiting_levels_adventurer: "注册成为冒险家" #"Sign up as an Adventurer"
|
||||
awaiting_levels_adventurer_suffix: "来优先尝试新关卡" #to be the first to play new levels."
|
||||
choose_your_level: "选择关卡" # The rest of this section is the old play view at /play-old and isn't very important.
|
||||
|
@ -218,13 +218,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
victory_rate_the_level: "评估关卡:" # Only in old-style levels.
|
||||
victory_return_to_ladder: "返回"
|
||||
victory_play_continue: "继续游戏"
|
||||
# victory_play_skip: "Skip Ahead"
|
||||
victory_play_skip: "跳过并继续"
|
||||
victory_play_next_level: "下一关"
|
||||
# victory_play_more_practice: "More Practice"
|
||||
# victory_play_too_easy: "Too Easy"
|
||||
# victory_play_just_right: "Just Right"
|
||||
# victory_play_too_hard: "Too Hard"
|
||||
# victory_saving_progress: "Saving Progress"
|
||||
victory_play_more_practice: "更多练习"
|
||||
victory_play_too_easy: "太简单"
|
||||
victory_play_just_right: "刚刚好"
|
||||
victory_play_too_hard: "太难"
|
||||
victory_saving_progress: "保存进度"
|
||||
victory_go_home: "返回主页" # Only in old-style levels.
|
||||
victory_review: "给我们反馈!" # Only in old-style levels.
|
||||
victory_hour_of_code_done: "你完成了吗?"
|
||||
|
@ -244,7 +244,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
tome_available_spells: "可用的法术"
|
||||
tome_your_skills: "你的技能"
|
||||
# tome_current_method: "Current Method"
|
||||
# hud_continue_short: "Continue"
|
||||
hud_continue_short: "继续"
|
||||
code_saved: "代码已保存"
|
||||
skip_tutorial: "跳过(esc)"
|
||||
keyboard_shortcuts: "快捷键"
|
||||
|
@ -268,7 +268,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
tip_debugging_program: "如果说调试是清除Bug的过程,那么编码就是放置Bug的过程。- Edsger W. Dijkstra"
|
||||
tip_forums: "到论坛去告诉我们你的想法!"
|
||||
tip_baby_coders: "在未来,就算小孩都能成为大法师."
|
||||
# tip_morale_improves: "Loading will continue until morale improves."
|
||||
tip_morale_improves: "在士气提升之前会一直进行读取."
|
||||
tip_all_species: "我们相信学习编程的机会对任何种族都是平等的。"
|
||||
# tip_reticulating: "Reticulating spines."
|
||||
tip_harry: "巫师, "
|
||||
|
@ -289,43 +289,43 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
customize_wizard: "自定义向导"
|
||||
|
||||
game_menu:
|
||||
# inventory_tab: "Inventory"
|
||||
inventory_tab: "道具箱"
|
||||
save_load_tab: "保存/打开"
|
||||
options_tab: "设置"
|
||||
guide_tab: "使用向导"
|
||||
multiplayer_tab: "多人游戏"
|
||||
# auth_tab: "Sign Up"
|
||||
# inventory_caption: "Equip your hero"
|
||||
# choose_hero_caption: "Choose hero, language"
|
||||
# save_load_caption: "... and view history"
|
||||
# options_caption: "Configure settings"
|
||||
# guide_caption: "Docs and tips"
|
||||
# multiplayer_caption: "Play with friends!"
|
||||
auth_tab: "注册"
|
||||
inventory_caption: "装备你的英雄"
|
||||
choose_hero_caption: "选择英雄和语言"
|
||||
save_load_caption: "... 观看历史"
|
||||
options_caption: "确认设置"
|
||||
guide_caption: "文档和提示"
|
||||
multiplayer_caption: "与你的朋友一起玩!"
|
||||
auth_caption: "保存进度"
|
||||
|
||||
inventory:
|
||||
choose_inventory: "装备道具"
|
||||
# equipped_item: "Equipped"
|
||||
# available_item: "Available"
|
||||
# restricted_title: "Restricted"
|
||||
equipped_item: "已装备"
|
||||
available_item: "可用"
|
||||
restricted_title: "被限制"
|
||||
should_equip: "(双击装备此道具)"
|
||||
equipped: "(已装备)"
|
||||
locked: "(需解锁)"
|
||||
restricted: "(本关卡不得使用)"
|
||||
# equip: "Equip"
|
||||
# unequip: "Unequip"
|
||||
equip: "装备"
|
||||
unequip: "取消装备"
|
||||
|
||||
# buy_gems:
|
||||
# few_gems: "A few gems"
|
||||
# pile_gems: "Pile of gems"
|
||||
# chest_gems: "Chest of gems"
|
||||
few_gems: "几个宝石"
|
||||
pile_gems: "一堆宝石"
|
||||
chest_gems: "一箱宝石"
|
||||
|
||||
choose_hero:
|
||||
choose_hero: "请选择您的英雄"
|
||||
programming_language: "编程语言"
|
||||
programming_language_description: "您希望使用那门编程语言?"
|
||||
# default: "Default"
|
||||
# experimental: "Experimental"
|
||||
# default: "默认"
|
||||
experimental: "实验性的"
|
||||
python_blurb: "简单而强大, Python是一个伟大的通用编程语言。"
|
||||
javascript_blurb: "为web开发而生的语言。"
|
||||
coffeescript_blurb: "一种更好的JavaScript语法."
|
||||
|
@ -353,18 +353,18 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# general_options: "General Options" # Check out the Options tab in the Game Menu while playing a level
|
||||
volume_label: "音量"
|
||||
music_label: "音乐"
|
||||
# music_description: "Turn background music on/off."
|
||||
# autorun_label: "Autorun"
|
||||
music_description: "开/关背景音乐"
|
||||
autorun_label: "自动运行"
|
||||
# autorun_description: "Control automatic code execution."
|
||||
editor_config: "编辑器配置"
|
||||
editor_config_title: "编辑器配置"
|
||||
# editor_config_level_language_label: "Language for This Level"
|
||||
editor_config_level_language_label: "这个等级的语言"
|
||||
# editor_config_level_language_description: "Define the programming language for this particular level."
|
||||
# editor_config_default_language_label: "Default Programming Language"
|
||||
# editor_config_default_language_description: "Define the programming language you want to code in when starting new levels."
|
||||
editor_config_default_language_label: "默认编程语言"
|
||||
editor_config_default_language_description: "在开始新游戏前确认你要在这个等级的游戏中使用的编程语言。"
|
||||
editor_config_keybindings_label: "按键设置s"
|
||||
editor_config_keybindings_default: "默认 (Ace)"
|
||||
# editor_config_keybindings_description: "Adds additional shortcuts known from the common editors."
|
||||
editor_config_keybindings_description: "在命令编辑器中增加已知的快捷键。"
|
||||
# editor_config_livecompletion_label: "Live Autocompletion"
|
||||
# editor_config_livecompletion_description: "Displays autocomplete suggestions while typing."
|
||||
editor_config_invisibles_label: "显示空白字符"
|
||||
|
@ -464,10 +464,10 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
keyboard_shortcuts: "热键"
|
||||
space: "空格"
|
||||
enter: "回车"
|
||||
# escape: "Escape"
|
||||
# shift: "Shift"
|
||||
# run_code: "Run current code."
|
||||
# run_real_time: "Run in real time."
|
||||
escape: "Esc"
|
||||
shift: "Shift"
|
||||
run_code: "运行当前代码"
|
||||
run_real_time: "实时运行"
|
||||
# continue_script: "Continue past current script."
|
||||
# skip_scripts: "Skip past all skippable scripts."
|
||||
toggle_playback: "继续/暂停按钮"
|
||||
|
@ -478,7 +478,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# toggle_grid: "Toggle grid overlay."
|
||||
# toggle_pathfinding: "Toggle pathfinding overlay."
|
||||
beautify: "利用标准编码格式美化你的代码。"
|
||||
# maximize_editor: "Maximize/minimize code editor."
|
||||
maximize_editor: "最大化/最小化代码编辑器"
|
||||
move_wizard: "在关卡中移动你的巫师角色。"
|
||||
|
||||
community:
|
||||
|
@ -491,12 +491,12 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
article_editor_prefix: "你在游戏中发现了错误了吗?想要自己设计一些指令吗?来看看我们的"
|
||||
article_editor_suffix: "来帮助玩家从游戏中学到更多的知识。"
|
||||
find_us: "通过这些站点联系我们"
|
||||
# social_blog: "Read the CodeCombat blog on Sett"
|
||||
# social_discource: "Join the discussion on our Discourse forum"
|
||||
social_blog: "阅读 CodeCombat 在 Sett 上面的博客"
|
||||
social_discource: "在我们的论坛参与讨论"
|
||||
social_facebook: "关注 CodeCombat 的 Facebook 主页"
|
||||
social_twitter: "关注 CodeCombat 的 Twitter"
|
||||
social_gplus: "关注 CodeCombat 的 Google+ 主页"
|
||||
# social_hipchat: "Chat with us in the public CodeCombat HipChat room"
|
||||
social_hipchat: "在公共的 CodeCombat HipChat 房间与我们交流"
|
||||
contribute_to_the_project: "为项目做贡献"
|
||||
|
||||
classes:
|
||||
|
@ -647,9 +647,9 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
diplomat_launch_url: "十月的发布"
|
||||
diplomat_introduction_suf: "中得到了什么启发:那就是全世界的人都对 CodeCombat 很感兴趣。我们召集了一群翻译者,尽快地把网站上的信息翻译成各国文字。如果你对即将发布的新内容很感兴趣,想让你的国家的人们玩上,就快来成为外交官吧。"
|
||||
diplomat_attribute_1: "既会说流利的英语,也熟悉自己的语言。编程是一件很复杂的事情,而要翻译复杂的概念,你必须对两种语言都在行!"
|
||||
# diplomat_i18n_page_prefix: "You can start translating our levels by going to our"
|
||||
# diplomat_i18n_page: "translations page"
|
||||
# diplomat_i18n_page_suffix: ", or our interface and website on GitHub."
|
||||
diplomat_i18n_page_prefix: "你可以在我们的"
|
||||
diplomat_i18n_page: "翻译页面"
|
||||
diplomat_i18n_page_suffix: "开始翻译游戏,或者在GibHub我们的页面上进行。"
|
||||
diplomat_join_pref_github: "在"
|
||||
diplomat_github_url: " GitHub "
|
||||
diplomat_join_suf_github: "找到你的语言文件 (中文的是: codecombat/app/locale/zh-HNAS.coffee),在线编辑它,然后提交一个合并请求。同时,选中下面这个复选框来关注最新的国际化开发!"
|
||||
|
@ -659,7 +659,7 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
ambassador_introduction: "这是一个正在成长的社区,而你将成为我们与世界的联结点。大家可以通过Olark即时聊天、邮件、参与者众多的社交网络来认识了解讨论我们的游戏。如果你想帮助大家尽早参与进来、获得乐趣、感受CodeCombat的脉搏、与我们同行,那么这将是一个适合你的职业。"
|
||||
ambassador_attribute_1: "有出色的沟通能力。能够辨识出玩家遇到的问题并帮助他们解决这些问题。与此同时,和我们保持联系,及时反馈玩家的喜恶和愿望!"
|
||||
ambassador_join_desc: "介绍一下你自己:你做过什么?你喜欢做什么?我们将从这里开始了解你!"
|
||||
# ambassador_join_note_strong: "Note"
|
||||
ambassador_join_note_strong: "注意"
|
||||
# ambassador_join_note_desc: "One of our top priorities is to build multiplayer where players having difficulty solving levels can summon higher level wizards to help them. This will be a great way for ambassadors to do their thing. We'll keep you posted!"
|
||||
more_about_ambassador: "了解如何成为一名使节"
|
||||
ambassador_subscribe_desc: "通过电子邮件获得支持系统的现状,以及多人游戏方面的新进展。"
|
||||
|
@ -694,14 +694,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
rank_submitting: "正在提交..."
|
||||
# rank_submitted: "Submitted for Ranking"
|
||||
rank_failed: "评分失败"
|
||||
# rank_being_ranked: "Game Being Ranked"
|
||||
# rank_last_submitted: "submitted "
|
||||
rank_being_ranked: "已评价"
|
||||
rank_last_submitted: "已提交"
|
||||
# help_simulate: "Help simulate games?"
|
||||
# code_being_simulated: "Your new code is being simulated by other players for ranking. This will refresh as new matches come in."
|
||||
# no_ranked_matches_pre: "No ranked matches for the "
|
||||
# no_ranked_matches_post: " team! Play against some competitors and then come back here to get your game ranked."
|
||||
choose_opponent: "选择一个对手"
|
||||
# select_your_language: "Select your language!"
|
||||
select_your_language: "选择你使用的语言!"
|
||||
tutorial_play: "玩教程"
|
||||
tutorial_recommended: "如果你从未玩过的话,推荐先玩下教程"
|
||||
tutorial_skip: "跳过教材"
|
||||
|
@ -709,11 +709,11 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
tutorial_play_first: "先玩一次教程."
|
||||
simple_ai: "简单电脑"
|
||||
warmup: "热身"
|
||||
# friends_playing: "Friends Playing"
|
||||
# log_in_for_friends: "Log in to play with your friends!"
|
||||
# social_connect_blurb: "Connect and play against your friends!"
|
||||
# invite_friends_to_battle: "Invite your friends to join you in battle!"
|
||||
# fight: "Fight!"
|
||||
friends_playing: "联机"
|
||||
log_in_for_friends: "登陆然后跟朋友一起玩!"
|
||||
social_connect_blurb: "连接然后与朋友对战!"
|
||||
invite_friends_to_battle: "邀请你的朋友参加战斗!"
|
||||
fight: "战斗!"
|
||||
# watch_victory: "Watch your victory"
|
||||
# defeat_the: "Defeat the"
|
||||
# tournament_ends: "Tournament ends"
|
||||
|
@ -722,8 +722,8 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# tournament_blurb: "Write code, collect gold, build armies, crush foes, win prizes, and upgrade your career in our $40,000 Greed tournament! Check out the details"
|
||||
# tournament_blurb_criss_cross: "Win bids, construct paths, outwit opponents, grab gems, and upgrade your career in our Criss-Cross tournament! Check out the details"
|
||||
# tournament_blurb_blog: "on our blog"
|
||||
# rules: "Rules"
|
||||
# winners: "Winners"
|
||||
rules: "规则"
|
||||
winners: "胜利者"
|
||||
|
||||
user:
|
||||
stats: "成就"
|
||||
|
@ -744,14 +744,14 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
last_earned: "最近取得的时间"
|
||||
amount_achieved: "数量"
|
||||
achievement: "成就"
|
||||
# category_contributor: "Contributor"
|
||||
category_contributor: "贡献"
|
||||
# category_miscellaneous: "Miscellaneous"
|
||||
# category_levels: "Levels"
|
||||
category_levels: "等级"
|
||||
# category_undefined: "Uncategorized"
|
||||
# current_xp_prefix: ""
|
||||
# current_xp_postfix: " in total"
|
||||
# new_xp_prefix: ""
|
||||
# new_xp_postfix: " earned"
|
||||
new_xp_postfix: "获取"
|
||||
# left_xp_prefix: ""
|
||||
# left_xp_infix: " until level "
|
||||
# left_xp_postfix: ""
|
||||
|
@ -798,9 +798,9 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# level_session: "Your Session"
|
||||
# opponent_session: "Opponent Session"
|
||||
# article: "Article"
|
||||
# user_names: "User Names"
|
||||
user_names: "用户名"
|
||||
# thang_names: "Thang Names"
|
||||
# files: "Files"
|
||||
files: "文件"
|
||||
# top_simulators: "Top Simulators"
|
||||
# source_document: "Source Document"
|
||||
# document: "Document"
|
||||
|
@ -811,13 +811,13 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
# user_remark: "User Remark"
|
||||
# user_remarks: "User Remarks"
|
||||
# versions: "Versions"
|
||||
# items: "Items"
|
||||
items: "物品"
|
||||
heroes: "英雄"
|
||||
# wizard: "Wizard"
|
||||
# achievement: "Achievement"
|
||||
wizard: "巫师"
|
||||
achievement: "成就"
|
||||
# clas: "CLAs"
|
||||
# play_counts: "Play Counts"
|
||||
# feedback: "Feedback"
|
||||
feedback: "反馈"
|
||||
|
||||
# delta:
|
||||
# added: "Added"
|
||||
|
@ -1091,10 +1091,10 @@ module.exports = nativeDescription: "简体中文", englishDescription: "Chinese
|
|||
|
||||
admin:
|
||||
# av_espionage: "Espionage" # Really not important to translate /admin controls.
|
||||
# av_espionage_placeholder: "Email or username"
|
||||
# av_usersearch: "User Search"
|
||||
# av_usersearch_placeholder: "Email, username, name, whatever"
|
||||
# av_usersearch_search: "Search"
|
||||
av_espionage_placeholder: "邮箱或用户名"
|
||||
av_usersearch: "用户搜索"
|
||||
av_usersearch_placeholder: "邮箱、用户名、姓名、任何东西"
|
||||
av_usersearch_search: "搜索"
|
||||
av_title: "管理员视图"
|
||||
av_entities_sub_title: "实体"
|
||||
av_entities_users_url: "用户"
|
||||
|
|
|
@ -68,13 +68,17 @@ module.exports = class Level extends CocoModel
|
|||
placeholders = {}
|
||||
placeholdersUsed = {}
|
||||
placeholderThangType = supermodel.getModelByOriginal(ThangType, levelThang.thangType)
|
||||
for defaultPlaceholderComponent in placeholderThangType.get('components')
|
||||
placeholders[defaultPlaceholderComponent.original] = defaultPlaceholderComponent
|
||||
for thangComponent in levelThang.components
|
||||
placeholders[thangComponent.original] = thangComponent
|
||||
levelThang.components = [] # We have stored the placeholder values, so we can inherit everything else.
|
||||
heroThangType = session?.get('heroConfig')?.thangType
|
||||
levelThang.thangType = heroThangType if heroThangType
|
||||
unless placeholderThangType
|
||||
console.error "Couldn't find placeholder ThangType for the hero!"
|
||||
isHero = false
|
||||
else
|
||||
for defaultPlaceholderComponent in placeholderThangType.get('components')
|
||||
placeholders[defaultPlaceholderComponent.original] = defaultPlaceholderComponent
|
||||
for thangComponent in levelThang.components
|
||||
placeholders[thangComponent.original] = thangComponent
|
||||
levelThang.components = [] # We have stored the placeholder values, so we can inherit everything else.
|
||||
heroThangType = session?.get('heroConfig')?.thangType
|
||||
levelThang.thangType = heroThangType if heroThangType
|
||||
|
||||
thangType = supermodel.getModelByOriginal(ThangType, levelThang.thangType, (m) -> m.get('components')?)
|
||||
|
||||
|
|
|
@ -181,6 +181,7 @@ module.exports = class SuperModel extends Backbone.Model
|
|||
@num += r.value
|
||||
_.defer @updateProgress
|
||||
r.clean()
|
||||
@stopListening r, 'failed', @onResourceFailed
|
||||
@trigger 'resource-loaded', r
|
||||
|
||||
onResourceFailed: (r) ->
|
||||
|
|
|
@ -250,11 +250,13 @@ module.exports = class ThangType extends CocoModel
|
|||
stage.update()
|
||||
stage.startTalking = ->
|
||||
sprite.gotoAndPlay 'portrait'
|
||||
return # TODO: causes infinite recursion in new EaselJS
|
||||
return if @tick
|
||||
@tick = (e) => @update(e)
|
||||
createjs.Ticker.addEventListener 'tick', @tick
|
||||
stage.stopTalking = ->
|
||||
sprite.gotoAndStop 'portrait'
|
||||
return # TODO: just breaks in new EaselJS
|
||||
@update()
|
||||
createjs.Ticker.removeEventListener 'tick', @tick
|
||||
@tick = null
|
||||
|
|
|
@ -143,15 +143,18 @@ module.exports = class User extends CocoModel
|
|||
application.tracker.identify experimentalLangGroup: @experimentalLangGroup
|
||||
@experimentalLangGroup
|
||||
|
||||
getHighlightArrowSoundGroup: ->
|
||||
return @highlightArrowGroup if @highlightArrowGroup
|
||||
group = me.get('testGroupNumber') % 8
|
||||
@highlightArrowGroup = switch group
|
||||
when 0, 1, 2, 3 then 'sound-off'
|
||||
when 4, 5, 6, 7 then 'sound-on'
|
||||
@highlightArrowGroup = 'sound-off' if me.isAdmin()
|
||||
application.tracker.identify highlightArrowGroup: @highlightArrowGroup unless me.isAdmin()
|
||||
@highlightArrowGroup
|
||||
## Test complete; feel free to repurpose for another test.
|
||||
# https://mixpanel.com/report/227350/segmentation/#action:segment,arb_event:'Saw%20Victory',bool_op:and,chart_type:bar,from_date:-17,segfilter:!((filter:(operand:!('Dungeons%20of%20Kithgard'),operator:%3D%3D),property:level,selected_property_type:string,type:string),(filter:(operand:'',operator:set),property:highlightArrowGroup,selected_property_type:string,type:string),(property:highlightArrowGroup,selected_property_type:string,type:string)),segment_type:string,to_date:0,type:unique,unit:day
|
||||
# https://www.dropbox.com/s/jot1ikz7nk7jti5/Screenshot%202014-11-18%2008.04.00.png?dl=0
|
||||
#getHighlightArrowSoundGroup: ->
|
||||
# return @highlightArrowGroup if @highlightArrowGroup
|
||||
# group = me.get('testGroupNumber') % 8
|
||||
# @highlightArrowGroup = switch group
|
||||
# when 0, 1, 2, 3 then 'sound-off'
|
||||
# when 4, 5, 6, 7 then 'sound-on'
|
||||
# @highlightArrowGroup = 'sound-off' if me.isAdmin()
|
||||
# application.tracker.identify highlightArrowGroup: @highlightArrowGroup unless me.isAdmin()
|
||||
# @highlightArrowGroup
|
||||
|
||||
getKithmazeGroup: ->
|
||||
return @kithmazeGroup if @kithmazeGroup
|
||||
|
|
|
@ -24,6 +24,7 @@ worldUpdatedEventSchema = c.object {required: ['world', 'firstWorld', 'goalState
|
|||
goalStates: goalStatesSchema
|
||||
team: {type: 'string'}
|
||||
firstChangedFrame: {type: 'integer', minimum: 0}
|
||||
finished: {type: 'boolean'}
|
||||
|
||||
module.exports =
|
||||
'god:user-code-problem': c.object {required: ['problem']},
|
||||
|
|
|
@ -2,10 +2,12 @@ c = require 'schemas/schemas'
|
|||
|
||||
module.exports =
|
||||
'ipad:products': c.object {required: ['products']},
|
||||
products: c.array {},
|
||||
products: c.array {},
|
||||
c.object {},
|
||||
price: { type: 'string' }
|
||||
id: { type: 'string' }
|
||||
|
||||
|
||||
'ipad:iap-complete': c.object {},
|
||||
productID: { type: 'string' }
|
||||
|
||||
'ipad:memory-warning': c.object {}
|
||||
|
|
|
@ -20,7 +20,27 @@
|
|||
top: -146px
|
||||
left: -3px
|
||||
|
||||
|
||||
//- Close modal button
|
||||
|
||||
#close-modal
|
||||
position: absolute
|
||||
left: 769px
|
||||
top: -5px
|
||||
width: 60px
|
||||
height: 60px
|
||||
color: white
|
||||
text-align: center
|
||||
font-size: 30px
|
||||
padding-top: 17px
|
||||
cursor: pointer
|
||||
z-index: 2
|
||||
@include rotate(-3deg)
|
||||
|
||||
&:hover
|
||||
color: yellow
|
||||
|
||||
|
||||
//- Nav bar
|
||||
|
||||
#game-menu-nav
|
||||
|
|
|
@ -106,11 +106,11 @@ $itemSlotGridHeight: 70px
|
|||
// opacity: 0.5
|
||||
|
||||
&.selected
|
||||
.placeholder, img.item
|
||||
.placeholder, .item
|
||||
border-color: rgb(81,153,236)
|
||||
background-color: rgb(81,153,236)
|
||||
@include box-shadow(0 0 10px rgb(81,153,236))
|
||||
img.item
|
||||
.item
|
||||
background: rgb(81,153,236)
|
||||
|
||||
&.should-equip
|
||||
|
@ -269,7 +269,7 @@ $itemSlotGridHeight: 70px
|
|||
.placeholder
|
||||
background-position: (-2 * $itemSlotInnerWidth) 0px
|
||||
|
||||
img.item
|
||||
.item
|
||||
position: absolute
|
||||
left: -2px
|
||||
top: -2px
|
||||
|
@ -299,7 +299,7 @@ $itemSlotGridHeight: 70px
|
|||
|
||||
//- Available equipment
|
||||
|
||||
&.Warrior #unequipped img.item:not(.Warrior), &.Ranger #unequipped img.item:not(.Ranger), &.Wizard #unequipped img.item:not(.Wizard)
|
||||
&.Warrior #unequipped .item:not(.Warrior), &.Ranger #unequipped .item:not(.Ranger), &.Wizard #unequipped .item:not(.Wizard)
|
||||
// Our code hides and shows (modifies display), but we can be invisible this other way.
|
||||
visibility: hidden
|
||||
position: absolute
|
||||
|
@ -313,7 +313,14 @@ $itemSlotGridHeight: 70px
|
|||
padding: 9px 0 9px 9px
|
||||
|
||||
#double-click-hint
|
||||
margin: 20px 50px 70px 0
|
||||
margin: 20px 40px 60px 0
|
||||
border: 3px solid #8585f4
|
||||
padding: 5px
|
||||
font-weight: bold
|
||||
.glyphicon
|
||||
margin-right: 5px
|
||||
position: relative
|
||||
top: 2px
|
||||
|
||||
h4
|
||||
clear: both
|
||||
|
@ -323,14 +330,28 @@ $itemSlotGridHeight: 70px
|
|||
text-transform: uppercase
|
||||
font-weight: bold
|
||||
|
||||
img.item
|
||||
.item
|
||||
float: left
|
||||
border: 1px solid black
|
||||
margin: 3px
|
||||
padding: 1px
|
||||
position: relative
|
||||
width: 60px
|
||||
height: 60px
|
||||
cursor: pointer
|
||||
|
||||
img
|
||||
width: 56px
|
||||
height: 56px
|
||||
display: block
|
||||
|
||||
button
|
||||
width: 100%
|
||||
height: 17px
|
||||
border: 1px solid rgb(46,46,46)
|
||||
background: white
|
||||
font-size: 11px
|
||||
border-radius: 1px
|
||||
padding: 0
|
||||
|
||||
|
||||
&.active
|
||||
background-color: rgb(81,153,236)
|
||||
|
@ -437,3 +458,7 @@ $itemSlotGridHeight: 70px
|
|||
border: 3px solid rgb(46,46,46)
|
||||
background: white
|
||||
font-size: 16px
|
||||
|
||||
#equip-item-viewed
|
||||
background: rgb(84,128,44)
|
||||
color: white
|
||||
|
|
|
@ -112,6 +112,36 @@
|
|||
color: white
|
||||
font-size: 18px
|
||||
|
||||
.multiplayer-area-container
|
||||
position: relative
|
||||
width: 100%
|
||||
height: 50px
|
||||
pointer-events: none
|
||||
|
||||
.multiplayer-area
|
||||
min-width: 200px
|
||||
max-width: 293px
|
||||
height: 60px
|
||||
margin: 0 auto
|
||||
padding: 8px
|
||||
border-image: url(/images/level/control_bar_level_name_background.png) 30 fill round
|
||||
border-width: 0 15px 15px 15px
|
||||
text-align: center
|
||||
position: absolute
|
||||
left: 50%
|
||||
cursor: pointer
|
||||
pointer-events: all
|
||||
@include translate(-50%, 0)
|
||||
|
||||
.multiplayer-label
|
||||
font-size: 12px
|
||||
color: $control-yellow-highlight
|
||||
margin-bottom: -5px
|
||||
|
||||
.multiplayer-status
|
||||
color: white
|
||||
font-size: 18px
|
||||
|
||||
.buttons-area
|
||||
position: absolute
|
||||
right: 35px
|
||||
|
@ -167,6 +197,12 @@ html.no-borderimage
|
|||
background: transparent url(/images/level/control_bar_level_name_background.png)
|
||||
background-size: contain
|
||||
background-repeat: no-repeat
|
||||
#control-bar-view .multiplayer-area
|
||||
border: 0
|
||||
background: transparent url(/images/level/control_bar_level_name_background.png)
|
||||
background-size: contain
|
||||
background-repeat: no-repeat
|
||||
|
||||
|
||||
body:not(.ipad)
|
||||
@media only screen and (max-width: 1300px)
|
||||
|
|
|
@ -1,16 +0,0 @@
|
|||
@import "app/styles/mixins"
|
||||
@import "app/styles/bootstrap/variables"
|
||||
|
||||
// TODO: Replace this devart with nice shinies
|
||||
|
||||
#multiplayer-status-view
|
||||
position: absolute
|
||||
|
||||
.player-count
|
||||
color: white
|
||||
.players-available
|
||||
color: lightblue
|
||||
.players-unavailable
|
||||
color: fuchsia
|
||||
.game-status
|
||||
color: lightgreen
|
|
@ -91,7 +91,7 @@
|
|||
background-color: rgba(255, 255, 255, 0.4)
|
||||
|
||||
.ace_content
|
||||
.executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error
|
||||
.executing, .executed, .problem-marker-info, .problem-marker-warning, .problem-marker-error, .problem-line
|
||||
position: absolute
|
||||
.executing
|
||||
// https://github.com/codecombat/codecombat/issues/6
|
||||
|
@ -108,11 +108,11 @@
|
|||
|
||||
+keyframes(pulseRedBackground)
|
||||
from
|
||||
background-color: rgba(255, 45, 27, 0.25)
|
||||
background-color: rgba(255, 45, 27, 0.4)
|
||||
50%
|
||||
background-color: rgba(255, 45, 27, 0.125)
|
||||
background-color: rgba(255, 45, 27, 0.2)
|
||||
to
|
||||
background-color: rgba(255, 45, 27, 0.25)
|
||||
background-color: rgba(255, 45, 27, 0.4)
|
||||
|
||||
// problem-marker-#{@aetherProblem.level} set in Problem.coffee
|
||||
.problem-marker-info
|
||||
|
@ -120,10 +120,11 @@
|
|||
.problem-marker-warning
|
||||
background-color: rgba(100, 65, 20, 0.25)
|
||||
.problem-marker-error
|
||||
background-color: rgba(255, 45, 27, 0.5)
|
||||
.problem-line
|
||||
// TODO: Pulses too quickly during playback
|
||||
@include animation(pulseRedBackground 1s infinite)
|
||||
|
||||
|
||||
&:not(.playback-ended)
|
||||
.executing:not(.ace_gutter-cell)
|
||||
background-size: 40px 40px
|
||||
|
|
|
@ -21,8 +21,12 @@
|
|||
position: absolute
|
||||
left: 860px
|
||||
top: 126px
|
||||
width: 330px
|
||||
width: 353px
|
||||
height: 449px
|
||||
|
||||
.nano-content
|
||||
right: 24px
|
||||
|
||||
//background: rgba(100,100,100,0.5)
|
||||
|
||||
#item-container
|
||||
|
|
|
@ -339,11 +339,13 @@
|
|||
.nano-content
|
||||
padding-left: 20px
|
||||
|
||||
#item-title
|
||||
left: 698px
|
||||
|
||||
#item-details-body
|
||||
left: 648px
|
||||
|
||||
#selected-item-unlock-button
|
||||
left: 645px
|
||||
#item-details-view
|
||||
|
||||
#item-title
|
||||
left: 698px
|
||||
|
||||
#item-details-body
|
||||
left: 648px
|
||||
|
||||
#selected-item-unlock-button, .unequippable
|
||||
left: 645px
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
.modal-content
|
||||
img(src="/images/pages/play/modal/game-menu-background.png")#game-menu-background
|
||||
|
||||
div#close-modal
|
||||
span.glyphicon.glyphicon-remove
|
||||
|
||||
ul#game-menu-nav.nav.nav-pills.nav-stacked
|
||||
li
|
||||
a#change-hero-tab
|
||||
|
|
|
@ -25,21 +25,27 @@
|
|||
if itemGroups.availableItems.models.length
|
||||
h4#available-description(data-i18n="inventory.available_item")
|
||||
for item in itemGroups.availableItems.models
|
||||
img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
|
||||
.item.available(class=item.classes, data-item-id=item.id)
|
||||
img(src=item.getPortraitURL())
|
||||
button.btn.equip-item(data-i18n="inventory.equip")
|
||||
.clearfix
|
||||
|
||||
#double-click-hint.alert.alert-info.secret(data-i18n="inventory.should_equip")
|
||||
#double-click-hint.alert.alert-info
|
||||
span.glyphicon.glyphicon-info-sign.spr
|
||||
span(data-i18n="inventory.should_equip")
|
||||
|
||||
if itemGroups.restrictedItems.models.length
|
||||
h4#restricted-description(data-i18n="inventory.restricted_title")
|
||||
for item in itemGroups.restrictedItems.models
|
||||
img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
|
||||
.item(class=item.classes, data-item-id=item.id)
|
||||
img(src=item.getPortraitURL())
|
||||
.clearfix
|
||||
|
||||
|
||||
if itemGroups.lockedItems.models.length
|
||||
h4#locked-description(data-i18n="play.locked")
|
||||
for item in itemGroups.lockedItems.models
|
||||
img.item(src=item.getPortraitURL(), class=item.classes, data-item-id=item.id)
|
||||
.item(class=item.classes, data-item-id=item.id)
|
||||
img(src=item.getPortraitURL())
|
||||
.clearfix
|
||||
|
||||
#item-details-view
|
||||
|
|
|
@ -9,10 +9,19 @@
|
|||
.glyphicon.glyphicon-play
|
||||
span(data-i18n="nav.play").home-text Levels
|
||||
|
||||
.level-name-area-container
|
||||
.level-name-area
|
||||
.level-label(data-i18n="play_level.level")
|
||||
.level-name= worldName
|
||||
if isMultiplayerLevel
|
||||
.multiplayer-area-container
|
||||
.multiplayer-area
|
||||
.multiplayer-label(data-i18n="play_level.control_bar_multiplayer")
|
||||
if multiplayerStatus
|
||||
.multiplayer-status= multiplayerStatus
|
||||
else
|
||||
.multiplayer-status(data-i18n="play_level.control_bar_join_game")
|
||||
else
|
||||
.level-name-area-container
|
||||
.level-name-area
|
||||
.level-label(data-i18n="play_level.level")
|
||||
.level-name= worldName
|
||||
|
||||
.buttons-area
|
||||
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
//- TODO: Replace this devart with nice shinies
|
||||
|
||||
div
|
||||
button#multiplayer-button Multiplayer
|
||||
//- span.spr
|
||||
//- span.player-count #{playerCount} total players
|
||||
span.spr
|
||||
span.players-available #{playersAvailable} available
|
||||
span.spr
|
||||
span.players-unavailable #{playersUnavailable} playing
|
||||
span.spr
|
||||
span.game-status #{status}
|
|
@ -17,6 +17,7 @@ module.exports = class GameMenuModal extends ModalView
|
|||
'change input.select': 'onSelectionChanged'
|
||||
'shown.bs.tab #game-menu-nav a': 'onTabShown'
|
||||
'click #change-hero-tab': -> @trigger 'change-hero'
|
||||
'click #close-modal': 'hide'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
|
|
@ -20,9 +20,10 @@ module.exports = class InventoryModal extends ModalView
|
|||
|
||||
events:
|
||||
'click .item-slot': 'onItemSlotClick'
|
||||
'click #unequipped img.item': 'onUnequippedItemClick'
|
||||
'doubletap #unequipped img.item': 'onUnequippedItemDoubleClick'
|
||||
'doubletap .item-slot img.item': 'onEquippedItemDoubleClick'
|
||||
'click #unequipped .item': 'onUnequippedItemClick'
|
||||
'doubletap #unequipped .item': 'onUnequippedItemDoubleClick'
|
||||
'doubletap .item-slot .item': 'onEquippedItemDoubleClick'
|
||||
'click button.equip-item': 'onClickEquipItemButton'
|
||||
'shown.bs.modal': 'onShown'
|
||||
'click #choose-hero-button': 'onClickChooseHero'
|
||||
'click #play-level-button': 'onClickPlayLevel'
|
||||
|
@ -126,6 +127,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
@insertSubView(@itemDetailsView)
|
||||
@requireLevelEquipment()
|
||||
@$el.find('.nano').nanoScroller({alwaysVisible: true})
|
||||
@onSelectionChanged()
|
||||
|
||||
afterInsert: ->
|
||||
super()
|
||||
|
@ -137,7 +139,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
#- Draggable logic
|
||||
|
||||
setUpDraggableEventsForAvailableEquipment: ->
|
||||
for availableItemEl in @$el.find('#unequipped img.item')
|
||||
for availableItemEl in @$el.find('#unequipped .item')
|
||||
availableItemEl = $(availableItemEl)
|
||||
continue if availableItemEl.hasClass('locked') or availableItemEl.hasClass('restricted')
|
||||
dragHelper = availableItemEl.clone().addClass('draggable-item')
|
||||
|
@ -201,12 +203,12 @@ module.exports = class InventoryModal extends ModalView
|
|||
|
||||
onUnequippedItemClick: (e) ->
|
||||
return if @justDoubleClicked
|
||||
itemEl = $(e.target).closest('img.item')
|
||||
itemEl = $(e.target).closest('.item')
|
||||
@selectUnequippedItem(itemEl)
|
||||
|
||||
onUnequippedItemDoubleClick: (e) ->
|
||||
item = $(e.target).closest('img.item')
|
||||
return if item.hasClass('locked') or item.hasClass('restricted')
|
||||
itemEl = $(e.target).closest('.item')
|
||||
return if itemEl.hasClass('locked') or itemEl.hasClass('restricted')
|
||||
@equipSelectedItem()
|
||||
@justDoubleClicked = true
|
||||
_.defer => @justDoubleClicked = false
|
||||
|
@ -215,6 +217,11 @@ module.exports = class InventoryModal extends ModalView
|
|||
onClickEquipItemViewed: -> @equipSelectedItem()
|
||||
onClickUnequipItemViewed: -> @unequipSelectedItem()
|
||||
|
||||
onClickEquipItemButton: (e) ->
|
||||
itemEl = $(e.target).closest('.item')
|
||||
@selectUnequippedItem(itemEl)
|
||||
@equipSelectedItem()
|
||||
|
||||
onUnlockButtonClicked: (e) ->
|
||||
button = $(e.target).closest('button')
|
||||
if button.hasClass('confirm')
|
||||
|
@ -249,7 +256,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
selectItemSlot: (slotEl) ->
|
||||
@clearSelection()
|
||||
slotEl.addClass('selected')
|
||||
selectedSlotItemID = slotEl.find('img.item').data('item-id')
|
||||
selectedSlotItemID = slotEl.find('.item').data('item-id')
|
||||
item = @items.get(selectedSlotItemID)
|
||||
if item then @showItemDetails(item, 'unequip')
|
||||
@onSelectionChanged()
|
||||
|
@ -270,7 +277,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
selectedItemEl.effect('transfer', to: slotEl, duration: 500, easing: 'easeOutCubic')
|
||||
unequipped = @unequipItemFromSlot(slotEl)
|
||||
selectedItemEl.addClass('equipped')
|
||||
slotEl.append(selectedItemEl.clone())
|
||||
slotEl.append(selectedItemEl.find('img').clone().addClass('item').data('item-id', selectedItem.id))
|
||||
@clearSelection()
|
||||
@showItemDetails(selectedItem, 'unequip')
|
||||
slotEl.addClass('selected')
|
||||
|
@ -302,17 +309,17 @@ module.exports = class InventoryModal extends ModalView
|
|||
@hideItemDetails()
|
||||
|
||||
unequipItemFromSlot: (slotEl) ->
|
||||
itemEl = slotEl.find('img.item')
|
||||
itemEl = slotEl.find('.item')
|
||||
itemIDToUnequip = itemEl.data('item-id')
|
||||
return unless itemIDToUnequip
|
||||
itemEl.remove()
|
||||
@$el.find("#unequipped img.item[data-item-id=#{itemIDToUnequip}]").removeClass('equipped')
|
||||
@$el.find("#unequipped .item[data-item-id=#{itemIDToUnequip}]").removeClass('equipped')
|
||||
|
||||
deselectAllSlots: ->
|
||||
@$el.find('#equipped .item-slot.selected').removeClass('selected')
|
||||
|
||||
deselectAllUnequippedItems: ->
|
||||
@$el.find('#unequipped img.item').removeClass('active')
|
||||
@$el.find('#unequipped .item').removeClass('active')
|
||||
|
||||
getSlot: (name) ->
|
||||
@$el.find(".item-slot[data-slot=#{name}]")
|
||||
|
@ -321,9 +328,13 @@ module.exports = class InventoryModal extends ModalView
|
|||
@$el.find('#equipped .item-slot.selected')
|
||||
|
||||
getSelectedUnequippedItem: ->
|
||||
@$el.find('#unequipped img.item.active')
|
||||
@$el.find('#unequipped .item.active')
|
||||
|
||||
onSelectionChanged: ->
|
||||
heroClass = @selectedHero?.get('heroClass')
|
||||
itemsCanBeEquipped = @$el.find('#unequipped .item.available:not(.equipped)').filter('.'+heroClass).length
|
||||
toShow = @$el.find('#double-click-hint, #available-description')
|
||||
if itemsCanBeEquipped then toShow.removeClass('secret') else toShow.addClass('secret')
|
||||
@delegateEvents()
|
||||
|
||||
|
||||
|
@ -340,7 +351,7 @@ module.exports = class InventoryModal extends ModalView
|
|||
config = {}
|
||||
for slot in @$el.find('.item-slot')
|
||||
slotName = $(slot).data('slot')
|
||||
slotItemID = $(slot).find('img.item').data('item-id')
|
||||
slotItemID = $(slot).find('.item').data('item-id')
|
||||
continue unless slotItemID
|
||||
item = _.find @items.models, {id:slotItemID}
|
||||
config[slotName] = item.get('original')
|
||||
|
@ -387,7 +398,6 @@ module.exports = class InventoryModal extends ModalView
|
|||
@highlightElement availableSlotSelector, delay: 500, sides: ['right'], rotation: Math.PI / 2
|
||||
@$el.find(availableSlotSelector).addClass 'should-equip'
|
||||
@$el.find("#equipped div[data-slot='#{slot}']").addClass 'should-equip'
|
||||
@$el.find('#double-click-hint').removeClass('secret')
|
||||
@remainingRequiredEquipment.push slot: slot, item: gear[item]
|
||||
if hadRequired and not @remainingRequiredEquipment.length
|
||||
@endHighlight()
|
||||
|
|
|
@ -99,7 +99,7 @@ module.exports = class CocoView extends Backbone.View
|
|||
@$el.find(selector).replaceWith(newTemplate.find(selector))
|
||||
@delegateEvents()
|
||||
@$el.i18n()
|
||||
|
||||
|
||||
render: ->
|
||||
return @ unless me
|
||||
view.destroy() for id, view of @subviews
|
||||
|
@ -358,8 +358,6 @@ module.exports = class CocoView extends Backbone.View
|
|||
animatePointer: =>
|
||||
$pointer = @getPointer()
|
||||
$pointer.css transition: 'all 0.6s ease-out', transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance-50}px)"
|
||||
if me.getHighlightArrowSoundGroup() is 'sound-on'
|
||||
Backbone.Mediator.publish 'audio-player:play-sound', trigger: 'dom_highlight', volume: 0.5
|
||||
setTimeout (=> $pointer.css transition: 'all 0.4s ease-in', transform: "rotate(#{@pointerRotation}rad) translate(-3px, #{@pointerRadialDistance}px)"), 800
|
||||
|
||||
endHighlight: ->
|
||||
|
|
|
@ -31,6 +31,8 @@ module.exports = class WorldMapView extends RootView
|
|||
'click #volume-button': 'onToggleVolume'
|
||||
|
||||
constructor: (options, @terrain) ->
|
||||
if options and application.isIPAdApp # TODO: later only clear the SuperModel if it has received a memory warning (not in app store yet)
|
||||
options.supermodel = null
|
||||
@terrain ?= 'dungeon' # or 'forest'
|
||||
super options
|
||||
@nextLevel = @getQueryVariable 'next'
|
||||
|
@ -282,6 +284,7 @@ module.exports = class WorldMapView extends RootView
|
|||
storage.save("loaded-menu-music-#{@terrain}", true) unless @probablyCachedMusic
|
||||
|
||||
preloadTopHeroes: ->
|
||||
return # Don't do this because these two have feature images, so we don't need the raw vector data for them. Later they'll all have feature images...
|
||||
for heroID in ['captain', 'knight']
|
||||
url = "/db/thang.type/#{ThangType.heroes[heroID]}/version"
|
||||
continue if @supermodel.getModel url
|
||||
|
|
|
@ -3,8 +3,10 @@ template = require 'templates/play/level/control_bar'
|
|||
{me} = require 'lib/auth'
|
||||
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
RealTimeModel = require 'models/RealTimeModel'
|
||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
|
||||
module.exports = class ControlBarView extends CocoView
|
||||
id: 'control-bar-view'
|
||||
|
@ -14,19 +16,24 @@ module.exports = class ControlBarView extends CocoView
|
|||
'bus:player-states-changed': 'onPlayerStatesChanged'
|
||||
'level:disable-controls': 'onDisableControls'
|
||||
'level:enable-controls': 'onEnableControls'
|
||||
'ipad:memory-warning': 'onIPadMemoryWarning'
|
||||
|
||||
events:
|
||||
'click #next-game-button': -> Backbone.Mediator.publish 'level:next-game-pressed', {}
|
||||
'click #game-menu-button': 'showGameMenuModal'
|
||||
'click': -> Backbone.Mediator.publish 'tome:focus-editor', {}
|
||||
'click .home a': 'onClickHome'
|
||||
'click .multiplayer-area': 'onClickMultiplayer'
|
||||
|
||||
constructor: (options) ->
|
||||
@worldName = options.worldName
|
||||
@session = options.session
|
||||
@level = options.level
|
||||
@levelID = @level.get('slug')
|
||||
@spectateGame = options.spectateGame ? false
|
||||
super options
|
||||
if @isMultiplayerLevel = @level.get('type') in ['hero-ladder']
|
||||
@multiplayerStatusManager = new MultiplayerStatusManager @levelID, @onMultiplayerStateChanged
|
||||
|
||||
setBus: (@bus) ->
|
||||
|
||||
|
@ -40,13 +47,17 @@ module.exports = class ControlBarView extends CocoView
|
|||
text += " (#{numPlayers})" if numPlayers > 1
|
||||
$('#multiplayer-button', @$el).text(text)
|
||||
|
||||
onMultiplayerStateChanged: => @render?()
|
||||
|
||||
getRenderData: (c={}) ->
|
||||
super c
|
||||
c.worldName = @worldName
|
||||
c.multiplayerEnabled = @session.get('multiplayer')
|
||||
c.ladderGame = @level.get('type') in ['ladder', 'hero-ladder']
|
||||
if c.isMultiplayerLevel = @isMultiplayerLevel
|
||||
c.multiplayerStatus = @multiplayerStatusManager?.status
|
||||
c.spectateGame = @spectateGame
|
||||
@homeViewArgs = [{supermodel: @supermodel}]
|
||||
@homeViewArgs = [{supermodel: if @hasReceivedMemoryWarning then null else @supermodel}]
|
||||
if @level.get('type', true) in ['ladder', 'ladder-tutorial', 'hero-ladder']
|
||||
levelID = @level.get('slug').replace /\-tutorial$/, ''
|
||||
@homeLink = c.homeLink = '/play/ladder/' + levelID
|
||||
|
@ -71,7 +82,7 @@ module.exports = class ControlBarView extends CocoView
|
|||
@openModalView gameMenuModal
|
||||
@listenToOnce gameMenuModal, 'change-hero', ->
|
||||
@setupManager?.destroy()
|
||||
@setupManager = new LevelSetupManager({supermodel: @supermodel, levelID: @level.get('slug'), parent: @, session: @session})
|
||||
@setupManager = new LevelSetupManager({supermodel: @supermodel, levelID: @levelID, parent: @, session: @session})
|
||||
@setupManager.open()
|
||||
|
||||
onClickHome: (e) ->
|
||||
|
@ -79,6 +90,9 @@ module.exports = class ControlBarView extends CocoView
|
|||
e.stopImmediatePropagation()
|
||||
Backbone.Mediator.publish 'router:navigate', route: @homeLink, viewClass: @homeViewClass, viewArgs: @homeViewArgs
|
||||
|
||||
onClickMultiplayer: (e) ->
|
||||
@openModalView new GameMenuModal showTab: 'multiplayer', level: @level, session: @session, supermodel: @supermodel
|
||||
|
||||
onDisableControls: (e) -> @toggleControls e, false
|
||||
onEnableControls: (e) -> @toggleControls e, true
|
||||
toggleControls: (e, enabled) ->
|
||||
|
@ -92,6 +106,67 @@ module.exports = class ControlBarView extends CocoView
|
|||
for level in campaign.levels
|
||||
return campaign.id if level.id is slug
|
||||
|
||||
onIPadMemoryWarning: (e) ->
|
||||
@hasReceivedMemoryWarning = true
|
||||
|
||||
destroy: ->
|
||||
@setupManager?.destroy()
|
||||
@multiplayerStatusManager?.destroy()
|
||||
super()
|
||||
|
||||
# MultiplayerStatusManager ######################################################
|
||||
#
|
||||
# Manages the multiplayer status, and calls @statusChangedCallback when it changes.
|
||||
#
|
||||
# It monitors these:
|
||||
# Real-time multiplayer players
|
||||
# Internal multiplayer status
|
||||
#
|
||||
# Real-time state variables:
|
||||
# @playersCollection - Real-time multiplayer players
|
||||
#
|
||||
# TODO: Not currently using player counts. Should remove if we keep simple design.
|
||||
#
|
||||
class MultiplayerStatusManager
|
||||
|
||||
constructor: (@levelID, @statusChangedCallback) ->
|
||||
@status = ''
|
||||
# @players = {}
|
||||
# @playersCollection = new RealTimeCollection('multiplayer_players/' + @levelID)
|
||||
# @playersCollection.on 'add', @onPlayerAdded
|
||||
# @playersCollection.each (player) => @onPlayerAdded player
|
||||
Backbone.Mediator.subscribe 'real-time-multiplayer:player-status', @onMultiplayerPlayerStatus
|
||||
|
||||
destroy: ->
|
||||
Backbone.Mediator.unsubscribe 'real-time-multiplayer:player-status', @onMultiplayerPlayerStatus
|
||||
# @playersCollection?.off 'add', @onPlayerAdded
|
||||
# player.off 'change', @onPlayerChanged for id, player of @players
|
||||
|
||||
onMultiplayerPlayerStatus: (e) =>
|
||||
@status = e.status
|
||||
@statusChangedCallback()
|
||||
|
||||
# onPlayerAdded: (player) =>
|
||||
# unless player.id is me.id
|
||||
# @players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
||||
# @players[player.id].on 'change', @onPlayerChanged
|
||||
# @countPlayers player
|
||||
#
|
||||
# onPlayerChanged: (player) =>
|
||||
# @countPlayers player
|
||||
#
|
||||
# countPlayers: (changedPlayer) =>
|
||||
# # TODO: save this stale hearbeat threshold setting somewhere
|
||||
# staleHeartbeat = new Date()
|
||||
# staleHeartbeat.setMinutes staleHeartbeat.getMinutes() - 3
|
||||
# @playerCount = 0
|
||||
# @playersCollectionAvailable = 0
|
||||
# @playersCollectionUnavailable = 0
|
||||
# @playersCollection.each (player) =>
|
||||
# # Assume changedPlayer is fresher than entry in @playersCollection collection
|
||||
# player = changedPlayer if changedPlayer? and player.id is changedPlayer.id
|
||||
# unless staleHeartbeat >= new Date(player.get('heartbeat'))
|
||||
# @playerCount++
|
||||
# @playersCollectionAvailable++ if player.get('state') is 'available'
|
||||
# @playersCollectionUnavailable++ if player.get('state') is 'unavailable'
|
||||
# @statusChangedCallback()
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
CocoView = require 'views/kinds/CocoView'
|
||||
template = require 'templates/play/level/multiplayer-status'
|
||||
{me} = require 'lib/auth'
|
||||
RealTimeModel = require 'models/RealTimeModel'
|
||||
RealTimeCollection = require 'collections/RealTimeCollection'
|
||||
GameMenuModal = require 'views/game-menu/GameMenuModal'
|
||||
|
||||
# Real-time Multiplayer ######################################################
|
||||
#
|
||||
# This view displays the real-time multiplayer status for the current level.
|
||||
#
|
||||
# It performs these actions:
|
||||
# Multiplayer button into game-menu multiplayer section
|
||||
# Display number of players waiting for an opponent in this level
|
||||
# Display number of players current playing a pvp game in this level
|
||||
# Status for user's current real-time multiplayer session
|
||||
#
|
||||
# It monitors these:
|
||||
# Real-time multiplayer players
|
||||
# Internal multiplayer status
|
||||
#
|
||||
# Real-time state variables:
|
||||
# @playersCollection - Real-time multiplayer players
|
||||
|
||||
module.exports = class MultiplayerStatusView extends CocoView
|
||||
id: 'multiplayer-status-view'
|
||||
template: template
|
||||
|
||||
subscriptions:
|
||||
'real-time-multiplayer:player-status': 'onRealTimeMultiplayerPlayerStatus'
|
||||
|
||||
events:
|
||||
'click #multiplayer-button': 'onClickMultiplayerButton'
|
||||
|
||||
constructor: (options) ->
|
||||
super(options)
|
||||
@session = options.session
|
||||
@level = options.level
|
||||
@levelID = options.levelID
|
||||
@status = ''
|
||||
@players = {}
|
||||
@playersCollection = new RealTimeCollection('multiplayer_players/' + @levelID)
|
||||
@playersCollection.on 'add', @onPlayerAdded
|
||||
@playersCollection.each (player) => @onPlayerAdded player
|
||||
|
||||
destroy: ->
|
||||
@playersCollection?.off 'add', @onPlayerAdded
|
||||
player.off 'change', @onPlayerChanged for id, player of @players
|
||||
super()
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
c.playerCount = @playerCount
|
||||
c.playersAvailable = @playersCollectionAvailable
|
||||
c.playersUnavailable = @playersCollectionUnavailable
|
||||
c.status = @status
|
||||
c
|
||||
|
||||
onRealTimeMultiplayerPlayerStatus: (e) ->
|
||||
@status = e.status
|
||||
@render?()
|
||||
|
||||
onClickMultiplayerButton: (e) ->
|
||||
@openModalView new GameMenuModal showTab: 'multiplayer', level: @level, session: @session, supermodel: @supermodel
|
||||
|
||||
onPlayerAdded: (player) =>
|
||||
# console.log 'MultiplayerStatusView onPlayerAdded', player
|
||||
unless player.id is me.id
|
||||
@players[player.id] = new RealTimeModel('multiplayer_players/' + @levelID + '/' + player.id)
|
||||
@players[player.id].on 'change', @onPlayerChanged
|
||||
@countPlayers player
|
||||
|
||||
onPlayerChanged: (player) =>
|
||||
# console.log 'MultiplayerStatusView onPlayerChanged', player
|
||||
@countPlayers player
|
||||
|
||||
countPlayers: (changedPlayer) =>
|
||||
# TODO: save this stale hearbeat threshold setting somewhere
|
||||
staleHeartbeat = new Date()
|
||||
staleHeartbeat.setMinutes staleHeartbeat.getMinutes() - 3
|
||||
@playerCount = 0
|
||||
@playersCollectionAvailable = 0
|
||||
@playersCollectionUnavailable = 0
|
||||
@playersCollection.each (player) =>
|
||||
# Assume changedPlayer is fresher than entry in @playersCollection collection
|
||||
player = changedPlayer if changedPlayer? and player.id is changedPlayer.id
|
||||
unless staleHeartbeat >= new Date(player.get('heartbeat'))
|
||||
@playerCount++
|
||||
@playersCollectionAvailable++ if player.get('state') is 'available'
|
||||
@playersCollectionUnavailable++ if player.get('state') is 'unavailable'
|
||||
# console.log 'MultiplayerStatusView countPlayers', @playerCount, @playersCollectionAvailable, @playersCollectionUnavailable
|
||||
@render()
|
||||
|
|
@ -36,7 +36,6 @@ GoldView = require './LevelGoldView'
|
|||
VictoryModal = require './modal/VictoryModal'
|
||||
HeroVictoryModal = require './modal/HeroVictoryModal'
|
||||
InfiniteLoopModal = require './modal/InfiniteLoopModal'
|
||||
MultiplayerStatusView = require './MultiplayerStatusView'
|
||||
LevelSetupManager = require 'lib/LevelSetupManager'
|
||||
|
||||
PROFILE_ME = false
|
||||
|
@ -78,6 +77,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
'real-time-multiplayer:joined-game': 'onRealTimeMultiplayerJoinedGame'
|
||||
'real-time-multiplayer:left-game': 'onRealTimeMultiplayerLeftGame'
|
||||
'real-time-multiplayer:manual-cast': 'onRealTimeMultiplayerCast'
|
||||
'ipad:memory-warning': 'onIPadMemoryWarning'
|
||||
|
||||
events:
|
||||
'click #level-done-button': 'onDonePressed'
|
||||
|
@ -255,8 +255,6 @@ module.exports = class PlayLevelView extends RootView
|
|||
@insertSubView new HUDView {level: @level}
|
||||
@insertSubView new LevelDialogueView {level: @level}
|
||||
@insertSubView new ChatView levelID: @levelID, sessionID: @session.id, session: @session
|
||||
if @level.get('type') in ['hero-ladder']
|
||||
@insertSubView new MultiplayerStatusView levelID: @levelID, session: @session, level: @level
|
||||
@insertSubView new ProblemAlertView {}
|
||||
worldName = utils.i18n @level.attributes, 'name'
|
||||
@controlBar = @insertSubView new ControlBarView {worldName: worldName, session: @session, level: @level, supermodel: @supermodel}
|
||||
|
@ -438,7 +436,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
|
||||
showVictory: ->
|
||||
@endHighlight()
|
||||
options = {level: @level, supermodel: @supermodel, session: @session}
|
||||
options = {level: @level, supermodel: @supermodel, session: @session, hasReceivedMemoryWarning: @hasReceivedMemoryWarning}
|
||||
ModalClass = if @level.get('type', true) in ['hero', 'hero-ladder', 'hero-coop'] then HeroVictoryModal else VictoryModal
|
||||
victoryModal = new ModalClass(options)
|
||||
@openModalView(victoryModal)
|
||||
|
@ -462,7 +460,7 @@ module.exports = class PlayLevelView extends RootView
|
|||
Backbone.Mediator.publish 'router:navigate', {
|
||||
route: nextLevelURL,
|
||||
viewClass: PlayLevelView,
|
||||
viewArgs: [{supermodel: @supermodel}, nextLevelID]}
|
||||
viewArgs: [{supermodel: if @hasReceivedMemoryWarning then null else @supermodel}, nextLevelID]}
|
||||
|
||||
getNextLevel: ->
|
||||
return null unless nextLevelOriginal = @level.get('nextLevel')?.original
|
||||
|
@ -905,3 +903,6 @@ module.exports = class PlayLevelView extends RootView
|
|||
if sessionState?
|
||||
# TODO: Don't hardcode spellName
|
||||
Backbone.Mediator.publish 'level:select-sprite', thangID: sessionState.selected, spellName: 'plan'
|
||||
|
||||
onIPadMemoryWarning: (e) ->
|
||||
@hasReceivedMemoryWarning = true
|
||||
|
|
|
@ -298,7 +298,7 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
skipPrompt ||= not (@skipAheadLevelLink or @morePractiveLevelLink) and me.getBranchingGroup() is 'choice-explicit'
|
||||
if skipPrompt
|
||||
# Preserve the supermodel as we navigate back to the world map.
|
||||
Backbone.Mediator.publish 'router:navigate', route: nextLevelLink, viewClass: require('views/play/WorldMapView'), viewArgs: [{supermodel: @supermodel}, @getNextLevelCampaign()]
|
||||
Backbone.Mediator.publish 'router:navigate', route: nextLevelLink, viewClass: require('views/play/WorldMapView'), viewArgs: [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @getNextLevelCampaign()]
|
||||
else
|
||||
# Hide everything except the buttons prompting them for which kind of next level to do
|
||||
@$el.find('.modal-footer, .modal-body > *').hide()
|
||||
|
@ -309,10 +309,10 @@ module.exports = class HeroVictoryModal extends ModalView
|
|||
route = $(e.target).data('href') or "/play/#{@getNextLevelCampaign()}"
|
||||
application.tracker?.trackEvent 'Branch Selected', level: @level.get('slug'), label: @level.get('slug'), branch: $(e.target).data('branch-key'), branchingGroup: me.getBranchingGroup(), route: route
|
||||
# Preserve the supermodel as we navigate back to world map.
|
||||
Backbone.Mediator.publish 'router:navigate', route: route, viewClass: require('views/play/WorldMapView'), viewArgs: [{supermodel: @supermodel}, @getNextLevelCampaign()]
|
||||
Backbone.Mediator.publish 'router:navigate', route: route, viewClass: require('views/play/WorldMapView'), viewArgs: [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @getNextLevelCampaign()]
|
||||
|
||||
onClickReturnToLadder: (e) ->
|
||||
e.preventDefault()
|
||||
route = $(e.target).data('href')
|
||||
# Preserve the supermodel as we navigate back to the ladder.
|
||||
Backbone.Mediator.publish 'router:navigate', route: route, viewClass: require('views/play/ladder/LadderView'), viewArgs: [{supermodel: @supermodel}, @level.get('slug')]
|
||||
Backbone.Mediator.publish 'router:navigate', route: route, viewClass: require('views/play/ladder/LadderView'), viewArgs: [{supermodel: if @options.hasReceivedMemoryWarning then null else @supermodel}, @level.get('slug')]
|
||||
|
|
|
@ -10,7 +10,7 @@ module.exports = class Problem
|
|||
Backbone.Mediator.publish("problem:problem-created", line: @annotation.row, text: @annotation.text) if application.isIPadApp
|
||||
|
||||
destroy: ->
|
||||
@removeMarkerRange()
|
||||
@removeMarkerRanges()
|
||||
@userCodeProblem.off() if @userCodeProblem
|
||||
|
||||
buildAnnotation: ->
|
||||
|
@ -27,14 +27,23 @@ module.exports = class Problem
|
|||
buildMarkerRange: ->
|
||||
return unless @aetherProblem.range
|
||||
[start, end] = @aetherProblem.range
|
||||
clazz = "problem-marker-#{@aetherProblem.level}"
|
||||
@markerRange = new Range start.row, start.col, end.row, end.col
|
||||
@markerRange.start = @ace.getSession().getDocument().createAnchor @markerRange.start
|
||||
@markerRange.end = @ace.getSession().getDocument().createAnchor @markerRange.end
|
||||
@markerRange.id = @ace.getSession().addMarker @markerRange, clazz, 'fullLine'
|
||||
textClazz = "problem-marker-#{@aetherProblem.level}"
|
||||
@textMarkerRange = new Range start.row, start.col, end.row, end.col
|
||||
@textMarkerRange.start = @ace.getSession().getDocument().createAnchor @textMarkerRange.start
|
||||
@textMarkerRange.end = @ace.getSession().getDocument().createAnchor @textMarkerRange.end
|
||||
@textMarkerRange.id = @ace.getSession().addMarker @textMarkerRange, textClazz, 'text'
|
||||
lineClazz = "problem-line"
|
||||
@lineMarkerRange = new Range start.row, start.col, end.row, end.col
|
||||
@lineMarkerRange.start = @ace.getSession().getDocument().createAnchor @lineMarkerRange.start
|
||||
@lineMarkerRange.end = @ace.getSession().getDocument().createAnchor @lineMarkerRange.end
|
||||
@lineMarkerRange.id = @ace.getSession().addMarker @lineMarkerRange, lineClazz, 'fullLine'
|
||||
|
||||
removeMarkerRange: ->
|
||||
return unless @markerRange
|
||||
@ace.getSession().removeMarker @markerRange.id
|
||||
@markerRange.start.detach()
|
||||
@markerRange.end.detach()
|
||||
removeMarkerRanges: ->
|
||||
if @textMarkerRange
|
||||
@ace.getSession().removeMarker @textMarkerRange.id
|
||||
@textMarkerRange.start.detach()
|
||||
@textMarkerRange.end.detach()
|
||||
if @lineMarkerRange
|
||||
@ace.getSession().removeMarker @lineMarkerRange.id
|
||||
@lineMarkerRange.start.detach()
|
||||
@lineMarkerRange.end.detach()
|
||||
|
|
|
@ -10,6 +10,7 @@ module.exports = class ProblemAlertView extends CocoView
|
|||
subscriptions:
|
||||
'tome:show-problem-alert': 'onShowProblemAlert'
|
||||
'tome:hide-problem-alert': 'onHideProblemAlert'
|
||||
'level:restart': 'onHideProblemAlert'
|
||||
'tome:jiggle-problem-alert': 'onJiggleProblemAlert'
|
||||
'tome:manual-cast': 'onHideProblemAlert'
|
||||
'real-time-multiplayer:manual-cast': 'onHideProblemAlert'
|
||||
|
|
|
@ -189,7 +189,7 @@ module.exports = class SpellView extends CocoView
|
|||
bindKey: {win: 'Ctrl-Shift-M', mac: 'Command-Shift-M|Ctrl-Shift-M'}
|
||||
exec: -> Backbone.Mediator.publish 'tome:toggle-maximize', {}
|
||||
addCommand
|
||||
# TODO: Restrict to beginner campaign levels
|
||||
# TODO: Restrict to beginner campaign levels, possibly with a CampaignOptions similar to LevelOptions
|
||||
name: 'enter-skip-delimiters'
|
||||
bindKey: 'Enter|Return'
|
||||
exec: =>
|
||||
|
@ -202,6 +202,10 @@ module.exports = class SpellView extends CocoView
|
|||
newRange.setEnd newRange.end.row, newRange.end.column + delimMatch[1].length
|
||||
@aceSession.selection.setSelectionRange newRange
|
||||
@ace.execCommand 'insertstring', '\n'
|
||||
addCommand
|
||||
name: 'disable-spaces'
|
||||
bindKey: 'Space'
|
||||
exec: => @ace.execCommand 'insertstring', ' ' unless LevelOptions[@options.level.get('slug')]?.disableSpaces
|
||||
|
||||
fillACE: ->
|
||||
@ace.setValue @spell.source
|
||||
|
|
|
@ -222,7 +222,8 @@ module.exports = class TomeView extends CocoView
|
|||
if spellName
|
||||
spell = _.find selectedThangSpells, {name: spellName}
|
||||
else
|
||||
spell = _.find selectedThangSpells, (spell) -> true # Just grab one
|
||||
spell = _.find selectedThangSpells, (spell) -> spell.canWrite()
|
||||
spell ?= _.find selectedThangSpells, (spell) -> spell.canRead()
|
||||
spell
|
||||
|
||||
reloadAllCode: ->
|
||||
|
|
|
@ -44,7 +44,6 @@ module.exports = class ItemDetailsView extends CocoView
|
|||
@listenToOnce docs, 'sync', @onDocsLoaded
|
||||
|
||||
@render()
|
||||
@$el.find('.nano:visible').nanoScroller()
|
||||
|
||||
onDocsLoaded: (levelComponents) ->
|
||||
for component in levelComponents.models
|
||||
|
@ -54,6 +53,10 @@ module.exports = class ItemDetailsView extends CocoView
|
|||
else
|
||||
@propDocs[propDoc.name] = propDoc
|
||||
@render()
|
||||
|
||||
afterRender: ->
|
||||
super()
|
||||
@$el.find('.nano:visible').nanoScroller({alwaysVisible: true})
|
||||
|
||||
getRenderData: ->
|
||||
c = super()
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
cd ~/Desktop/coco
|
||||
cp ~/Desktop/treema/treema.js ./vendor/scripts/
|
||||
cp ~/Desktop/treema/treema.css ./vendor/styles/
|
115
vendor/scripts/SpriteContainer.js
vendored
115
vendor/scripts/SpriteContainer.js
vendored
|
@ -3,7 +3,7 @@
|
|||
* Visit http://createjs.com/ for documentation, updates and examples.
|
||||
*
|
||||
* Copyright (c) 2010 gskinner.com, inc.
|
||||
*
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
|
@ -12,10 +12,10 @@
|
|||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
|
@ -30,71 +30,55 @@
|
|||
this.createjs = this.createjs||{};
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A SpriteContainer is a nestable display list that enables aggressively optimized rendering of bitmap content.
|
||||
* In order to accomplish these optimizations, SpriteContainer enforces a few restrictions on its content.
|
||||
*
|
||||
* Restrictions:
|
||||
* - only Sprite, SpriteContainer, BitmapText and DOMElement are allowed to be added as children.
|
||||
* - a spriteSheet MUST be either be passed into the constructor or defined on the first child added.
|
||||
* - all children (with the exception of DOMElement) MUST use the same spriteSheet.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* var data = {
|
||||
* images: ["sprites.jpg"],
|
||||
* frames: {width:50, height:50},
|
||||
* animations: {run:[0,4], jump:[5,8,"run"]}
|
||||
* };
|
||||
* var spriteSheet = new createjs.SpriteSheet(data);
|
||||
* var container = new createjs.SpriteContainer(spriteSheet);
|
||||
* container.addChild(spriteInstance, spriteInstance2);
|
||||
* container.x = 100;
|
||||
*
|
||||
* <strong>Note:</strong> SpriteContainer is not included in the minified version of EaselJS.
|
||||
*
|
||||
* @class SpriteContainer
|
||||
* @extends Container
|
||||
* @constructor
|
||||
* @param {SpriteSheet} [spriteSheet] The spriteSheet to use for this SpriteContainer and its children.
|
||||
**/
|
||||
var SpriteContainer = function(spriteSheet) {
|
||||
this.initialize(spriteSheet);
|
||||
};
|
||||
var p = SpriteContainer.prototype = new createjs.Container();
|
||||
|
||||
// public properties:
|
||||
|
||||
/**
|
||||
* The SpriteSheet that this container enforces use of.
|
||||
* @property spriteSheet
|
||||
* @type {SpriteSheet}
|
||||
* @readonly
|
||||
* A SpriteContainer is a nestable display list that enables aggressively optimized rendering of bitmap content.
|
||||
* In order to accomplish these optimizations, SpriteContainer enforces a few restrictions on its content.
|
||||
*
|
||||
* Restrictions:
|
||||
* - only Sprite, SpriteContainer, BitmapText and DOMElement are allowed to be added as children.
|
||||
* - a spriteSheet MUST be either be passed into the constructor or defined on the first child added.
|
||||
* - all children (with the exception of DOMElement) MUST use the same spriteSheet.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* var data = {
|
||||
* images: ["sprites.jpg"],
|
||||
* frames: {width:50, height:50},
|
||||
* animations: {run:[0,4], jump:[5,8,"run"]}
|
||||
* };
|
||||
* var spriteSheet = new createjs.SpriteSheet(data);
|
||||
* var container = new createjs.SpriteContainer(spriteSheet);
|
||||
* container.addChild(spriteInstance, spriteInstance2);
|
||||
* container.x = 100;
|
||||
*
|
||||
* <strong>Note:</strong> SpriteContainer is not included in the minified version of EaselJS.
|
||||
*
|
||||
* @class SpriteContainer
|
||||
* @extends Container
|
||||
* @constructor
|
||||
* @param {SpriteSheet} [spriteSheet] The spriteSheet to use for this SpriteContainer and its children.
|
||||
**/
|
||||
p.spriteSheet = null;
|
||||
|
||||
// constructor:
|
||||
|
||||
/**
|
||||
* @property Container_initialize
|
||||
* @type Function
|
||||
* @private
|
||||
**/
|
||||
p.Container_initialize = p.initialize;
|
||||
|
||||
/**
|
||||
* Initialization method.
|
||||
* @method initialize
|
||||
* @param {SpriteSheet} spriteSheet Optional. The spriteSheet to use for this SpriteContainer and its children.
|
||||
* @protected
|
||||
*/
|
||||
p.initialize = function(spriteSheet) {
|
||||
this.Container_initialize();
|
||||
function SpriteContainer(spriteSheet) {
|
||||
this.Container_constructor();
|
||||
|
||||
|
||||
// public properties:
|
||||
/**
|
||||
* The SpriteSheet that this container enforces use of.
|
||||
* @property spriteSheet
|
||||
* @type {SpriteSheet}
|
||||
* @readonly
|
||||
**/
|
||||
this.spriteSheet = spriteSheet;
|
||||
};
|
||||
}
|
||||
var p = createjs.extend(SpriteContainer, createjs.Container);
|
||||
|
||||
|
||||
|
||||
// public methods:
|
||||
|
||||
/**
|
||||
* Adds a child to the top of the display list.
|
||||
* Only children of type SpriteContainer, Sprite, Bitmap, BitmapText, or DOMElement are allowed.
|
||||
|
@ -127,7 +111,7 @@ var p = SpriteContainer.prototype = new createjs.Container();
|
|||
* Only children of type SpriteContainer, Sprite, Bitmap, BitmapText, or DOMElement are allowed.
|
||||
* The child must have the same spritesheet as this container (unless it's a DOMElement).
|
||||
* If a spritesheet hasn't been defined, this container uses this child's spritesheet.
|
||||
*
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* addChildAt(child1, index);
|
||||
*
|
||||
|
@ -163,7 +147,7 @@ var p = SpriteContainer.prototype = new createjs.Container();
|
|||
}
|
||||
if (child._spritestage_compatibility <= 4) {
|
||||
var spriteSheet = child.spriteSheet;
|
||||
if ((!spriteSheet || !spriteSheet._images || spriteSheet._images.length > 1) || (this.spritesheet && spritesheet !== spritesheet)) {
|
||||
if ((!spriteSheet || !spriteSheet._images || spriteSheet._images.length > 1) || (this.spriteSheet && this.spriteSheet !== spriteSheet)) {
|
||||
console && console.log("Error: A child's spriteSheet must be equal to its parent spriteSheet and only use one image. [" + child.toString() + "]");
|
||||
return child;
|
||||
}
|
||||
|
@ -184,5 +168,6 @@ var p = SpriteContainer.prototype = new createjs.Container();
|
|||
return "[SpriteContainer (name="+ this.name +")]";
|
||||
};
|
||||
|
||||
createjs.SpriteContainer = SpriteContainer;
|
||||
}());
|
||||
|
||||
createjs.SpriteContainer = createjs.promote(SpriteContainer, "Container");
|
||||
}());
|
||||
|
|
522
vendor/scripts/SpriteStage.js
vendored
522
vendor/scripts/SpriteStage.js
vendored
|
@ -36,54 +36,237 @@ this.createjs = this.createjs||{};
|
|||
(function() {
|
||||
"use strict";
|
||||
|
||||
// Set which classes are compatible with SpriteStage.
|
||||
// The order is important!!! If it's changed/appended, make sure that any logic that
|
||||
// checks _spritestage_compatibility accounts for it!
|
||||
[createjs.SpriteContainer, createjs.Sprite, createjs.BitmapText, createjs.Bitmap, createjs.DOMElement].forEach(function(_class, index) {
|
||||
_class.prototype._spritestage_compatibility = index + 1;
|
||||
});
|
||||
|
||||
/**
|
||||
* A sprite stage is the root level {{#crossLink "Container"}}{{/crossLink}} for an aggressively optimized display list. Each time its {{#crossLink "Stage/tick"}}{{/crossLink}}
|
||||
* method is called, it will render its display list to its target canvas. WebGL content is fully compatible with the existing Context2D renderer.
|
||||
* On devices or browsers that don't support WebGL, content will automatically be rendered via canvas 2D.
|
||||
*
|
||||
* Restrictions:
|
||||
* - only Sprite, SpriteContainer, BitmapText, Bitmap and DOMElement are allowed to be added to the display list.
|
||||
* - a child being added (with the exception of DOMElement) MUST have an image or spriteSheet defined on it.
|
||||
* - a child's image/spriteSheet MUST never change while being on the display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* This example creates a sprite stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child
|
||||
* and redraw the stage using {{#crossLink "SpriteStage/update"}}{{/crossLink}}.
|
||||
*
|
||||
* var stage = new createjs.SpriteStage("canvasElementId", false, false);
|
||||
* stage.updateViewport(800, 600);
|
||||
* var image = new createjs.Bitmap("imagePath.png");
|
||||
* stage.addChild(image);
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* image.x += 10;
|
||||
* stage.update();
|
||||
* }
|
||||
*
|
||||
* <strong>Note:</strong> SpriteStage is not included in the minified version of EaselJS.
|
||||
*
|
||||
* @class SpriteStage
|
||||
* @extends Stage
|
||||
* @constructor
|
||||
* @param {HTMLCanvasElement | String | Object} canvas A canvas object that the SpriteStage will render to, or the string id
|
||||
* of a canvas object in the current document.
|
||||
* @param {Boolean} preserveDrawingBuffer If true, the canvas is NOT auto-cleared by WebGL (spec discourages true). Useful if you want to use p.autoClear = false.
|
||||
* @param {Boolean} antialias Specifies whether or not the browser's WebGL implementation should try to perform antialiasing.
|
||||
**/
|
||||
var SpriteStage = function(canvas, preserveDrawingBuffer, antialias) {
|
||||
this.initialize(canvas, preserveDrawingBuffer, antialias);
|
||||
};
|
||||
var p = SpriteStage.prototype = new createjs.Stage();
|
||||
// Set which classes are compatible with SpriteStage.
|
||||
// The order is important!!! If it's changed/appended, make sure that any logic that
|
||||
// checks _spritestage_compatibility accounts for it!
|
||||
[createjs.SpriteContainer, createjs.Sprite, createjs.BitmapText, createjs.Bitmap, createjs.DOMElement].forEach(function(_class, index) {
|
||||
_class.prototype._spritestage_compatibility = index + 1;
|
||||
});
|
||||
|
||||
|
||||
// static properties:
|
||||
// constructor:
|
||||
/**
|
||||
* A sprite stage is the root level {{#crossLink "Container"}}{{/crossLink}} for an aggressively optimized display list. Each time its {{#crossLink "Stage/tick"}}{{/crossLink}}
|
||||
* method is called, it will render its display list to its target canvas. WebGL content is fully compatible with the existing Context2D renderer.
|
||||
* On devices or browsers that don't support WebGL, content will automatically be rendered via canvas 2D.
|
||||
*
|
||||
* Restrictions:
|
||||
* - only Sprite, SpriteContainer, BitmapText, Bitmap and DOMElement are allowed to be added to the display list.
|
||||
* - a child being added (with the exception of DOMElement) MUST have an image or spriteSheet defined on it.
|
||||
* - a child's image/spriteSheet MUST never change while being on the display list.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
* This example creates a sprite stage, adds a child to it, then uses {{#crossLink "Ticker"}}{{/crossLink}} to update the child
|
||||
* and redraw the stage using {{#crossLink "SpriteStage/update"}}{{/crossLink}}.
|
||||
*
|
||||
* var stage = new createjs.SpriteStage("canvasElementId", false, false);
|
||||
* stage.updateViewport(800, 600);
|
||||
* var image = new createjs.Bitmap("imagePath.png");
|
||||
* stage.addChild(image);
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* image.x += 10;
|
||||
* stage.update();
|
||||
* }
|
||||
*
|
||||
* <strong>Note:</strong> SpriteStage is not included in the minified version of EaselJS.
|
||||
*
|
||||
* @class SpriteStage
|
||||
* @extends Stage
|
||||
* @constructor
|
||||
* @param {HTMLCanvasElement | String | Object} canvas A canvas object that the SpriteStage will render to, or the string id
|
||||
* of a canvas object in the current document.
|
||||
* @param {Boolean} preserveDrawingBuffer If true, the canvas is NOT auto-cleared by WebGL (spec discourages true). Useful if you want to use p.autoClear = false.
|
||||
* @param {Boolean} antialias Specifies whether or not the browser's WebGL implementation should try to perform antialiasing.
|
||||
**/
|
||||
function SpriteStage(canvas, preserveDrawingBuffer, antialias) {
|
||||
this.Stage_constructor(canvas);
|
||||
|
||||
|
||||
// private properties:
|
||||
/**
|
||||
* Specifies whether or not the canvas is auto-cleared by WebGL. Spec discourages true.
|
||||
* If true, the canvas is NOT auto-cleared by WebGL. Value is ignored if `_alphaEnabled` is false.
|
||||
* Useful if you want to use `autoClear = false`.
|
||||
* @property _preserveDrawingBuffer
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
this._preserveDrawingBuffer = preserveDrawingBuffer||false;
|
||||
|
||||
/**
|
||||
* Specifies whether or not the browser's WebGL implementation should try to perform antialiasing.
|
||||
* @property _antialias
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
this._antialias = antialias||false;
|
||||
|
||||
/**
|
||||
* The width of the canvas element.
|
||||
* @property _viewportWidth
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 0
|
||||
**/
|
||||
this._viewportWidth = 0;
|
||||
|
||||
/**
|
||||
* The height of the canvas element.
|
||||
* @property _viewportHeight
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 0
|
||||
**/
|
||||
this._viewportHeight = 0;
|
||||
|
||||
/**
|
||||
* A 2D projection matrix used to convert WebGL's clipspace into normal pixels.
|
||||
* @property _projectionMatrix
|
||||
* @protected
|
||||
* @type {Float32Array}
|
||||
* @default null
|
||||
**/
|
||||
this._projectionMatrix = null;
|
||||
|
||||
/**
|
||||
* The current WebGL canvas context.
|
||||
* @property _webGLContext
|
||||
* @protected
|
||||
* @type {WebGLRenderingContext}
|
||||
* @default null
|
||||
**/
|
||||
this._webGLContext = null;
|
||||
|
||||
/**
|
||||
* Indicates whether or not an error has been detected when dealing with WebGL.
|
||||
* If the is true, the behavior should be to use Canvas 2D rendering instead.
|
||||
* @property _webGLErrorDetected
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
this._webGLErrorDetected = false;
|
||||
|
||||
/**
|
||||
* The color to use when the WebGL canvas has been cleared.
|
||||
* @property _clearColor
|
||||
* @protected
|
||||
* @type {Object}
|
||||
* @default null
|
||||
**/
|
||||
this._clearColor = null;
|
||||
|
||||
/**
|
||||
* The maximum number of textures WebGL can work with per draw call.
|
||||
* @property _maxTexturesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 1
|
||||
**/
|
||||
this._maxTexturesPerDraw = 1; // TODO: this is currently unused.
|
||||
|
||||
/**
|
||||
* The maximum total number of boxes points that can be defined per draw call.
|
||||
* @property _maxBoxesPointsPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
this._maxBoxesPointsPerDraw = null;
|
||||
|
||||
/**
|
||||
* The maximum number of boxes (sprites) that can be drawn in one draw call.
|
||||
* @property _maxBoxesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
this._maxBoxesPerDraw = null;
|
||||
|
||||
/**
|
||||
* The maximum number of indices that can be drawn in one draw call.
|
||||
* @property _maxIndicesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
this._maxIndicesPerDraw = null;
|
||||
|
||||
/**
|
||||
* The shader program used to draw everything.
|
||||
* @property _shaderProgram
|
||||
* @protected
|
||||
* @type {WebGLProgram}
|
||||
* @default null
|
||||
**/
|
||||
this._shaderProgram = null;
|
||||
|
||||
/**
|
||||
* The vertices data for the current draw call.
|
||||
* @property _vertices
|
||||
* @protected
|
||||
* @type {Float32Array}
|
||||
* @default null
|
||||
**/
|
||||
this._vertices = null;
|
||||
|
||||
/**
|
||||
* The buffer that contains all the vertices data.
|
||||
* @property _verticesBuffer
|
||||
* @protected
|
||||
* @type {WebGLBuffer}
|
||||
* @default null
|
||||
**/
|
||||
this._verticesBuffer = null;
|
||||
|
||||
/**
|
||||
* The indices to the vertices defined in this._vertices.
|
||||
* @property _indices
|
||||
* @protected
|
||||
* @type {Uint16Array}
|
||||
* @default null
|
||||
**/
|
||||
this._indices = null;
|
||||
|
||||
/**
|
||||
* The buffer that contains all the indices data.
|
||||
* @property _indicesBuffer
|
||||
* @protected
|
||||
* @type {WebGLBuffer}
|
||||
* @default null
|
||||
**/
|
||||
this._indicesBuffer = null;
|
||||
|
||||
/**
|
||||
* The current box index being defined for drawing.
|
||||
* @property _currentBoxIndex
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default -1
|
||||
**/
|
||||
this._currentBoxIndex = -1;
|
||||
|
||||
/**
|
||||
* The current texture that will be used to draw into the GPU.
|
||||
* @property _drawTexture
|
||||
* @protected
|
||||
* @type {WebGLTexture}
|
||||
* @default null
|
||||
**/
|
||||
this._drawTexture = null;
|
||||
|
||||
|
||||
// setup:
|
||||
this._initializeWebGL();
|
||||
}
|
||||
var p = createjs.extend(SpriteStage, createjs.Stage);
|
||||
|
||||
|
||||
// constants:
|
||||
/**
|
||||
* The number of properties defined per vertex in p._verticesBuffer.
|
||||
* x, y, textureU, textureV, alpha
|
||||
|
@ -149,7 +332,8 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
* @readonly
|
||||
**/
|
||||
SpriteStage.MAX_BOXES_POINTS_INCREMENT = SpriteStage.MAX_INDEX_SIZE / 4;
|
||||
|
||||
|
||||
|
||||
// getter / setters:
|
||||
/**
|
||||
* Indicates whether WebGL is being used for rendering. For example, this would be false if WebGL is not
|
||||
|
@ -168,209 +352,8 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
});
|
||||
} catch (e) {} // TODO: use Log
|
||||
|
||||
// private properties:
|
||||
|
||||
/**
|
||||
* Specifies whether or not the canvas is auto-cleared by WebGL. Spec discourages true.
|
||||
* If true, the canvas is NOT auto-cleared by WebGL. Value is ignored if p._alphaEnabled is false.
|
||||
* Useful if you want to use p.autoClear = false.
|
||||
* @property _preserveDrawingBuffer
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
p._preserveDrawingBuffer = false;
|
||||
|
||||
/**
|
||||
* Specifies whether or not the browser's WebGL implementation should try to perform antialiasing.
|
||||
* @property _antialias
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
p._antialias = false;
|
||||
|
||||
/**
|
||||
* The width of the canvas element.
|
||||
* @property _viewportWidth
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 0
|
||||
**/
|
||||
p._viewportWidth = 0;
|
||||
|
||||
/**
|
||||
* The height of the canvas element.
|
||||
* @property _viewportHeight
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 0
|
||||
**/
|
||||
p._viewportHeight = 0;
|
||||
|
||||
/**
|
||||
* A 2D projection matrix used to convert WebGL's clipspace into normal pixels.
|
||||
* @property _projectionMatrix
|
||||
* @protected
|
||||
* @type {Float32Array}
|
||||
* @default null
|
||||
**/
|
||||
p._projectionMatrix = null;
|
||||
|
||||
/**
|
||||
* The current WebGL canvas context.
|
||||
* @property _webGLContext
|
||||
* @protected
|
||||
* @type {WebGLRenderingContext}
|
||||
* @default null
|
||||
**/
|
||||
p._webGLContext = null;
|
||||
|
||||
/**
|
||||
* Indicates whether or not an error has been detected when dealing with WebGL.
|
||||
* If the is true, the behavior should be to use Canvas 2D rendering instead.
|
||||
* @property _webGLErrorDetected
|
||||
* @protected
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
p._webGLErrorDetected = false;
|
||||
|
||||
/**
|
||||
* The color to use when the WebGL canvas has been cleared.
|
||||
* @property _clearColor
|
||||
* @protected
|
||||
* @type {Object}
|
||||
* @default null
|
||||
**/
|
||||
p._clearColor = null;
|
||||
|
||||
/**
|
||||
* The maximum number of textures WebGL can work with per draw call.
|
||||
* @property _maxTexturesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default 1
|
||||
**/
|
||||
p._maxTexturesPerDraw = 1;
|
||||
|
||||
/**
|
||||
* The maximum total number of boxes points that can be defined per draw call.
|
||||
* @property _maxBoxesPointsPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
p._maxBoxesPointsPerDraw = null;
|
||||
|
||||
/**
|
||||
* The maximum number of boxes (sprites) that can be drawn in one draw call.
|
||||
* @property _maxBoxesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
p._maxBoxesPerDraw = null;
|
||||
|
||||
/**
|
||||
* The maximum number of indices that can be drawn in one draw call.
|
||||
* @property _maxIndicesPerDraw
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default null
|
||||
**/
|
||||
p._maxIndicesPerDraw = null;
|
||||
|
||||
/**
|
||||
* The shader program used to draw everything.
|
||||
* @property _shaderProgram
|
||||
* @protected
|
||||
* @type {WebGLProgram}
|
||||
* @default null
|
||||
**/
|
||||
p._shaderProgram = null;
|
||||
|
||||
/**
|
||||
* The vertices data for the current draw call.
|
||||
* @property _vertices
|
||||
* @protected
|
||||
* @type {Float32Array}
|
||||
* @default null
|
||||
**/
|
||||
p._vertices = null;
|
||||
|
||||
/**
|
||||
* The buffer that contains all the vertices data.
|
||||
* @property _verticesBuffer
|
||||
* @protected
|
||||
* @type {WebGLBuffer}
|
||||
* @default null
|
||||
**/
|
||||
p._verticesBuffer = null;
|
||||
|
||||
/**
|
||||
* The indices to the vertices defined in p._vertices.
|
||||
* @property _indices
|
||||
* @protected
|
||||
* @type {Uint16Array}
|
||||
* @default null
|
||||
**/
|
||||
p._indices = null;
|
||||
|
||||
/**
|
||||
* The buffer that contains all the indices data.
|
||||
* @property _indicesBuffer
|
||||
* @protected
|
||||
* @type {WebGLBuffer}
|
||||
* @default null
|
||||
**/
|
||||
p._indicesBuffer = null;
|
||||
|
||||
/**
|
||||
* The current box index being defined for drawing.
|
||||
* @property _currentBoxIndex
|
||||
* @protected
|
||||
* @type {Number}
|
||||
* @default -1
|
||||
**/
|
||||
p._currentBoxIndex = -1;
|
||||
|
||||
/**
|
||||
* The current texture that will be used to draw into the GPU.
|
||||
* @property _drawTexture
|
||||
* @protected
|
||||
* @type {WebGLTexture}
|
||||
* @default null
|
||||
**/
|
||||
p._drawTexture = null;
|
||||
|
||||
// constructor:
|
||||
|
||||
/**
|
||||
* @property Stage_initialize
|
||||
* @type Function
|
||||
* @private
|
||||
**/
|
||||
p.Stage_initialize = p.initialize;
|
||||
|
||||
/**
|
||||
* Initialization method.
|
||||
* @method initialize
|
||||
* @param {HTMLCanvasElement | String | Object} canvas A canvas object, or the string id of a canvas object in the current document.
|
||||
* @param {Boolean} preserveDrawingBuffer If true, the canvas is NOT auto-cleared by WebGL (spec discourages true). Useful if you want to use p.autoClear = false.
|
||||
* @param {Boolean} antialias Specifies whether or not the browser's WebGL implementation should try to perform antialiasing.
|
||||
* @protected
|
||||
**/
|
||||
p.initialize = function(canvas, preserveDrawingBuffer, antialias) {
|
||||
this._preserveDrawingBuffer = preserveDrawingBuffer !== undefined ? preserveDrawingBuffer : this._preserveDrawingBuffer;
|
||||
this._antialias = antialias !== undefined ? antialias : this._antialias;
|
||||
|
||||
this.Stage_initialize(canvas);
|
||||
this._initializeWebGL();
|
||||
};
|
||||
|
||||
// public methods:
|
||||
|
||||
/**
|
||||
* Adds a child to the top of the display list.
|
||||
* Only children of type SpriteContainer, Sprite, Bitmap, BitmapText, or DOMElement are allowed.
|
||||
|
@ -403,6 +386,7 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
* Children also MUST have either an image or spriteSheet defined on them (unless it's a DOMElement).
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* addChildAt(child1, index);
|
||||
*
|
||||
* You can also add multiple children, such as:
|
||||
|
@ -432,7 +416,6 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
if (child._spritestage_compatibility >= 1) {
|
||||
// The child is compatible with SpriteStage.
|
||||
} else {
|
||||
console.trace();
|
||||
console && console.log("Error: You can only add children of type SpriteContainer, Sprite, Bitmap, BitmapText, or DOMElement. [" + child.toString() + "]");
|
||||
return child;
|
||||
}
|
||||
|
@ -447,32 +430,10 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
return child;
|
||||
};
|
||||
|
||||
/**
|
||||
* Each time the update method is called, the stage will tick all descendants (see: {{#crossLink "DisplayObject/tick"}}{{/crossLink}})
|
||||
* and then render the display list to the canvas using WebGL. If WebGL is not supported in the browser, it will default to a 2D context.
|
||||
*
|
||||
* Any parameters passed to `update()` will be passed on to any
|
||||
* {{#crossLink "DisplayObject/tick:event"}}{{/crossLink}} event handlers.
|
||||
*
|
||||
* Some time-based features in EaselJS (for example {{#crossLink "Sprite/framerate"}}{{/crossLink}} require that
|
||||
* a tick event object (or equivalent) be passed as the first parameter to update(). For example:
|
||||
*
|
||||
* Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(evtObj) {
|
||||
* // do some work here, then update the stage, passing through the event object:
|
||||
* myStage.update(evtObj);
|
||||
* }
|
||||
*
|
||||
* @method update
|
||||
* @param {*} [params]* Params to include when ticking descendants. The first param should usually be a tick event.
|
||||
**/
|
||||
p.update = function(params) {
|
||||
/** docced in super class **/
|
||||
p.update = function(props) {
|
||||
if (!this.canvas) { return; }
|
||||
if (this.tickOnUpdate) {
|
||||
this.dispatchEvent("tickstart"); // TODO: make cancellable?
|
||||
this._tick((arguments.length ? arguments : null));
|
||||
this.dispatchEvent("tickend");
|
||||
}
|
||||
if (this.tickOnUpdate) { this.tick(props); }
|
||||
this.dispatchEvent("drawstart"); // TODO: make cancellable?
|
||||
if (this.autoClear) { this.clear(); }
|
||||
var ctx = this._setWebGLContext();
|
||||
|
@ -508,13 +469,6 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @property Stage_draw
|
||||
* @type {Function}
|
||||
* @private
|
||||
**/
|
||||
p.Stage_draw = p.draw;
|
||||
|
||||
/**
|
||||
* Draws the stage into the specified context (using WebGL) ignoring its visible, alpha, shadow, and transform.
|
||||
* If WebGL is not supported in the browser, it will default to a 2D context.
|
||||
|
@ -881,11 +835,10 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
for (var i = 0, l = kids.length; i < l; i++) {
|
||||
kid = kids[i];
|
||||
if (!kid.isVisible()) { continue; }
|
||||
mtx = kid._matrix;
|
||||
mtx = kid._props.matrix;
|
||||
|
||||
// Get the kid's global matrix (relative to the stage):
|
||||
mtx = (parentMVMatrix ? mtx.copy(parentMVMatrix) : mtx.identity())
|
||||
.appendTransform(kid.x, kid.y, kid.scaleX, kid.scaleY, kid.rotation, kid.skewX, kid.skewY, kid.regX, kid.regY);
|
||||
mtx = (parentMVMatrix ? mtx.copy(parentMVMatrix) : mtx.identity()).prependTransform(kid.x, kid.y, kid.scaleX, kid.scaleY, kid.rotation, kid.skewX, kid.skewY, kid.regX, kid.regY);
|
||||
|
||||
// Set default texture coordinates:
|
||||
var uStart = 0, uEnd = 1,
|
||||
|
@ -1027,5 +980,6 @@ var p = SpriteStage.prototype = new createjs.Stage();
|
|||
this._drawTexture = null;
|
||||
};
|
||||
|
||||
createjs.SpriteStage = SpriteStage;
|
||||
|
||||
createjs.SpriteStage = createjs.promote(SpriteStage, "Stage");
|
||||
}());
|
||||
|
|
3
vendor/scripts/checkout.js
vendored
Normal file
3
vendor/scripts/checkout.js
vendored
Normal file
File diff suppressed because one or more lines are too long
9883
vendor/scripts/easeljs-NEXT.combined.js
vendored
9883
vendor/scripts/easeljs-NEXT.combined.js
vendored
File diff suppressed because it is too large
Load diff
163
vendor/scripts/preloadjs-NEXT.combined.js
vendored
163
vendor/scripts/preloadjs-NEXT.combined.js
vendored
|
@ -27,7 +27,7 @@ this.createjs = this.createjs||{};
|
|||
* @type String
|
||||
* @static
|
||||
**/
|
||||
s.buildDate = /*date*/"Thu, 06 Mar 2014 22:58:10 GMT"; // injected by build process
|
||||
s.buildDate = /*date*/"Wed, 22 Oct 2014 16:11:35 GMT"; // injected by build process
|
||||
|
||||
})();
|
||||
/*
|
||||
|
@ -78,7 +78,7 @@ this.createjs = this.createjs||{};
|
|||
/**
|
||||
* Contains properties and methods shared by all events for use with
|
||||
* {{#crossLink "EventDispatcher"}}{{/crossLink}}.
|
||||
*
|
||||
*
|
||||
* Note that Event objects are often reused, so you should never
|
||||
* rely on an event object's state outside of the call stack it was received in.
|
||||
* @class Event
|
||||
|
@ -91,6 +91,7 @@ var Event = function(type, bubbles, cancelable) {
|
|||
this.initialize(type, bubbles, cancelable);
|
||||
};
|
||||
var p = Event.prototype;
|
||||
Event.prototype.constructor = Event;
|
||||
|
||||
// events:
|
||||
|
||||
|
@ -194,7 +195,7 @@ var p = Event.prototype;
|
|||
* @readonly
|
||||
*/
|
||||
p.immediatePropagationStopped = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
|
||||
* @property removed
|
||||
|
@ -249,21 +250,21 @@ var p = Event.prototype;
|
|||
p.stopImmediatePropagation = function() {
|
||||
this.immediatePropagationStopped = this.propagationStopped = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Causes the active listener to be removed via removeEventListener();
|
||||
*
|
||||
*
|
||||
* myBtn.addEventListener("click", function(evt) {
|
||||
* // do stuff...
|
||||
* evt.remove(); // removes this listener.
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @method remove
|
||||
**/
|
||||
p.remove = function() {
|
||||
this.removed = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a clone of the Event instance.
|
||||
* @method clone
|
||||
|
@ -375,6 +376,7 @@ var EventDispatcher = function() {
|
|||
/* this.initialize(); */ // not needed.
|
||||
};
|
||||
var p = EventDispatcher.prototype;
|
||||
EventDispatcher.prototype.constructor = EventDispatcher;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -579,19 +581,19 @@ var p = EventDispatcher.prototype;
|
|||
* @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
|
||||
* While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
|
||||
* dispatchEvent will construct an Event instance with the specified type.
|
||||
* @param {Object} [target] The object to use as the target property of the event object. This will default to the
|
||||
* dispatching object. <b>This parameter is deprecated and will be removed.</b>
|
||||
* @return {Boolean} Returns the value of eventObj.defaultPrevented.
|
||||
**/
|
||||
p.dispatchEvent = function(eventObj, target) {
|
||||
p.dispatchEvent = function(eventObj) {
|
||||
if (typeof eventObj == "string") {
|
||||
// won't bubble, so skip everything if there's no listeners:
|
||||
var listeners = this._listeners;
|
||||
if (!listeners || !listeners[eventObj]) { return false; }
|
||||
eventObj = new createjs.Event(eventObj);
|
||||
} else if (eventObj.target && eventObj.clone) {
|
||||
// redispatching an active event object, so clone it:
|
||||
eventObj = eventObj.clone();
|
||||
}
|
||||
// TODO: deprecated. Target param is deprecated, only use case is MouseEvent/mousemove, remove.
|
||||
eventObj.target = target||this;
|
||||
try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events
|
||||
|
||||
if (!eventObj.bubbles || !this.parent) {
|
||||
this._dispatchEvent(eventObj, 2);
|
||||
|
@ -663,8 +665,8 @@ var p = EventDispatcher.prototype;
|
|||
if (eventObj && listeners) {
|
||||
var arr = listeners[eventObj.type];
|
||||
if (!arr||!(l=arr.length)) { return; }
|
||||
eventObj.currentTarget = this;
|
||||
eventObj.eventPhase = eventPhase;
|
||||
try { eventObj.currentTarget = this; } catch (e) {}
|
||||
try { eventObj.eventPhase = eventPhase; } catch (e) {}
|
||||
eventObj.removed = false;
|
||||
arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
|
||||
for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) {
|
||||
|
@ -904,29 +906,37 @@ this.createjs = this.createjs||{};
|
|||
this.init();
|
||||
};
|
||||
|
||||
AbstractLoader.prototype = new createjs.EventDispatcher(); //TODO: TEST!
|
||||
var p = AbstractLoader.prototype;
|
||||
var p = AbstractLoader.prototype = new createjs.EventDispatcher();
|
||||
AbstractLoader.prototype.constructor = AbstractLoader;
|
||||
var s = AbstractLoader;
|
||||
|
||||
/**
|
||||
* The RegExp pattern to use to parse file URIs. This supports simple file names, as well as full domain URIs with
|
||||
* query strings. The resulting match is: protocol:$1 domain:$2 relativePath:$3 path:$4 file:$5 extension:$6 query:$7.
|
||||
* @property FILE_PATTERN
|
||||
* @type {RegExp}
|
||||
* The Regular Expression used to test file URLS for an absolute path.
|
||||
* @property ABSOLUTE_PATH
|
||||
* @static
|
||||
* @protected
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.FILE_PATTERN = /^(?:(\w+:)\/{2}(\w+(?:\.\w+)*\/?)|(.{0,2}\/{1}))?([/.]*?(?:[^?]+)?\/)?((?:[^/?]+)\.(\w+))(?:\?(\S+)?)?$/;
|
||||
s.ABSOLUTE_PATT = /^(?:\w+:)?\/{2}/i;
|
||||
|
||||
/**
|
||||
* The RegExp pattern to use to parse path URIs. This supports protocols, relative files, and paths. The resulting
|
||||
* match is: protocol:$1 relativePath:$2 path$3.
|
||||
* @property PATH_PATTERN
|
||||
* @type {RegExp}
|
||||
* The Regular Expression used to test file URLS for an absolute path.
|
||||
* @property RELATIVE_PATH
|
||||
* @static
|
||||
* @protected
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.PATH_PATTERN = /^(?:(\w+:)\/{2})|(.{0,2}\/{1})?([/.]*?(?:[^?]+)?\/?)?$/;
|
||||
s.RELATIVE_PATT = (/^[./]*?\//i);
|
||||
|
||||
/**
|
||||
* The Regular Expression used to test file URLS for an extension. Note that URIs must already have the query string
|
||||
* removed.
|
||||
* @property EXTENSION_PATT
|
||||
* @static
|
||||
* @type {RegExp}
|
||||
* @since 0.4.2
|
||||
*/
|
||||
s.EXTENSION_PATT = /\/?[^/]+\.(\w{1,5})$/i;
|
||||
|
||||
/**
|
||||
* If the loader has completed loading. This provides a quick check, but also ensures that the different approaches
|
||||
|
@ -1164,29 +1174,49 @@ this.createjs = this.createjs||{};
|
|||
};
|
||||
|
||||
/**
|
||||
* Parse a file URI using the {{#crossLink "AbstractLoader/FILE_PATTERN:property"}}{{/crossLink}} RegExp pattern.
|
||||
* @method _parseURI
|
||||
* @param {String} path The file path to parse.
|
||||
* @return {Array} The matched file contents. Please see the FILE_PATTERN property for details on the return value.
|
||||
* This will return null if it does not match.
|
||||
* @protected
|
||||
* Parse a file path to determine the information we need to work with it. Currently, PreloadJS needs to know:
|
||||
* <ul>
|
||||
* <li>If the path is absolute. Absolute paths start with a protocol (such as `http://`, `file://`, or
|
||||
* `//networkPath`)</li>
|
||||
* <li>If the path is relative. Relative paths start with `../` or `/path` (or similar)</li>
|
||||
* <li>The file extension. This is determined by the filename with an extension. Query strings are dropped, and
|
||||
* the file path is expected to follow the format `name.ext`.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <strong>Note:</strong> This has changed from earlier versions, which used a single, complicated Regular Expression, which
|
||||
* was difficult to maintain, and over-aggressive in determining all file properties. It has been simplified to
|
||||
* only pull out what it needs.
|
||||
* @param path
|
||||
* @returns {Object} An Object with an `absolute` and `relative` Boolean, as well as an optional 'extension` String
|
||||
* property, which is the lowercase extension.
|
||||
* @private
|
||||
*/
|
||||
p._parseURI = function(path) {
|
||||
if (!path) { return null; }
|
||||
return path.match(s.FILE_PATTERN);
|
||||
};
|
||||
var info = { absolute: false, relative:false };
|
||||
if (path == null) { return info; };
|
||||
|
||||
/**
|
||||
* Parse a file URI using the {{#crossLink "AbstractLoader/PATH_PATTERN"}}{{/crossLink}} RegExp pattern.
|
||||
* @method _parsePath
|
||||
* @param {String} path The file path to parse.
|
||||
* @return {Array} The matched path contents. Please see the PATH_PATTERN property for details on the return value.
|
||||
* This will return null if it does not match.
|
||||
* @protected
|
||||
*/
|
||||
p._parsePath = function(path) {
|
||||
if (!path) { return null; }
|
||||
return path.match(s.PATH_PATTERN);
|
||||
// Drop the query string
|
||||
var queryIndex = path.indexOf("?");
|
||||
if (queryIndex > -1) {
|
||||
path = path.substr(0,queryIndex);
|
||||
}
|
||||
|
||||
// Absolute
|
||||
var match;
|
||||
if (s.ABSOLUTE_PATT.test(path)) {
|
||||
info.absolute = true;
|
||||
|
||||
// Relative
|
||||
} else if (s.RELATIVE_PATT.test(path)) {
|
||||
info.relative = true;
|
||||
}
|
||||
|
||||
// Extension
|
||||
if (match = path.match(s.EXTENSION_PATT)) {
|
||||
info.extension = match[1].toLowerCase();
|
||||
}
|
||||
return info;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -1541,6 +1571,7 @@ TODO: WINDOWS ISSUES
|
|||
};
|
||||
|
||||
var p = LoadQueue.prototype = new createjs.AbstractLoader();
|
||||
LoadQueue.prototype.constructor = LoadQueue;
|
||||
var s = LoadQueue;
|
||||
|
||||
/**
|
||||
|
@ -2078,7 +2109,7 @@ TODO: WINDOWS ISSUES
|
|||
for (var n in this._loadItemsById) {
|
||||
this._disposeItem(this._loadItemsById[n]);
|
||||
}
|
||||
this.init(this.useXHR);
|
||||
this.init(this.useXHR, this._basePath, this._crossOrigin);
|
||||
|
||||
// Remove specific items
|
||||
} else {
|
||||
|
@ -2593,7 +2624,7 @@ TODO: WINDOWS ISSUES
|
|||
|
||||
// Determine Extension, etc.
|
||||
var match = this._parseURI(item.src);
|
||||
if (match != null) { item.ext = match[6]; }
|
||||
if (match.extension) { item.ext = match.extension; }
|
||||
if (item.type == null) {
|
||||
item.type = this._getTypeByExtension(item.ext);
|
||||
}
|
||||
|
@ -2602,13 +2633,13 @@ TODO: WINDOWS ISSUES
|
|||
var bp = ""; // Store the generated basePath
|
||||
var useBasePath = basePath || this._basePath;
|
||||
var autoId = item.src;
|
||||
if (match && match[1] == null && match[3] == null) {
|
||||
if (!match.absolute && !match.relative) {
|
||||
if (path) {
|
||||
bp = path;
|
||||
var pathMatch = this._parsePath(path);
|
||||
var pathMatch = this._parseURI(path);
|
||||
autoId = path + autoId;
|
||||
// Also append basePath
|
||||
if (useBasePath != null && pathMatch && pathMatch[1] == null && pathMatch[2] == null) {
|
||||
if (useBasePath != null && !pathMatch.absolute && !pathMatch.relative) {
|
||||
bp = useBasePath + bp;
|
||||
}
|
||||
} else if (useBasePath != null) {
|
||||
|
@ -2666,8 +2697,8 @@ TODO: WINDOWS ISSUES
|
|||
|
||||
// Update the extension in case the type changed:
|
||||
match = this._parseURI(item.src);
|
||||
if (match != null && match[6] != null) {
|
||||
item.ext = match[6].toLowerCase();
|
||||
if (match.extension != null) {
|
||||
item.ext = match.extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3252,6 +3283,7 @@ this.createjs = this.createjs||{};
|
|||
};
|
||||
|
||||
var p = TagLoader.prototype = new createjs.AbstractLoader();
|
||||
TagLoader.prototype.constructor = TagLoader;
|
||||
|
||||
// Protected
|
||||
|
||||
|
@ -3396,7 +3428,16 @@ this.createjs = this.createjs||{};
|
|||
item.type == createjs.LoadQueue.CSS) {
|
||||
this._startTagVisibility = tag.style.visibility;
|
||||
tag.style.visibility = "hidden";
|
||||
(document.body || document.getElementsByTagName("body")[0]).appendChild(tag);
|
||||
var node = document.body || document.getElementsByTagName("body")[0];
|
||||
if (node == null) {
|
||||
if (item.type == createjs.LoadQueue.SVG) {
|
||||
this._handleSVGError();
|
||||
return;
|
||||
} else {
|
||||
node = document.head || document.getElementsByTagName("head");
|
||||
}
|
||||
}
|
||||
node.appendChild(tag);
|
||||
}
|
||||
|
||||
// Note: Previous versions didn't seem to work when we called load() for OGG tags in Firefox. Seems fixed in 15.0.1
|
||||
|
@ -3405,6 +3446,13 @@ this.createjs = this.createjs||{};
|
|||
}
|
||||
};
|
||||
|
||||
p._handleSVGError = function() {
|
||||
this._clean();
|
||||
var event = new createjs.Event("error");
|
||||
event.text = "SVG_NO_BODY";
|
||||
this._sendError(event);
|
||||
};
|
||||
|
||||
p._handleJSONPLoad = function(data) {
|
||||
this._jsonResult = data;
|
||||
};
|
||||
|
@ -3488,8 +3536,8 @@ this.createjs = this.createjs||{};
|
|||
// case createjs.LoadQueue.CSS:
|
||||
//LM: We may need to remove CSS tags loaded using a LINK
|
||||
tag.style.visibility = this._startTagVisibility;
|
||||
(document.body || document.getElementsByTagName("body")[0]).removeChild(tag);
|
||||
break;
|
||||
tag.parentNode && tag.parentNode.contains(tag) && tag.parentNode.removeChild(tag);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
|
@ -3618,6 +3666,7 @@ this.createjs = this.createjs || {};
|
|||
];
|
||||
|
||||
var p = XHRLoader.prototype = new createjs.AbstractLoader();
|
||||
XHRLoader.prototype.constructor = XHRLoader;
|
||||
|
||||
//Protected
|
||||
/**
|
||||
|
|
1444
vendor/scripts/soundjs-NEXT.combined.js
vendored
1444
vendor/scripts/soundjs-NEXT.combined.js
vendored
File diff suppressed because it is too large
Load diff
695
vendor/scripts/tweenjs-NEXT.combined.js
vendored
695
vendor/scripts/tweenjs-NEXT.combined.js
vendored
|
@ -46,7 +46,7 @@ this.createjs = this.createjs||{};
|
|||
/**
|
||||
* Contains properties and methods shared by all events for use with
|
||||
* {{#crossLink "EventDispatcher"}}{{/crossLink}}.
|
||||
*
|
||||
*
|
||||
* Note that Event objects are often reused, so you should never
|
||||
* rely on an event object's state outside of the call stack it was received in.
|
||||
* @class Event
|
||||
|
@ -59,6 +59,7 @@ var Event = function(type, bubbles, cancelable) {
|
|||
this.initialize(type, bubbles, cancelable);
|
||||
};
|
||||
var p = Event.prototype;
|
||||
Event.prototype.constructor = Event;
|
||||
|
||||
// events:
|
||||
|
||||
|
@ -162,7 +163,7 @@ var p = Event.prototype;
|
|||
* @readonly
|
||||
*/
|
||||
p.immediatePropagationStopped = false;
|
||||
|
||||
|
||||
/**
|
||||
* Indicates if {{#crossLink "Event/remove"}}{{/crossLink}} has been called on this event.
|
||||
* @property removed
|
||||
|
@ -217,21 +218,21 @@ var p = Event.prototype;
|
|||
p.stopImmediatePropagation = function() {
|
||||
this.immediatePropagationStopped = this.propagationStopped = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Causes the active listener to be removed via removeEventListener();
|
||||
*
|
||||
*
|
||||
* myBtn.addEventListener("click", function(evt) {
|
||||
* // do stuff...
|
||||
* evt.remove(); // removes this listener.
|
||||
* });
|
||||
*
|
||||
*
|
||||
* @method remove
|
||||
**/
|
||||
p.remove = function() {
|
||||
this.removed = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a clone of the Event instance.
|
||||
* @method clone
|
||||
|
@ -343,6 +344,7 @@ var EventDispatcher = function() {
|
|||
/* this.initialize(); */ // not needed.
|
||||
};
|
||||
var p = EventDispatcher.prototype;
|
||||
EventDispatcher.prototype.constructor = EventDispatcher;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -547,19 +549,19 @@ var p = EventDispatcher.prototype;
|
|||
* @param {Object | String | Event} eventObj An object with a "type" property, or a string type.
|
||||
* While a generic object will work, it is recommended to use a CreateJS Event instance. If a string is used,
|
||||
* dispatchEvent will construct an Event instance with the specified type.
|
||||
* @param {Object} [target] The object to use as the target property of the event object. This will default to the
|
||||
* dispatching object. <b>This parameter is deprecated and will be removed.</b>
|
||||
* @return {Boolean} Returns the value of eventObj.defaultPrevented.
|
||||
**/
|
||||
p.dispatchEvent = function(eventObj, target) {
|
||||
p.dispatchEvent = function(eventObj) {
|
||||
if (typeof eventObj == "string") {
|
||||
// won't bubble, so skip everything if there's no listeners:
|
||||
var listeners = this._listeners;
|
||||
if (!listeners || !listeners[eventObj]) { return false; }
|
||||
eventObj = new createjs.Event(eventObj);
|
||||
} else if (eventObj.target && eventObj.clone) {
|
||||
// redispatching an active event object, so clone it:
|
||||
eventObj = eventObj.clone();
|
||||
}
|
||||
// TODO: deprecated. Target param is deprecated, only use case is MouseEvent/mousemove, remove.
|
||||
eventObj.target = target||this;
|
||||
try { eventObj.target = this; } catch (e) {} // try/catch allows redispatching of native events
|
||||
|
||||
if (!eventObj.bubbles || !this.parent) {
|
||||
this._dispatchEvent(eventObj, 2);
|
||||
|
@ -631,8 +633,8 @@ var p = EventDispatcher.prototype;
|
|||
if (eventObj && listeners) {
|
||||
var arr = listeners[eventObj.type];
|
||||
if (!arr||!(l=arr.length)) { return; }
|
||||
eventObj.currentTarget = this;
|
||||
eventObj.eventPhase = eventPhase;
|
||||
try { eventObj.currentTarget = this; } catch (e) {}
|
||||
try { eventObj.eventPhase = eventPhase; } catch (e) {}
|
||||
eventObj.removed = false;
|
||||
arr = arr.slice(); // to avoid issues with items being removed or added during the dispatch
|
||||
for (var i=0; i<l && !eventObj.immediatePropagationStopped; i++) {
|
||||
|
@ -651,6 +653,613 @@ var p = EventDispatcher.prototype;
|
|||
createjs.EventDispatcher = EventDispatcher;
|
||||
}());
|
||||
/*
|
||||
* Ticker
|
||||
* Visit http://createjs.com/ for documentation, updates and examples.
|
||||
*
|
||||
* Copyright (c) 2010 gskinner.com, inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
* obtaining a copy of this software and associated documentation
|
||||
* files (the "Software"), to deal in the Software without
|
||||
* restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following
|
||||
* conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @module CreateJS
|
||||
*/
|
||||
|
||||
// namespace:
|
||||
this.createjs = this.createjs||{};
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
|
||||
|
||||
// constructor:
|
||||
/**
|
||||
* The Ticker provides a centralized tick or heartbeat broadcast at a set interval. Listeners can subscribe to the tick
|
||||
* event to be notified when a set time interval has elapsed.
|
||||
*
|
||||
* Note that the interval that the tick event is called is a target interval, and may be broadcast at a slower interval
|
||||
* during times of high CPU load. The Ticker class uses a static interface (ex. <code>Ticker.getPaused()</code>) and
|
||||
* should not be instantiated.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* // Actions carried out each frame
|
||||
* if (!event.paused) {
|
||||
* // Actions carried out when the Ticker is not paused.
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* To update a stage every tick, the {{#crossLink "Stage"}}{{/crossLink}} instance can also be used as a listener, as
|
||||
* it will automatically update when it receives a tick event:
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", stage);
|
||||
*
|
||||
* @class Ticker
|
||||
* @uses EventDispatcher
|
||||
* @static
|
||||
**/
|
||||
function Ticker() {
|
||||
throw "Ticker cannot be instantiated.";
|
||||
}
|
||||
|
||||
|
||||
// constants:
|
||||
/**
|
||||
* In this mode, Ticker uses the requestAnimationFrame API, but attempts to synch the ticks to target framerate. It
|
||||
* uses a simple heuristic that compares the time of the RAF return to the target time for the current frame and
|
||||
* dispatches the tick when the time is within a certain threshold.
|
||||
*
|
||||
* This mode has a higher variance for time between frames than TIMEOUT, but does not require that content be time
|
||||
* based as with RAF while gaining the benefits of that API (screen synch, background throttling).
|
||||
*
|
||||
* Variance is usually lowest for framerates that are a divisor of the RAF frequency. This is usually 60, so
|
||||
* framerates of 10, 12, 15, 20, and 30 work well.
|
||||
*
|
||||
* Falls back on TIMEOUT if the requestAnimationFrame API is not supported.
|
||||
* @property RAF_SYNCHED
|
||||
* @static
|
||||
* @type {String}
|
||||
* @default "synched"
|
||||
* @readonly
|
||||
**/
|
||||
Ticker.RAF_SYNCHED = "synched";
|
||||
|
||||
/**
|
||||
* In this mode, Ticker passes through the requestAnimationFrame heartbeat, ignoring the target framerate completely.
|
||||
* Because requestAnimationFrame frequency is not deterministic, any content using this mode should be time based.
|
||||
* You can leverage {{#crossLink "Ticker/getTime"}}{{/crossLink}} and the tick event object's "delta" properties
|
||||
* to make this easier.
|
||||
*
|
||||
* Falls back on TIMEOUT if the requestAnimationFrame API is not supported.
|
||||
* @property RAF
|
||||
* @static
|
||||
* @type {String}
|
||||
* @default "raf"
|
||||
* @readonly
|
||||
**/
|
||||
Ticker.RAF = "raf";
|
||||
|
||||
/**
|
||||
* In this mode, Ticker uses the setTimeout API. This provides predictable, adaptive frame timing, but does not
|
||||
* provide the benefits of requestAnimationFrame (screen synch, background throttling).
|
||||
* @property TIMEOUT
|
||||
* @static
|
||||
* @type {String}
|
||||
* @default "timer"
|
||||
* @readonly
|
||||
**/
|
||||
Ticker.TIMEOUT = "timeout";
|
||||
|
||||
|
||||
// static events:
|
||||
/**
|
||||
* Dispatched each tick. The event will be dispatched to each listener even when the Ticker has been paused using
|
||||
* {{#crossLink "Ticker/setPaused"}}{{/crossLink}}.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* function handleTick(event) {
|
||||
* console.log("Paused:", event.paused, event.delta);
|
||||
* }
|
||||
*
|
||||
* @event tick
|
||||
* @param {Object} target The object that dispatched the event.
|
||||
* @param {String} type The event type.
|
||||
* @param {Boolean} paused Indicates whether the ticker is currently paused.
|
||||
* @param {Number} delta The time elapsed in ms since the last tick.
|
||||
* @param {Number} time The total time in ms since Ticker was initialized.
|
||||
* @param {Number} runTime The total time in ms that Ticker was not paused since it was initialized. For example,
|
||||
* you could determine the amount of time that the Ticker has been paused since initialization with time-runTime.
|
||||
* @since 0.6.0
|
||||
*/
|
||||
|
||||
|
||||
// public static properties:
|
||||
/**
|
||||
* Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}, and will be removed in a future version. If true, timingMode will
|
||||
* use {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} by default.
|
||||
* @deprecated Deprecated in favour of {{#crossLink "Ticker/timingMode"}}{{/crossLink}}.
|
||||
* @property useRAF
|
||||
* @static
|
||||
* @type {Boolean}
|
||||
* @default false
|
||||
**/
|
||||
Ticker.useRAF = false;
|
||||
|
||||
/**
|
||||
* Specifies the timing api (setTimeout or requestAnimationFrame) and mode to use. See
|
||||
* {{#crossLink "Ticker/TIMEOUT"}}{{/crossLink}}, {{#crossLink "Ticker/RAF"}}{{/crossLink}}, and
|
||||
* {{#crossLink "Ticker/RAF_SYNCHED"}}{{/crossLink}} for mode details.
|
||||
* @property timingMode
|
||||
* @static
|
||||
* @type {String}
|
||||
* @default Ticker.TIMEOUT
|
||||
**/
|
||||
Ticker.timingMode = null;
|
||||
|
||||
/**
|
||||
* Specifies a maximum value for the delta property in the tick event object. This is useful when building time
|
||||
* based animations and systems to prevent issues caused by large time gaps caused by background tabs, system sleep,
|
||||
* alert dialogs, or other blocking routines. Double the expected frame duration is often an effective value
|
||||
* (ex. maxDelta=50 when running at 40fps).
|
||||
*
|
||||
* This does not impact any other values (ex. time, runTime, etc), so you may experience issues if you enable maxDelta
|
||||
* when using both delta and other values.
|
||||
*
|
||||
* If 0, there is no maximum.
|
||||
* @property maxDelta
|
||||
* @static
|
||||
* @type {number}
|
||||
* @default 0
|
||||
*/
|
||||
Ticker.maxDelta = 0;
|
||||
|
||||
|
||||
// mix-ins:
|
||||
// EventDispatcher methods:
|
||||
Ticker.removeEventListener = null;
|
||||
Ticker.removeAllEventListeners = null;
|
||||
Ticker.dispatchEvent = null;
|
||||
Ticker.hasEventListener = null;
|
||||
Ticker._listeners = null;
|
||||
createjs.EventDispatcher.initialize(Ticker); // inject EventDispatcher methods.
|
||||
Ticker._addEventListener = Ticker.addEventListener;
|
||||
Ticker.addEventListener = function() {
|
||||
!Ticker._inited&&Ticker.init();
|
||||
return Ticker._addEventListener.apply(Ticker, arguments);
|
||||
};
|
||||
|
||||
|
||||
// private static properties:
|
||||
/**
|
||||
* @property _paused
|
||||
* @type {Boolean}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._paused = false;
|
||||
|
||||
/**
|
||||
* @property _inited
|
||||
* @type {Boolean}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._inited = false;
|
||||
|
||||
/**
|
||||
* @property _startTime
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._startTime = 0;
|
||||
|
||||
/**
|
||||
* @property _pausedTime
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._pausedTime=0;
|
||||
|
||||
/**
|
||||
* The number of ticks that have passed
|
||||
* @property _ticks
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._ticks = 0;
|
||||
|
||||
/**
|
||||
* The number of ticks that have passed while Ticker has been paused
|
||||
* @property _pausedTicks
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._pausedTicks = 0;
|
||||
|
||||
/**
|
||||
* @property _interval
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._interval = 50;
|
||||
|
||||
/**
|
||||
* @property _lastTime
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._lastTime = 0;
|
||||
|
||||
/**
|
||||
* @property _times
|
||||
* @type {Array}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._times = null;
|
||||
|
||||
/**
|
||||
* @property _tickTimes
|
||||
* @type {Array}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._tickTimes = null;
|
||||
|
||||
/**
|
||||
* Stores the timeout or requestAnimationFrame id.
|
||||
* @property _timerId
|
||||
* @type {Number}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._timerId = null;
|
||||
|
||||
/**
|
||||
* True if currently using requestAnimationFrame, false if using setTimeout.
|
||||
* @property _raf
|
||||
* @type {Boolean}
|
||||
* @protected
|
||||
**/
|
||||
Ticker._raf = true;
|
||||
|
||||
|
||||
// public static methods:
|
||||
/**
|
||||
* Starts the tick. This is called automatically when the first listener is added.
|
||||
* @method init
|
||||
* @static
|
||||
**/
|
||||
Ticker.init = function() {
|
||||
if (Ticker._inited) { return; }
|
||||
Ticker._inited = true;
|
||||
Ticker._times = [];
|
||||
Ticker._tickTimes = [];
|
||||
Ticker._startTime = Ticker._getTime();
|
||||
Ticker._times.push(Ticker._lastTime = 0);
|
||||
Ticker.setInterval(Ticker._interval);
|
||||
};
|
||||
|
||||
/**
|
||||
* Stops the Ticker and removes all listeners. Use init() to restart the Ticker.
|
||||
* @method reset
|
||||
* @static
|
||||
**/
|
||||
Ticker.reset = function() {
|
||||
if (Ticker._raf) {
|
||||
var f = window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || window.msCancelAnimationFrame;
|
||||
f&&f(Ticker._timerId);
|
||||
} else {
|
||||
clearTimeout(Ticker._timerId);
|
||||
}
|
||||
Ticker.removeAllEventListeners("tick");
|
||||
Ticker._timerId = null;
|
||||
Ticker._inited = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the target time (in milliseconds) between ticks. Default is 50 (20 FPS).
|
||||
*
|
||||
* Note actual time between ticks may be more than requested depending on CPU load.
|
||||
* @method setInterval
|
||||
* @static
|
||||
* @param {Number} interval Time in milliseconds between ticks. Default value is 50.
|
||||
**/
|
||||
Ticker.setInterval = function(interval) {
|
||||
Ticker._interval = interval;
|
||||
if (!Ticker._inited) { return; }
|
||||
Ticker._setupTick();
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the current target time between ticks, as set with {{#crossLink "Ticker/setInterval"}}{{/crossLink}}.
|
||||
* @method getInterval
|
||||
* @static
|
||||
* @return {Number} The current target interval in milliseconds between tick events.
|
||||
**/
|
||||
Ticker.getInterval = function() {
|
||||
return Ticker._interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the target frame rate in frames per second (FPS). For example, with an interval of 40, <code>getFPS()</code>
|
||||
* will return 25 (1000ms per second divided by 40 ms per tick = 25fps).
|
||||
* @method setFPS
|
||||
* @static
|
||||
* @param {Number} value Target number of ticks broadcast per second.
|
||||
**/
|
||||
Ticker.setFPS = function(value) {
|
||||
Ticker.setInterval(1000/value);
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the target frame rate in frames per second (FPS). For example, with an interval of 40, <code>getFPS()</code>
|
||||
* will return 25 (1000ms per second divided by 40 ms per tick = 25fps).
|
||||
* @method getFPS
|
||||
* @static
|
||||
* @return {Number} The current target number of frames / ticks broadcast per second.
|
||||
**/
|
||||
Ticker.getFPS = function() {
|
||||
return 1000/Ticker._interval;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the average time spent within a tick. This can vary significantly from the value provided by getMeasuredFPS
|
||||
* because it only measures the time spent within the tick execution stack.
|
||||
*
|
||||
* Example 1: With a target FPS of 20, getMeasuredFPS() returns 20fps, which indicates an average of 50ms between
|
||||
* the end of one tick and the end of the next. However, getMeasuredTickTime() returns 15ms. This indicates that
|
||||
* there may be up to 35ms of "idle" time between the end of one tick and the start of the next.
|
||||
*
|
||||
* Example 2: With a target FPS of 30, getFPS() returns 10fps, which indicates an average of 100ms between the end of
|
||||
* one tick and the end of the next. However, getMeasuredTickTime() returns 20ms. This would indicate that something
|
||||
* other than the tick is using ~80ms (another script, DOM rendering, etc).
|
||||
* @method getMeasuredTickTime
|
||||
* @static
|
||||
* @param {Number} [ticks] The number of previous ticks over which to measure the average time spent in a tick.
|
||||
* Defaults to the number of ticks per second. To get only the last tick's time, pass in 1.
|
||||
* @return {Number} The average time spent in a tick in milliseconds.
|
||||
**/
|
||||
Ticker.getMeasuredTickTime = function(ticks) {
|
||||
var ttl=0, times=Ticker._tickTimes;
|
||||
if (!times || times.length < 1) { return -1; }
|
||||
|
||||
// by default, calculate average for the past ~1 second:
|
||||
ticks = Math.min(times.length, ticks||(Ticker.getFPS()|0));
|
||||
for (var i=0; i<ticks; i++) { ttl += times[i]; }
|
||||
return ttl/ticks;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the actual frames / ticks per second.
|
||||
* @method getMeasuredFPS
|
||||
* @static
|
||||
* @param {Number} [ticks] The number of previous ticks over which to measure the actual frames / ticks per second.
|
||||
* Defaults to the number of ticks per second.
|
||||
* @return {Number} The actual frames / ticks per second. Depending on performance, this may differ
|
||||
* from the target frames per second.
|
||||
**/
|
||||
Ticker.getMeasuredFPS = function(ticks) {
|
||||
var times = Ticker._times;
|
||||
if (!times || times.length < 2) { return -1; }
|
||||
|
||||
// by default, calculate fps for the past ~1 second:
|
||||
ticks = Math.min(times.length-1, ticks||(Ticker.getFPS()|0));
|
||||
return 1000/((times[0]-times[ticks])/ticks);
|
||||
};
|
||||
|
||||
/**
|
||||
* Changes the "paused" state of the Ticker, which can be retrieved by the {{#crossLink "Ticker/getPaused"}}{{/crossLink}}
|
||||
* method, and is passed as the "paused" property of the <code>tick</code> event. When the ticker is paused, all
|
||||
* listeners will still receive a tick event, but the <code>paused</code> property will be false.
|
||||
*
|
||||
* Note that in EaselJS v0.5.0 and earlier, "pauseable" listeners would <strong>not</strong> receive the tick
|
||||
* callback when Ticker was paused. This is no longer the case.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* createjs.Ticker.setPaused(true);
|
||||
* function handleTick(event) {
|
||||
* console.log("Paused:", event.paused, createjs.Ticker.getPaused());
|
||||
* }
|
||||
*
|
||||
* @method setPaused
|
||||
* @static
|
||||
* @param {Boolean} value Indicates whether to pause (true) or unpause (false) Ticker.
|
||||
**/
|
||||
Ticker.setPaused = function(value) {
|
||||
Ticker._paused = value;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether Ticker is currently paused, as set with {{#crossLink "Ticker/setPaused"}}{{/crossLink}}.
|
||||
* When the ticker is paused, all listeners will still receive a tick event, but this value will be false.
|
||||
*
|
||||
* Note that in EaselJS v0.5.0 and earlier, "pauseable" listeners would <strong>not</strong> receive the tick
|
||||
* callback when Ticker was paused. This is no longer the case.
|
||||
*
|
||||
* <h4>Example</h4>
|
||||
*
|
||||
* createjs.Ticker.addEventListener("tick", handleTick);
|
||||
* createjs.Ticker.setPaused(true);
|
||||
* function handleTick(event) {
|
||||
* console.log("Paused:", createjs.Ticker.getPaused());
|
||||
* }
|
||||
*
|
||||
* @method getPaused
|
||||
* @static
|
||||
* @return {Boolean} Whether the Ticker is currently paused.
|
||||
**/
|
||||
Ticker.getPaused = function() {
|
||||
return Ticker._paused;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of milliseconds that have elapsed since Ticker was initialized via {{#crossLink "Ticker/init"}}.
|
||||
* Returns -1 if Ticker has not been initialized. For example, you could use
|
||||
* this in a time synchronized animation to determine the exact amount of time that has elapsed.
|
||||
* @method getTime
|
||||
* @static
|
||||
* @param {Boolean} [runTime=false] If true only time elapsed while Ticker was not paused will be returned.
|
||||
* If false, the value returned will be total time elapsed since the first tick event listener was added.
|
||||
* @return {Number} Number of milliseconds that have elapsed since Ticker was initialized or -1.
|
||||
**/
|
||||
Ticker.getTime = function(runTime) {
|
||||
return Ticker._startTime ? Ticker._getTime() - Ticker._startTime - (runTime ? Ticker._pausedTime : 0) : -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Similar to getTime(), but returns the time included with the current (or most recent) tick event object.
|
||||
* @method getEventTime
|
||||
* @param runTime {Boolean} [runTime=false] If true, the runTime property will be returned instead of time.
|
||||
* @returns {number} The time or runTime property from the most recent tick event or -1.
|
||||
*/
|
||||
Ticker.getEventTime = function(runTime) {
|
||||
return Ticker._startTime ? (Ticker._lastTime || Ticker._startTime) - (runTime ? Ticker._pausedTime : 0) : -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the number of ticks that have been broadcast by Ticker.
|
||||
* @method getTicks
|
||||
* @static
|
||||
* @param {Boolean} pauseable Indicates whether to include ticks that would have been broadcast
|
||||
* while Ticker was paused. If true only tick events broadcast while Ticker is not paused will be returned.
|
||||
* If false, tick events that would have been broadcast while Ticker was paused will be included in the return
|
||||
* value. The default value is false.
|
||||
* @return {Number} of ticks that have been broadcast.
|
||||
**/
|
||||
Ticker.getTicks = function(pauseable) {
|
||||
return Ticker._ticks - (pauseable ?Ticker._pausedTicks : 0);
|
||||
};
|
||||
|
||||
|
||||
// private static methods:
|
||||
/**
|
||||
* @method _handleSynch
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
Ticker._handleSynch = function() {
|
||||
Ticker._timerId = null;
|
||||
Ticker._setupTick();
|
||||
|
||||
// run if enough time has elapsed, with a little bit of flexibility to be early:
|
||||
if (Ticker._getTime() - Ticker._lastTime >= (Ticker._interval-1)*0.97) {
|
||||
Ticker._tick();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @method _handleRAF
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
Ticker._handleRAF = function() {
|
||||
Ticker._timerId = null;
|
||||
Ticker._setupTick();
|
||||
Ticker._tick();
|
||||
};
|
||||
|
||||
/**
|
||||
* @method _handleTimeout
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
Ticker._handleTimeout = function() {
|
||||
Ticker._timerId = null;
|
||||
Ticker._setupTick();
|
||||
Ticker._tick();
|
||||
};
|
||||
|
||||
/**
|
||||
* @method _setupTick
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
Ticker._setupTick = function() {
|
||||
if (Ticker._timerId != null) { return; } // avoid duplicates
|
||||
|
||||
var mode = Ticker.timingMode||(Ticker.useRAF&&Ticker.RAF_SYNCHED);
|
||||
if (mode == Ticker.RAF_SYNCHED || mode == Ticker.RAF) {
|
||||
var f = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame;
|
||||
if (f) {
|
||||
Ticker._timerId = f(mode == Ticker.RAF ? Ticker._handleRAF : Ticker._handleSynch);
|
||||
Ticker._raf = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
Ticker._raf = false;
|
||||
Ticker._timerId = setTimeout(Ticker._handleTimeout, Ticker._interval);
|
||||
};
|
||||
|
||||
/**
|
||||
* @method _tick
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
Ticker._tick = function() {
|
||||
var time = Ticker._getTime();
|
||||
var adjTime = time-Ticker._startTime;
|
||||
var elapsedTime = time-Ticker._lastTime;
|
||||
var paused = Ticker._paused;
|
||||
|
||||
Ticker._ticks++;
|
||||
if (paused) {
|
||||
Ticker._pausedTicks++;
|
||||
Ticker._pausedTime += elapsedTime;
|
||||
}
|
||||
Ticker._lastTime = time;
|
||||
|
||||
if (Ticker.hasEventListener("tick")) {
|
||||
var event = new createjs.Event("tick");
|
||||
var maxDelta = Ticker.maxDelta;
|
||||
event.delta = (maxDelta && elapsedTime > maxDelta) ? maxDelta : elapsedTime;
|
||||
event.paused = paused;
|
||||
event.time = adjTime;
|
||||
event.runTime = adjTime-Ticker._pausedTime;
|
||||
Ticker.dispatchEvent(event);
|
||||
}
|
||||
|
||||
Ticker._tickTimes.unshift(Ticker._getTime()-time);
|
||||
while (Ticker._tickTimes.length > 100) { Ticker._tickTimes.pop(); }
|
||||
|
||||
Ticker._times.unshift(adjTime);
|
||||
while (Ticker._times.length > 100) { Ticker._times.pop(); }
|
||||
};
|
||||
|
||||
/**
|
||||
* @method _getTime
|
||||
* @static
|
||||
* @protected
|
||||
**/
|
||||
var now = window.performance && (performance.now || performance.mozNow || performance.msNow || performance.oNow || performance.webkitNow);
|
||||
Ticker._getTime = function() {
|
||||
return (now&&now.call(performance))||(new Date().getTime());
|
||||
};
|
||||
|
||||
|
||||
createjs.Ticker = Ticker;
|
||||
}());
|
||||
/*
|
||||
* Tween
|
||||
* Visit http://createjs.com/ for documentation, updates and examples.
|
||||
*
|
||||
|
@ -710,11 +1319,6 @@ createjs.EventDispatcher = EventDispatcher;
|
|||
* //Tween complete
|
||||
* }
|
||||
*
|
||||
* <h4>Required Support<h4>
|
||||
* Tweenjs requires a ticker function, which is included in <a href="http://www.easeljs.com">EaselJS</a>.
|
||||
* If you are not using EaselJS, you must build your own ticker function that calls {{#crossLink "Tween/tick"}}{{/crossLink}}
|
||||
* on the tweens.
|
||||
*
|
||||
* <h4>Browser Support</h4>
|
||||
* TweenJS will work in all browsers.
|
||||
*
|
||||
|
@ -764,7 +1368,7 @@ this.createjs = this.createjs||{};
|
|||
* All properties default to false. Supported props are:<UL>
|
||||
* <LI> loop: sets the loop property on this tween.</LI>
|
||||
* <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI>
|
||||
* <LI> ignoreGlobalPause: sets the ignoreGlobalPause property on this tween.</LI>
|
||||
* <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on this tween.</LI>
|
||||
* <LI> override: if true, `Tween.removeTweens(target)` will be called to remove any other tweens with the same target.
|
||||
* <LI> paused: indicates whether to start the tween paused.</LI>
|
||||
* <LI> position: indicates the initial position for this tween.</LI>
|
||||
|
@ -779,6 +1383,7 @@ var Tween = function(target, props, pluginData) {
|
|||
this.initialize(target, props, pluginData);
|
||||
};
|
||||
var p = Tween.prototype = new createjs.EventDispatcher();
|
||||
Tween.prototype.constructor = Tween;
|
||||
|
||||
// static interface:
|
||||
/**
|
||||
|
@ -843,7 +1448,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
* All properties default to false. Supported props are:<UL>
|
||||
* <LI> loop: sets the loop property on this tween.</LI>
|
||||
* <LI> useTicks: uses ticks for all durations instead of milliseconds.</LI>
|
||||
* <LI> ignoreGlobalPause: sets the ignoreGlobalPause property on this tween.</LI>
|
||||
* <LI> ignoreGlobalPause: sets the {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}} property on this tween.</LI>
|
||||
* <LI> override: if true, Tween.removeTweens(target) will be called to remove any other tweens with the same target.
|
||||
* <LI> paused: indicates whether to start the tween paused.</LI>
|
||||
* <LI> position: indicates the initial position for this tween.</LI>
|
||||
|
@ -863,15 +1468,13 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
};
|
||||
|
||||
/**
|
||||
* Advances all tweens. This typically uses the Ticker class (available in the EaselJS library), but you can call it
|
||||
* Advances all tweens. This typically uses the {{#crossLink "Ticker"}}{{/crossLink}} class, but you can call it
|
||||
* manually if you prefer to use your own "heartbeat" implementation.
|
||||
*
|
||||
* Note: Currently, EaselJS must be included <em>before</em> TweenJS to ensure Ticker exists during initialization.
|
||||
* @method tick
|
||||
* @param {Number} delta The change in time in milliseconds since the last tick. Required unless all tweens have
|
||||
* <code>useTicks</code> set to true.
|
||||
* @param {Boolean} paused Indicates whether a global pause is in effect. Tweens with <code>ignoreGlobalPause</code>
|
||||
* will ignore this, but all others will pause if this is true.
|
||||
* @param {Boolean} paused Indicates whether a global pause is in effect. Tweens with {{#crossLink "Tween/ignoreGlobalPause:property"}}{{/crossLink}}
|
||||
* will ignore this, but all others will pause if this is `true`.
|
||||
* @static
|
||||
*/
|
||||
Tween.tick = function(delta, paused) {
|
||||
|
@ -887,7 +1490,8 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
* Handle events that result from Tween being used as an event handler. This is included to allow Tween to handle
|
||||
* tick events from <code>createjs.Ticker</code>. No other events are handled in Tween.
|
||||
* @method handleEvent
|
||||
* @param {Object} event An event object passed in by the EventDispatcher. Will usually be of type "tick".
|
||||
* @param {Object} event An event object passed in by the {{#crossLink "EventDispatcher"}}{{/crossLink}}. Will
|
||||
* usually be of type "tick".
|
||||
* @private
|
||||
* @static
|
||||
* @since 0.4.2
|
||||
|
@ -909,9 +1513,10 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
if (!target.tweenjs_count) { return; }
|
||||
var tweens = Tween._tweens;
|
||||
for (var i=tweens.length-1; i>=0; i--) {
|
||||
if (tweens[i]._target == target) {
|
||||
tweens[i]._paused = true;
|
||||
tweens.splice(i,1);
|
||||
var tween = tweens[i];
|
||||
if (tween._target == target) {
|
||||
tween._paused = true;
|
||||
tweens.splice(i, 1);
|
||||
}
|
||||
}
|
||||
target.tweenjs_count = 0;
|
||||
|
@ -927,7 +1532,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
var tweens = Tween._tweens;
|
||||
for (var i= 0, l=tweens.length; i<l; i++) {
|
||||
var tween = tweens[i];
|
||||
tween.paused = true;
|
||||
tween._paused = true;
|
||||
tween.target.tweenjs_count = 0;
|
||||
}
|
||||
tweens.length = 0;
|
||||
|
@ -947,8 +1552,8 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
};
|
||||
|
||||
/**
|
||||
* Installs a plugin, which can modify how certain properties are handled when tweened. See the CSSPlugin for an
|
||||
* example of how to write TweenJS plugins.
|
||||
* Installs a plugin, which can modify how certain properties are handled when tweened. See the {{#crossLink "CSSPlugin"}}{{/crossLink}}
|
||||
* for an example of how to write TweenJS plugins.
|
||||
* @method installPlugin
|
||||
* @static
|
||||
* @param {Object} plugin The plugin class to install
|
||||
|
@ -974,7 +1579,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
* Registers or unregisters a tween with the ticking system.
|
||||
* @method _register
|
||||
* @param {Tween} tween The tween instance to register or unregister.
|
||||
* @param {Boolean} value If true, the tween is registered. If false the tween is unregistered.
|
||||
* @param {Boolean} value If true, the tween is registered. If false the tween is unregistered.
|
||||
* @static
|
||||
* @protected
|
||||
*/
|
||||
|
@ -1000,9 +1605,10 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
|
||||
// public properties:
|
||||
/**
|
||||
* Causes this tween to continue playing when a global pause is active. For example, if TweenJS is using Ticker,
|
||||
* then setting this to true (the default) will cause this tween to be paused when <code>Ticker.setPaused(true)</code> is called.
|
||||
* See Tween.tick() for more info. Can be set via the props param.
|
||||
* Causes this tween to continue playing when a global pause is active. For example, if TweenJS is using {{#crossLink "Ticker"}}{{/crossLink}},
|
||||
* then setting this to true (the default) will cause this tween to be paused when <code>Ticker.setPaused(true)</code>
|
||||
* is called. See the Tween {{#crossLink "Tween/tick"}}{{/crossLink}} method for more info. Can be set via the props
|
||||
* parameter.
|
||||
* @property ignoreGlobalPause
|
||||
* @type Boolean
|
||||
* @default false
|
||||
|
@ -1360,7 +1966,8 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
|
||||
/**
|
||||
* Advances this tween by the specified amount of time in milliseconds (or ticks if <code>useTicks</code> is true).
|
||||
* This is normally called automatically by the Tween engine (via <code>Tween.tick</code>), but is exposed for advanced uses.
|
||||
* This is normally called automatically by the Tween engine (via <code>Tween.tick</code>), but is exposed for
|
||||
* advanced uses.
|
||||
* @method tick
|
||||
* @param {Number} delta The time to advance in milliseconds (or ticks if <code>useTicks</code> is true).
|
||||
*/
|
||||
|
@ -1376,6 +1983,7 @@ var p = Tween.prototype = new createjs.EventDispatcher();
|
|||
* @return {Tween} This tween instance (for chaining calls)
|
||||
*/
|
||||
p.setPaused = function(value) {
|
||||
if (this._paused === !!value) { return this; }
|
||||
this._paused = !!value;
|
||||
Tween._register(this, !value);
|
||||
return this;
|
||||
|
@ -1630,6 +2238,7 @@ var Timeline = function(tweens, labels, props) {
|
|||
this.initialize(tweens, labels, props);
|
||||
};
|
||||
var p = Timeline.prototype = new createjs.EventDispatcher();
|
||||
Timeline.prototype.constructor = Timeline;
|
||||
|
||||
// public properties:
|
||||
|
||||
|
@ -1701,7 +2310,7 @@ var p = Timeline.prototype = new createjs.EventDispatcher();
|
|||
* @protected
|
||||
**/
|
||||
p._labels = null;
|
||||
|
||||
|
||||
/**
|
||||
* @property _labelList
|
||||
* @type Array[Object]
|
||||
|
@ -1828,7 +2437,7 @@ var p = Timeline.prototype = new createjs.EventDispatcher();
|
|||
p.setLabels = function(o) {
|
||||
this._labels = o ? o : {};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns a sorted list of the labels defined on this timeline.
|
||||
* @method getLabels
|
||||
|
@ -1846,7 +2455,7 @@ var p = Timeline.prototype = new createjs.EventDispatcher();
|
|||
}
|
||||
return list;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the name of the label on or immediately before the current position. For example, given a timeline with
|
||||
* two labels, "first" on frame index 4, and "second" on frame 8, getCurrentLabel would return:<UL>
|
||||
|
@ -1867,7 +2476,7 @@ var p = Timeline.prototype = new createjs.EventDispatcher();
|
|||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Unpauses this timeline and jumps to the specified position or label.
|
||||
* @method gotoAndPlay
|
||||
|
@ -1953,7 +2562,7 @@ var p = Timeline.prototype = new createjs.EventDispatcher();
|
|||
* @param {String|Number} positionOrLabel A numeric position value or label string.
|
||||
**/
|
||||
p.resolve = function(positionOrLabel) {
|
||||
var pos = parseFloat(positionOrLabel);
|
||||
var pos = Number(positionOrLabel);
|
||||
if (isNaN(pos)) { pos = this._labels[positionOrLabel]; }
|
||||
return pos;
|
||||
};
|
||||
|
@ -2755,6 +3364,6 @@ this.createjs = this.createjs || {};
|
|||
* @type String
|
||||
* @static
|
||||
**/
|
||||
s.buildDate = /*date*/"Thu, 12 Dec 2013 23:37:07 GMT"; // injected by build process
|
||||
s.buildDate = /*date*/"Fri, 24 Oct 2014 16:09:53 GMT"; // injected by build process
|
||||
|
||||
})();
|
||||
|
|
Loading…
Reference in a new issue