mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 14:03:28 -04:00
Added WebGL paths.
This commit is contained in:
parent
6ebc9e8c28
commit
aab51178e2
4 changed files with 122 additions and 316 deletions
app/lib
|
@ -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
|
||||
|
@ -456,7 +454,8 @@ 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
|
||||
@updatePaths()
|
||||
|
||||
onIdleChanged: (e) ->
|
||||
@setPaused e.idle unless @ended
|
||||
|
@ -540,10 +539,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 +577,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 +694,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@normalStage.clear()
|
||||
@webGLStage.clear()
|
||||
@musicPlayer?.destroy()
|
||||
@trailmaster?.destroy()
|
||||
@normalStage.removeAllChildren()
|
||||
@webGLStage.removeAllChildren()
|
||||
@webGLStage.removeEventListener 'stagemousemove', @onMouseMove
|
||||
|
|
108
app/lib/surface/TrailMaster.coffee
Normal file
108
app/lib/surface/TrailMaster.coffee
Normal file
|
@ -0,0 +1,108 @@
|
|||
PAST_PATH_ALPHA = 0.75
|
||||
PAST_PATH_WIDTH = 5
|
||||
FUTURE_PATH_ALPHA = 0.4
|
||||
FUTURE_PATH_WIDTH = 2
|
||||
|
||||
Camera = require './Camera'
|
||||
CocoClass = require 'lib/CocoClass'
|
||||
|
||||
module.exports = class TrailMaster extends CocoClass
|
||||
paths: null # dictionary of thang ids to containers for their paths
|
||||
pathDisplayObject: null
|
||||
world: null
|
||||
|
||||
constructor: (@camera, @layerAdapter) ->
|
||||
super()
|
||||
@tweenedSprites = []
|
||||
@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 = []
|
||||
|
||||
createGraphics: ->
|
||||
color = @colorForThang(@thang.team, PAST_PATH_ALPHA)
|
||||
@targetDotKey = @cachePathDot(10, color)
|
||||
@pastDotKey = @cachePathDot(PAST_PATH_WIDTH, color)
|
||||
@futureDotKey = @cachePathDot(FUTURE_PATH_WIDTH, @colorForThang(@thang.team, FUTURE_PATH_ALPHA))
|
||||
|
||||
cachePathDot: (width, color) ->
|
||||
key = "path-dot-#{width}-#{color}"
|
||||
color = createjs.Graphics.getRGB(color...)
|
||||
unless key in @layerAdapter.spriteSheet.getAnimations()
|
||||
circle = new createjs.Shape()
|
||||
radius = width/2
|
||||
circle.graphics.setStrokeStyle(1).beginFill(color).beginStroke('#000000').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
|
||||
params = { interval: 8, frameKey: @pastDotKey }
|
||||
return @createPath(points, params)
|
||||
|
||||
createFuturePath: ->
|
||||
return unless points = @world.pointsForThang @thang.id, @camera
|
||||
interval = Math.max(1, parseInt(@world.frameRate / 4))
|
||||
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.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.gotoAndStop(key)
|
||||
sprite.x = x
|
||||
sprite.y = y
|
||||
container.addChild(sprite)
|
||||
if lastSprite and options.animate
|
||||
createjs.Tween.get(lastSprite, {loop: true}).to({x:x, y:y}, 1000)
|
||||
@tweenedSprites.push lastSprite
|
||||
lastSprite = sprite
|
||||
|
||||
@logged = true
|
||||
container
|
||||
|
||||
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
|
|
@ -551,7 +551,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 +570,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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue