require('TemplateLoader'); class PlayerNavigationHud { constructor() { this.templateLoader = new TemplateLoader(); this.containerId = "navigation-container"; this.systemContext = null; this.mousePosition = { x: 0, y: 0 }; this.lastSector = { x: 3, y: 1 }; this.currentSector = { x: 3, y: 1 }; this.targetSector = { x: 3, y: 1 }; this.invalidSectors = []; this.gridSize = 32; this.halfGridSize = 16; this.travelEndTime = 0; this.travelDuration = 0; } async attach(parent) { let template = await this.templateLoader.get('navigation'); let container = document.getElementById(this.containerId); container.innerHTML = template; this.systemCanvas = document.getElementById("navigation--system"); this.impulseButton = document.getElementById("navigation--impulse"); this.impulseButton.addEventListener('click', (event) => this.startShipTravel(event)); this.starchartCanvas = document.getElementById("navigation--starchart"); this.jumpButton = document.getElementById("navigation--jump"); this.systemCanvas.addEventListener('mousemove', (event) => this.handleMouseMove(event)); this.systemCanvas.addEventListener('click', (event) => this.handleMouseClick(event)); this.handleResize(); this.buildSectorData(); this.impulseButton.style.visibility = "hidden"; this.hide(); } buildSectorData() { this.invalidSectors = []; for (let x = 0; x <= Math.floor(this.systemCanvas.width / this.gridSize); x++) { for (let y = 0; y <= Math.floor(this.systemCanvas.height / this.gridSize); y++) { this.invalidSectors.push({ x: x, y: y }); } } let items = game.sector.getItems(); for (let i = 0; i < items.length; i++) { let itemCoords = items[i].getCoordinates(); this.invalidSectors.splice(this.invalidSectors.findIndex((sector) => { return sector.x == itemCoords.x && sector.y == itemCoords.y; }), 1); } this.impulseButton.style.visibility = "hidden"; } draw() { let currentTime = new Date().getTime(); if (this.travelEndTime > currentTime) { let distanceTraveled = 1 - ((this.travelEndTime - currentTime) / this.travelDuration); let xDelta = this.targetSector.x - this.lastSector.x; let yDelta = this.targetSector.y - this.lastSector.y; this.currentSector.x = this.lastSector.x + (xDelta * distanceTraveled); this.currentSector.y = this.lastSector.y + (yDelta * distanceTraveled); } if (this.systemCanvas) { this.systemContext.clearRect(0, 0, this.systemCanvas.width, this.systemCanvas.height); this.systemContext.save(); this.systemContext.translate(0.5, 0.5); this.systemDraw(this.systemContext); this.drawMovementCursor(this.systemContext); this.systemContext.restore(); } } drawMovementCursor(context) { if (this.isInvalidSector(this.mousePosition)) { context.strokeStyle = "#FF0000"; } else { context.strokeStyle = "#00FF00"; } context.save(); context.translate((this.mousePosition.x * this.gridSize) + this.halfGridSize, (this.mousePosition.y * this.gridSize) + this.halfGridSize); context.lineWidth = 2; this.cursor(context); context.restore(); this.drawTargetSector(context); this.drawCurrentSector(context); } isInvalidSector(position) { for (let i = 0; i < this.invalidSectors.length; i++) { let sector = this.invalidSectors[i]; if (position.x == sector.x && position.y == sector.y) { return true; } } return false; } drawCurrentSector(context) { context.strokeStyle = "#0000FF"; context.save(); context.translate(Math.floor(this.currentSector.x * this.gridSize) + this.halfGridSize, Math.floor(this.currentSector.y * this.gridSize) + this.halfGridSize); context.lineWidth = 2; this.cursor(context); context.restore(); } cursor(context) { context.beginPath(); context.moveTo(-this.halfGridSize, -this.halfGridSize); context.lineTo(-this.halfGridSize, -(this.halfGridSize / 2)); context.moveTo(-this.halfGridSize, -this.halfGridSize); context.lineTo(-(this.halfGridSize / 2), -this.halfGridSize); context.moveTo(this.halfGridSize, this.halfGridSize); context.lineTo(this.halfGridSize, (this.halfGridSize / 2)); context.moveTo(this.halfGridSize, this.halfGridSize); context.lineTo((this.halfGridSize / 2), this.halfGridSize); context.moveTo(-this.halfGridSize, this.halfGridSize); context.lineTo(-this.halfGridSize, (this.halfGridSize / 2)); context.moveTo(-this.halfGridSize, this.halfGridSize); context.lineTo(-(this.halfGridSize / 2), this.halfGridSize); context.moveTo(this.halfGridSize, -this.halfGridSize); context.lineTo(this.halfGridSize, -(this.halfGridSize / 2)); context.moveTo(this.halfGridSize, -this.halfGridSize); context.lineTo((this.halfGridSize / 2), -this.halfGridSize); context.stroke(); } drawTargetSector(context) { context.strokeStyle = "#FFFF00"; context.save(); context.translate(Math.floor(this.targetSector.x * this.gridSize) + this.halfGridSize, Math.floor(this.targetSector.y * this.gridSize) + this.halfGridSize); context.lineWidth = 2; this.cursor(context); context.restore(); if (this.currentSector.x != this.targetSector.x || this.currentSector.y != this.targetSector.y) { context.strokeStyle = "#FFFF00"; context.lineWidth = 1; context.setLineDash([3, 6]); context.beginPath(); context.moveTo(Math.floor(this.currentSector.x * this.gridSize) + this.halfGridSize, Math.floor(this.currentSector.y * this.gridSize) + this.halfGridSize); context.lineTo(Math.floor(this.targetSector.x * this.gridSize) + this.halfGridSize, Math.floor(this.targetSector.y * this.gridSize) + this.halfGridSize); context.stroke(); context.setLineDash([]); } } systemDraw(context) { game.sector.drawNav(context, this.gridSize, this.halfGridSize); } handleResize(event) { let dpi = system.getDpi(); this.gridSize = 32 * dpi; this.halfGridSize = 16 * dpi; if (this.systemCanvas) { this.systemCanvas.width = this.systemCanvas.clientWidth * dpi; this.systemCanvas.height = this.systemCanvas.clientHeight * dpi; this.systemContext = this.systemCanvas.getContext('2d'); this.systemContext.webkitImageSmoothingEnabled = true; this.systemContext.imageSmoothingEnabled = true; this.systemCenter = { x: Math.floor(this.systemCanvas.width / 2), y: Math.floor(this.systemCanvas.height / 2) }; } } startShipTravel(event) { game.startShipTravel(); } startTravelAnimation(duration) { this.travelDuration = duration; this.travelEndTime = new Date().getTime() + duration; } finishShipTravel() { this.currentSector.x = this.targetSector.x; this.currentSector.y = this.targetSector.y; this.lastSector.x = this.currentSector.x; this.lastSector.y = this.currentSector.y; this.buildSectorData(); } hide() { document.getElementById(this.containerId).style.opacity = "0"; document.getElementById(this.containerId).style.visibility = "hidden"; } show() { document.getElementById(this.containerId).style.opacity = "1"; document.getElementById(this.containerId).style.visibility = "visible"; } handleMouseMove(event) { let dpi = system.getDpi(); this.mousePosition.x = Math.floor((event.offsetX * dpi) / this.gridSize); this.mousePosition.y = Math.floor((event.offsetY * dpi) / this.gridSize); } handleMouseClick(event) { if (!this.isInvalidSector(this.mousePosition)) { this.targetSector = { x: this.mousePosition.x, y: this.mousePosition.y }; this.impulseButton.style.visibility = "visible"; } if (this.currentSector.x == this.targetSector.x && this.currentSector.y == this.targetSector.y) { this.impulseButton.style.visibility = "hidden"; } } }