hp : 1
move : 0.5
power : 1
- orbit : 9
- width : 9
- height : 9
- color: '#0A9CFF'
-
+ orbit : 8
+ width : 8
+ height : 8
+ colors:
+ body : '#0A9CFF'
+ shine : '#195FBC'
return new Vec(this.layerWidth,this.layerHeight);
var bb = this.bbox
- , ox1 = bb.x1, oy1 = bb.y1
, ow = this.realWidth, lw, olw = lw = this.layerWidth, cw
, oh = this.realHeight, lh, olh = lh = this.layerHeight, ch
, changes = {}, cchanges = {}
this.realWidth = w;
lw = Math.round(w); // HTMLElement.{width,height} is a long
if (lw !== olw) {
- this.layerWidth = changes.width = lw;
+ this.layerWidth = changes.width = lw;
this.canvasWidth = cchanges.width = cw = Math.ceil(w);
dirtied = true;
}
this.realHeight = h;
lh = Math.round(h); // HTMLElement.{width,height} is a long
if (lh !== olh) {
- this.layerHeight = changes.height = lh;
+ this.layerHeight = changes.height = lh;
this.canvasHeight = cchanges.height = ch = Math.ceil(h);
dirtied = true;
}
var x1 = bb.x1 | 0
, y1 = bb.y1 | 0;
- if (ox1 !== x1)
- changes.left = x1;
- if (oy1 !== y1)
- changes.top = y1;
+ if (x1 !== this.layerX)
+ changes.left = this.layerX = x1;
+ if (y1 !== this.layerY)
+ changes.top = this.layerY = y1;
this.layer.css(changes);
scrollWidth : function scrollWidth(v){ return this.layer.attr('scrollWidth', v); },
scrollHeight : function scrollHeight(v){ return this.layer.attr('scrollHeight', v); },
+ /**
+ * Calculates angle in radians from the Layer's origin to (x,y).
+ * @param {Number} x
+ * @param {Number} y
+ * @return {Number} Angle in radians.
+ */
+ angleTo : function angleTo(x,y){
+ var loc = this.loc
+ , x0 = x - loc.x
+ , y0 = y - loc.y
+ ;
+ return Math.atan2(y0,x0);
+ },
+
/// Transformations ///
},
/**
+ * @return {Number} The layer's current angle of rotation in radians.
+ */
+ /**
* Rotates this layer by r radians.
+ * @param {Number} r Radians to rotate.
+ * @return {this}
+ */
+ /**
+ * Rotates this layer by the angle between the layer's origin and (x,y).
+ * @param {Number} x
+ * @param {Number} y
+ * @return {this}
*/
- rotate : function rotate(r){
+ rotate : function rotate(x,y){
var t = this.transform;
- if (r === undefined)
+ if (x === undefined && y === undefined)
return t.rotate;
- t.rotate = r;
+ t.rotate = (y === undefined ? x : this.angleTo(x,y));
return this._applyTransforms();
},
return this;
},
- erase : function erase(x,y, w,h, alsoChildren){
- this._erased.push({ 'x':x,'y':y, 'w':w,'h':h, 'alsoChildren':alsoChildren });
+ eraseRect : function eraseRect(x,y, w,h, alsoChildren){
+ return this._addErasedPath('rect', x,y, { 'w':w,'h':h }, alsoChildren);
+ },
+
+ eraseCircle : function eraseCircle(x,y, r, alsoChildren){
+ return this._addErasedPath('circle', x,y, { 'r':r }, alsoChildren);
+ },
+
+ _addErasedPath : function _addErasedPath(type, x,y, args, alsoChildren){
+ this._erased.push( Y.extend({ 'type':type, 'x':x,'y':y, 'alsoChildren':alsoChildren }, args||{}) );
this.dirty = true;
if (alsoChildren)
- this.children.invoke('erase', x,y, w,h, alsoChildren);
+ this.children.invoke('_addErasedPath', x,y, args, alsoChildren);
return this;
},
_erase : function _erase(args){
- var x = args.x, y = args.y
- , w = args.w, h = args.h;
+ var ctx = this.ctx
+ , gco = ctx.globalCompositeOperation
+
+ , pw = this.canvas.width()
+ , ph = this.canvas.height()
+
+ , type = args.type
+ , x = args.x, y = args.y
+ ;
- if (w < 0) w = this.canvas.width() + w;
- if (h < 0) h = this.canvas.height() + h;
+ ctx.beginPath();
+ ctx.fillStyle = '#000000';
+ ctx.lineWidth = 0;
+
+ switch (args.type) {
+ case 'rect':
+ var w = args.w, h = args.h;
+ if (w < 0) w = pw + w;
+ if (h < 0) h = ph + h;
+ ctx.clearRect(x,y, w,h);
+ break;
+
+ case 'circle':
+ var r = args.r;
+ if (r <= 0) r = Math.min(pw-x,ph-y)/2 + (r || 0);
+ ctx.globalCompositeOperation = 'destination-out';
+ ctx.arc(x,y, r, 0, Math.PI*2, false);
+ ctx.fill();
+ break;
+
+ default: break;
+ }
- this.ctx.beginPath();
- this.ctx.clearRect(x,y, w,h);
- this.ctx.closePath();
+ ctx.closePath();
+ ctx.globalCompositeOperation = gco;
},
/**
;
// Check we're in the DOM, otherwise jQuery vomits
if ( el && el.attr('parentNode') )
- pos = this.position();
+ pos = el.position();
return this.className+'['+pos.left+','+pos.top+']( children='+kids+' )';
}
});
},
toString : function(){
- var loc = this.loc
- , x1 = loc.x, y1 = loc.y
- , x2 = x1+this.layerWidth, y2 = y1 + this.layerHeight;
- return this.className+'['+x1+','+y1+', '+x2+','+y2+'](w='+this.layerWidth+', h='+this.layerHeight+')';
+ // var loc = this.loc
+ // , x1 = loc.x, y1 = loc.y
+ // , x2 = x1+this.layerWidth, y2 = y1 + this.layerHeight;
+ return this.className+this.bbox+'(w='+this.layerWidth+', h='+this.layerHeight+')';
}
});
--- /dev/null
+var Y = require('Y').Y
+, Vec = require('ezl/math/vec').Vec
+, Rect = require('ezl/shape').Rect
+
+// , ORIGIN = new Vec(0,0)
+// , FACING_RIGHT = exports['FACING_RIGHT'] = 'right'
+// , FACING_LEFT = exports['FACING_LEFT'] = 'left'
+,
+
+Barrel =
+exports['Barrel'] =
+Rect.subclass('Barrel', {
+ originX : 0,
+ originY : '50%',
+ // facing : FACING_RIGHT,
+
+
+ /**
+ * @constructor
+ * @param {Number} width
+ * @param {Number} height
+ * @param {Number|String} [pivotX=0] x coordinate of pivot point (in pixels or as a percentage of width).
+ * @param {Number} [pivotY='50%'] y coordinate of pivot point (in pixels or as a percentage of height).
+ * @return {this}
+ */
+ init : function initBarrel(w,h, pivotX,pivotY){
+ this.originX = pivotX || 0;
+ this.originY = pivotY || '50%';
+ // this.facing = facing || FACING_RIGHT;
+ Rect.init.call(this, w,h);
+ },
+
+
+ /**
+ * Converts (pageX,pageY) from global to local coordinates (x,y), and then
+ * rotates this layer by the angle between the layer's origin and (x,y).
+ * @param {Number} pageX
+ * @param {Number} pageY
+ * @return {this}
+ */
+ rotateRelPage : function rotateRelPage(pageX,pageY){
+ var off = this.offset()
+ , w = this.realWidth, h = this.realHeight
+ , x = off.left + w/2 - pageX
+ , y = off.top + h/2 - pageY
+ , theta = Math.atan2(-y,-x)
+ ;
+ return this.rotate(theta);
+ },
+
+ /**
+ * Calculates the coordinates of the barrel tip based on barrel facing and rotation.
+ * @param {Number} [wiggle=0] Optional offset distance in front of the barrel tip.
+ * @param {Boolean} [relParent=false] If true, coordinates will be relative to parent's origin.
+ * @return {Vec} Coordinates of barrel tip (with offset).
+ */
+ barrelTipLoc : function barrelTipLoc(wiggle, relParent){
+ var theta = this.transform.rotate
+ , sin = Math.sin(theta), cos = Math.cos(theta)
+
+ // (sqrt(2)/2 * wiggle) is max diagonal to ensure projectile doesn't overlap with firing unit
+ , len = this.bbox.originRight + (wiggle || 0)*0.707
+
+ // , len = this.bbox.originDist(this.facing) + (wiggle || 0)*0.707
+ // , olen = (this.facing === FACING_LEFT ? this.bbox.originLeft : this.bbox.originRight)
+ // , len = olen + (wiggle || 0)*0.707
+
+ , o = ((relParent && this.parent) ? this.parent.loc : ORIGIN)
+ , x = o.x + this.loc.x + len*cos
+ , y = o.y + this.loc.y + len*sin
+ ;
+ return new Vec(x,y);
+ }
+
+
+})
+;
-var Y = require('Y').Y;
-
-Y.extend(exports, {
- 'Explosion' : require('tanks/fx/explosion').Explosion
-});
\ No newline at end of file
+var Y = require('Y').Y
+, barrel = require('tanks/fx/barrel')
+, explosion = require('tanks/fx/explosion')
+;
+Y.core.extend(exports, {
+ 'Barrel' : barrel.Barrel,
+ 'Explosion' : explosion.Explosion
+});
.position(0,0)
.fill(this.shadowFillStyle)
.stroke(this.strokeStyle, this.lineWidth)
- .erase(ss,ss, -ss,-ss)
+ .eraseRect(ss,ss, -ss,-ss)
.appendTo( this.shape );
return this;
isReflective : false, // Projectiles bounce off agent rather than explode?
hasInventory : false, // Agent can acquire items?
- orbit : 9,
- width : 9,
- height : 9,
+ orbit : 8,
+ width : 8,
+ height : 8,
- color : '#0A9CFF',
+ colors: {
+ body : '#0A9CFF',
+ shine : '#195FBC'
+ },
stats : {}, // radial speed in revolutions/sec
this.radsPerTick = TWO_PI * this.stats.move.val / 1000 * MS_PER_FRAME;
this.trajectory = new CircularTrajectory(this, oloc.x,oloc.y, this.radius, this.radsPerTick, this.radialPosition);
+ this.colors = Y.extend({}, this.colors);
this.act(0);
},
, to = tvsl.traverse(this.radsPerTick);
this.game.moveThingTo(this, to.x,to.y);
-
- // var oloc = this.owner.loc
- // , t = (this.radialPosition += this.radsPerTick)
- // , r = this.radius
- // , x = oloc.x + r*Math.cos(t)
- // , y = oloc.y + r*Math.sin(t)
- // ;
- // this.game.moveThingTo(this, x,y);
return this;
},
render : function render(parent){
this.remove();
- var loc = this.loc;
- this.shape = new Circle(this.width/2)
+ var loc = this.loc
+ , d = this.width, r = d/2;
+
+ this.shape = new Circle(r)
.position(loc.x, loc.y)
- .fill(this.color)
+ .fill(this.colors.body)
.appendTo( parent );
+ this.shine = new Circle(r)
+ .position(r,r)
+ .fill(this.colors.shine)
+ // .eraseCircle(-r,-r, d*SQRT_TWO)
+ .eraseCircle(r*0.2,-r*1.5, 1.1*d*SQRT_TWO)
+ .appendTo( this.shape );
return this;
}
})