unloading

This commit is contained in:
Bastian Wagner 2025-04-26 12:14:08 +02:00
parent ce7de1dc59
commit 9d1f4649d7
10 changed files with 212 additions and 43 deletions

View File

@ -1,5 +1,7 @@
<div #gameContainer class="game-container"></div> <div #gameContainer class="game-container"></div>
<!-- <app-ship-dialog></app-ship-dialog> --> @if (gameService.showShipInfo) {
<app-ship-dialog />
}
@if (gameService.showPlanetInfo) { @if (gameService.showPlanetInfo) {
<app-planet-dialog></app-planet-dialog> <app-planet-dialog></app-planet-dialog>
} }

View File

@ -0,0 +1,66 @@
<div class="ui-panel">
<div class="ui-title">
<div class="image"><img [src]="'sprites/ships/01-starter.png'" alt=""></div>
<div>{{ ship.name }}</div>
</div>
<div class="ui-body">
<div class="ui-section">
@if (ship.status == 'traveling') {
<div>Fliegt nach {{ destination }}</div>
} @else if (ship.status == 'loading') {
<div>Lädt Waren</div>
} @else if (ship.status == 'unloading') {
<div>Entlädt Waren</div>
} @else if (ship.status == 'waiting') {
<div>Wartet auf Abfertigung</div>
} @else {
<div>Untätig</div>
}
</div>
<div class="ui-section">
<ul>
<li class="flex">
<div>Geschwindigkeit: </div>
<div>{{ ship.maxSpeed | number:'0.0-0' }} km/s</div>
</li>
<li class="flex">
<div>Beschleunigung: </div>
<div>{{ ship.acceleration | number:'0.0-0' }}</div>
</li>
<li class="flex">
<div>Frachtraum: </div>
<div>{{ ship.cargoSize | number:'0.0-0' }} t</div>
</li>
<li class="flex">
<div>Ladegeschwindigkeit: </div>
<div>{{ ship.loadingSpeed | number:'0.0-2' }} t/s</div>
</li>
</ul>
<div>
</div>
</div>
<div class="ui-section">
<div>📦 Fracht:</div>
<ul>
@for (item of cargo; track $index) {
<li>{{ item.type }}: {{ item.amount | number:'0.0-0' }}</li>
}
</ul>
</div>
<div class="ui-section">
<button class="button">Produktion upgraden</button>
<button class="button">Siedeln</button>
<button class="button" (click)="close()" >Schließen</button>
</div>
</div>
</div>

View File

@ -9,3 +9,8 @@
// background-color: var(--background-color); // background-color: var(--background-color);
// color: var(--primary-color); // color: var(--primary-color);
} }
img {
width: 92px;
height: 92px;
}

View File

@ -1,5 +1,9 @@
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
import { Component } from '@angular/core'; import { Component, inject } from '@angular/core';
import { GameService } from '../../../service/game.service';
import { Ship } from '../../../model/ships/ship.model';
import { Good } from '../../../model/goods/good.interface';
import { TradeInstance } from '../../../model/planet.model';
@Component({ @Component({
selector: 'app-ship-dialog', selector: 'app-ship-dialog',
@ -8,5 +12,25 @@ import { Component } from '@angular/core';
styleUrl: './ship-dialog.component.scss' styleUrl: './ship-dialog.component.scss'
}) })
export class ShipDialogComponent { export class ShipDialogComponent {
public gameService: GameService = inject(GameService);
get ship(): Ship {
return this.gameService.showShipInfo!;
}
close() {
this.gameService.showShipInfo = undefined;
}
get cargo(): TradeInstance[] {
return this.ship.cargoSpace.filter(c => c.amount);
}
get destination(): string {
if (this.ship.route) {
return this.ship.route.nextPlanetName;
}
return ''
}
} }

View File

