mirror of
https://github.com/codeninjasllc/codecombat.git
synced 2025-05-02 00:43:34 -04:00
Merge pull request #1289 from jayant1992/terrain-generator
Terrain generator
This commit is contained in:
commit
2a571b5ce2
5 changed files with 345 additions and 0 deletions
app
styles
templates
views
128
app/styles/terrain_randomise.sass
Normal file
128
app/styles/terrain_randomise.sass
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
#terrain-randomise-modal
|
||||||
|
|
||||||
|
.choose-option
|
||||||
|
margin-bottom: 15px
|
||||||
|
width: 100%
|
||||||
|
height: 100px
|
||||||
|
overflow: hidden
|
||||||
|
background: white
|
||||||
|
border: 1px solid #333
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
-webkit-transition: opacity 0.3s ease-in-out
|
||||||
|
-moz-transition: opacity 0.3s ease-in-out
|
||||||
|
-ms-transition: opacity 0.3s ease-in-out
|
||||||
|
-o-transition: opacity 0.3s ease-in-out
|
||||||
|
transition: opacity 0.3s ease-in-out
|
||||||
|
|
||||||
|
opacity: 0.4
|
||||||
|
|
||||||
|
border-radius: 5px
|
||||||
|
.only-one
|
||||||
|
-webkit-transition: opacity 0.3s ease-in-out
|
||||||
|
-moz-transition: opacity 0.3s ease-in-out
|
||||||
|
-ms-transition: opacity 0.3s ease-in-out
|
||||||
|
-o-transition: opacity 0.3s ease-in-out
|
||||||
|
transition: opacity 0.3s ease-in-out
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.choose-option:hover
|
||||||
|
opacity: 1
|
||||||
|
.only-one
|
||||||
|
opacity: 1
|
||||||
|
|
||||||
|
.my-icon
|
||||||
|
position: relative
|
||||||
|
left: 0
|
||||||
|
top: -10px
|
||||||
|
z-index: 1
|
||||||
|
|
||||||
|
.my-team-icon
|
||||||
|
height: 60px
|
||||||
|
position: relative
|
||||||
|
top: -10px
|
||||||
|
left: 10px
|
||||||
|
z-index: 0
|
||||||
|
|
||||||
|
.opponent-team-icon
|
||||||
|
height: 60px
|
||||||
|
position: relative
|
||||||
|
top: 10px
|
||||||
|
right: 10px
|
||||||
|
z-index: 0
|
||||||
|
float: right
|
||||||
|
-moz-transform: scaleX(-1)
|
||||||
|
-o-transform: scaleX(-1)
|
||||||
|
-webkit-transform: scaleX(-1)
|
||||||
|
transform: scaleX(-1)
|
||||||
|
filter: FlipH
|
||||||
|
-ms-filter: "FlipH"
|
||||||
|
|
||||||
|
.opponent-icon
|
||||||
|
position: relative
|
||||||
|
float: right
|
||||||
|
right: 0
|
||||||
|
top: -10px
|
||||||
|
-moz-transform: scaleX(-1)
|
||||||
|
-o-transform: scaleX(-1)
|
||||||
|
-webkit-transform: scaleX(-1)
|
||||||
|
transform: scaleX(-1)
|
||||||
|
filter: FlipH
|
||||||
|
-ms-filter: "FlipH"
|
||||||
|
z-index: 1
|
||||||
|
|
||||||
|
.name-label
|
||||||
|
border-bottom: 20px solid lightslategray
|
||||||
|
height: 0
|
||||||
|
width: 40%
|
||||||
|
position: absolute
|
||||||
|
bottom: 0
|
||||||
|
color: black
|
||||||
|
font-weight: bold
|
||||||
|
text-align: center
|
||||||
|
z-index: 2
|
||||||
|
|
||||||
|
span
|
||||||
|
position: relative
|
||||||
|
top: 1px
|
||||||
|
|
||||||
|
.my-name
|
||||||
|
border-right: 15px solid transparent
|
||||||
|
left: 0
|
||||||
|
span
|
||||||
|
left: 3px
|
||||||
|
|
||||||
|
.preset-size
|
||||||
|
border-left: 15px solid transparent
|
||||||
|
right: 0
|
||||||
|
//text-align: right
|
||||||
|
span
|
||||||
|
right: 3px
|
||||||
|
|
||||||
|
.preset-name
|
||||||
|
border-top: 25px solid darkgray
|
||||||
|
border-left: 20px solid transparent
|
||||||
|
border-right: 20px solid transparent
|
||||||
|
height: 0
|
||||||
|
width: 30%
|
||||||
|
position: absolute
|
||||||
|
left: 35%
|
||||||
|
top: 0
|
||||||
|
color: black
|
||||||
|
text-align: center
|
||||||
|
font-size: 18px
|
||||||
|
font-weight: bold
|
||||||
|
|
||||||
|
span
|
||||||
|
position: relative
|
||||||
|
top: -25px
|
||||||
|
|
||||||
|
.easy-option .preset-name
|
||||||
|
border-top: 25px solid limegreen
|
||||||
|
|
||||||
|
.medium-option .preset-name
|
||||||
|
border-top: 25px solid darkorange
|
||||||
|
|
||||||
|
.hard-option .preset-name
|
||||||
|
border-top: 25px solid black
|
||||||
|
color: white
|
|
@ -79,6 +79,8 @@ block header
|
||||||
a(data-i18n="common.fork")#fork-level-start-button Fork
|
a(data-i18n="common.fork")#fork-level-start-button Fork
|
||||||
li(class=anonymous ? "disabled": "")
|
li(class=anonymous ? "disabled": "")
|
||||||
a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
|
a(data-toggle="coco-modal", data-target="modal/revert", data-i18n="editor.revert")#revert-button Revert
|
||||||
|
li(class=anonymous ? "disabled": "")
|
||||||
|
a(data-toggle="coco-modal", data-target="modal/terrain_randomise", data-i18n="editor.randomise")#randomise-button Randomise
|
||||||
li(class=anonymous ? "disabled": "")
|
li(class=anonymous ? "disabled": "")
|
||||||
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
|
a(data-i18n="editor.pop_i18n")#pop-level-i18n-button Populate i18n
|
||||||
li.divider
|
li.divider
|
||||||
|
|
14
app/templates/modal/terrain_randomise.jade
Normal file
14
app/templates/modal/terrain_randomise.jade
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
extends /templates/modal/modal_base
|
||||||
|
|
||||||
|
block modal-header-content
|
||||||
|
h3(data-i18n="editor.pick_a_terrain") Pick a Terrain
|
||||||
|
|
||||||
|
block modal-body-content
|
||||||
|
div#normal-view
|
||||||
|
a(href="#")
|
||||||
|
div.choose-option(data-preset-type="grassy", data-preset-size="small")
|
||||||
|
div.preset-size.name-label
|
||||||
|
span(data-i18n="ladder.small") Small
|
||||||
|
div.preset-name
|
||||||
|
span(data-i18n="ladder.grassy") Grassy
|
||||||
|
//- for model in models
|
|
@ -43,6 +43,7 @@ module.exports = class ThangsTabView extends View
|
||||||
'sprite:mouse-up': 'onSpriteMouseUp'
|
'sprite:mouse-up': 'onSpriteMouseUp'
|
||||||
'sprite:double-clicked': 'onSpriteDoubleClicked'
|
'sprite:double-clicked': 'onSpriteDoubleClicked'
|
||||||
'surface:stage-mouse-up': 'onStageMouseUp'
|
'surface:stage-mouse-up': 'onStageMouseUp'
|
||||||
|
'randomise:terrain-generated': 'onRandomiseTerrain'
|
||||||
|
|
||||||
events:
|
events:
|
||||||
'click #extant-thangs-filter button': 'onFilterExtantThangs'
|
'click #extant-thangs-filter button': 'onFilterExtantThangs'
|
||||||
|
@ -57,6 +58,8 @@ module.exports = class ThangsTabView extends View
|
||||||
'delete, del, backspace': 'deleteSelectedExtantThang'
|
'delete, del, backspace': 'deleteSelectedExtantThang'
|
||||||
'left': -> @moveAddThangSelection -1
|
'left': -> @moveAddThangSelection -1
|
||||||
'right': -> @moveAddThangSelection 1
|
'right': -> @moveAddThangSelection 1
|
||||||
|
'ctrl+z': 'undoAction'
|
||||||
|
'ctrl+shift+z': 'redoAction'
|
||||||
|
|
||||||
constructor: (options) ->
|
constructor: (options) ->
|
||||||
super options
|
super options
|
||||||
|
@ -221,6 +224,11 @@ module.exports = class ThangsTabView extends View
|
||||||
return unless e.thang
|
return unless e.thang
|
||||||
@editThang thangID: e.thang.id
|
@editThang thangID: e.thang.id
|
||||||
|
|
||||||
|
onRandomiseTerrain: (e) ->
|
||||||
|
for thang in e.thangs
|
||||||
|
@selectAddThangType thang.id
|
||||||
|
@addThang @addThangType, thang.pos
|
||||||
|
|
||||||
# TODO: figure out a good way to have all Surface clicks and Treema clicks just proxy in one direction, so we can maintain only one way of handling selection and deletion
|
# TODO: figure out a good way to have all Surface clicks and Treema clicks just proxy in one direction, so we can maintain only one way of handling selection and deletion
|
||||||
onExtantThangSelected: (e) ->
|
onExtantThangSelected: (e) ->
|
||||||
@selectedExtantSprite?.setNameLabel? null unless @selectedExtantSprite is e.sprite
|
@selectedExtantSprite?.setNameLabel? null unless @selectedExtantSprite is e.sprite
|
||||||
|
@ -450,6 +458,12 @@ module.exports = class ThangsTabView extends View
|
||||||
$('#add-thangs-column').toggle()
|
$('#add-thangs-column').toggle()
|
||||||
@onWindowResize e
|
@onWindowResize e
|
||||||
|
|
||||||
|
undoAction: (e) ->
|
||||||
|
@thangsTreema.undo()
|
||||||
|
|
||||||
|
redoAction: (e) ->
|
||||||
|
@thangsTreema.redo()
|
||||||
|
|
||||||
class ThangsNode extends TreemaNode.nodeMap.array
|
class ThangsNode extends TreemaNode.nodeMap.array
|
||||||
valueClass: 'treema-array-replacement'
|
valueClass: 'treema-array-replacement'
|
||||||
getChildren: ->
|
getChildren: ->
|
||||||
|
|
187
app/views/modal/terrain_randomise_modal.coffee
Normal file
187
app/views/modal/terrain_randomise_modal.coffee
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
ModalView = require 'views/kinds/ModalView'
|
||||||
|
template = require 'templates/modal/terrain_randomise'
|
||||||
|
CocoModel = require 'models/CocoModel'
|
||||||
|
|
||||||
|
clusters = {
|
||||||
|
'rocks': ['Rock 1', 'Rock 2', 'Rock 3', 'Rock 4', 'Rock 5', 'Rock Cluster 1', 'Rock Cluster 2', 'Rock Cluster 3']
|
||||||
|
'trees': ['Tree 1', 'Tree 2', 'Tree 3', 'Tree 4']
|
||||||
|
'shrubs': ['Shrub 1', 'Shrub 2', 'Shrub 3']
|
||||||
|
'houses': ['House 1', 'House 2', 'House 3', 'House 4']
|
||||||
|
'animals': ['Cow', 'Horse']
|
||||||
|
'wood': ['Firewood 1', 'Firewood 2', 'Firewood 3', 'Barrel']
|
||||||
|
'farm': ['Farm']
|
||||||
|
}
|
||||||
|
|
||||||
|
presets = {
|
||||||
|
# 'dungeon': {
|
||||||
|
# 'type':'dungeon'
|
||||||
|
# 'borders':['Dungeon Wall']
|
||||||
|
# 'floors':['Dungeon Floor']
|
||||||
|
# 'decorations':[]
|
||||||
|
# }
|
||||||
|
'grassy': {
|
||||||
|
'type':'grassy'
|
||||||
|
'borders':['Tree 1', 'Tree 2', 'Tree 3']
|
||||||
|
'floors':['Grass01', 'Grass02', 'Grass03']
|
||||||
|
'decorations': {
|
||||||
|
'house': {
|
||||||
|
'num':[1,2] #min-max
|
||||||
|
'width': 20
|
||||||
|
'height': 20
|
||||||
|
'clusters': {
|
||||||
|
'houses':[1,1]
|
||||||
|
'trees':[1,2]
|
||||||
|
'shrubs':[0,3]
|
||||||
|
'rocks':[1,2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
'farm': {
|
||||||
|
'num':[1,2] #min-max
|
||||||
|
'width': 20
|
||||||
|
'height': 20
|
||||||
|
'clusters': {
|
||||||
|
'farm':[1,1]
|
||||||
|
'shrubs':[2,3]
|
||||||
|
'wood':[2,4]
|
||||||
|
'animals':[2,3]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sizes = {
|
||||||
|
'small': {
|
||||||
|
'x':80
|
||||||
|
'y':68
|
||||||
|
}
|
||||||
|
'large': {
|
||||||
|
'x':160
|
||||||
|
'y':136
|
||||||
|
}
|
||||||
|
'floorSize': {
|
||||||
|
'x':20
|
||||||
|
'y':20
|
||||||
|
}
|
||||||
|
'borderSize': {
|
||||||
|
'x':4
|
||||||
|
'y':4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = class TerrainRandomiseModal extends ModalView
|
||||||
|
id: 'terrain-randomise-modal'
|
||||||
|
template: template
|
||||||
|
thangs = []
|
||||||
|
|
||||||
|
events:
|
||||||
|
'click .choose-option': 'onRandomise'
|
||||||
|
|
||||||
|
onRevertModel: (e) ->
|
||||||
|
id = $(e.target).val()
|
||||||
|
CocoModel.backedUp[id].revert()
|
||||||
|
$(e.target).closest('tr').remove()
|
||||||
|
@reloadOnClose = true
|
||||||
|
|
||||||
|
onRandomise: (e) ->
|
||||||
|
target = $(e.target)
|
||||||
|
presetType = target.attr 'data-preset-type'
|
||||||
|
presetSize = target.attr 'data-preset-size'
|
||||||
|
@randomiseThangs presetType, presetSize
|
||||||
|
Backbone.Mediator.publish('randomise:terrain-generated',
|
||||||
|
'thangs': @thangs
|
||||||
|
)
|
||||||
|
|
||||||
|
randomiseThangs: (presetName, presetSize) ->
|
||||||
|
preset = presets[presetName]
|
||||||
|
presetSize = sizes[presetSize]
|
||||||
|
@thangs = []
|
||||||
|
@randomiseFloor preset, presetSize
|
||||||
|
@randomiseBorder preset, presetSize
|
||||||
|
@randomiseDecorations preset, presetSize
|
||||||
|
|
||||||
|
randomiseFloor: (preset, presetSize) ->
|
||||||
|
for i in _.range(0, presetSize.x, sizes.floorSize.x)
|
||||||
|
for j in _.range(0, presetSize.y, sizes.floorSize.y)
|
||||||
|
@thangs.push {
|
||||||
|
'id': @getRandomThang(preset.floors)
|
||||||
|
'pos': {
|
||||||
|
'x': i
|
||||||
|
'y': j
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
randomiseBorder: (preset, presetSize) ->
|
||||||
|
for i in _.range(0-sizes.floorSize.x/2+sizes.borderSize.x, presetSize.x-sizes.floorSize.x/2, sizes.borderSize.x)
|
||||||
|
@thangs.push {
|
||||||
|
'id': @getRandomThang(preset.borders)
|
||||||
|
'pos': {
|
||||||
|
'x': i
|
||||||
|
'y': 0-sizes.floorSize.x/2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@thangs.push {
|
||||||
|
'id': @getRandomThang(preset.borders)
|
||||||
|
'pos': {
|
||||||
|
'x': i
|
||||||
|
'y': presetSize.y - sizes.borderSize.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in _.range(0-sizes.floorSize.y/2, presetSize.y-sizes.borderSize.y, sizes.borderSize.y)
|
||||||
|
@thangs.push {
|
||||||
|
'id': @getRandomThang(preset.borders)
|
||||||
|
'pos': {
|
||||||
|
'x': 0-sizes.floorSize.x/2+sizes.borderSize.x
|
||||||
|
'y': i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@thangs.push {
|
||||||
|
'id': @getRandomThang(preset.borders)
|
||||||
|
'pos': {
|
||||||
|
'x': presetSize.x - sizes.borderSize.x - sizes.floorSize.x/2
|
||||||
|
'y': i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
randomiseDecorations: (preset, presetSize)->
|
||||||
|
for name, decoration of preset.decorations
|
||||||
|
for num in _.range(_.random(decoration.num[0], decoration.num[1]))
|
||||||
|
center =
|
||||||
|
{
|
||||||
|
'x':_.random(decoration.width, presetSize.x - decoration.width),
|
||||||
|
'y':_.random(decoration.height, presetSize.y - decoration.height)
|
||||||
|
}
|
||||||
|
min =
|
||||||
|
{
|
||||||
|
'x':center.x - decoration.width/2
|
||||||
|
'y':center.y - decoration.height/2
|
||||||
|
}
|
||||||
|
max =
|
||||||
|
{
|
||||||
|
'x':center.x + decoration.width/2
|
||||||
|
'y':center.y + decoration.height/2
|
||||||
|
}
|
||||||
|
for cluster, range of decoration.clusters
|
||||||
|
for i in _.range(_.random(range[0], range[1]))
|
||||||
|
@thangs.push {
|
||||||
|
'id':@getRandomThang(clusters[cluster])
|
||||||
|
'pos':{
|
||||||
|
'x':_.random(min.x, max.x)
|
||||||
|
'y':_.random(min.y, max.y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
getRandomThang: (thangList) ->
|
||||||
|
return thangList[_.random(0, thangList.length-1)]
|
||||||
|
|
||||||
|
getRenderData: ->
|
||||||
|
c = super()
|
||||||
|
models = _.values CocoModel.backedUp
|
||||||
|
models = (m for m in models when m.hasLocalChanges())
|
||||||
|
c.models = models
|
||||||
|
c
|
||||||
|
|
||||||
|
onHidden: ->
|
||||||
|
location.reload() if @reloadOnClose
|
Loading…
Add table
Add a link
Reference in a new issue