Change targetting line to dashed
This commit is contained in:
@@ -125,7 +125,10 @@ export const GAME_CONFIG = {
|
|||||||
// Targeting
|
// Targeting
|
||||||
targetingLineColor: 0xff0000,
|
targetingLineColor: 0xff0000,
|
||||||
targetingLineWidth: 2,
|
targetingLineWidth: 2,
|
||||||
targetingLineAlpha: 0.7
|
targetingLineAlpha: 0.7,
|
||||||
|
targetingLineDash: 6,
|
||||||
|
targetingLineGap: 4,
|
||||||
|
targetingLineShorten: 8
|
||||||
},
|
},
|
||||||
|
|
||||||
gameplay: {
|
gameplay: {
|
||||||
|
|||||||
@@ -207,7 +207,7 @@ export class GameScene extends Phaser.Scene {
|
|||||||
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
|
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
|
||||||
// Already targeting - execute shoot
|
// Already targeting - execute shoot
|
||||||
if (this.targetingSystem.cursorPos) {
|
if (this.targetingSystem.cursorPos) {
|
||||||
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
|
this.executeThrow();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -219,6 +219,8 @@ export class GameScene extends Phaser.Scene {
|
|||||||
item.id,
|
item.id,
|
||||||
player.pos,
|
player.pos,
|
||||||
this.world,
|
this.world,
|
||||||
|
this.entityManager,
|
||||||
|
this.playerId,
|
||||||
this.dungeonRenderer.seenArray,
|
this.dungeonRenderer.seenArray,
|
||||||
this.world.width,
|
this.world.width,
|
||||||
{ x: tx, y: ty }
|
{ x: tx, y: ty }
|
||||||
@@ -240,7 +242,7 @@ export class GameScene extends Phaser.Scene {
|
|||||||
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
|
if (this.targetingSystem.isActive && this.targetingSystem.itemId === item.id) {
|
||||||
// Already targeting - execute throw
|
// Already targeting - execute throw
|
||||||
if (this.targetingSystem.cursorPos) {
|
if (this.targetingSystem.cursorPos) {
|
||||||
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
|
this.executeThrow();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -251,6 +253,8 @@ export class GameScene extends Phaser.Scene {
|
|||||||
item.id,
|
item.id,
|
||||||
player.pos,
|
player.pos,
|
||||||
this.world,
|
this.world,
|
||||||
|
this.entityManager,
|
||||||
|
this.playerId,
|
||||||
this.dungeonRenderer.seenArray,
|
this.dungeonRenderer.seenArray,
|
||||||
this.world.width,
|
this.world.width,
|
||||||
{ x: tx, y: ty }
|
{ x: tx, y: ty }
|
||||||
@@ -323,7 +327,7 @@ export class GameScene extends Phaser.Scene {
|
|||||||
// Only Left Click throws
|
// Only Left Click throws
|
||||||
if (p.button === 0) {
|
if (p.button === 0) {
|
||||||
if (this.targetingSystem.cursorPos) {
|
if (this.targetingSystem.cursorPos) {
|
||||||
this.executeThrow(this.targetingSystem.cursorPos.x, this.targetingSystem.cursorPos.y);
|
this.executeThrow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -615,7 +619,7 @@ export class GameScene extends Phaser.Scene {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
private executeThrow(_targetX: number, _targetY: number) {
|
private executeThrow() {
|
||||||
const success = this.targetingSystem.executeThrow(
|
const success = this.targetingSystem.executeThrow(
|
||||||
this.world,
|
this.world,
|
||||||
this.playerId,
|
this.playerId,
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ export class EventBridge {
|
|||||||
commitActionFn: (action: any) => void,
|
commitActionFn: (action: any) => void,
|
||||||
emitUIUpdateFn: () => void,
|
emitUIUpdateFn: () => void,
|
||||||
restartGameFn: () => void,
|
restartGameFn: () => void,
|
||||||
executeThrowFn: (x: number, y: number) => void
|
executeThrowFn: () => void
|
||||||
): void {
|
): void {
|
||||||
// Menu state listeners (from UI)
|
// Menu state listeners (from UI)
|
||||||
this.scene.events.on("menu-toggled", (isOpen: boolean) => {
|
this.scene.events.on("menu-toggled", (isOpen: boolean) => {
|
||||||
@@ -115,7 +115,7 @@ export class EventBridge {
|
|||||||
if (targetingSystem.isActive && targetingSystem.itemId === item.id) {
|
if (targetingSystem.isActive && targetingSystem.itemId === item.id) {
|
||||||
// Already targeting - execute throw
|
// Already targeting - execute throw
|
||||||
if (targetingSystem.cursorPos) {
|
if (targetingSystem.cursorPos) {
|
||||||
executeThrowFn(targetingSystem.cursorPos.x, targetingSystem.cursorPos.y);
|
executeThrowFn();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -124,6 +124,8 @@ export class EventBridge {
|
|||||||
item.id,
|
item.id,
|
||||||
player.pos,
|
player.pos,
|
||||||
(this.scene as any).world,
|
(this.scene as any).world,
|
||||||
|
(this.scene as any).entityManager,
|
||||||
|
(this.scene as any).playerId,
|
||||||
dungeonRenderer.seenArray,
|
dungeonRenderer.seenArray,
|
||||||
(this.scene as any).world.width
|
(this.scene as any).world.width
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ export class TargetingSystem {
|
|||||||
private targetingItemId: string | null = null;
|
private targetingItemId: string | null = null;
|
||||||
private cursor: Vec2 | 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) {
|
constructor(scene: Phaser.Scene) {
|
||||||
this.graphics = scene.add.graphics();
|
this.graphics = scene.add.graphics();
|
||||||
this.graphics.setDepth(2000); // High depth to draw over world
|
this.graphics.setDepth(2000); // High depth to draw over world
|
||||||
@@ -35,11 +40,16 @@ export class TargetingSystem {
|
|||||||
itemId: string,
|
itemId: string,
|
||||||
playerPos: Vec2,
|
playerPos: Vec2,
|
||||||
world: World,
|
world: World,
|
||||||
|
entityManager: EntityManager,
|
||||||
|
playerId: EntityId,
|
||||||
seenArray: Uint8Array,
|
seenArray: Uint8Array,
|
||||||
worldWidth: number,
|
worldWidth: number,
|
||||||
initialTargetPos?: Vec2
|
initialTargetPos?: Vec2
|
||||||
): void {
|
): void {
|
||||||
this.targetingItemId = itemId;
|
this.targetingItemId = itemId;
|
||||||
|
this.world = world;
|
||||||
|
this.entityManager = entityManager;
|
||||||
|
this.playerId = playerId;
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
|
||||||
// Auto-target closest visible enemy
|
// Auto-target closest visible enemy
|
||||||
@@ -122,6 +132,9 @@ export class TargetingSystem {
|
|||||||
this.active = false;
|
this.active = false;
|
||||||
this.targetingItemId = null;
|
this.targetingItemId = null;
|
||||||
this.cursor = null;
|
this.cursor = null;
|
||||||
|
this.world = null;
|
||||||
|
this.entityManager = null;
|
||||||
|
this.playerId = null;
|
||||||
this.graphics.clear();
|
this.graphics.clear();
|
||||||
this.crosshairSprite.setVisible(false);
|
this.crosshairSprite.setVisible(false);
|
||||||
console.log("Targeting cancelled");
|
console.log("Targeting cancelled");
|
||||||
@@ -164,18 +177,72 @@ export class TargetingSystem {
|
|||||||
const startX = playerPos.x * TILE_SIZE + TILE_SIZE / 2;
|
const startX = playerPos.x * TILE_SIZE + TILE_SIZE / 2;
|
||||||
const startY = playerPos.y * 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 aimEndX = this.cursor.x * TILE_SIZE + TILE_SIZE / 2;
|
||||||
const endY = this.cursor.y * TILE_SIZE + TILE_SIZE / 2;
|
const aimEndY = this.cursor.y * TILE_SIZE + TILE_SIZE / 2;
|
||||||
|
|
||||||
// Update crosshair position
|
// Predictive impact point
|
||||||
this.crosshairSprite.setPosition(endX, endY);
|
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(
|
this.graphics.lineStyle(
|
||||||
GAME_CONFIG.ui.targetingLineWidth,
|
GAME_CONFIG.ui.targetingLineWidth,
|
||||||
GAME_CONFIG.ui.targetingLineColor,
|
GAME_CONFIG.ui.targetingLineColor,
|
||||||
GAME_CONFIG.ui.targetingLineAlpha
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user