codecombat/app/lib/world/world_frame.coffee
Nick Winter d77625bc77 Game dev levels (#3810)
* Tweak API doc behavior and styling

* Instead of moving to the left during active dialogues, just move to the top
* Allow pointer events
* Adjust close button
* Re-enable pinning API docs for game-dev and web-dev levels

* Make sidebar in PlayGameDevLevelView stretch, better layout columns

* Set up content of PlayGameDevLevelView sidebar to scroll

* Add rest of PlayGameDevLevelView sidebar content, rework what loading looks like

* Finish PlayGameDevLevelView

* Add share area below
* Cover the brown background, paint it gray

* Tweak PlayGameDevLevelView

* Have progress bar show everything
* Fix Surface resize handling

* Fix PlayGameDevLevelView resizing incorrectly when playing

* Add GameDevVictoryModal to PlayGameDevLevelView

* Don't show missing-doctype annotation in Ace

* Hook up GameDevVictoryModal copy button

* Fix onChangeAnnotation runtime error

* Fix onLevelLoaded runtime error

* Have CourseVictoryModal link to /courses when course is done

* Trim, update CourseDetailsView

* Remove last vestiges of teacherMode
* Remove giant navigation buttons at top
* Quick switch to flat style

* Add analytics for game-dev

* Update Analytics events for gamedev

* Prefix event names with context
* Send to Mixpanel
* Include more properties

* Mostly set up indefinite play and autocast for game-dev levels

* Set up cast buttons and shortcut for game-dev

* Add rudimentary instructions when students play game-dev levels

* Couple tweaks

* fix a bit of code that expects frames to always stick around
* have PlayGameDevLevelView render a couple frames on load

* API Docs use 'game' instead of 'hero'

* Move tags to head without combining

* Add HTML comment-start string

Fixes missing entry point arrows

* Fix some whitespace
2016-07-28 13:39:58 -07:00

70 lines
3.2 KiB
CoffeeScript

ThangState = require './thang_state'
module.exports = class WorldFrame
@className: 'WorldFrame'
constructor: (@world, @time=0) ->
@thangStateMap = {}
@setState() if @world
getNextFrame: ->
# Optimized. Must be called while thangs are current at this frame.
nextTime = @time + @world.dt
return null if nextTime > @world.lifespan and not @world.indefiniteLength
@hash = @world.rand.seed
@hash += system.update() for system in @world.systems
nextFrame = new WorldFrame(@world, nextTime)
return nextFrame
setState: ->
for thang in @world.thangs when not thang.stateless
@thangStateMap[thang.id] = thang.getState()
restoreState: ->
thangState.restore() for thangID, thangState of @thangStateMap
for thang in @world.thangs
if not @thangStateMap[thang.id] and not thang.stateless
#console.log 'Frame', @time, 'restoring state for', thang.id, 'and saying it don\'t exist'
thang.exists = false
restorePartialState: (ratio) ->
thangState.restorePartial ratio for thangID, thangState of @thangStateMap
restoreStateForThang: (thang) ->
thangState = @thangStateMap[thang.id]
if not thangState
if not thang.stateless
thang.exists = false
#console.log 'Frame', @time, 'restoring state for', thang.id, 'in particular and saying it don\'t exist'
return
thangState.restore()
clearEvents: -> thang.currentEvents = [] for thang in @world.thangs
toString: ->
map = ((' ' for x in [0 .. @world.width]) \
for y in [0 .. @world.height])
symbols = '.ox@dfga[]/D'
for thang, i in @world.thangs when thang.rectangle
rect = thang.rectangle().axisAlignedBoundingBox()
for y in [Math.floor(rect.y - rect.height / 2) ... Math.ceil(rect.y + rect.height / 2)]
for x in [Math.floor(rect.x - rect.width / 2) ... Math.ceil(rect.x + rect.width / 2)]
map[y][x] = symbols[i % symbols.length] if 0 <= y < @world.height and 0 <= x < @world.width
@time + '\n' + (xs.join(' ') for xs in map).join('\n') + '\n'
serialize: (frameIndex, trackedPropertiesThangIDs, trackedPropertiesPerThangIndices, trackedPropertiesPerThangTypes, trackedPropertiesPerThangValues, specialValuesToKeys, specialKeysToValues) ->
# Optimize
for thangID, thangIndex in trackedPropertiesThangIDs
thangState = @thangStateMap[thangID]
if thangState
thangState.serialize(frameIndex, trackedPropertiesPerThangIndices[thangIndex], trackedPropertiesPerThangTypes[thangIndex], trackedPropertiesPerThangValues[thangIndex], specialValuesToKeys, specialKeysToValues)
@hash
@deserialize: (world, frameIndex, trackedPropertiesThangIDs, trackedPropertiesThangs, trackedPropertiesPerThangKeys, trackedPropertiesPerThangTypes, trackedPropertiesPerThangValues, specialKeysToValues, hash, age) ->
# Optimize
wf = new WorldFrame null, age
wf.world = world
wf.hash = hash
for thangID, thangIndex in trackedPropertiesThangIDs
wf.thangStateMap[thangID] = ThangState.deserialize world, frameIndex, trackedPropertiesThangs[thangIndex], trackedPropertiesPerThangKeys[thangIndex], trackedPropertiesPerThangTypes[thangIndex], trackedPropertiesPerThangValues[thangIndex], specialKeysToValues
wf