mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2024-12-11 00:02:19 -05:00
commit
ac6a32bdbc
13 changed files with 147 additions and 45 deletions
|
@ -190,7 +190,7 @@ module.exports = class Angel extends CocoClass
|
|||
goalStates = testGM?.getGoalStates()
|
||||
serialized = testWorld.serialize().serializedWorld
|
||||
window.BOX2D_ENABLED = false
|
||||
World.deserialize serialized, @angelsShare.worldClassMap, @hsared.lastSerializedWorldFrames, @finishBeholdingWorld(goalStates)
|
||||
World.deserialize serialized, @angelsShare.worldClassMap, @shared.lastSerializedWorldFrames, @finishBeholdingWorld(goalStates)
|
||||
window.BOX2D_ENABLED = true
|
||||
@shared.lastSerializedWorldFrames = serialized.frames
|
||||
|
||||
|
|
|
@ -30,7 +30,6 @@ module.exports = class SurfaceScriptModule extends ScriptModule
|
|||
e.pos = focus.target if _.isPlainObject focus.target
|
||||
e.thangID = focus.target if _.isString focus.target
|
||||
e.zoom = focus.zoom or 2.0 # TODO: test only doing this if e.pos, e.thangID, or focus.zoom?
|
||||
e.zoom *= 2 if e.zoom # On 2014-03-16, we doubled the canvas width/height, so now we have a legacy zoom multipler.
|
||||
e.duration = if focus.duration? then focus.duration else 1500
|
||||
e.duration = 0 if instant
|
||||
e.bounds = focus.bounds if focus.bounds?
|
||||
|
|
|
@ -10,6 +10,8 @@ MIN_ZOOM = 0.1
|
|||
DEFAULT_ZOOM = 2.0
|
||||
DEFAULT_TARGET = {x:0, y:0}
|
||||
DEFAULT_TIME = 1000
|
||||
STANDARD_ZOOM_WIDTH = 924
|
||||
STANDARD_ZOOM_HEIGHT = 589
|
||||
|
||||
# You can't mutate any of the constructor parameters after construction.
|
||||
# You can only call zoomTo to change the zoom target and zoom level.
|
||||
|
@ -46,12 +48,16 @@ module.exports = class Camera extends CocoClass
|
|||
|
||||
constructor: (@canvasWidth, @canvasHeight, angle=Math.asin(0.75), hFOV=d2r(30)) ->
|
||||
super()
|
||||
@offset = {x: 0, y:0}
|
||||
@offset = {x: 0, y: 0}
|
||||
@calculateViewingAngle angle
|
||||
@calculateFieldOfView hFOV
|
||||
@calculateAxisConversionFactors()
|
||||
@calculateMinMaxZoom()
|
||||
@updateViewports()
|
||||
@calculateMinZoom()
|
||||
|
||||
onResize: (newCanvasWidth, newCanvasHeight) ->
|
||||
@canvasScaleFactorX = newCanvasWidth / @canvasWidth
|
||||
@canvasScaleFactorY = newCanvasHeight / @canvasHeight
|
||||
|
||||
calculateViewingAngle: (angle) ->
|
||||
# Operate on open interval between 0 - 90 degrees to make the math easier
|
||||
|
@ -91,15 +97,11 @@ module.exports = class Camera extends CocoClass
|
|||
surfaceToCanvas: (pos) ->
|
||||
{x: (pos.x - @surfaceViewport.x) * @zoom, y: (pos.y - @surfaceViewport.y) * @zoom}
|
||||
|
||||
# TODO: do we even need separate screen coordinates?
|
||||
# We would need some other properties for the actual ratio of screen size to canvas size.
|
||||
canvasToScreen: (pos) ->
|
||||
#{x: pos.x * @someCanvasToScreenXScaleFactor, y: pos.y * @someCanvasToScreenYScaleFactor}
|
||||
{x: pos.x, y: pos.y}
|
||||
{x: pos.x * @canvasScaleFactorX, y: pos.y * @canvasScaleFactorY}
|
||||
|
||||
screenToCanvas: (pos) ->
|
||||
#{x: pos.x / @someCanvasToScreenXScaleFactor, y: pos.y / @someCanvasToScreenYScaleFactor}
|
||||
{x: pos.x, y: pos.y}
|
||||
{x: pos.x / @canvasScaleFactorX, y: pos.y / @canvasScaleFactorY}
|
||||
|
||||
canvasToSurface: (pos) ->
|
||||
{x: pos.x / @zoom + @surfaceViewport.x, y: pos.y / @zoom + @surfaceViewport.y}
|
||||
|
@ -161,11 +163,9 @@ module.exports = class Camera extends CocoClass
|
|||
newHeight = @canvasHeight / newZoom
|
||||
newTargetX = mousePoint.x - (newWidth * ratioPosX) + (newWidth / 2)
|
||||
newTargetY = mousePoint.y - (newHeight * ratioPosY) + (newHeight / 2)
|
||||
target = {x: newTargetX, y:newTargetY}
|
||||
target = {x: newTargetX, y: newTargetY}
|
||||
else
|
||||
target = @target
|
||||
newZoom = Math.min newZoom, MAX_ZOOM
|
||||
newZoom = Math.max newZoom, MIN_ZOOM, @minZoom
|
||||
@zoomTo target, newZoom, 0
|
||||
|
||||
onMouseDown: (e) ->
|
||||
|
@ -175,10 +175,9 @@ module.exports = class Camera extends CocoClass
|
|||
onMouseDragged: (e) ->
|
||||
return if @dragDisabled
|
||||
target = @boundTarget(@target, @zoom)
|
||||
newPos = {
|
||||
newPos =
|
||||
x: target.x + (@lastPos.x - e.originalEvent.rawX) / @zoom
|
||||
y: target.y + (@lastPos.y - e.originalEvent.rawY) / @zoom
|
||||
}
|
||||
@zoomTo newPos, @zoom, 0
|
||||
@lastPos = {x: e.originalEvent.rawX, y: e.originalEvent.rawY}
|
||||
Backbone.Mediator.publish 'camera:dragged'
|
||||
|
@ -192,7 +191,7 @@ module.exports = class Camera extends CocoClass
|
|||
# receives an array of two world points. Normalize and apply them
|
||||
@firstBounds = worldBounds unless @firstBounds
|
||||
@bounds = @normalizeBounds(worldBounds)
|
||||
@calculateMinZoom()
|
||||
@calculateMinMaxZoom()
|
||||
@updateZoom true if updateZoom
|
||||
@target = @currentTarget unless @focusedOnSprite()
|
||||
|
||||
|
@ -208,29 +207,31 @@ module.exports = class Camera extends CocoClass
|
|||
p2 = @worldToSurface({x:right, y:bottom})
|
||||
{x:p1.x, y:p1.y, width:p2.x-p1.x, height:p2.y-p1.y}
|
||||
|
||||
calculateMinZoom: ->
|
||||
calculateMinMaxZoom: ->
|
||||
# Zoom targets are always done in Surface coordinates.
|
||||
if not @bounds
|
||||
@minZoom = 0.5
|
||||
return
|
||||
@maxZoom = MAX_ZOOM
|
||||
return @minZoom = MIN_ZOOM unless @bounds
|
||||
@minZoom = Math.max @canvasWidth / @bounds.width, @canvasHeight / @bounds.height
|
||||
@zoom = Math.max(@minZoom, @zoom) if @zoom
|
||||
if @zoom
|
||||
@zoom = Math.max @minZoom, @zoom
|
||||
@zoom = Math.min @maxZoom, @zoom
|
||||
|
||||
zoomTo: (newTarget=null, newZoom=1.0, time=1500) ->
|
||||
# Target is either just a {x, y} pos or a display object with {x, y} that might change; surface coordinates.
|
||||
time = 0 if @instant
|
||||
newTarget ?= {x:0, y:0}
|
||||
newTarget ?= {x: 0, y: 0}
|
||||
newTarget = (@newTarget or @target) if @locked
|
||||
newZoom = Math.min((Math.max @minZoom, newZoom), MAX_ZOOM)
|
||||
newZoom = Math.max newZoom, @minZoom
|
||||
newZoom = Math.min newZoom, @maxZoom
|
||||
|
||||
thangType = @target?.sprite?.thangType
|
||||
if thangType
|
||||
@offset = _.clone(thangType.get('positions')?.torso or {x: 0, y:0})
|
||||
@offset = _.clone(thangType.get('positions')?.torso or {x: 0, y: 0})
|
||||
scale = thangType.get('scale') or 1
|
||||
@offset.x *= scale
|
||||
@offset.y *= scale
|
||||
else
|
||||
@offset = {x: 0, y:0}
|
||||
@offset = {x: 0, y: 0}
|
||||
|
||||
return if @zoom is newZoom and newTarget is newTarget.x and newTarget.y is newTarget.y
|
||||
|
||||
|
@ -311,4 +312,4 @@ module.exports = class Camera extends CocoClass
|
|||
super()
|
||||
|
||||
onZoomTo: (pos, time) ->
|
||||
@zoomTo(@worldToSurface(pos), @zoom, time)
|
||||
@zoomTo @worldToSurface(pos), @zoom, time
|
||||
|
|
|
@ -24,7 +24,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
build: ->
|
||||
@mouseEnabled = @mouseChildren = false
|
||||
@addChild @background = new createjs.Shape()
|
||||
@addChild @label = new createjs.Text("", "bold 32px Arial", "#FFFFFF")
|
||||
@addChild @label = new createjs.Text("", "bold 16px Arial", "#FFFFFF")
|
||||
@label.name = 'Coordinate Display Text'
|
||||
@label.shadow = new createjs.Shadow("#000000", 1, 1, 0)
|
||||
@background.name = "Coordinate Display Background"
|
||||
|
@ -37,7 +37,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
$('#surface').addClass('flag-cursor') unless $('#surface').hasClass('flag-cursor')
|
||||
else if @mouseInBounds
|
||||
$('#surface').removeClass('flag-cursor') if $('#surface').hasClass('flag-cursor')
|
||||
wop = @camera.canvasToWorld x: e.x, y: e.y
|
||||
wop = @camera.screenToWorld x: e.x, y: e.y
|
||||
wop.x = Math.round(wop.x)
|
||||
wop.y = Math.round(wop.y)
|
||||
return if wop.x is @lastPos?.x and wop.y is @lastPos?.y
|
||||
|
@ -47,7 +47,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
|
||||
onMouseDown: (e) ->
|
||||
return unless key.shift
|
||||
wop = @camera.canvasToWorld x: e.x, y: e.y
|
||||
wop = @camera.screenToWorld x: e.x, y: e.y
|
||||
wop.x = Math.round wop.x
|
||||
wop.y = Math.round wop.y
|
||||
Backbone.Mediator.publish 'surface:coordinate-selected', wop
|
||||
|
@ -63,8 +63,8 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
@uncache()
|
||||
|
||||
updateSize: ->
|
||||
margin = 6
|
||||
radius = 5
|
||||
margin = 3
|
||||
radius = 2.5
|
||||
width = @label.getMeasuredWidth() + 2 * margin
|
||||
height = @label.getMeasuredHeight() + 2 * margin
|
||||
@label.regX = @background.regX = width / 2 - margin
|
||||
|
@ -85,7 +85,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
[width, height] = @updateSize()
|
||||
sup = @camera.worldToSurface @lastPos
|
||||
@x = sup.x
|
||||
@y = sup.y - 5
|
||||
@y = sup.y - 2.5
|
||||
@addChild @background
|
||||
@addChild @label
|
||||
@cache -width / 2, -height / 2, width, height
|
||||
|
|
|
@ -25,10 +25,10 @@ module.exports = class DebugDisplay extends createjs.Container
|
|||
|
||||
build: ->
|
||||
@mouseEnabled = @mouseChildren = false
|
||||
@addChild @frameText = new createjs.Text "...", "40px Arial", "#FFF"
|
||||
@addChild @frameText = new createjs.Text "...", "20px Arial", "#FFF"
|
||||
@frameText.name = 'frame text'
|
||||
@frameText.x = @canvasWidth - 100
|
||||
@frameText.y = @canvasHeight - 50
|
||||
@frameText.x = @canvasWidth - 50
|
||||
@frameText.y = @canvasHeight - 25
|
||||
@frameText.alpha = 0.5
|
||||
|
||||
updateFrame: (currentFrame) ->
|
||||
|
@ -42,4 +42,4 @@ module.exports = class DebugDisplay extends createjs.Container
|
|||
@framesRenderedThisSecond = 0
|
||||
|
||||
@frameText.text = Math.round(currentFrame) + (if @fps? then " - " + @fps + ' fps' else '')
|
||||
@frameText.x = @canvasWidth - @frameText.getMeasuredWidth() - 20
|
||||
@frameText.x = @canvasWidth - @frameText.getMeasuredWidth() - 10
|
||||
|
|
|
@ -61,7 +61,7 @@ module.exports = class Label extends CocoClass
|
|||
o.fontWeight = {D: "bold", S: "bold", N: "bold"}[st]
|
||||
o.shadow = {D: false, S: true, N: true}[st]
|
||||
o.shadowColor = {D: "#FFF", S: "#000", N: "#FFF"}[st]
|
||||
o.fontSize = {D: 50, S: 24, N: 24}[st]
|
||||
o.fontSize = {D: 25, S: 12, N: 12}[st]
|
||||
fontFamily = {D: "Arial", S: "Arial", N: "Arial"}[st]
|
||||
o.fontDescriptor = "#{o.fontWeight} #{o.fontSize}px #{fontFamily}"
|
||||
o.fontColor = {D: "#000", S: "#FFF", N: "#00a"}[st]
|
||||
|
@ -174,6 +174,8 @@ module.exports = class Label extends CocoClass
|
|||
if width > maxWidth
|
||||
if row.length is 1 # one long word, truncate it
|
||||
row[0] = _.string.truncate(row[0], 40)
|
||||
text.text = row[0]
|
||||
textWidth = Math.max(text.getMeasuredWidth(), textWidth)
|
||||
rows.push(row)
|
||||
row = []
|
||||
else
|
||||
|
@ -182,7 +184,7 @@ module.exports = class Label extends CocoClass
|
|||
row = [word]
|
||||
else
|
||||
textWidth = Math.max(textWidth, width)
|
||||
rows.push(row)
|
||||
rows.push(row) if row.length
|
||||
for row, i in rows
|
||||
rows[i] = _.string.join(" ", row...)
|
||||
text: _.string.join("\n", rows...), textWidth: textWidth
|
||||
|
|
|
@ -81,7 +81,7 @@ module.exports = class Mark extends CocoClass
|
|||
shape.graphics.endStroke()
|
||||
shape.graphics.endFill()
|
||||
|
||||
text = new createjs.Text "" + index, "40px Arial", color.replace('0.5', '1')
|
||||
text = new createjs.Text "" + index, "20px Arial", color.replace('0.5', '1')
|
||||
text.regX = text.getMeasuredWidth() / 2
|
||||
text.regY = text.getMeasuredHeight() / 2
|
||||
text.shadow = new createjs.Shadow("#000000", 1, 1, 0)
|
||||
|
|
|
@ -264,7 +264,7 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
worldPos = sprite?.thang?.pos
|
||||
worldPos ?= @camera.canvasToWorld {x: e.originalEvent.rawX, y: e.originalEvent.rawY} if e
|
||||
if worldPos and (@options.navigateToSelection or not sprite or treemaThangSelected)
|
||||
@camera.zoomTo(sprite?.displayObject or @camera.worldToSurface(worldPos), @camera.zoom, 1000)
|
||||
@camera.zoomTo(sprite?.displayObject or @camera.worldToSurface(worldPos), @camera.zoom, 1000, true)
|
||||
sprite = null if @options.choosing # Don't select sprites while choosing
|
||||
if sprite isnt @selectedSprite
|
||||
@selectedSprite?.selected = false
|
||||
|
|
|
@ -81,6 +81,8 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@options = _.extend(@options, givenOptions) if givenOptions
|
||||
@initEasel()
|
||||
@initAudio()
|
||||
@onResize = _.debounce @onResize, 500
|
||||
$(window).on 'resize', @onResize
|
||||
|
||||
destroy: ->
|
||||
@dead = true
|
||||
|
@ -102,6 +104,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@stage.enableDOMEvents false
|
||||
@stage.enableMouseOver 0
|
||||
@canvas.off 'mousewheel', @onMouseWheel
|
||||
$(window).off 'resize', @onResize
|
||||
super()
|
||||
|
||||
setWorld: (@world) ->
|
||||
|
@ -377,8 +380,8 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
initEasel: ->
|
||||
# takes DOM objects, not jQuery objects
|
||||
@stage = new createjs.Stage(@canvas[0])
|
||||
canvasWidth = parseInt(@canvas.attr('width'), 10)
|
||||
canvasHeight = parseInt(@canvas.attr('height'), 10)
|
||||
canvasWidth = parseInt @canvas.attr('width'), 10
|
||||
canvasHeight = parseInt @canvas.attr('height'), 10
|
||||
@camera?.destroy()
|
||||
@camera = new Camera canvasWidth, canvasHeight
|
||||
AudioPlayer.camera = @camera
|
||||
|
@ -398,6 +401,18 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@hookUpChooseControls() if @options.choosing
|
||||
createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED
|
||||
createjs.Ticker.setFPS @options.frameRate
|
||||
@onResize()
|
||||
|
||||
onResize: (e) =>
|
||||
oldWidth = parseInt @canvas.attr('width'), 10
|
||||
oldHeight = parseInt @canvas.attr('height'), 10
|
||||
newWidth = @canvas.width()
|
||||
newHeight = @canvas.height()
|
||||
console.log "had size", oldWidth, oldHeight, "moving to", newWidth, newHeight
|
||||
@canvas.attr width: newWidth, height: newHeight
|
||||
@stage.scaleX *= newWidth / oldWidth
|
||||
@stage.scaleY *= newHeight / oldHeight
|
||||
@camera.onResize newWidth, newHeight
|
||||
|
||||
showLevel: ->
|
||||
return if @dead
|
||||
|
|
|
@ -237,12 +237,12 @@ module.exports = class GoalManager extends CocoClass
|
|||
# saveThangs: by default we would want to save all the Thangs, which means that we would want none of them to be "done"
|
||||
numNeeded = _.size(stateThangs) - Math.max((goal.howMany ? 1), _.size stateThangs) + 1
|
||||
numDone = _.filter(stateThangs).length
|
||||
console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs
|
||||
#console.log "needed", numNeeded, "done", numDone, "of total", _.size(stateThangs), "with how many", goal.howMany, "and stateThangs", stateThangs
|
||||
return unless numDone >= numNeeded
|
||||
return if state.status and not success # already failed it; don't wipe keyframe
|
||||
state.status = if success then "success" else "failure"
|
||||
state.keyFrame = frameNumber
|
||||
console.log goalID, "became", success, "on frame", frameNumber, "with overallStatus", @checkOverallStatus true
|
||||
#console.log goalID, "became", success, "on frame", frameNumber, "with overallStatus", @checkOverallStatus true
|
||||
if overallStatus = @checkOverallStatus true
|
||||
matchedGoals = (_.find(@goals, {id: goalID}) for goalID, goalState of @goalStates when goalState.status is overallStatus)
|
||||
mostEagerGoal = _.min matchedGoals, 'worldEndsAfter'
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
@import "app/styles/bootstrap/mixins"
|
||||
|
||||
#gold-view
|
||||
display: none
|
||||
position: absolute
|
||||
right: 46%
|
||||
top: 42px
|
||||
|
|
|
@ -466,7 +466,7 @@ module.exports = class PlayLevelView extends View
|
|||
|
||||
onSessionWillSave: (e) ->
|
||||
# Something interesting has happened, so (at a lower frequency), we'll save a screenshot.
|
||||
@saveScreenshot e.session
|
||||
#@saveScreenshot e.session
|
||||
|
||||
# Throttled
|
||||
saveScreenshot: (session) =>
|
||||
|
|
84
scripts/transpile.coffee
Normal file
84
scripts/transpile.coffee
Normal file
|
@ -0,0 +1,84 @@
|
|||
do (setupLodash = this) ->
|
||||
GLOBAL._ = require 'lodash'
|
||||
_.str = require 'underscore.string'
|
||||
_.mixin _.str.exports()
|
||||
Aether = require "aether"
|
||||
async = require 'async'
|
||||
|
||||
serverSetup = require '../server_setup'
|
||||
Level = require '../server/levels/Level.coffee'
|
||||
LevelSession = require '../server/levels/sessions/LevelSession.coffee'
|
||||
|
||||
Aether.addGlobal 'Vector', require '../app/lib/world/vector'
|
||||
Aether.addGlobal '_', _
|
||||
|
||||
transpileLevelSession = (sessionID, cb) ->
|
||||
query = LevelSession
|
||||
.find("_id": sessionID)
|
||||
.select("submittedCode")
|
||||
.lean()
|
||||
query.exec (err, session) ->
|
||||
if err then return cb err
|
||||
submittedCode = session.submittedCode
|
||||
transpiledCode = {}
|
||||
|
||||
for thang, spells of submittedCode
|
||||
transpiledCode[thang] = {}
|
||||
for spellID, spell of spells
|
||||
aetherOptions =
|
||||
problems: {}
|
||||
language: "javascript"
|
||||
functionName: spellID
|
||||
functionParameters: {}
|
||||
yieldConditionally: spellID is "plan"
|
||||
globals: ['Vector', '_']
|
||||
protectAPI: true
|
||||
includeFlow: false
|
||||
aether = new Aether aetherOptions
|
||||
transpiledCode[thang][spellID] = aether.transpile spell
|
||||
cb "Prematurely ended"
|
||||
|
||||
|
||||
|
||||
|
||||
findLadderLevelSessions = (levelID, cb) ->
|
||||
queryParameters =
|
||||
level:
|
||||
original: levelID + ""
|
||||
submitted: true
|
||||
|
||||
selectString = "_id"
|
||||
query = LevelSession
|
||||
.find(queryParameters)
|
||||
.select(selectString)
|
||||
.lean()
|
||||
query.exec (err, levelSessions) ->
|
||||
if err then return cb err
|
||||
levelSessionIDs = _.pluck levelSessions, "_id"
|
||||
async.each levelSessionIDs, transpileLevelSession, (err) ->
|
||||
if err then return cb err
|
||||
cb null
|
||||
|
||||
|
||||
transpileLadderSessions = ->
|
||||
queryParameters =
|
||||
type: "ladder"
|
||||
version:
|
||||
"isLatestMajor": true
|
||||
"isLatestMinor": true
|
||||
selectString = "original"
|
||||
query = Level
|
||||
.find(queryParameters)
|
||||
.select(selectString)
|
||||
.lean()
|
||||
query.exec (err, ladderLevels) ->
|
||||
throw err if err
|
||||
ladderLevels = _.pluck ladderLevels, "original"
|
||||
console.log "Found ladderlevels"
|
||||
console.log ladderLevels
|
||||
async.each ladderLevels, findLadderLevelSessions, (err) ->
|
||||
throw err if err
|
||||
serverSetup.connectToDatabase()
|
||||
transpileLadderSessions()
|
||||
|
||||
|
Loading…
Reference in a new issue