1
0
Fork 0

Fixed move exclusion radius

This commit is contained in:
Michaël Lemaire 2017-05-29 20:12:57 +02:00
parent 4105319fff
commit 6d01734238
10 changed files with 76 additions and 35 deletions

1
TODO
View file

@ -22,6 +22,7 @@
* Arena: add auto-move to attack
* Arena: fix effects originating from real ship location instead of current sprite (when AI fires then moves)
* Arena: add engine trail
* Arena: draw move exclusion circles (only on clonflict or in tactical mode ?)
* Fix capacity limit effect not refreshing associated value (for example, on "limit power capacity to 3", potential "power" value change is not broadcast)
* Actions: show power usage/recovery in power bar, on action hover
* Actions: fix targetting not resetting when using keyboard shortcuts

@ -1 +1 @@
Subproject commit 9957f153b1da5f1d30beebd670cc0a952d541304
Subproject commit df24442f844494bf0f799fcf5bdcf5bcad36501e

View file

@ -411,6 +411,13 @@ module TS.SpaceTac {
return distance <= radius;
}
/**
* Get the distance to another ship
*/
getDistanceTo(other: Ship): number {
return Target.newFromShip(this).getDistanceTo(Target.newFromShip(other));
}
/**
* Rotate the ship in place to face a direction
*/

View file

@ -2,17 +2,31 @@ module TS.SpaceTac {
// Find the nearest intersection between a line and a circle
// Circle is supposed to be centered at (0,0)
// Nearest intersection to (x1,y1) is returned
function intersectLineCircle(x1: number, y1: number, x2: number, y2: number, r: number): [number, number] {
// See http://mathworld.wolfram.com/Circle-LineIntersection.html
var dx = x2 - x1;
var dy = y2 - y1;
var dr = Math.sqrt(dx * dx + dy * dy);
var d = x1 * y2 - x2 * y1;
var delta = r * r * dr * dr - d * d;
function intersectLineCircle(x1: number, y1: number, x2: number, y2: number, r: number): [number, number] | null {
let a = y2 - y1;
let b = -(x2 - x1);
let c = -(a * x1 + b * y1);
let x0 = -a * c / (a * a + b * b), y0 = -b * c / (a * a + b * b);
let EPS = 10e-8;
if (c * c > r * r * (a * a + b * b) + EPS) {
return null;
} else if (Math.abs(c * c - r * r * (a * a + b * b)) < EPS) {
return [x0, y0];
} else {
let d = r * r - c * c / (a * a + b * b);
let mult = Math.sqrt(d / (a * a + b * b));
let ax, ay, bx, by;
ax = x0 + b * mult;
bx = x0 - b * mult;
ay = y0 - a * mult;
by = y0 + a * mult;
var rx = (d * dy - dx * Math.sqrt(delta)) / (dr * dr);
var ry = (-d * dx - dy * Math.sqrt(delta)) / (dr * dr);
return [rx, ry];
let candidates: [number, number][] = [
[x0 + b * mult, y0 - a * mult],
[x0 - b * mult, y0 + a * mult]
]
return minBy(candidates, ([x, y]) => Math.sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)));
}
}
// Target for a capability
@ -99,9 +113,12 @@ module TS.SpaceTac {
return this;
} else {
// Find nearest intersection with circle
var res = intersectLineCircle(sourcex - circlex, sourcey - circley,
this.x - circlex, this.y - circley, radius);
return Target.newFromLocation(res[0] + circlex, res[1] + circley);
var res = intersectLineCircle(sourcex - circlex, sourcey - circley, dx, dy, radius);
if (res) {
return Target.newFromLocation(res[0] + circlex, res[1] + circley);
} else {
return this;
}
}
}
}

View file

@ -103,5 +103,22 @@ module TS.SpaceTac {
result = action.checkLocationTarget(ship, Target.newFromLocation(12, 5));
expect(result).toEqual(Target.newFromLocation(12, 5));
});
it("move exclusion radius is applied correctly over two ships", function () {
var battle = TestTools.createBattle(1, 2);
var ship = battle.fleets[0].ships[0];
var enemy1 = battle.fleets[1].ships[0];
var enemy2 = battle.fleets[1].ships[1];
TestTools.setShipAP(ship, 100);
enemy1.setArenaPosition(0, 80);
enemy2.setArenaPosition(0, 100);
var action = new MoveAction(new Equipment());
action.distance_per_power = 1000;
action.safety_distance = 15;
var result = action.checkLocationTarget(ship, Target.newFromLocation(0, 110));
expect(result).toEqual(Target.newFromLocation(0, 65));
});
});
}

View file