@ -102,23 +102,6 @@ export class Planet {
} }
deliver(ship: Ship) {
if (!ship || ship.cargoSpace.length == 0) { return; }
const requests = this.requestedGoods;
if (requests.length == 0) { return; }
for (let request of requests) {
const offer = ship.cargoSpace.find(cargo => cargo.type == request?.type);
if (!offer) { continue; }
const transfer = Math.min(offer.amount, request.amount);
const good = this.getGood(request.type);
if (!good) { continue; }
good.amount += transfer;
offer.amount -= transfer;
console.log(`Ausgeladen: ${good.type}: ${transfer}`)
}
}
/** /**
* Gets a list of goods that the planet needs to import * Gets a list of goods that the planet needs to import
* @returns Array of goods with their type and requested amount * @returns Array of goods with their type and requested amount

View File

@ -1,6 +1,6 @@
import { MapScene } from "../scene/map.scene"; import { MapScene } from "../scene/map.scene";
import { GameService } from "../service/game.service";
import { PlanetUi } from "../ui/planet.ui"; import { PlanetUi } from "../ui/planet.ui";
import { GoodType } from "./goods/good-type.enum";
import { TradeInstance } from "./planet.model"; import { TradeInstance } from "./planet.model";
import { Ship } from "./ships/ship.model"; import { Ship } from "./ships/ship.model";
@ -9,11 +9,11 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
private target: PlanetUi | null = null; private target: PlanetUi | null = null;
private targetVector: Phaser.Math.Vector2 | null = null; // Später Planet! private targetVector: Phaser.Math.Vector2 | null = null; // Später Planet!
public model: Ship = new Ship(); public model: Ship = new Ship();
public gameService: GameService;
constructor(scene: MapScene, x: number, y: number, gameService: GameService) {
constructor(scene: MapScene, x: number, y: number) {
super(scene, x, y, 'ship'); super(scene, x, y, 'ship');
this.gameService = gameService;
scene.add.existing(this); scene.add.existing(this);
@ -27,14 +27,21 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
} }
this.setInteractive(conf) this.setInteractive(conf)
this.activateRoute(); this.activateRoute();
this.on('pointerdown', (pointer: Phaser.Input.Pointer) => {
if (pointer.button == Phaser.Input.MOUSE_DOWN) {
this.gameService.showShip(this.model);
} else if (pointer.button == Phaser.Input.MOUSE_UP) {
}
});
} }
moveTo(target: PlanetUi | undefined) { moveTo(target: PlanetUi | undefined) {
if (!target) { return; } if (!target) { return; }
this.target = target; this.target = target;
this.targetVector = new Phaser.Math.Vector2(target.getWorldPoint().x, target.getWorldPoint().y); this.targetVector = new Phaser.Math.Vector2(target.getWorldPoint().x, target.getWorldPoint().y);
const angle = Phaser.Math.Angle.Between(this.getWorldPoint().x, this.getWorldPoint().y, target.getWorldPoint().x, target.getWorldPoint().y); this.model.status = 'traveling';
// this.setRotation(angle); // Zeigt Schiff zur Zielrichtung
if (!this.body) { return; } if (!this.body) { return; }
} }
@ -75,8 +82,8 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
} }
targetReached(target: PlanetUi) { async targetReached(target: PlanetUi) {
this.model.exchangeGoods(target.model) await this.model.exchangeGoods(target.model)
if (this.model.route) { if (this.model.route) {
this.model.route.routePointReached(); this.model.route.routePointReached();
const target = (this.scene as MapScene).getPlanetUiByName(this.model.route.nextPlanetName); const target = (this.scene as MapScene).getPlanetUiByName(this.model.route.nextPlanetName);

View File

@ -9,17 +9,55 @@ export class Ship {
public cargoSize = 100; public cargoSize = 100;
cargoSpace: TradeInstance[] = []; cargoSpace: TradeInstance[] = [];
public route: TradeRoute | undefined = new TradeRoute([]) public route: TradeRoute | undefined = new TradeRoute([])
public name = "Pioneer-01";
public loadingSpeed = 1.5;
exchangeGoods(planet: Planet) { public status: 'loading' | 'unloading' | 'waiting' | 'idle' | 'traveling' = 'idle'
if (!this.route) { return; }
planet.deliver(this); async exchangeGoods(planet: Planet) {
if (!this.route) {
return Promise.resolve(null)
}
console.log(`\n[${planet.name}] Starting new Trade. Free cargospace: ${this.freeCargoSpace.toFixed(2)}`) await this.unloadGoods(planet);
await this.loadGoods(planet);
return Promise.resolve(null);
}
private async unloadGoods(planet: Planet) {
if (!planet || this.cargoSpace.length == 0) { return Promise.resolve(null); }
const planetRequests = planet.requestedGoods;
if (planetRequests.length == 0) { return Promise.resolve(null); }
this.status = 'unloading';
for (const request of planetRequests) {
const offer = this.cargoSpace.find(cargo => cargo.type == request.type);
if (!offer) { continue; }
const transfer = Math.min(offer.amount, request.amount);
const good = planet.getGood(offer.type);
if (!good) { continue; }
await this.removeFromCargoSpace({type: offer.type, amount: transfer});
good.amount += transfer;
}
this.cargoSpace = this.cargoSpace.filter(c => c.amount != 0)
return Promise.resolve(null);
}
private async loadGoods(planet: Planet) {
if (!this.route) {
return Promise.resolve(null)
}
this.status = 'loading';
const demands = this.route.getTradeRouteDemands(); const demands = this.route.getTradeRouteDemands();
if (demands.length == 0) { return; } if (demands.length == 0) {
console.log(JSON.parse(JSON.stringify(demands))) return Promise.resolve(null)
}
for (let demand of demands) { for (let demand of demands) {
// requested amount: demand - storage // requested amount: demand - storage
@ -27,26 +65,59 @@ export class Ship {
if (stored) { demand.amount -= stored.amount; }; if (stored) { demand.amount -= stored.amount; };
demand.amount = Math.min(demand.amount, this.freeCargoSpace); demand.amount = Math.min(demand.amount, this.freeCargoSpace);
demand.amount = Math.max(demand.amount, 0) demand.amount = Math.max(demand.amount, 0)
if (demand.amount > 0) { console.log(`[${planet.name}] Requesting ${demand.amount.toFixed(2)} ${demand.type}`); }
if (demand.amount == 0) { continue; } if (demand.amount == 0) { continue; }
const received = planet.request(demand); const received = planet.request(demand);
this.addToCargoSpace({type: demand.type, amount: received}) await this.addToCargoSpace({type: demand.type, amount: received})
} }
console.log(`Cargo: ${this.cargoSpace.map(c => `${c.type}: ${c.amount.toFixed(2)}`).join(', ')}`); return Promise.resolve(null)
} }
get freeCargoSpace(): number { get freeCargoSpace(): number {
return this.cargoSize - this.cargoSpace.reduce((acc, succ) => acc + succ.amount, 0) return this.cargoSize - this.cargoSpace.reduce((acc, succ) => acc + succ.amount, 0)
} }
addToCargoSpace(cargo: TradeInstance) { private async removeFromCargoSpace(cargo: TradeInstance) {
const existing = this.cargoSpace.find(c => c.type == cargo.type); const steps = Math.ceil(cargo.amount)
for (let i = 1; i <= steps; i++) {
const existing = this.cargoSpace.find(c => c.type == cargo.type);
if (existing) { if (existing) {
existing.amount += cargo.amount; existing.amount -= (cargo.amount / steps);
}
await this.waitForLoading(1)
}
return Promise.resolve(null)
}
private async addToCargoSpace(cargo: TradeInstance) {
const steps = Math.ceil(cargo.amount)
for (let i = 1; i <= steps; i++) {
const existing = this.cargoSpace.find(c => c.type == cargo.type);
if (existing) {
existing.amount += (cargo.amount / steps);
} else { } else {
this.cargoSpace.push(cargo); this.cargoSpace.push({
} type: cargo.type,
amount: cargo.amount / steps
});
}
await this.waitForLoading(1)
}
return Promise.resolve(null)
}
async waitForLoading(amount: number) {
return new Promise(resolve => {
setTimeout(() => {
resolve(null);
}, amount * 1000 / this.loadingSpeed)
})
} }
} }

View File

@ -93,7 +93,7 @@ export class MapScene extends Phaser.Scene {
}); });
setTimeout(() => { setTimeout(() => {
const s = new ShipUi(this, 100, 100); const s = new ShipUi(this, 100, 100, this.gameService);
s.model.route = new TradeRoute(this.planets.filter(planet => ['Terra Nova', 'Aqualis'].includes(planet.model.name)).map(planet => planet.model)) s.model.route = new TradeRoute(this.planets.filter(planet => ['Terra Nova', 'Aqualis'].includes(planet.model.name)).map(planet => planet.model))
this.ships.push(s) this.ships.push(s)
this.physics.world.enable(s); this.physics.world.enable(s);

View File

@ -2,12 +2,14 @@ import { inject, Injectable } from "@angular/core";
import { MatDialog, MatDialogRef } from "@angular/material/dialog"; import { MatDialog, MatDialogRef } from "@angular/material/dialog";
import { PlanetDialogComponent } from "../components/dialog/planet-dialog/planet-dialog.component"; import { PlanetDialogComponent } from "../components/dialog/planet-dialog/planet-dialog.component";
import { Planet } from "../model/planet.model"; import { Planet } from "../model/planet.model";
import { Ship } from "../model/ships/ship.model";
@Injectable({ @Injectable({
providedIn: 'root', providedIn: 'root',
}) })
export class GameService { export class GameService {
public showPlanetInfo: Planet | undefined; public showPlanetInfo: Planet | undefined;
public showShipInfo: Ship | undefined;
constructor() {} constructor() {}
@ -15,6 +17,10 @@ export class GameService {
this.showPlanetInfo = planet; this.showPlanetInfo = planet;
} }
showShip(ship: Ship) {
this.showShipInfo = ship;
}
get canDrag(): boolean { get canDrag(): boolean {
return true; return true;
} }

View File

@ -109,3 +109,8 @@ $font-size-base: 14px;
margin-top: 8px; margin-top: 8px;
} }
} }
.flex {
display: flex;
justify-content: space-between;
}