- type: player
align: 1
loc: [325,475]
- - type: green
- align: 2
- loc: [75,25]
- type: blue
align: 1
loc: [75,475]
- - type: blue
- align: 1
- loc: [175,475]
+ # - type: blue
+ # align: 1
+ # loc: [175,475]
+ - type: green
+ align: 2
+ loc: [75,25]
- type: green
align: 2
loc: [25,375]
, vec = require('ezl/math/vec')
, Vec = vec.Vec
, Line = require('ezl/math/line').Line
-, QuadTree = require('ezl/util/tree/quadtree').QuadTree
, BinaryHeap = require('ezl/util/tree/binaryheap').BinaryHeap
, config = require('tanks/config').config
, BoundsType = constants.BoundsType
, DensityType = constants.DensityType
, Map = require('tanks/map/pathing/map').Map
-, Trajectory = require('tanks/map/pathing/trajectory').Trajectory
-, Traversal = require('tanks/map/pathing/traversal').Traversal
-, Thing = require('tanks/thing/thing').Thing
-, Bullet = require('tanks/thing/bullet').Bullet
, _X = 0, _Y = 1
-, BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000
, SQRT_TWO = Math.sqrt(2)
-
-, kTrue = op.K(true)
-, isBullet = Y.is(Bullet)
;
-/**
- * A QuadTree which aids in pathing for AI.
- * - QuadTree methods which took rect coords (x1,y1, x2,y2) will accept
- * anything Rect-like (having properties x1,y1, x2,y2).
- * - Pathing methods will account for the unit's size when calculating paths,
- * intersections, blocking, and similar tasks.
- */
Y.core.extend(Map.fn, {
/**
, vec = require('ezl/math/vec')
, Vec = vec.Vec
-, Line = require('ezl/math/line').Line
-, QuadTree = require('ezl/util/tree/quadtree').QuadTree
-, BinaryHeap = require('ezl/util/tree/binaryheap').BinaryHeap
+, manhattan = vec.manhattan
-, config = require('tanks/config').config
-, constants = require('tanks/constants')
-, BoundsType = constants.BoundsType
-, DensityType = constants.DensityType
, Map = require('tanks/map/pathing/map').Map
, Trajectory = require('tanks/map/pathing/trajectory').Trajectory
-, Traversal = require('tanks/map/pathing/traversal').Traversal
-, Thing = require('tanks/thing/thing').Thing
, Bullet = require('tanks/thing/bullet').Bullet
, _X = 0, _Y = 1
-, BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000
+, BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000 // FIXME: different projectile types move at different rates!
, SQRT_TWO = Math.sqrt(2)
;
Y.core.extend(Map.fn, {
- // moveAwayFrom : function moveAwayFrom(agent){
- // var mid = this.midpoint
- // , trj = agent.trajectory.tangent(mid)
- //
- // , wall = this.closestOf(this.game.map.allWalls)
- // , wmid = wall.midpoint
- //
- // , lvl = this.game.level.bbox, w = lvl.width, h = lvl.height
- // , x = ((mid.x - wmid.x) > 0 ? w : 0)
- // , y = ((mid.y - wmid.y) > 0 ? h : 0)
- // , to = this.currentMove = trj.near(x,y);
- //
- // this.forceCurrentMove = this.willCollide.bind(this, [agent], 5);
- // this.currentMoveLimit = this.now + 1000;
- //
- // this.move(to.x, to.y);
- //
- // // console.log(' --> Dodge', agent, 'away from', wall, 'to', to);
- // return to;
- // },
-
findNearLike : function findNearLike(me, ticks, fn){
if (fn) fn = fn.toFunction();
return dudes;
},
+ findNearBullets : function findNearBullets(me, ticks){
+ return this.findNearLike(me, ticks, this._nearBulletFilter);
+ },
+ _nearBulletFilter : function nearBulletFilter(agent){
+ return agent.isProjectile;
+ },
+
findNearEnemies : function findNearEnemies(me, ticks){
return this.findNearLike(me, ticks, this._nearEnemyFilter);
},
-
_nearEnemyFilter : function nearEnemyFilter(agent){
var me = this; // Runs in the context of the 'me' unit; @see this.findNearLike()
return agent.isCombatant && agent.align !== me.align;
findNearEnemiesInSight : function findNearEnemiesInSight(me, ticks){
return this.findNearLike(me, ticks, this._nearEnemyInSightFilter);
},
-
_nearEnemyInSightFilter : function nearEnemyInSightFilter(agent){
var me = this; // Runs in the context of the 'me' unit; @see this.findNearLike()
return ( agent.align !== me.align && agent.isCombatant &&
- new Trajectory(me, me.loc, agent.loc).pathBlocked(agent) );
+ new Trajectory(me, me.loc, agent.loc).canSee(agent) );
},
closestOf : function closestOf(me, agents){
})[0];
},
+ closestWall : function closestWall(me){
+ return this.closestOf(me, this.allWalls);
+ },
+
willCollide : function willCollide(me, bullets, wiggle){
bullets = ( Y.isArray(bullets) ? bullets : [bullets] );
wiggle = wiggle || 0;
,
+/**
+ * A QuadTree which aids in pathing for AI.
+ * - QuadTree methods which took rect coords (x1,y1, x2,y2) will accept
+ * anything Rect-like (having properties x1,y1, x2,y2).
+ * - Pathing methods will account for the unit's size when calculating paths,
+ * intersections, blocking, and similar tasks.
+ */
Map =
exports['Map'] =
QuadTree.subclass('Map', {
return ( t <= ft && (dw <= w || dh <= h) );
},
+ canSee : function canSee(obj, ignore){
+ var blockers =
+ this.map.denseWalls
+ .apply('remove', [this.owner, obj].concat(ignore || []) )
+ .filter( this.intersects )
+ .sort( this.compare );
+ return !!blockers.length;
+ },
+
pathBlocked : function pathBlocked(obj, ignore){
- var walls, blockers;
- if (this.owner.isProjectile)
- walls = this.map.denseWalls;
- else
- walls = this.map.innerWalls; // FIXME: won't filter out concave intersections with the bounds
+ // var walls, blockers
+ // if (this.owner.isProjectile)
+ // walls = this.map.denseWalls;
+ // else
+ // walls = this.map.innerWalls; // FIXME: won't filter out concave intersections with the bounds
- blockers = walls
+ var blockers = this.map.innerWalls
.concat( this.game.units )
.apply('remove', [this.owner].concat(ignore || []) )
.filter( this.intersects )
, op = require('Y/op')
, vec = require('ezl/math/vec')
-, shape = require('ezl/shape')
+, Vec = vec.Vec
, Cooldown = require('ezl/loop').Cooldown
, CooldownGauge = require('ezl/widget').CooldownGauge
-, Vec = vec.Vec
-, manhattan = vec.manhattan
+, shape = require('ezl/shape')
, Rect = shape.Rect
, Circle = shape.Circle
, Thing = require('tanks/thing/thing').Thing
, Bullet = require('tanks/thing/bullet').Bullet
-, isBullet = Y.is(Bullet)
-, BULLET_MOVE_PER_FRAME = MS_PER_FRAME * Bullet.fn.stats.move*REF_SIZE/1000
, _X = 0, _Y = 1
,
this['act'] =
function act(elapsed, now){
- var ai = this.ai;
+ var ai = this.ai, map = this.game.map;
this.elapsed = elapsed;
this.now = now;
// Try to shoot down nearby bullets
if (ai.shootIncoming.ready && this.ableToShoot()) {
- var bs = this.willCollide( this.findNearLike(25, isBullet) );
+ var bs = map.willCollide(this, map.findNearBullets(this, 25) );
// console.log('['+TICKS+':'+this.id, this, '] Shoot down bullets?', bs.size() && bs);
if ( bs.size() ) {
ai.shootIncoming.activate(now);
- var b = this.closestOf(bs);
+ var b = map.closestOf(this, bs);
// console.log(' --> Incoming! Shoot it down!', b);
this.shoot(b.loc.x, b.loc.y);
return this;
// Dodge incoming bullet
if (ai.dodge.ready) {
- var bs = this.willCollide(this.findNearLike(71, isBullet), 5);
+ var bs = map.willCollide(this, map.findNearBullets(this, 71), 5);
// console.log('['+TICKS+':'+this.id, this, '] Dodge bullets?', bs.size() && bs);
if (bs.size()) {
ai.dodge.activate(now);
- var bullet = this.closestOf(bs);
+ var bullet = map.closestOf(this, bs);
this.moveAwayFrom(bullet);
return this;
}
// Try to blow up nearby tanks
if (ai.shootEnemy.ready && (this.stats.shots.val - this.nShots > 1)) {
- var t = this.findNearEnemies(71, true).shift();
+ var t = map.findNearEnemiesInSight(this, 71).shift();
// console.log('['+TICKS+':'+this.id, this, '] Shoot at enemies?', t);
if (t) {
ai.shootEnemy.activate(now);
this['continueMove'] =
function continueMove(){
if ( !this.currentMove || this.ai.path.ready ){
- var target = this.findNearEnemies(10000).shift();
+ var target = this.game.map.findNearEnemies(this, 10000).shift();
if (target)
this.calculatePath(target.loc);
else
};
+ this['moveAwayFrom'] =
+ function moveAwayFrom(agent){
+ var map = this.game.map
+ , mid = this.midpoint
+ , trj = agent.trajectory.tangent(mid)
+
+ , wall = map.closestWall(this)
+ , wmid = wall.midpoint
+
+ , lvl = this.game.level.bbox, w = lvl.width, h = lvl.height
+ , x = ((mid.x - wmid.x) > 0 ? w : 0)
+ , y = ((mid.y - wmid.y) > 0 ? h : 0)
+ , to = this.currentMove = trj.near(x,y);
+
+ this.forceCurrentMove = map.willCollide.bind(map, this, [agent], 5);
+ this.currentMoveLimit = this.now + 1000;
+
+ this.move(to.x, to.y);
+
+ // console.log(' --> Dodge', agent, 'away from', wall, 'to', to);
+ return to;
+ };
+
+
this['getTurretLoc'] =
function getTurretLoc(){
var WIGGLE = 2