mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-04-14 05:55:00 -04:00
Add flag cursor and pending flags.
This commit is contained in:
parent
f44d802934
commit
3125c2b129
10 changed files with 121 additions and 20 deletions
app
lib/surface
CocoSprite.coffeeFlagSprite.coffeeIndieSprite.coffeeSpriteBoss.coffeeSurface.coffeeWizardSprite.coffee
schemas/subscriptions
styles/play
views/play/level
|
@ -320,6 +320,8 @@ module.exports = CocoSprite = class CocoSprite extends CocoClass
|
|||
[@imageObject.x, @imageObject.y] = [sup.x, sup.y]
|
||||
@lastPos = p1.copy?() or _.clone(p1)
|
||||
@hasMoved = true
|
||||
if @thangType.get('name') is 'Flag' and not @notOfThisWorld
|
||||
_.defer => Backbone.Mediator.publish 'surface:flag-appeared', sprite: @
|
||||
|
||||
updateBaseScale: ->
|
||||
scale = 1
|
||||
|
|
34
app/lib/surface/FlagSprite.coffee
Normal file
34
app/lib/surface/FlagSprite.coffee
Normal file
|
@ -0,0 +1,34 @@
|
|||
IndieSprite = require 'lib/surface/IndieSprite'
|
||||
{me} = require 'lib/auth'
|
||||
|
||||
module.exports = class FlagSprite extends IndieSprite
|
||||
subscriptions:
|
||||
'surface:mouse-moved': 'onMouseMoved'
|
||||
|
||||
#shortcuts:
|
||||
|
||||
defaultPos: -> x: 20, y: 20, z: 1
|
||||
|
||||
constructor: (thangType, options) ->
|
||||
super thangType, options
|
||||
@toggleCursor options.isCursor
|
||||
|
||||
makeIndieThang: (thangType, options) ->
|
||||
thang = super thangType, options
|
||||
thang.width = thang.height = thang.depth = 2
|
||||
thang.pos.z = 1
|
||||
thang.isSelectable = false
|
||||
thang.color = options.color
|
||||
thang.team = options.team
|
||||
thang
|
||||
|
||||
onMouseMoved: (e) ->
|
||||
return unless @options.isCursor
|
||||
wop = @options.camera.screenToWorld x: e.x, y: e.y
|
||||
@thang.pos.x = wop.x
|
||||
@thang.pos.y = wop.y
|
||||
|
||||
toggleCursor: (to) ->
|
||||
@options.isCursor = to
|
||||
@thang.alpha = if to then 0.33 else 0.67 # 1.0 is for flags that have been placed
|
||||
@updateAlpha()
|
|
@ -1,8 +1,5 @@
|
|||
{me} = require('lib/auth')
|
||||
Thang = require 'lib/world/thang'
|
||||
Vector = require 'lib/world/vector'
|
||||
CocoSprite = require 'lib/surface/CocoSprite'
|
||||
Camera = require './Camera'
|
||||
|
||||
module.exports = IndieSprite = class IndieSprite extends CocoSprite
|
||||
notOfThisWorld: true
|
||||
|
@ -11,16 +8,16 @@ module.exports = IndieSprite = class IndieSprite extends CocoSprite
|
|||
'note-group-ended': 'onNoteGroupEnded'
|
||||
|
||||
constructor: (thangType, options) ->
|
||||
options.thang = @makeIndieThang thangType, options.thangID, options.pos
|
||||
options.thang = @makeIndieThang thangType, options
|
||||
super thangType, options
|
||||
@shadow = @thang
|
||||
|
||||
makeIndieThang: (thangType, thangID, pos) ->
|
||||
@thang = thang = new Thang null, thangType.get('name'), thangID
|
||||
makeIndieThang: (thangType, options) ->
|
||||
@thang = thang = new Thang null, thangType.get('name'), options.thangID
|
||||
# Build needed results of what used to be Exists, Physical, Acts, and Selectable Components
|
||||
thang.exists = true
|
||||
thang.width = thang.height = thang.depth = 4
|
||||
thang.pos = pos ? @defaultPos()
|
||||
thang.pos = options.pos ? @defaultPos()
|
||||
thang.pos.z = thang.depth / 2
|
||||
thang.shape = 'ellipsoid'
|
||||
thang.rotation = 0
|
||||
|
|
|
@ -3,6 +3,7 @@ CocoClass = require 'lib/CocoClass'
|
|||
Layer = require './Layer'
|
||||
IndieSprite = require 'lib/surface/IndieSprite'
|
||||
WizardSprite = require 'lib/surface/WizardSprite'
|
||||
FlagSprite = require 'lib/surface/FlagSprite'
|
||||
CocoSprite = require 'lib/surface/CocoSprite'
|
||||
Mark = require './Mark'
|
||||
Grid = require 'lib/world/Grid'
|
||||
|
@ -22,6 +23,10 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
'god:streaming-world-updated': 'onNewWorld'
|
||||
'camera:dragged': 'onCameraDragged'
|
||||
'sprite:loaded': -> @update(true)
|
||||
'level:flag-color-selected': 'onFlagColorSelected'
|
||||
'level:flag-updated': 'onFlagUpdated'
|
||||
'surface:flag-appeared': 'onFlagAppeared'
|
||||
'surface:remove-selected-flag': 'onRemoveSelectedFlag'
|
||||
|
||||
constructor: (@options) ->
|
||||
super()
|
||||
|
@ -37,6 +42,7 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
@selfWizardSprite = null
|
||||
@createLayers()
|
||||
@spriteSheetCache = {}
|
||||
@pendingFlags = []
|
||||
|
||||
destroy: ->
|
||||
@removeSprite sprite for thangID, sprite of @sprites
|
||||
|
@ -316,6 +322,39 @@ module.exports = class SpriteBoss extends CocoClass
|
|||
instance.addEventListener 'complete', ->
|
||||
Backbone.Mediator.publish 'thang-finished-talking', thang: sprite?.thang
|
||||
|
||||
onFlagColorSelected: (e) ->
|
||||
@removeSprite @flagCursorSprite if @flagCursorSprite
|
||||
@flagCursorSprite = null
|
||||
return unless e.color
|
||||
@flagCursorSprite = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Flag Cursor', color: e.color, team: me.team, isCursor: true, pos: e.pos)
|
||||
@addSprite @flagCursorSprite, @flagCursorSprite.thang.id, @spriteLayers['Floating']
|
||||
|
||||
onFlagUpdated: (e) ->
|
||||
return unless e.active
|
||||
pendingFlag = new FlagSprite @thangTypeFor('Flag'), @createSpriteOptions(thangID: 'Pending Flag ' + Math.random(), color: e.color, team: me.team, isCursor: false, pos: e.pos)
|
||||
@addSprite pendingFlag, pendingFlag.thang.id, @spriteLayers['Floating']
|
||||
@pendingFlags.push pendingFlag
|
||||
|
||||
onFlagAppeared: (e) ->
|
||||
# Remove the pending flag that matches this one's color/team/position, and any color/team matches placed earlier.
|
||||
t1 = e.sprite.thang
|
||||
pending = (@pendingFlags ? []).slice()
|
||||
foundExactMatch = false
|
||||
for i in [pending.length - 1 .. 0] by -1
|
||||
pendingFlag = pending[i]
|
||||
t2 = pendingFlag.thang
|
||||
matchedType = t1.color is t2.color and t1.team is t2.team
|
||||
matched = matchedType and (foundExactMatch or Math.abs(t1.pos.x - t2.pos.x) < 0.00001 and Math.abs(t1.pos.y - t2.pos.y) < 0.00001)
|
||||
if matched
|
||||
foundExactMatch = true
|
||||
@pendingFlags.splice(i, 1)
|
||||
@removeSprite pendingFlag
|
||||
null
|
||||
|
||||
onRemoveSelectedFlag: (e) ->
|
||||
return unless @selectedSprite and @selectedSprite.thangType.get('name') is 'Flag' and @selectedSprite.thang.team is me.team
|
||||
Backbone.Mediator.publish 'surface:remove-flag', color: @selectedSprite.thang.color
|
||||
|
||||
# Marks
|
||||
|
||||
updateSelection: ->
|
||||
|
|
|
@ -69,6 +69,7 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
'camera:zoom-updated': 'onZoomUpdated'
|
||||
'playback:real-time-playback-started': 'onRealTimePlaybackStarted'
|
||||
'playback:real-time-playback-ended': 'onRealTimePlaybackEnded'
|
||||
'level:flag-color-selected': 'onFlagColorSelected'
|
||||
#'god:world-load-progress-changed': -> console.log 'it is actually', @world.age
|
||||
|
||||
shortcuts:
|
||||
|
@ -634,10 +635,11 @@ module.exports = Surface = class Surface extends CocoClass
|
|||
@realTime = false
|
||||
@onResize()
|
||||
@spriteBoss.selfWizardSprite?.toggle true
|
||||
@canvas.removeClass 'flag-selected'
|
||||
@canvas.removeClass 'flag-color-selected'
|
||||
|
||||
onFlagSelected: (e) ->
|
||||
@canvas.toggleClass 'flag-selected', Boolean(e.color)
|
||||
onFlagColorSelected: (e) ->
|
||||
@canvas.toggleClass 'flag-color-selected', Boolean(e.color)
|
||||
e.pos = @camera.screenToWorld @mouseScreenPos if @mouseScreenPos
|
||||
|
||||
# paths - TODO: move to SpriteBoss? but only update on frame drawing instead of on every frame update?
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
IndieSprite = require 'lib/surface/IndieSprite'
|
||||
Camera = require './Camera'
|
||||
{me} = require 'lib/auth'
|
||||
|
||||
module.exports = class WizardSprite extends IndieSprite
|
||||
|
@ -38,8 +37,8 @@ module.exports = class WizardSprite extends IndieSprite
|
|||
else if options.name
|
||||
@setNameLabel options.name
|
||||
|
||||
makeIndieThang: (thangType, thangID, pos) ->
|
||||
thang = super thangType, thangID, pos
|
||||
makeIndieThang: (thangType, options) ->
|
||||
thang = super thangType, options
|
||||
thang.isSelectable = false
|
||||
thang.bobHeight = 0.75
|
||||
thang.bobTime = 2
|
||||
|
|
|
@ -57,13 +57,21 @@ module.exports =
|
|||
'level:victory-hidden':
|
||||
{} # TODO schema
|
||||
|
||||
'level:flag-selected':
|
||||
'level:flag-color-selected':
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
properties:
|
||||
color: # omitted if we've deselected
|
||||
color:
|
||||
type: 'string'
|
||||
enum: ['green', 'black', 'violet']
|
||||
description: 'The flag color to place next, or omitted/null if deselected.'
|
||||
pos:
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
required: ['x', 'y']
|
||||
properties:
|
||||
x: {type: 'number'}
|
||||
y: {type: 'number'}
|
||||
|
||||
'level:flag-updated':
|
||||
type: 'object'
|
||||
|
|
|
@ -94,3 +94,15 @@ module.exports = # /app/lib/surface
|
|||
|
||||
'echo-all-wizard-sprites':
|
||||
{} # TODO schema
|
||||
|
||||
'surface:flag-appeared':
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
required: ['sprite']
|
||||
properties:
|
||||
sprite:
|
||||
type: 'object'
|
||||
|
||||
'surface:remove-selected-flag':
|
||||
type: 'object'
|
||||
additionalProperties: false
|
||||
|
|
|
@ -47,7 +47,7 @@ body.is-playing
|
|||
z-index: 1
|
||||
@include transition(0.5s ease-out)
|
||||
|
||||
&.flag-selected
|
||||
&.flag-color-selected
|
||||
cursor: crosshair
|
||||
|
||||
min-width: 1024px
|
||||
|
|
|
@ -12,6 +12,7 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
'surface:stage-mouse-down': 'onStageMouseDown'
|
||||
'god:new-world-created': 'onNewWorld'
|
||||
'god:streaming-world-updated': 'onNewWorld'
|
||||
'surface:remove-flag': 'onRemoveFlag'
|
||||
|
||||
events:
|
||||
'click .green-flag': -> @onFlagSelected color: 'green', source: 'button'
|
||||
|
@ -23,6 +24,7 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
'b': -> @onFlagSelected color: 'black', source: 'shortcut'
|
||||
'v': -> @onFlagSelected color: 'violet', source: 'shortcut'
|
||||
'esc': -> @onFlagSelected color: null, source: 'shortcut'
|
||||
'delete, del, backspace': 'onDeletePressed'
|
||||
|
||||
constructor: (options) ->
|
||||
super options
|
||||
|
@ -39,9 +41,10 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
@$el.hide()
|
||||
|
||||
onFlagSelected: (e) ->
|
||||
return if @flagColor is e.color
|
||||
color = if e.source is 'button' and e.color is @flagColor then null else e.color
|
||||
@flagColor = color
|
||||
Backbone.Mediator.publish 'level:flag-selected', color: color
|
||||
Backbone.Mediator.publish 'level:flag-color-selected', color: color
|
||||
@$el.find('.flag-button').removeClass('active')
|
||||
@$el.find(".#{color}-flag").addClass('active') if color
|
||||
|
||||
|
@ -52,14 +55,19 @@ module.exports = class LevelFlagsView extends CocoView
|
|||
@flags[@flagColor] = flag
|
||||
@flagHistory.push flag
|
||||
Backbone.Mediator.publish 'level:flag-updated', flag
|
||||
console.log 'trying to place flag at', @world.age, 'and think it will happen by', flag.time
|
||||
#console.log 'trying to place flag at', @world.age, 'and think it will happen by', flag.time
|
||||
|
||||
removeFlag: (e) ->
|
||||
onDeletePressed: (e) ->
|
||||
return unless @realTime
|
||||
Backbone.Mediator.publish 'surface:remove-selected-flag', {}
|
||||
@onFlagSelected color: null, source: 'shortcut'
|
||||
|
||||
onRemoveFlag: (e) ->
|
||||
delete @flags[e.color]
|
||||
console.log e.color, 'deleted'
|
||||
flag = player: me.id, team: me.team, color: e.color, time: @world.dt * @world.frames.length, active: false
|
||||
@flagHistory.push flag
|
||||
Backbone.Mediator.publish 'level:flag-updated', flag
|
||||
#console.log e.color, 'deleted at time', flag.time
|
||||
|
||||
onNewWorld: (event) ->
|
||||
return unless event.world.name is @world.name
|
||||
|
|
Loading…
Add table
Reference in a new issue