# showGridCoords : false
map:
refSize : &ref_size 50
- minSplitSize : 12.5
+ rockSizeMin : 12.5
+ rockGapOnDivide : true
pathing:
pathSquare : *ref_size
overlayAiPaths : false
- type: fence
args: [360,210, 30,30]
- - type: drywall
+ - type: rock
args: [400,200, 25,25]
- - type: drywall
+ - type: rock
args: [425,225, 25,25]
- type: fence
args: [460,210, 30,30]
- type: fence
args: [210,210, 30,30]
- - type: drywall
+ - type: rock
args: [50,350, 50,50]
- - type: drywall
+ - type: rock
args: [100,350, 50,50]
- - type: drywall
+ - type: rock
args: [50,400, 50,50]
- - type: drywall
+ - type: rock
args: [100,400, 50,50]
- - type: drywall
+ - type: rock
args: [150,300, 50,50]
units:
- type: player
align: 1
- loc: [325,475]
+ loc: [425,425]
- type: blue
align: 1
- loc: [75,475]
- # - type: blue
- # align: 1
- # loc: [175,475]
+ loc: [175,475]
- type: green
align: 2
loc: [75,25]
loc: [25,375]
- type: green
align: 2
- loc: [425,75]
+ loc: [425,125]
items:
- type: nitro
- loc: [425,425]
+ loc: [325,475]
events: []
art:
bg: ''
},
/**
+ * @param {Number} dv Amount to add to base and max value.
+ * @param {StatInvariant} [inv=FULL] Invariant to restore for current value.
+ * @return {this}
+ */
+ setBase : function setBase(v, inv){
+ var dv = v - this.base;
+ this.base = v;
+ return this.modifyMax(dv, inv || FULL);
+ },
+
+ /**
+ * @param {Number} dv Amount to add to current value.
+ * @param {StatInvariant} [inv=FULL] Invariant to restore for current value.
+ * @return {this}
+ */
+ setMax : function setMax(v, inv){
+ return this.modifyMax(v - this.max, inv);
+ },
+
+ setPart : function setPart(part, v, inv){
+ var method =
+ (part === 'max' ? 'setMax' :
+ (part === 'base' ? 'setBase' : 'set'));
+ return this[method](v, inv);
+ },
+
+
+ /**
* @param {Number} dv Amount to add to current value. Values above the max will be set to max.
* @return {this}
*/
*/
modifyMax : function modifyMax(dv, inv){
var v = this.val
- , oldmax = this.max;
- this.max += dv;
+ , oldmax = this.max
+ , max = this.max = oldmax + dv;
switch ( inv ) {
case NONE: break;
case RATIO:
- v = (v / oldmax) * this.max;
+ v = (v / oldmax) * max;
break;
case FULL:
v += dv;
break;
}
+ if (v > max) v = max;
this.val = (this.integer ? Math.round(v) : v);
- this.ratio = this.val / this.max;
+ this.ratio = this.val / max;
return this;
},
+++ /dev/null
-var Y = require('Y').Y
-, clamp = require('ezl/math').clamp
-, Vec = require('ezl/math/vec').Vec
-
-, config = require('tanks/config').config
-, Wall = require('tanks/map/wall').Wall
-,
-
-
-Drywall =
-exports['Drywall'] =
-Wall.subclass('Drywall', {
- // config
- minSplitSize : null,
- get canSplit() { return (this.width > this.minSplitSize); },
-
- // instance
- isReflective : false,
- isBoundary : false,
-
- fillStyle : 'rgba(196,167,158, 0.25)',
- strokeStyle : 'rgba(0,0,0, 0.25)',
- lineWidth : 1,
-
- stats : {
- hp : 1,
- },
-
-
-
- init : function initDrywall(x,y, w,h, hp){
- this.lineWidth = clamp(Math.round(Math.min(w,h) * 0.2), 1, 3);
- Wall.init.call(this, x,y, w,h, this.isBoundary);
- },
-
- divide : function divide(){
- if (!this.canSplit)
- return this;
-
- var _x = this.loc.x, _y = this.loc.y
- , mx = _x+this.width, my = _y+this.height
- , size = this.width * 0.5
- , x, y, wall
- ;
- for (x = _x; x<mx; x+=size) {
- for (y = _y; y<my; y+=size){
- wall = new Drywall(x,y, size,size);
- }
- }
- return this;
- },
-
- toString : Wall.fn.toString
-
-});
-
-// Divide on death (if possible)
-Drywall.addEventListener('destroy', function(evt){
- evt.data.unit.divide();
-});
-
-config.updateOnChange('map.minSplitSize', Drywall.fn);
-
'Map' : require('tanks/map/pathing').Map,
'Level' : require('tanks/map/level').Level,
'Wall' : require('tanks/map/wall').Wall,
- 'Drywall' : require('tanks/map/drywall').Drywall,
+ 'Rock' : require('tanks/map/rock').Rock,
'Fence' : require('tanks/map/fence').Fence
});
--- /dev/null
+var Y = require('Y').Y
+, clamp = require('ezl/math').clamp
+, Vec = require('ezl/math/vec').Vec
+
+, config = require('tanks/config').config
+, Wall = require('tanks/map/wall').Wall
+,
+
+
+Rock =
+exports['Rock'] =
+Wall.subclass('Rock', {
+ // config
+ rockSizeMin : null,
+ rockGapOnDivide : true,
+
+
+ // instance
+ isReflective : false,
+ isBoundary : false,
+ get isDivisible() { return (this.width > this.rockSizeMin); },
+
+
+ fillStyle : 'rgba(196,167,158, 0.25)',
+ strokeStyle : 'rgba(0,0,0, 0.25)',
+ lineWidth : 1,
+ lineRatio : 0.2, // ratio of min(width,height) to lineWidth
+
+ stats : {
+ hp : 1,
+ },
+
+
+
+ init : function initRock(x,y, w,h, hp){
+ this.lineWidth = clamp(Math.round(Math.min(w,h) * this.lineRatio), 1, 3);
+ Wall.init.call(this, x,y, w,h, this.isBoundary);
+ if (hp) this.stats.hp.setMax(hp);
+ },
+
+ divide : function divide(gap){
+ if (!this.isDivisible)
+ return this;
+
+ var _x = this.loc.x, _y = this.loc.y
+ , xMax = _x+this.width, yMax = _y+this.height
+ , size = this.width * 0.5
+
+ , gapOk = this.rockGapOnDivide
+ , gapX = gap ? gap.x : Infinity
+ , gapY = gap ? gap.y : Infinity
+ // , hp = Math.max(Math.round(this.stats.hp.max * 0.5), 1.0)
+ , x, y, nextX, nextY, rock
+ ;
+
+ for (x = _x; x<xMax; x=nextX) {
+ nextX = x + size;
+ for (y = _y; y<yMax; y=nextY){
+ nextY = y + size;
+ rock = new Rock(x,y, size,size);
+ if ( gapOk && (x <= gapX && gapX <= nextX) && (y <= gapY && gapY <= nextY) ) {
+ rock.dead = true; // Don't recursively fire destroy event
+ rock.divide(gap).remove();
+ this.game.killThing(rock);
+ }
+ }
+ }
+ return this;
+ },
+
+ toString : Wall.fn.toString
+
+});
+
+// Divide on death (if possible)
+Rock.addEventListener('destroy', function(evt){
+ var d = evt.data
+ , killer = d.killer
+ , side = d.side
+ , gap = killer && side && side.intersection(killer.trajectory);
+ if (gap) evt.data.unit.divide(gap);
+});
+
+config.updateOnChange(
+ ['map.rockSizeMin', 'map.rockGapOnDivide'], Rock.fn);
+
});
Wall.register('wall', Wall);
-Wall.addEventListener('subclass',
+Wall.addEventListener('subclass',
function(evt){
var subcls = evt.data.child;
Wall.register(Y(subcls.className).camelToSnake(), subcls);