2016-07-12 17:07:10 -04:00
|
|
|
RootView = require 'views/core/RootView'
|
|
|
|
|
|
|
|
GameUIState = require 'models/GameUIState'
|
|
|
|
God = require 'lib/God'
|
|
|
|
LevelLoader = require 'lib/LevelLoader'
|
|
|
|
GoalManager = require 'lib/world/GoalManager'
|
2016-07-13 19:04:44 -04:00
|
|
|
ScriptManager = require 'lib/scripts/ScriptManager'
|
2016-07-12 17:07:10 -04:00
|
|
|
Surface = require 'lib/surface/Surface'
|
|
|
|
ThangType = require 'models/ThangType'
|
2016-07-12 18:12:11 -04:00
|
|
|
Level = require 'models/Level'
|
|
|
|
LevelSession = require 'models/LevelSession'
|
2016-07-13 14:43:25 -04:00
|
|
|
State = require 'models/State'
|
2016-07-28 16:39:58 -04:00
|
|
|
utils = require 'core/utils'
|
|
|
|
urls = require 'core/urls'
|
|
|
|
Course = require 'models/Course'
|
|
|
|
GameDevVictoryModal = require './modal/GameDevVictoryModal'
|
2016-07-13 14:43:25 -04:00
|
|
|
|
|
|
|
TEAM = 'humans'
|
2016-07-12 17:07:10 -04:00
|
|
|
|
|
|
|
module.exports = class PlayGameDevLevelView extends RootView
|
|
|
|
id: 'play-game-dev-level-view'
|
|
|
|
template: require 'templates/play/level/play-game-dev-level-view'
|
2016-07-28 16:39:58 -04:00
|
|
|
|
|
|
|
subscriptions:
|
|
|
|
'god:new-world-created': 'onNewWorld'
|
2016-07-15 23:03:12 -04:00
|
|
|
|
2016-07-13 14:43:25 -04:00
|
|
|
events:
|
|
|
|
'click #play-btn': 'onClickPlayButton'
|
2016-07-28 16:39:58 -04:00
|
|
|
'click #copy-url-btn': 'onClickCopyURLButton'
|
|
|
|
'click #play-more-codecombat-btn': 'onClickPlayMoreCodeCombatButton'
|
2016-07-13 14:43:25 -04:00
|
|
|
|
2016-07-12 17:07:10 -04:00
|
|
|
initialize: (@options, @levelID, @sessionID) ->
|
2016-07-13 14:43:25 -04:00
|
|
|
@state = new State({
|
|
|
|
loading: true
|
2016-07-13 16:28:54 -04:00
|
|
|
progress: 0
|
2016-08-10 14:13:20 -04:00
|
|
|
creatorString: ''
|
2016-07-13 14:43:25 -04:00
|
|
|
})
|
2016-07-15 23:03:12 -04:00
|
|
|
|
2016-07-13 16:28:54 -04:00
|
|
|
@supermodel.on 'update-progress', (progress) =>
|
|
|
|
@state.set({progress: (progress*100).toFixed(1)+'%'})
|
2016-07-12 18:12:11 -04:00
|
|
|
@level = new Level()
|
|
|
|
@session = new LevelSession()
|
2016-07-12 17:07:10 -04:00
|
|
|
@gameUIState = new GameUIState()
|
2016-07-14 19:49:48 -04:00
|
|
|
@courseID = @getQueryVariable 'course'
|
2016-07-28 16:39:58 -04:00
|
|
|
@god = new God({ @gameUIState, indefiniteLength: true })
|
2016-07-14 19:49:48 -04:00
|
|
|
@levelLoader = new LevelLoader({ @supermodel, @levelID, @sessionID, observing: true, team: TEAM, @courseID })
|
2016-07-28 16:39:58 -04:00
|
|
|
@supermodel.setMaxProgress 1 # Hack, why are we setting this to 0.2 in LevelLoader?
|
|
|
|
@listenTo @state, 'change', _.debounce @renderAllButCanvas
|
2016-07-12 17:07:10 -04:00
|
|
|
|
2016-07-13 16:28:54 -04:00
|
|
|
@levelLoader.loadWorldNecessities()
|
2016-07-12 17:07:10 -04:00
|
|
|
|
2016-07-13 16:52:22 -04:00
|
|
|
.then (levelLoader) =>
|
2016-07-13 16:28:54 -04:00
|
|
|
{ @level, @session, @world } = levelLoader
|
2016-07-15 23:03:12 -04:00
|
|
|
@god.setLevel(@level.serialize {@supermodel, @session})
|
2016-07-13 16:28:54 -04:00
|
|
|
@god.setWorldClassMap(@world.classMap)
|
|
|
|
@goalManager = new GoalManager(@world, @level.get('goals'), @team)
|
|
|
|
@god.setGoalManager(@goalManager)
|
2016-07-13 18:45:06 -04:00
|
|
|
@god.angelsShare.firstWorld = false # HACK
|
2016-07-13 16:28:54 -04:00
|
|
|
me.team = TEAM
|
|
|
|
@session.set 'team', TEAM
|
2016-07-13 19:04:44 -04:00
|
|
|
@scriptManager = new ScriptManager({
|
|
|
|
scripts: @world.scripts or [], view: @, @session, levelID: @level.get('slug')})
|
|
|
|
@scriptManager.loadFromSession() # Should we? TODO: Figure out how scripts work for game dev levels
|
2016-09-14 13:35:12 -04:00
|
|
|
@howToPlayText = utils.i18n(@level.attributes, 'studentPlayInstructions')
|
|
|
|
@howToPlayText ?= $.i18n.t('play_game_dev_level.default_student_instructions')
|
|
|
|
@howToPlayText = marked(@howToPlayText, { sanitize: true })
|
2016-07-28 16:39:58 -04:00
|
|
|
@renderAllButCanvas()
|
2016-07-13 16:52:22 -04:00
|
|
|
@supermodel.finishLoading()
|
2016-07-15 23:03:12 -04:00
|
|
|
|
2016-07-13 16:28:54 -04:00
|
|
|
.then (supermodel) =>
|
|
|
|
@levelLoader.destroy()
|
|
|
|
@levelLoader = null
|
|
|
|
webGLSurface = @$('canvas#webgl-surface')
|
|
|
|
normalSurface = @$('canvas#normal-surface')
|
|
|
|
@surface = new Surface(@world, normalSurface, webGLSurface, {
|
|
|
|
thangTypes: @supermodel.getModels(ThangType)
|
|
|
|
levelType: @level.get('type', true)
|
|
|
|
@gameUIState
|
2016-07-28 16:39:58 -04:00
|
|
|
resizeStrategy: 'wrapper-size'
|
2016-07-13 16:28:54 -04:00
|
|
|
})
|
2016-07-28 16:39:58 -04:00
|
|
|
@listenTo @surface, 'resize', @onSurfaceResize
|
2016-07-13 16:28:54 -04:00
|
|
|
worldBounds = @world.getBounds()
|
|
|
|
bounds = [{x: worldBounds.left, y: worldBounds.top}, {x: worldBounds.right, y: worldBounds.bottom}]
|
|
|
|
@surface.camera.setBounds(bounds)
|
|
|
|
@surface.camera.zoomTo({x: 0, y: 0}, 0.1, 0)
|
|
|
|
@surface.setWorld(@world)
|
2016-07-13 19:04:44 -04:00
|
|
|
@scriptManager.initializeCamera()
|
2016-07-13 16:28:54 -04:00
|
|
|
@renderSelectors '#info-col'
|
2016-07-15 23:47:09 -04:00
|
|
|
@spells = @session.generateSpellsObject level: @level
|
2016-07-28 16:39:58 -04:00
|
|
|
goalNames = (utils.i18n(goal, 'name') for goal in @goalManager.goals)
|
|
|
|
|
|
|
|
course = if @courseID then new Course({_id: @courseID}) else null
|
|
|
|
shareURL = urls.playDevLevel({@level, @session, course})
|
|
|
|
|
|
|
|
@state.set({
|
|
|
|
loading: false
|
|
|
|
goalNames
|
|
|
|
shareURL
|
2016-08-10 14:13:20 -04:00
|
|
|
creatorString: $.i18n.t('play_game_dev_level.created_by').replace('{{name}}', @session.get('creatorName'))
|
2016-07-28 16:39:58 -04:00
|
|
|
})
|
|
|
|
@eventProperties = {
|
|
|
|
category: 'Play GameDev Level'
|
|
|
|
@courseID
|
|
|
|
sessionID: @session.id
|
|
|
|
levelID: @level.id
|
|
|
|
levelSlug: @level.get('slug')
|
|
|
|
}
|
|
|
|
window.tracker?.trackEvent 'Play GameDev Level - Load', @eventProperties, ['Mixpanel']
|
|
|
|
@god.createWorld(@spells, false, false, true)
|
2016-07-12 17:07:10 -04:00
|
|
|
|
2016-07-28 16:39:58 -04:00
|
|
|
.catch (e) =>
|
|
|
|
throw e if e.stack
|
|
|
|
@state.set('errorMessage', e.message)
|
2016-07-13 14:43:25 -04:00
|
|
|
|
|
|
|
onClickPlayButton: ->
|
|
|
|
@god.createWorld(@spells, false, true)
|
|
|
|
Backbone.Mediator.publish('playback:real-time-playback-started', {})
|
|
|
|
Backbone.Mediator.publish('level:set-playing', {playing: true})
|
2016-07-28 16:39:58 -04:00
|
|
|
action = if @state.get('playing') then 'Play GameDev Level - Restart Level' else 'Play GameDev Level - Start Level'
|
|
|
|
window.tracker?.trackEvent(action, @eventProperties, ['Mixpanel'])
|
2016-07-13 14:43:25 -04:00
|
|
|
@state.set('playing', true)
|
2016-07-14 18:13:02 -04:00
|
|
|
|
2016-07-28 16:39:58 -04:00
|
|
|
onClickCopyURLButton: ->
|
|
|
|
@$('#copy-url-input').val(@state.get('shareURL')).select()
|
|
|
|
@tryCopy()
|
|
|
|
window.tracker?.trackEvent('Play GameDev Level - Copy URL', @eventProperties, ['Mixpanel'])
|
|
|
|
|
|
|
|
onClickPlayMoreCodeCombatButton: ->
|
|
|
|
window.tracker?.trackEvent('Play GameDev Level - Click Play More CodeCombat', @eventProperties, ['Mixpanel'])
|
|
|
|
|
|
|
|
onSurfaceResize: ({height}) ->
|
|
|
|
@state.set('surfaceHeight', height)
|
|
|
|
|
|
|
|
renderAllButCanvas: ->
|
|
|
|
@renderSelectors('#info-col', '#share-row')
|
|
|
|
height = @state.get('surfaceHeight')
|
|
|
|
if height
|
|
|
|
@$el.find('#info-col').css('height', @state.get('surfaceHeight'))
|
|
|
|
|
|
|
|
onNewWorld: (e) ->
|
|
|
|
if @goalManager.checkOverallStatus() is 'success'
|
|
|
|
modal = new GameDevVictoryModal({ shareURL: @state.get('shareURL'), @eventProperties })
|
|
|
|
@openModalView(modal)
|
|
|
|
modal.once 'replay', @onClickPlayButton, @
|
|
|
|
|
2016-07-14 18:13:02 -04:00
|
|
|
destroy: ->
|
|
|
|
@levelLoader?.destroy()
|
|
|
|
@surface?.destroy()
|
|
|
|
@god?.destroy()
|
|
|
|
@goalManager?.destroy()
|
|
|
|
@scriptManager?.destroy()
|
|
|
|
delete window.world # not sure where this is set, but this is one way to clean it up
|
|
|
|
super()
|