@ -2,19 +2,19 @@ module TS.SpaceTac {
// Action to move to a given location
export class MoveAction extends BaseAction {
// Distance allowed for each power point
distance_per_power: number;
distance_per_power: number
// Safety distance from other ships
safety_distance: number;
// Safety distance from other ships and arena borders
safety_distance: number
// Equipment cannot be null (engine)
equipment: Equipment;
equipment: Equipment
constructor(equipment: Equipment, distance_per_power = 0) {
super("move", "Move", true, equipment);
this.distance_per_power = distance_per_power;
this.safety_distance = 50;
this.safety_distance = 120;
}
checkCannotBeApplied(ship: Ship, remaining_ap: number | null = null): string | null {
@ -62,11 +62,10 @@ module TS.SpaceTac {
// Apply collision prevention
let battle = ship.getBattle();
if (battle) {
battle.play_order.forEach((iship: Ship) => {
if (iship !== ship) {
target = target.moveOutOfCircle(iship.arena_x, iship.arena_y, this.safety_distance,
ship.arena_x, ship.arena_y);
}
let ships = imaterialize(ifilter(battle.iships(true), s => s !== ship));
ships = ships.sort((a, b) => cmp(a.getDistanceTo(ship), b.getDistanceTo(ship), true));
ships.forEach(s => {
target = target.moveOutOfCircle(s.arena_x, s.arena_y, this.safety_distance, ship.arena_x, ship.arena_y);
});
}

View file

@ -5,26 +5,26 @@ module TS.SpaceTac.Equipments {
let equipment = template.generate(1);
expect(equipment.requirements).toEqual({ "skill_human": 1 });
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 300, 10, 100, [new ValueEffect("hull", 5)]));
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 300, 10, 150, [new ValueEffect("hull", 5)]));
equipment = template.generate(2);
expect(equipment.requirements).toEqual({ "skill_human": 2 });
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 310, 11, 110, [new ValueEffect("hull", 6)]));
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 310, 11, 155, [new ValueEffect("hull", 6)]));
equipment = template.generate(3);
expect(equipment.requirements).toEqual({ "skill_human": 3 });
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 320, 12, 120, [new ValueEffect("hull", 7)]));
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 320, 12, 160, [new ValueEffect("hull", 7)]));
equipment = template.generate(10);
expect(equipment.requirements).toEqual({ "skill_human": 10 });
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 390, 19, 190, [new ValueEffect("hull", 14)]));
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 390, 19, 195, [new ValueEffect("hull", 14)]));
});
it("generates a drone that may repair ships hull", function () {
let template = new RepairDrone();
let equipment = template.generate(1);
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 300, 10, 100, [new ValueEffect("hull", 5)]));
expect(equipment.action).toEqual(new DeployDroneAction(equipment, 4, 300, 10, 150, [new ValueEffect("hull", 5)]));
let battle = new Battle();
let ship = battle.fleets[0].addShip();

View file

@ -10,7 +10,7 @@ module TS.SpaceTac.Equipments {
this.setSkillsRequirements({ "skill_human": 1 });
this.setCooldown(irepeat(1), istep(3, irepeat(0.2)));
this.addDroneAction(irepeat(4), istep(300, irepeat(10)), istep(10, irepeat(1)), istep(100, irepeat(10)), [
this.addDroneAction(irepeat(4), istep(300, irepeat(10)), istep(10, irepeat(1)), istep(150, irepeat(5)), [
new EffectTemplate(new ValueEffect("hull"), { "value": istep(5) })
]);
}

View file

@ -6,22 +6,22 @@ module TS.SpaceTac.Equipments {
let equipment = template.generate(1);
expect(equipment.requirements).toEqual({ "skill_gravity": 1 });
expect(equipment.cooldown).toEqual(new Cooldown(3, 3));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 100, 0, [new ValueTransferEffect("shield", -20)]));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 150, 0, [new ValueTransferEffect("shield", -20)]));
equipment = template.generate(2);
expect(equipment.requirements).toEqual({ "skill_gravity": 2 });
expect(equipment.cooldown).toEqual(new Cooldown(3, 3));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 110, 0, [new ValueTransferEffect("shield", -22)]));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 160, 0, [new ValueTransferEffect("shield", -22)]));
equipment = template.generate(3);
expect(equipment.requirements).toEqual({ "skill_gravity": 3 });
expect(equipment.cooldown).toEqual(new Cooldown(3, 3));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 120, 0, [new ValueTransferEffect("shield", -24)]));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 170, 0, [new ValueTransferEffect("shield", -24)]));
equipment = template.generate(10);
expect(equipment.requirements).toEqual({ "skill_gravity": 10 });
expect(equipment.cooldown).toEqual(new Cooldown(3, 3));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 190, 0, [new ValueTransferEffect("shield", -38)]));
expect(equipment.action).toEqual(new FireWeaponAction(equipment, 3, 240, 0, [new ValueTransferEffect("shield", -38)]));
})
})
}

View file

@ -7,7 +7,7 @@ module TS.SpaceTac.Equipments {
this.setSkillsRequirements({ "skill_gravity": 1 });
this.setCooldown(irepeat(3), irepeat(3));
this.addFireAction(irepeat(3), istep(100, irepeat(10)), 0, [
this.addFireAction(irepeat(3), istep(150, irepeat(10)), 0, [
new EffectTemplate(new ValueTransferEffect("shield"), { "amount": istep(-20, irepeat(-2)) })
]);
}