mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-26 05:53:39 -04:00
Refactored grid. Fixed #158.
This commit is contained in:
parent
3e9adf6b1a
commit
35b107cf58
6 changed files with 127 additions and 96 deletions
app
lib/surface
locale
templates/play/level
views/play/level
|
@ -11,7 +11,9 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
super()
|
||||
@initialize()
|
||||
@camera = options.camera
|
||||
console.error 'CoordinateDisplay needs camera.' unless @camera
|
||||
@layer = options.layer
|
||||
console.error @toString(), 'needs a camera.' unless @camera
|
||||
console.error @toString(), 'needs a layer.' unless @layer
|
||||
@build()
|
||||
@show = _.debounce @show, 125
|
||||
Backbone.Mediator.subscribe(channel, @[func], @) for channel, func of @subscriptions
|
||||
|
@ -21,6 +23,8 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
@show = null
|
||||
@destroyed = true
|
||||
|
||||
toString: -> '<CoordinateDisplay>'
|
||||
|
||||
build: ->
|
||||
@mouseEnabled = @mouseChildren = false
|
||||
@addChild @background = new createjs.Shape()
|
||||
|
@ -30,6 +34,7 @@ module.exports = class CoordinateDisplay extends createjs.Container
|
|||
@label.shadow = new createjs.Shadow('#000000', 1, 1, 0)
|
||||
@background.name = 'Coordinate Display Background'
|
||||
@pointMarker.name = 'Point Marker'
|
||||
@layer.addChild @
|
||||
|
||||
onMouseOver: (e) -> @mouseInBounds = true
|
||||
onMouseOut: (e) -> @mouseInBounds = false
|
||||
|
|
102
app/lib/surface/CoordinateGrid.coffee
Normal file
102
app/lib/surface/CoordinateGrid.coffee
Normal file
|
@ -0,0 +1,102 @@
|
|||
CocoClass = require 'lib/CocoClass'
|
||||
|
||||
module.exports = class CoordinateGrid extends CocoClass
|
||||
subscriptions:
|
||||
'level-toggle-grid': 'onToggleGrid'
|
||||
'level-set-grid': 'onSetGrid'
|
||||
|
||||
shortcuts:
|
||||
'ctrl+g, ⌘+g': 'onToggleGrid'
|
||||
|
||||
constructor: (options, worldSize) ->
|
||||
super()
|
||||
options ?= {}
|
||||
@camera = options.camera
|
||||
@layer = options.layer
|
||||
@textLayer = options.textLayer
|
||||
console.error @toString(), 'needs a camera.' unless @camera
|
||||
console.error @toString(), 'needs a layer.' unless @layer
|
||||
console.error @toString(), 'needs a textLayer.' unless @textLayer
|
||||
@build worldSize
|
||||
|
||||
destroy: ->
|
||||
super()
|
||||
|
||||
toString: -> '<CoordinateGrid>'
|
||||
|
||||
build: (worldSize) ->
|
||||
worldWidth = worldSize[0] ? 80
|
||||
worldHeight = worldSize[1] ? 68
|
||||
@gridContainer = new createjs.Container()
|
||||
@gridShape = new createjs.Shape()
|
||||
@gridContainer.addChild @gridShape
|
||||
@gridContainer.mouseEnabled = false
|
||||
@gridShape.alpha = 0.125
|
||||
@gridShape.graphics.setStrokeStyle 1
|
||||
@gridShape.graphics.beginStroke 'blue'
|
||||
gridSize = Math.round(worldWidth / 20)
|
||||
wopStart = x: 0, y: 0
|
||||
wopEnd = x: worldWidth, y: worldHeight
|
||||
supStart = @camera.worldToSurface wopStart
|
||||
supEnd = @camera.worldToSurface wopEnd
|
||||
wop = x: wopStart.x, y: wopStart.y
|
||||
@labels = []
|
||||
linesDrawn = 0
|
||||
while wop.x <= wopEnd.x
|
||||
sup = @camera.worldToSurface wop
|
||||
@gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y)
|
||||
if ++linesDrawn % 2
|
||||
t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue')
|
||||
t.textAlign = 'center'
|
||||
t.textBaseline = 'bottom'
|
||||
t.x = sup.x
|
||||
t.y = supStart.y
|
||||
t.alpha = 0.75
|
||||
@labels.push t
|
||||
wop.x += gridSize
|
||||
if wopEnd.x < wop.x <= wopEnd.x - gridSize / 2
|
||||
wop.x = wopEnd.x
|
||||
linesDrawn = 0
|
||||
while wop.y <= wopEnd.y
|
||||
sup = @camera.worldToSurface wop
|
||||
@gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y)
|
||||
if ++linesDrawn % 2
|
||||
t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue')
|
||||
t.textAlign = 'left'
|
||||
t.textBaseline = 'middle'
|
||||
t.x = 0
|
||||
t.y = sup.y
|
||||
t.alpha = 0.75
|
||||
@labels.push t
|
||||
wop.y += gridSize
|
||||
console.log wop.y, wopEnd.y, gridSize
|
||||
if wopEnd.y < wop.y <= wopEnd.y - gridSize / 2
|
||||
wop.y = wopEnd.y
|
||||
@gridShape.graphics.endStroke()
|
||||
bounds = x: supStart.x, y: supEnd.y, width: supEnd.x - supStart.x, height: supStart.y - supEnd.y
|
||||
return unless bounds?.width and bounds.height
|
||||
@gridContainer.cache bounds.x, bounds.y, bounds.width, bounds.height
|
||||
|
||||
showGrid: ->
|
||||
return if @gridShowing()
|
||||
@layer.addChild @gridContainer
|
||||
@textLayer.addChild label for label in @labels
|
||||
|
||||
hideGrid: ->
|
||||
return unless @gridShowing()
|
||||
@layer.removeChild @gridContainer
|
||||
@textLayer.removeChild label for label in @labels
|
||||
|
||||
gridShowing: ->
|
||||
@gridContainer?.parent?
|
||||
|
||||
onToggleGrid: (e) ->
|
||||
# TODO: figure out a better way of managing grid / debug so it's not split across PlaybackView and Surface
|
||||
e?.preventDefault?()
|
||||
if @gridShowing() then @hideGrid() else @showGrid()
|
||||
flag = $('#grid-toggle i.icon-ok')
|
||||
flag.toggleClass 'invisible', not @gridShowing()
|
||||
|
||||
onSetGrid: (e) ->
|
||||
if e.grid then @showGrid() else @hideGrid()
|
||||
|
|
@ -12,6 +12,7 @@ CountdownScreen = require './CountdownScreen'
|
|||
PlaybackOverScreen = require './PlaybackOverScreen'
|
||||
DebugDisplay = require './DebugDisplay'
|
||||
CoordinateDisplay = require './CoordinateDisplay'
|
||||
CoordinateGrid = require './CoordinateGrid'
|
||||
SpriteBoss = require './SpriteBoss'
|
||||
PointChooser = require './PointChooser'
|
||||
RegionChooser = require './RegionChooser'
|
||||
|
@ -24,7 +25,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
surfaceLayer: null
|
||||
surfaceTextLayer: null
|
||||
screenLayer: null
|
||||
gridLayer: null # TODO: maybe
|
||||
gridLayer: null
|
||||
|
||||
spriteBoss: null
|
||||
|
||||
|
@ -56,8 +57,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
'level-set-playing': 'onSetPlaying'
|
||||
'level-set-debug': 'onSetDebug'
|
||||
'level-toggle-debug': 'onToggleDebug'
|
||||
'level-set-grid': 'onSetGrid'
|
||||
'level-toggle-grid': 'onToggleGrid'
|
||||
'level-toggle-pathfinding': 'onTogglePathFinding'
|
||||
'level-set-time': 'onSetTime'
|
||||
'level-set-surface-camera': 'onSetCamera'
|
||||
|
@ -75,7 +74,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
shortcuts:
|
||||
'ctrl+\\, ⌘+\\': 'onToggleDebug'
|
||||
'ctrl+g, ⌘+g': 'onToggleGrid'
|
||||
'ctrl+o, ⌘+o': 'onTogglePathFinding'
|
||||
|
||||
# external functions
|
||||
|
@ -103,6 +101,8 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@dimmer?.destroy()
|
||||
@countdownScreen?.destroy()
|
||||
@playbackOverScreen?.destroy()
|
||||
@coordinateDisplay?.destroy()
|
||||
@coordinateGrid?.destroy()
|
||||
@stage.clear()
|
||||
@musicPlayer?.destroy()
|
||||
@stage.removeAllChildren()
|
||||
|
@ -126,10 +126,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
@showLevel()
|
||||
@updateState true if @loaded
|
||||
# TODO: synchronize both ways of choosing whether to show coords (@world via UI System or @options via World Select modal)
|
||||
if @world.showCoordinates and @options.coords and not @coordinateDisplay
|
||||
@coordinateDisplay = new CoordinateDisplay camera: @camera
|
||||
@surfaceTextLayer.addChild @coordinateDisplay
|
||||
@onFrameChanged()
|
||||
Backbone.Mediator.publish 'surface:world-set-up'
|
||||
|
||||
|
@ -364,6 +360,9 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
|
||||
onNewWorld: (event) ->
|
||||
return unless event.world.name is @world.name
|
||||
@onStreamingWorldUpdated event
|
||||
|
||||
onStreamingWorldUpdated: (event) ->
|
||||
@casting = false
|
||||
@spriteBoss.play()
|
||||
|
||||
|
@ -390,22 +389,21 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
# initialization
|
||||
|
||||
initEasel: ->
|
||||
# takes DOM objects, not jQuery objects
|
||||
@stage = new createjs.Stage(@canvas[0])
|
||||
@stage = new createjs.Stage(@canvas[0]) # Takes DOM objects, not jQuery objects.
|
||||
canvasWidth = parseInt @canvas.attr('width'), 10
|
||||
canvasHeight = parseInt @canvas.attr('height'), 10
|
||||
@camera?.destroy()
|
||||
@camera = new Camera @canvas
|
||||
AudioPlayer.camera = @camera
|
||||
@camera = AudioPlayer.camera = new Camera @canvas
|
||||
@layers.push @surfaceLayer = new Layer name: 'Surface', layerPriority: 0, transform: Layer.TRANSFORM_SURFACE, camera: @camera
|
||||
@layers.push @surfaceTextLayer = new Layer name: 'Surface Text', layerPriority: 1, transform: Layer.TRANSFORM_SURFACE_TEXT, camera: @camera
|
||||
@layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 2, transform: Layer.TRANSFORM_SCREEN, camera: @camera
|
||||
@layers.push @gridLayer = new Layer name: 'Grid', layerPriority: 2, transform: Layer.TRANSFORM_SURFACE, camera: @camera
|
||||
@layers.push @screenLayer = new Layer name: 'Screen', layerPriority: 3, transform: Layer.TRANSFORM_SCREEN, camera: @camera
|
||||
@stage.addChild @layers...
|
||||
@surfaceLayer.addChild @cameraBorder = new CameraBorder bounds: @camera.bounds
|
||||
@screenLayer.addChild new Letterbox canvasWidth: canvasWidth, canvasHeight: canvasHeight
|
||||
@spriteBoss = new SpriteBoss camera: @camera, surfaceLayer: @surfaceLayer, surfaceTextLayer: @surfaceTextLayer, world: @world, thangTypes: @options.thangTypes, choosing: @options.choosing, navigateToSelection: @options.navigateToSelection, showInvisible: @options.showInvisible
|
||||
@countdownScreen ?= new CountdownScreen camera: @camera, layer: @screenLayer
|
||||
@playbackOverScreen ?= new PlaybackOverScreen camera: @camera, layer: @screenLayer
|
||||
@countdownScreen = new CountdownScreen camera: @camera, layer: @screenLayer
|
||||
@playbackOverScreen = new PlaybackOverScreen camera: @camera, layer: @screenLayer
|
||||
@initCoordinates()
|
||||
@stage.enableMouseOver(10)
|
||||
@stage.addEventListener 'stagemousemove', @onMouseMove
|
||||
@stage.addEventListener 'stagemousedown', @onMouseDown
|
||||
|
@ -416,6 +414,11 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
createjs.Ticker.setFPS @options.frameRate
|
||||
@onResize()
|
||||
|
||||
initCoordinates: ->
|
||||
@coordinateGrid ?= new CoordinateGrid {camera: @camera, layer: @gridLayer, textLayer: @surfaceTextLayer}, @world.size()
|
||||
@coordinateGrid.showGrid() if @world.showGrid or @options.grid
|
||||
@coordinateDisplay ?= new CoordinateDisplay camera: @camera, layer: @surfaceTextLayer if @world.showCoordinates or @options.coords
|
||||
|
||||
onResize: (e) =>
|
||||
return if @destroyed
|
||||
oldWidth = parseInt @canvas.attr('width'), 10
|
||||
|
@ -450,7 +453,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
Backbone.Mediator.publish 'registrar-echo-states'
|
||||
@updateState true
|
||||
@drawCurrentFrame()
|
||||
@showGrid() if @options.grid # TODO: pay attention to world grid setting (which we only know when world simulates)
|
||||
createjs.Ticker.addEventListener 'tick', @tick
|
||||
Backbone.Mediator.publish 'level:started'
|
||||
|
||||
|
@ -460,67 +462,6 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
initAudio: ->
|
||||
@musicPlayer = new MusicPlayer()
|
||||
|
||||
# grid; should probably refactor into separate class
|
||||
|
||||
showGrid: ->
|
||||
return if @gridShowing()
|
||||
unless @gridLayer
|
||||
@gridLayer = new createjs.Container()
|
||||
@gridShape = new createjs.Shape()
|
||||
@gridLayer.addChild @gridShape
|
||||
@gridLayer.z = 90019001
|
||||
@gridLayer.mouseEnabled = false
|
||||
@gridShape.alpha = 0.125
|
||||
@gridShape.graphics.beginStroke 'blue'
|
||||
gridSize = Math.round(@world.size()[0] / 20)
|
||||
unless gridSize > 0.1
|
||||
return console.error 'Grid size is', gridSize, 'so we can\'t draw a grid.'
|
||||
wopStart = x: 0, y: 0
|
||||
wopEnd = x: @world.size()[0], y: @world.size()[1]
|
||||
supStart = @camera.worldToSurface wopStart
|
||||
supEnd = @camera.worldToSurface wopEnd
|
||||
wop = x: wopStart.x, y: wopStart.y
|
||||
while wop.x < wopEnd.x
|
||||
sup = @camera.worldToSurface wop
|
||||
@gridShape.graphics.mt(sup.x, supStart.y).lt(sup.x, supEnd.y)
|
||||
t = new createjs.Text(wop.x.toFixed(0), '16px Arial', 'blue')
|
||||
t.x = sup.x - t.getMeasuredWidth() / 2
|
||||
t.y = supStart.y - 10 - t.getMeasuredHeight() / 2
|
||||
t.alpha = 0.75
|
||||
@gridLayer.addChild t
|
||||
wop.x += gridSize
|
||||
while wop.y < wopEnd.y
|
||||
sup = @camera.worldToSurface wop
|
||||
@gridShape.graphics.mt(supStart.x, sup.y).lt(supEnd.x, sup.y)
|
||||
t = new createjs.Text(wop.y.toFixed(0), '16px Arial', 'blue')
|
||||
t.x = 10 - t.getMeasuredWidth() / 2
|
||||
t.y = sup.y - t.getMeasuredHeight() / 2
|
||||
t.alpha = 0.75
|
||||
@gridLayer.addChild t
|
||||
wop.y += gridSize
|
||||
@gridShape.graphics.endStroke()
|
||||
bounds = @gridLayer.getBounds()
|
||||
return unless bounds?.width and bounds.height
|
||||
@gridLayer.cache bounds.x, bounds.y, bounds.width, bounds.height
|
||||
@surfaceLayer.addChild @gridLayer
|
||||
|
||||
hideGrid: ->
|
||||
return unless @gridShowing()
|
||||
@gridLayer.parent.removeChild @gridLayer
|
||||
|
||||
gridShowing: ->
|
||||
@gridLayer?.parent?
|
||||
|
||||
onToggleGrid: (e) ->
|
||||
# TODO: figure out a better way of managing grid / debug so it's not split across PlaybackView and Surface
|
||||
e?.preventDefault?()
|
||||
if @gridShowing() then @hideGrid() else @showGrid()
|
||||
flag = $('#grid-toggle i.icon-ok')
|
||||
flag.toggleClass 'invisible', not @gridShowing()
|
||||
|
||||
onSetGrid: (e) ->
|
||||
if e.grid then @showGrid() else @hideGrid()
|
||||
|
||||
onToggleDebug: (e) ->
|
||||
e?.preventDefault?()
|
||||
Backbone.Mediator.publish 'level-set-debug', {debug: not @debug}
|
||||
|
|
|
@ -355,7 +355,6 @@
|
|||
|
||||
play_level:
|
||||
done: "Done"
|
||||
grid: "Grid"
|
||||
customize_wizard: "Customize Wizard"
|
||||
home: "Home"
|
||||
stop: "Stop"
|
||||
|
|
|
@ -37,10 +37,6 @@ button.btn.btn-xs.btn-inverse#music-button(title="Toggle Music")
|
|||
li.selectable#view-keyboard-shortcuts
|
||||
i.icon-info-sign
|
||||
span(data-i18n="play_level.keyboard_shortcuts") Key Shortcuts
|
||||
li(title="Ctrl/Cmd + G: Toggle grid display").selectable#grid-toggle
|
||||
i.icon-th
|
||||
span(data-i18n="play_level.grid") Grid
|
||||
i.icon-ok.secret.invisible
|
||||
li.selectable#edit-wizard-settings
|
||||
i.icon-user
|
||||
span(data-i18n="play_level.customize_wizard") Customize Wizard
|
||||
|
|
|
@ -18,8 +18,6 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
'level-scrub-back': 'onScrubBack'
|
||||
'level-set-volume': 'onSetVolume'
|
||||
'level-set-debug': 'onSetDebug'
|
||||
'level-set-grid': 'onSetGrid'
|
||||
'level-toggle-grid': 'onToggleGrid'
|
||||
'surface:frame-changed': 'onFrameChanged'
|
||||
'god:new-world-created': 'onNewWorld'
|
||||
'god:streaming-world-updated': 'onNewWorld'
|
||||
|
@ -30,7 +28,6 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
|
||||
events:
|
||||
'click #debug-toggle': 'onToggleDebug'
|
||||
'click #grid-toggle': 'onToggleGrid'
|
||||
'click #edit-wizard-settings': 'onEditWizardSettings'
|
||||
'click #edit-editor-config': 'onEditEditorConfig'
|
||||
'click #view-keyboard-shortcuts': 'onViewKeyboardShortcuts'
|
||||
|
@ -188,11 +185,6 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
flag = $('#debug-toggle i.icon-ok')
|
||||
Backbone.Mediator.publish('level-set-debug', {debug: flag.hasClass('invisible')})
|
||||
|
||||
onToggleGrid: ->
|
||||
return if @shouldIgnore()
|
||||
flag = $('#grid-toggle i.icon-ok')
|
||||
Backbone.Mediator.publish('level-set-grid', {grid: flag.hasClass('invisible')})
|
||||
|
||||
onEditWizardSettings: ->
|
||||
Backbone.Mediator.publish 'edit-wizard-settings'
|
||||
|
||||
|
@ -316,10 +308,6 @@ module.exports = class LevelPlaybackView extends CocoView
|
|||
flag = $('#debug-toggle i.icon-ok')
|
||||
flag.toggleClass 'invisible', not e.debug
|
||||
|
||||
onSetGrid: (e) ->
|
||||
flag = $('#grid-toggle i.icon-ok')
|
||||
flag.toggleClass 'invisible', not e.grid
|
||||
|
||||
# to refactor
|
||||
|
||||
hookUpScrubber: ->
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue