Merge pull request #993 from codecombat/master

Master into production
This commit is contained in:
Michael Schmatz 2014-05-12 19:08:16 -07:00
commit ac6a32bdbc
13 changed files with 147 additions and 45 deletions

View file

@ -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

View file

@ -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?

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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'

View file

@ -2,6 +2,7 @@
@import "app/styles/bootstrap/mixins"
#gold-view
display: none
position: absolute
right: 46%
top: 42px

View file

@ -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
View 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()