From 172d97ed830498694c062f12f89ff540c6d9a776 Mon Sep 17 00:00:00 2001 From: Nick Winter <livelily@gmail.com> Date: Wed, 15 Jan 2014 13:04:48 -0800 Subject: [PATCH] Fixed #87 I hope; at least, dramatically reduced memory leakage. --- app/lib/God.coffee | 2 ++ app/lib/surface/SpriteBoss.coffee | 8 ++------ app/lib/world/world.coffee | 3 ++- app/locale/fr.coffee | 10 +++++----- app/models/ThangType.coffee | 19 ++++++++++--------- app/views/play/level/hud_view.coffee | 4 ++++ app/views/play/level/thang_avatar_view.coffee | 4 ++++ app/views/play/level/tome/spell.coffee | 1 - .../level/tome/spell_list_entry_view.coffee | 4 ++++ .../tome/spell_list_tab_entry_view.coffee | 4 ++++ .../play/level/tome/spell_list_view.coffee | 6 +++++- .../tome/spell_palette_entry_view.coffee | 4 ++-- .../play/level/tome/spell_palette_view.coffee | 2 +- 13 files changed, 45 insertions(+), 26 deletions(-) diff --git a/app/lib/God.coffee b/app/lib/God.coffee index 044bd5c32..3e3686b1a 100644 --- a/app/lib/God.coffee +++ b/app/lib/God.coffee @@ -18,6 +18,7 @@ module.exports = class God @angels = [] @firstWorld = true Backbone.Mediator.subscribe 'tome:cast-spells', @onTomeCast, @ + console.log @id, "initialized with world", @world.id onTomeCast: (e) -> return if @dead @@ -92,6 +93,7 @@ module.exports = class God for scriptNote in @world.scriptNotes Backbone.Mediator.publish scriptNote.channel, scriptNote.event @firstWorld = false + @testWorld = null getUserCodeMap: -> userCodeMap = {} diff --git a/app/lib/surface/SpriteBoss.coffee b/app/lib/surface/SpriteBoss.coffee index 14718d136..ded4db112 100644 --- a/app/lib/surface/SpriteBoss.coffee +++ b/app/lib/surface/SpriteBoss.coffee @@ -179,15 +179,11 @@ module.exports = class SpriteBoss extends CocoClass wallSprites = (sprite for thangID, sprite of @sprites when sprite.thangType?.get('name') is 'Dungeon Wall') walls = (sprite.thang for sprite in wallSprites) @world.calculateBounds() - if @wallGrid and @wallGrid.width is @world.width and @wallGrid.height is @world.height - @wallGrid.update walls - else - @wallGrid = new Grid walls, @world.size()... + wallGrid = new Grid walls, @world.size()... for wallSprite in wallSprites - wallSprite.updateActionDirection @wallGrid + wallSprite.updateActionDirection wallGrid wallSprite.updateScale() wallSprite.updatePosition() - # TODO: there's some bug whereby a new wall isn't drawn properly when cached the first time #console.log @wallGrid.toString() @spriteLayers["Obstacle"].uncache() if @spriteLayers["Obstacle"].cacheID # might have changed sizes @spriteLayers["Obstacle"].cache() diff --git a/app/lib/world/world.coffee b/app/lib/world/world.coffee index a6ba95418..75794f1a1 100644 --- a/app/lib/world/world.coffee +++ b/app/lib/world/world.coffee @@ -28,6 +28,7 @@ module.exports = class World @scriptNotes = [] @rand = new Rand 0 @frames = [new WorldFrame(@, 0)] + @id = Math.random() age: 0 ended: false @@ -255,7 +256,7 @@ module.exports = class World o = {name: @name, totalFrames: @totalFrames, maxTotalFrames: @maxTotalFrames, frameRate: @frameRate, dt: @dt, victory: @victory, userCodeMap: {}} o[prop] = @[prop] for prop in @trackedProperties or [] - + for thangID, methods of @userCodeMap serializedMethods = o.userCodeMap[thangID] = {} for methodName, method of methods diff --git a/app/locale/fr.coffee b/app/locale/fr.coffee index 57cd483d0..680604b06 100644 --- a/app/locale/fr.coffee +++ b/app/locale/fr.coffee @@ -280,10 +280,10 @@ module.exports = nativeDescription: "français", englishDescription: "French", t and: "et" about: - who_is_codecombat: "Qui est CodeCombat?" - why_codecombat: "Pourquoi CodeCombat?" - who_description_prefix: "avons commencé ensembles en 2013. Nous avons aussi créé " - who_description_suffix: "en 2008, qui a grandi jusqu'à devenir la première application web et iOS pour apprendre à écrire les caractères chinois et japonais." + who_is_codecombat: "Qui est CodeCombat?" + why_codecombat: "Pourquoi CodeCombat?" + who_description_prefix: "avons commencé ensembles en 2013. Nous avons aussi créé " + who_description_suffix: "en 2008, qui a grandi jusqu'à devenir la première application web et iOS pour apprendre à écrire les caractères chinois et japonais." # who_description_ending: "Now it's time to teach people to write code." # why_paragraph_1: "When making Skritter, George didn't know how to program and was constantly frustrated by his inability to implement his ideas. Afterwards, he tried learning, but the lessons were too slow. His housemate, wanting to reskill and stop teaching, tried Codecademy, but \"got bored.\" Each week another friend started Codecademy, then dropped off. We realized it was the same problem we'd solved with Skritter: people learning a skill via slow, intensive lessons when what they need is fast, extensive practice. We know how to fix that." # why_paragraph_2: "Need to learn to code? You don't need lessons. You need to write a lot of code and have a great time doing it." @@ -293,7 +293,7 @@ module.exports = nativeDescription: "français", englishDescription: "French", t # why_paragraph_3_italic_caps: "NO MOM I HAVE TO FINISH THE LEVEL!" # why_paragraph_3_suffix: "That's why CodeCombat is a multiplayer game, not a gamified lesson course. We won't stop until you can't stop--but this time, that's a good thing." # why_paragraph_4: "If you're going to get addicted to some game, get addicted to this one and become one of the wizards of the tech age." - why_ending: "Et au fait, c'est gratuit. " + why_ending: "Et au fait, c'est gratuit. " # why_ending_url: "Start wizarding now!" # george_description: "CEO, business guy, web designer, game designer, and champion of beginning programmers everywhere." # scott_description: "Programmer extraordinaire, software architect, kitchen wizard, and master of finances. Scott is the reasonable one." diff --git a/app/models/ThangType.coffee b/app/models/ThangType.coffee index 62885e3b4..cb54bbc00 100644 --- a/app/models/ThangType.coffee +++ b/app/models/ThangType.coffee @@ -24,7 +24,7 @@ module.exports = class ThangType extends CocoModel getActions: -> return @actions or @buildActions() - + buildActions: -> @actions = _.cloneDeep(@get('actions')) for name, action of @actions @@ -33,12 +33,12 @@ module.exports = class ThangType extends CocoModel relatedAction.name = action.name + "_" + relatedName @actions[relatedAction.name] = relatedAction @actions - + getSpriteSheet: (options) -> options = @fillOptions options key = @spriteSheetKey(options) return @spriteSheets[key] or @buildSpriteSheet(options) - + fillOptions: (options) -> options ?= {} options = _.clone options @@ -60,7 +60,7 @@ module.exports = class ThangType extends CocoModel @builder = new createjs.SpriteSheetBuilder() @builder.padding = 2 @frames = {} - + addPortrait: -> # The portrait is built very differently than the other animations, so it gets a separate function. return unless @actions @@ -98,7 +98,7 @@ module.exports = class ThangType extends CocoModel next = action.goesTo if action.goesTo next = false if action.loops is false @builder.addAnimation name, frames, next - + for name, action of @actions when action.container and not action.animation continue if name is 'portrait' scale = @options.resolutionFactor * (action.scale or @get('scale') or 1) @@ -131,15 +131,17 @@ module.exports = class ThangType extends CocoModel @builder.buildAsync() @builder.on 'complete', @onBuildSpriteSheetComplete, @, true, key return true - + console.warn 'Building', @get('name'), 'and blocking the main thread. LevelLoader should have it built asynchronously instead.' spriteSheet = @builder.build() @spriteSheets[key] = spriteSheet spriteSheet - + onBuildSpriteSheetComplete: (e, key) -> @spriteSheets[key] = e.target.spriteSheet @trigger 'build-complete' + @builder = null + @vectorParser = null spriteSheetKey: (options) -> colorConfigs = [] @@ -183,7 +185,7 @@ module.exports = class ThangType extends CocoModel createjs.Ticker.removeEventListener 'tick', @tick @tick = null stage - + uploadGenericPortrait: (callback) -> src = @getPortraitSource() return callback?() unless src @@ -198,4 +200,3 @@ module.exports = class ThangType extends CocoModel onFileUploaded: => console.log 'Image uploaded' - diff --git a/app/views/play/level/hud_view.coffee b/app/views/play/level/hud_view.coffee index 3eb295a6f..7a251205c 100644 --- a/app/views/play/level/hud_view.coffee +++ b/app/views/play/level/hud_view.coffee @@ -21,6 +21,7 @@ module.exports = class HUDView extends View 'dialogue-sound-completed': 'onDialogueSoundCompleted' 'thang-began-talking': 'onThangBeganTalking' 'thang-finished-talking': 'onThangFinishedTalking' + 'god:new-world-created': 'onNewWorld' events: 'click': -> Backbone.Mediator.publish 'focus-editor' @@ -61,6 +62,9 @@ module.exports = class HUDView extends View onSpriteClearDialogue: -> @clearSpeaker() + onNewWorld: (e) -> + @thang = e.world.thangMap[@thang.id] if @thang + setThang: (thang, thangType) -> unless @speaker if not thang? and not @thang? then return diff --git a/app/views/play/level/thang_avatar_view.coffee b/app/views/play/level/thang_avatar_view.coffee index a03d4a63c..40dece4f1 100644 --- a/app/views/play/level/thang_avatar_view.coffee +++ b/app/views/play/level/thang_avatar_view.coffee @@ -8,6 +8,7 @@ module.exports = class ThangAvatarView extends View subscriptions: 'tome:problems-updated': "onProblemsUpdated" + 'god:new-world-created': 'onNewWorld' constructor: (options) -> super options @@ -50,3 +51,6 @@ module.exports = class ThangAvatarView extends View worstLevel = level break @setProblems myProblems.length, worstLevel + + onNewWorld: (e) -> + @options.thang = @thang = e.world.thangMap[@thang.id] if @thang diff --git a/app/views/play/level/tome/spell.coffee b/app/views/play/level/tome/spell.coffee index 0c256d751..19f88bd3a 100644 --- a/app/views/play/level/tome/spell.coffee +++ b/app/views/play/level/tome/spell.coffee @@ -17,7 +17,6 @@ module.exports = class Spell @thangs = {} @view = new SpellView {spell: @, session: @session} @view.render() # Get it ready and code loaded in advance - console.log 'spell creates tab entry view', @supermodel @tabView = new SpellListTabEntryView spell: @, supermodel: @supermodel @tabView.render() diff --git a/app/views/play/level/tome/spell_list_entry_view.coffee b/app/views/play/level/tome/spell_list_entry_view.coffee index 944326103..66f259418 100644 --- a/app/views/play/level/tome/spell_list_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_entry_view.coffee @@ -15,6 +15,7 @@ module.exports = class SpellListEntryView extends View 'tome:problems-updated': "onProblemsUpdated" 'level-disable-controls': 'onDisableControls' 'level-enable-controls': 'onEnableControls' + 'god:new-world-created': 'onNewWorld' events: 'click': 'onClick' @@ -96,3 +97,6 @@ module.exports = class SpellListEntryView extends View # Should refactor the disabling list so we can target the spell list separately? # Should not call it 'editor' any more? @$el.toggleClass('disabled', disabled).find('*').prop('disabled', disabled) + + onNewWorld: (e) -> + @lastSelectedThang = e.world.thangMap[@lastSelectedThang.id] if @lastSelectedThang diff --git a/app/views/play/level/tome/spell_list_tab_entry_view.coffee b/app/views/play/level/tome/spell_list_tab_entry_view.coffee index 9c4092646..06e6639bf 100644 --- a/app/views/play/level/tome/spell_list_tab_entry_view.coffee +++ b/app/views/play/level/tome/spell_list_tab_entry_view.coffee @@ -10,6 +10,7 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView subscriptions: 'tome:spell-loaded': "onSpellLoaded" 'tome:spell-changed': "onSpellChanged" + 'god:new-world-created': 'onNewWorld' events: 'click .spell-list-button': 'onDropdownClick' @@ -26,6 +27,9 @@ module.exports = class SpellListTabEntryView extends SpellListEntryView super() @$el.addClass 'spell-tab' + onNewWorld: (e) -> + @thang = e.world.thangMap[@thang.id] if @thang + setThang: (thang) -> return if thang.id is @thang?.id @thang = thang diff --git a/app/views/play/level/tome/spell_list_view.coffee b/app/views/play/level/tome/spell_list_view.coffee index bf09b1ca1..60821af49 100644 --- a/app/views/play/level/tome/spell_list_view.coffee +++ b/app/views/play/level/tome/spell_list_view.coffee @@ -14,7 +14,8 @@ module.exports = class SpellListView extends View id: 'spell-list-view' template: template - subscriptions: {} + subscriptions: + 'god:new-world-created': 'onNewWorld' constructor: (options) -> super options @@ -64,6 +65,9 @@ module.exports = class SpellListView extends View @$el.append entry.el entry.render() # Render after appending so that we can access parent container for popover + onNewWorld: (e) -> + @thang = e.world.thangMap[@thang.id] if @thang + setThangAndSpell: (@thang, @spell) -> @entries[0]?.setSelected false @sortSpells() diff --git a/app/views/play/level/tome/spell_palette_entry_view.coffee b/app/views/play/level/tome/spell_palette_entry_view.coffee index 37904ff54..56e6e40e0 100644 --- a/app/views/play/level/tome/spell_palette_entry_view.coffee +++ b/app/views/play/level/tome/spell_palette_entry_view.coffee @@ -51,6 +51,6 @@ module.exports = class SpellPaletteEntryView extends View onFrameChanged: (e) -> return unless e.selectedThang?.id is @thang.id - @thang = e.selectedThang # Update our thang to the current version - @doc = Docs.getDocsFor(@thang, [@doc.prop])[0] + @options.thang = @thang = e.selectedThang # Update our thang to the current version + @options.doc = @doc = Docs.getDocsFor(@thang, [@doc.prop])[0] @$el.find("code.current-value").text(@doc.formatValue()) # Don't call any functions. (?? What does this mean?) diff --git a/app/views/play/level/tome/spell_palette_view.coffee b/app/views/play/level/tome/spell_palette_view.coffee index ee080950e..445364274 100644 --- a/app/views/play/level/tome/spell_palette_view.coffee +++ b/app/views/play/level/tome/spell_palette_view.coffee @@ -55,7 +55,7 @@ module.exports = class SpellPaletteView extends View onFrameChanged: (e) -> return unless e.selectedThang?.id is @thang.id - @thang = e.selectedThang # Update our thang to the current version + @options.thang = @thang = e.selectedThang # Update our thang to the current version destroy: -> super()