Change targetting line to dashed

This commit is contained in:
Peter Stockings
2026-01-20 23:05:18 +11:00
parent 1a91aa5274
commit 327b6aa0eb
4 changed files with 89 additions and 13 deletions

View File

@@ -125,7 +125,10 @@ export const GAME_CONFIG = {
// Targeting
targetingLineColor: 0xff0000,
targetingLineWidth: 2,
targetingLineAlpha: 0.7
targetingLineAlpha: 0.7,
targetingLineDash: 6,
targetingLineGap: 4,
targetingLineShorten: 8
},
gameplay: {

View File

@@ -207,7 +207,7 @@ export class GameScene extends Phaser.Scene {
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
// Already targeting - execute shoot
if (this.targetingSystem.cursorPos) {
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
this.executeThrow();
}
return;
}
@@ -219,6 +219,8 @@ export class GameScene extends Phaser.Scene {
item.id,
player.pos,
this.world,
this.entityManager,
this.playerId,
this.dungeonRenderer.seenArray,
this.world.width,
{ x: tx, y: ty }
@@ -240,7 +242,7 @@ export class GameScene extends Phaser.Scene {
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
// Already targeting - execute throw
if (this.targetingSystem.cursorPos) {
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
this.executeThrow();
}
return;
}
@@ -251,6 +253,8 @@ export class GameScene extends Phaser.Scene {
item.id,
player.pos,
this.world,
this.entityManager,
this.playerId,
this.dungeonRenderer.seenArray,
this.world.width,
{ x: tx, y: ty }
@@ -323,7 +327,7 @@ export class GameScene extends Phaser.Scene {
// Only Left Click throws
if (p.button === 0) {
if (this.targetingSystem.cursorPos) {
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
this.executeThrow();
}
}
return;
@@ -615,7 +619,7 @@ export class GameScene extends Phaser.Scene {
private executeThrow(_targetX: number, _targetY: number) {
private executeThrow() {
const success = this.targetingSystem.executeThrow(
this.world,
this.playerId,

View File

@@ -28,7 +28,7 @@ export class EventBridge {
commitActionFn: (action: any) => void,
emitUIUpdateFn: () => void,
restartGameFn: () => void,
executeThrowFn: (x: number, y: number) => void
executeThrowFn: () => void
): void {
// Menu state listeners (from UI)
this.scene.events.on("menu-toggled", (isOpen: boolean) => {
@@ -115,7 +115,7 @@ export class EventBridge {
if (targetingSystem.isActive && targetingSystem.itemId === item.id) {
// Already targeting - execute throw
if (targetingSystem.cursorPos) {
executeThrowFn(targetingSystem.cursorPos.x, targetingSystem.cursorPos.y);
executeThrowFn();
}
return;
}
@@ -124,6 +124,8 @@ export class EventBridge {
item.id,
player.pos,
(this.scene as any).world,
(this.scene as any).entityManager,
(this.scene as any).playerId,
dungeonRenderer.seenArray,
(this.scene as any).world.width
);

View File

@@ -16,6 +16,11 @@ export class TargetingSystem {
private active: boolean = false;
private targetingItemId: string | null = null;
private cursor: Vec2 | null = null;
// Context for predictive visual
private world: World | null = null;
private entityManager: EntityManager | null = null;
private playerId: EntityId | null = null;
constructor(scene: Phaser.Scene) {
this.graphics = scene.add.graphics();
@@ -35,11 +40,16 @@ export class TargetingSystem {
itemId: string,
playerPos: Vec2,
world: World,
entityManager: EntityManager,
playerId: EntityId,
seenArray: Uint8Array,
worldWidth: number,
initialTargetPos?: Vec2
): void {
this.targetingItemId = itemId;
this.world = world;
this.entityManager = entityManager;
this.playerId = playerId;
this.active = true;
// Auto-target closest visible enemy
@@ -122,6 +132,9 @@ export class TargetingSystem {
this.active = false;
this.targetingItemId = null;
this.cursor = null;
this.world = null;
this.entityManager = null;
this.playerId = null;
this.graphics.clear();
this.crosshairSprite.setVisible(false);
console.log("Targeting cancelled");
@@ -164,18 +177,72 @@ export class TargetingSystem {
const startX = playerPos.x * TILE_SIZE + TILE_SIZE / 2;
const startY = playerPos.y * TILE_SIZE + TILE_SIZE / 2;
const endX = this.cursor.x * TILE_SIZE + TILE_SIZE / 2;
const endY = this.cursor.y * TILE_SIZE + TILE_SIZE / 2;
const aimEndX = this.cursor.x * TILE_SIZE + TILE_SIZE / 2;
const aimEndY = this.cursor.y * TILE_SIZE + TILE_SIZE / 2;
// Update crosshair position
this.crosshairSprite.setPosition(endX, endY);
// Predictive impact point
let finalEndX = aimEndX;
let finalEndY = aimEndY;
// Draw Line
if (this.world && this.entityManager && this.playerId !== null) {
const result = traceProjectile(this.world, playerPos, this.cursor, this.entityManager, this.playerId);
const bPos = result.blockedPos;
finalEndX = bPos.x * TILE_SIZE + TILE_SIZE / 2;
finalEndY = bPos.y * TILE_SIZE + TILE_SIZE / 2;
}
// Update crosshair position to ACTUAL impact point
this.crosshairSprite.setPosition(finalEndX, finalEndY);
// Draw Main Line (dashed to impact)
this.graphics.lineStyle(
GAME_CONFIG.ui.targetingLineWidth,
GAME_CONFIG.ui.targetingLineColor,
GAME_CONFIG.ui.targetingLineAlpha
);
this.graphics.lineBetween(startX, startY, endX, endY);
const dx = finalEndX - startX;
const dy = finalEndY - startY;
const dist = Math.sqrt(dx * dx + dy * dy);
const shortenAmt = GAME_CONFIG.ui.targetingLineShorten;
if (dist > shortenAmt) {
const ratio = (dist - shortenAmt) / dist;
const shortenedEndX = startX + dx * ratio;
const shortenedEndY = startY + dy * ratio;
this.drawDashedLine(startX, startY, shortenedEndX, shortenedEndY);
}
}
/**
* Manual dashed line implementation for Phaser Graphics
*/
private drawDashedLine(x1: number, y1: number, x2: number, y2: number): void {
const dashLen = GAME_CONFIG.ui.targetingLineDash;
const gapLen = GAME_CONFIG.ui.targetingLineGap;
const dx = x2 - x1;
const dy = y2 - y1;
const distance = Math.sqrt(dx * dx + dy * dy);
if (distance === 0) return;
const angle = Math.atan2(dy, dx);
const cos = Math.cos(angle);
const sin = Math.sin(angle);
let currentDist = 0;
while (currentDist < distance) {
const len = Math.min(dashLen, distance - currentDist);
const sx = x1 + currentDist * cos;
const sy = y1 + currentDist * sin;
const ex = sx + len * cos;
const ey = sy + len * sin;
this.graphics.lineBetween(sx, sy, ex, ey);
currentDist += dashLen + gapLen;
}
}
}