1
0
Fork 0

Move actions now uses integer AP, displayed on targetting line

This commit is contained in:
Michaël Lemaire 2017-01-19 19:33:56 +01:00
parent 6ee0352cc1
commit 4ba37774aa
14 changed files with 115 additions and 7 deletions

4
TODO
View file

@ -1,11 +1,13 @@
* Floor movement power usage, and show it on the displayed line
* Add auto-move to attack
* Re-style cancel button and allow to cancel by clicking the action again
* Fix energy depleter effect not fading after one turn
* Add equipment info (or summary) in ship tooltip
* Handle effects overflowing ship tooltip when too numerous
* Proper arena scaling (not graphical, only space coordinates)
* Mobile: think UI layout so that fingers do not block the view (right and left handed)
* Mobile: display tooltips larger and on the side of screen where the finger is not
* Mobile: targetting in two times, using a draggable target indicator
* AI: apply safety distances to move actions
* Add a defeat screen (game over for now)
* Add a victory screen, with loot display
* Add retreat from battle

Binary file not shown.

Before

Width:  |  Height:  |  Size: 536 B

After

Width:  |  Height:  |  Size: 1,020 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 522 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

After

Width:  |  Height:  |  Size: 401 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 523 B

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,004 B

View file

@ -13,6 +13,8 @@ module SpaceTac.Game {
engine.ap_usage = 2;
var action = new MoveAction(engine);
expect(action.getDistanceByActionPoint(ship)).toBe(0.5);
var result = action.checkTarget(battle, ship, Target.newFromLocation(0, 2));
expect(result).toEqual(Target.newFromLocation(0, 2));

View file

@ -29,16 +29,23 @@ module SpaceTac.Game {
}
var distance = Target.newFromShip(ship).getDistanceTo(target);
return this.equipment.ap_usage * distance / this.equipment.distance;
return Math.ceil(this.equipment.ap_usage * distance / this.equipment.distance);
}
getRangeRadius(ship: Ship): number {
return ship.ap_current.current * this.equipment.distance / this.equipment.ap_usage;
}
/**
* Get the distance that may be traveled with 1 action point
*/
getDistanceByActionPoint(ship: Ship): number {
return this.equipment.distance / this.equipment.ap_usage;
}
checkLocationTarget(battle: Battle, ship: Ship, target: Target): Target {
// Apply maximal distance
var max_distance = this.equipment.distance * ship.ap_current.current / this.equipment.ap_usage;
var max_distance = this.getRangeRadius(ship);
target = target.constraintInRange(ship.arena_x, ship.arena_y, max_distance);
// Apply collision prevention

View file

@ -7,8 +7,8 @@ module SpaceTac.Game.Equipments {
super(SlotType.Engine, "Conventional Engine");
this.min_level = new IntegerRange(1, 1);
this.distance = new Range(300, 300);
this.ap_usage = new IntegerRange(3);
this.distance = new Range(100, 100);
this.ap_usage = new IntegerRange(1);
this.addPermanentAttributeMaxEffect(AttributeCode.Initiative, 1);
}

View file

@ -30,6 +30,7 @@ module SpaceTac.View {
this.loadImage("battle/shiplist-shield-full.png");
this.loadImage("battle/background.jpg");
this.loadImage("battle/arena/background.png");
this.loadImage("battle/arena/ap-indicator.png");
this.loadImage("battle/actionbar.png");
this.loadImage("battle/actionbar-cancel.png");
this.loadImage("battle/action-inactive.png");

View file

@ -52,7 +52,7 @@ module SpaceTac.View {
this.addChild(this.layer_icon);
let show_info = () => {
if (this.bar.ship)  {
if (this.bar.ship) {
this.bar.tooltip.setAction(this);
this.battleview.arena.range_hint.setSecondary(this.ship, this.action);
}
@ -99,6 +99,9 @@ module SpaceTac.View {
this.targetting.setSource(this.battleview.arena.findShipSprite(this.ship));
this.targetting.targetSelected.add(this.processSelection, this);
this.targetting.targetHovered.add(this.processHover, this);
if (this.action instanceof Game.MoveAction) {
this.targetting.setApIndicatorsInterval(this.action.getDistanceByActionPoint(this.ship));
}
} else {
// No target needed, apply action immediately
this.processSelection(null);

View file

@ -45,7 +45,11 @@ module SpaceTac.View {
this.position.set(action.x, action.y + action.height + 44);
this.main_title.setText(action.action.equipment ? action.action.equipment.name : action.action.name);
this.sub_title.setText(action.action.equipment ? action.action.name : "");
this.cost.setText(action.action.equipment ? `Cost: ${action.action.equipment.ap_usage} power` : "");
let cost = action.action.equipment ? `Cost: ${action.action.equipment.ap_usage} power` : "";
if (action.action instanceof Game.MoveAction) {
cost += ` per ${action.action.equipment.distance}km`;
}
this.cost.setText(cost);
this.description.setText(action.action.equipment ? action.action.equipment.getActionDescription() : "");
Animation.fadeIn(this.game, this, 200, 0.9);

View file

@ -20,5 +20,49 @@ module SpaceTac.View.Specs {
expect(hovered).toEqual([Game.Target.newFromLocation(1, 2)]);
expect(selected).toEqual([Game.Target.newFromLocation(1, 2)]);
});
inbattleview_it("displays action point indicators", (battleview) => {
let source = new Phaser.Group(battleview.game, battleview.arena);
source.position.set(0, 0);
let init_children = battleview.arena.children.length;
let targetting = new Targetting(battleview);
targetting.setSource(source);
targetting.setTargetSpace(200, 100);
targetting.update();
targetting.updateApIndicators();
expect(targetting.ap_indicators.length).toBe(0);
expect(battleview.arena.children.length).toBe(init_children + 3);
targetting.setApIndicatorsInterval(Math.sqrt(5) * 20);
expect(targetting.ap_indicators.length).toBe(5);
expect(battleview.arena.children.length).toBe(init_children + 3 + 5);
expect(targetting.ap_indicators[0].position.x).toBe(0);
expect(targetting.ap_indicators[0].position.y).toBe(0);
expect(targetting.ap_indicators[1].position.x).toBeCloseTo(40);
expect(targetting.ap_indicators[1].position.y).toBeCloseTo(20);
expect(targetting.ap_indicators[2].position.x).toBeCloseTo(80);
expect(targetting.ap_indicators[2].position.y).toBeCloseTo(40);
expect(targetting.ap_indicators[3].position.x).toBeCloseTo(120);
expect(targetting.ap_indicators[3].position.y).toBeCloseTo(60);
expect(targetting.ap_indicators[4].position.x).toBeCloseTo(160);
expect(targetting.ap_indicators[4].position.y).toBeCloseTo(80);
targetting.setApIndicatorsInterval(1000);
expect(targetting.ap_indicators.length).toBe(1);
expect(battleview.arena.children.length).toBe(init_children + 3 + 1);
targetting.setApIndicatorsInterval(1);
expect(targetting.ap_indicators.length).toBe(224);
expect(battleview.arena.children.length).toBe(init_children + 3 + 224);
targetting.destroy();
expect(battleview.arena.children.length).toBe(init_children);
});
});
}

View file

@ -20,6 +20,10 @@ module SpaceTac.View {
// Signal to receive targetting events
targetSelected: Phaser.Signal;
// AP usage display
ap_interval: number = 0;
ap_indicators: Phaser.Image[] = [];
// Access to the parent battle view
private battleview: BattleView;
@ -63,6 +67,13 @@ module SpaceTac.View {
if (this.blast) {
this.blast.destroy();
}
this.ap_indicators.forEach(indicator => indicator.destroy());
}
// Set AP indicators to display at fixed interval along the line
setApIndicatorsInterval(interval: number) {
this.ap_interval = interval;
this.updateApIndicators();
}
// Update visual effects for current targetting
@ -98,6 +109,40 @@ module SpaceTac.View {
} else {
this.blast.visible = false;
}
this.updateApIndicators();
}
}
// Update the AP indicators display
updateApIndicators() {
// Get indicator count
let count = 0;
let distance = 0;
if (this.line_corrected.visible && this.ap_interval > 0) {
distance = this.target_corrected.getDistanceTo(Game.Target.newFromLocation(this.source.x, this.source.y)) - 0.00001;
count = Math.ceil(distance / this.ap_interval);
}
// Adjust object count to match
while (this.ap_indicators.length < count) {
let indicator = new Phaser.Image(this.battleview.game, 0, 0, "battle-arena-ap-indicator");
indicator.anchor.set(0.5, 0.5);
this.battleview.arena.addChild(indicator);
this.ap_indicators.push(indicator);
}
while (this.ap_indicators.length > count) {
this.ap_indicators[this.ap_indicators.length - 1].destroy();
this.ap_indicators.pop();
}
// Spread indicators
if (count > 0 && distance > 0) {
let dx = this.ap_interval * (this.target_corrected.x - this.source.x) / distance;
let dy = this.ap_interval * (this.target_corrected.y - this.source.y) / distance;
this.ap_indicators.forEach((indicator, index) => {
indicator.position.set(this.source.x + dx * index, this.source.y + dy * index);
});
}
}