diff --git a/TODO b/TODO index 4473bab..bfdbd47 100644 --- a/TODO +++ b/TODO @@ -22,14 +22,13 @@ * 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 ?) +* Arena: draw move exclusion circles and border (in move targetting only) * Remove "initial events" injection * 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 * Suspend AI operation when the game is paused (window not focused) * Add actions with cost dependent of distance (like current move actions) -* Keep move and drone actions out of arena borders * Find incentives to move from starting position * Outcome: disable the loot button if there is no loot * Ensure that tweens and particle emitters get destroyed once animation is done (or view changes) diff --git a/src/core/Target.spec.ts b/src/core/Target.spec.ts index 5104ae9..a025f30 100644 --- a/src/core/Target.spec.ts +++ b/src/core/Target.spec.ts @@ -52,5 +52,11 @@ module TS.SpaceTac.Specs { expect(target.moveOutOfCircle(8, 5, 6, 0, 5)).toEqual(Target.newFromLocation(2, 5)); expect(target.moveOutOfCircle(2, 5, 6, 10, 5)).toEqual(Target.newFromLocation(8, 5)); }); + + it("keeps a target inside a rectangle", () => { + var target = Target.newFromLocation(5, 5); + expect(target.keepInsideRectangle(0, 0, 10, 10, 0, 0)).toBe(target); + expect(target.keepInsideRectangle(8, 0, 13, 10, 10, 5)).toEqual(Target.newFromLocation(8, 5)); + }); }); } diff --git a/src/core/Target.ts b/src/core/Target.ts index 5789a3e..8d68406 100644 --- a/src/core/Target.ts +++ b/src/core/Target.ts @@ -121,5 +121,36 @@ module TS.SpaceTac { } } } + + /** + * Keep the target inside a rectangle + * + * May return the original target if it's already inside the rectangle + */ + keepInsideRectangle(xmin: number, ymin: number, xmax: number, ymax: number, sourcex: number, sourcey: number): Target { + let length = this.getDistanceTo({ x: sourcex, y: sourcey }); + let result: Target = this; + if (result.x < xmin) { + let factor = (xmin - sourcex) / (result.x - sourcex); + length *= factor; + result = result.constraintInRange(sourcex, sourcey, length); + } + if (result.x > xmax) { + let factor = (xmax - sourcex) / (result.x - sourcex); + length *= factor; + result = result.constraintInRange(sourcex, sourcey, length); + } + if (result.y < ymin) { + let factor = (ymin - sourcey) / (result.y - sourcey); + length *= factor; + result = result.constraintInRange(sourcex, sourcey, length); + } + if (result.y > ymax) { + let factor = (ymax - sourcey) / (result.y - sourcey); + length *= factor; + result = result.constraintInRange(sourcex, sourcey, length); + } + return result; + } } } diff --git a/src/core/actions/MoveAction.ts b/src/core/actions/MoveAction.ts index e6f14d5..cd96a51 100644 --- a/src/core/actions/MoveAction.ts +++ b/src/core/actions/MoveAction.ts @@ -59,9 +59,15 @@ module TS.SpaceTac { var max_distance = this.getRangeRadius(ship); target = target.constraintInRange(ship.arena_x, ship.arena_y, max_distance); - // Apply collision prevention let battle = ship.getBattle(); if (battle) { + // Keep out of arena borders + let border = this.safety_distance * 0.5; + target = target.keepInsideRectangle(border, border, + battle.width - border, battle.height - border, + ship.arena_x, ship.arena_y); + + // Apply collision prevention 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 => {