This commit is contained in:
Bastian Wagner 2025-04-26 15:06:04 +02:00
parent 758c358eea
commit 9007d94b0d
14 changed files with 104 additions and 56 deletions

BIN
public/title-image.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 MiB

View File

@ -8,6 +8,9 @@
<div class="ui-body">
<div class="ui-text-secondary" style="padding: 16px;">👥 Bevölkerung: {{ population }} 🚀</div>
<div class="ui-section">
<div>Landebuchten: {{ planet.dockCapacity }}</div>
</div>
<div class="ui-section">
<div>🏭 Produktion:</div>
<ul>
@ -33,12 +36,20 @@
<li>{{ item.type }}: {{ item.demandRate * planet.population | number:'0.0-1' }}/s</li>
}
</ul>
</div>
<div class="ui-section">
<div>📦 In Lieferung:</div>
<ul>
@for (item of goodsInTransit; track $index) {
<li>{{ item.type }}: {{ item.amount | number:'0.0-1' }}</li>
}
</ul>
</div>
</div>
<div class="ui-section">
<button class="button">Produktion upgraden</button>
<button class="button" (click)="upgradeHarbour()" >Raumhafen upgraden</button>
<button class="button">Siedeln</button>
<button class="button" (click)="close()" >Schließen</button>
</div>

View File

@ -1,5 +1,5 @@
import { Component, inject, InjectionToken } from '@angular/core';
import { Planet } from '../../../model/planet.model';
import { Planet, TradeInstance } from '../../../model/planet.model';
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
import { CommonModule } from '@angular/common';
import { Good } from '../../../model/goods/good.interface';
@ -58,5 +58,14 @@ export class PlanetDialogComponent {
close() {
this.gameService.showPlanetInfo = undefined;
}
get goodsInTransit(): TradeInstance[] {
return this.planet.goodsInTransit;
}
upgradeHarbour() {
this.planet.upgradeHarbour()
}
}

View File

@ -54,17 +54,26 @@
<div>📦 Fracht:</div>
<ul>
@for (item of cargo; track $index) {
<li>{{ item.type }}: {{ item.amount | number:'0.0-0' }}</li>
<li>{{ item.type }}: {{ item.amount | number:'0.0-0' }} => {{ item.target }}</li>
}
</ul>
</div>
<div class="ui-section">
<div>🛣️ Aktive Route:</div>
<div class="flex route">
@for (item of activeRoute; track $index) {
<div>{{ item }}</div>
}
</div>
</div>
</div>
<div class="ui-section">
<button class="button">Produktion upgraden</button>
<button class="button">Siedeln</button>
<button class="button" (click)="onClick($event); close();" >Schließen</button>
</div>
</div>
</div>

View File

@ -16,3 +16,7 @@ img {
width: 92px;
height: 92px;
}
.route {
padding: 16px 8px;
}

View File

@ -38,4 +38,8 @@ export class ShipDialogComponent {
event.stopPropagation();
console.log(event)
}
get activeRoute(): string[] {
return this.ship.route?.planetNames ?? []
}
}

View File

@ -4,6 +4,7 @@ import { GOODS_DATA } from "./goods/good-config";
import { Good } from "./goods/good.interface";
import { ShipUi } from "./ship";
import { Ship } from "./ships/ship.model";
import { GameService } from "../service/game.service";
export class Planet {
public population: number = 100;
@ -20,14 +21,16 @@ export class Planet {
private productionLevel: Map<GoodType, number> = new Map();
private dockedShips: Ship[] = [];
private dockCapacity: number = 0;
public dockCapacity: number = 0;
private shipsWaitingForDocking: Ship[] = [];
private gameService: GameService;
constructor(config: PlanetInit) {
constructor(config: PlanetInit, gameService: GameService) {
this.name = config.name;
this.image = config.name.toLowerCase().split(' ').join('-')
this.gameService = gameService;
/** set all empty */
Object.values(GoodType).forEach(c => {
this.goods.set(c, {
@ -128,9 +131,16 @@ export class Planet {
continue; // Skip if we have enough in stock
}
const inTransit = this.goodsInTransit.filter(g => g.type == good.type).reduce((acc, succ) => acc + succ.amount, 0);
if (demand < good.amount + inTransit) {
continue; // Es werden genug geliefert.
}
result.push({
amount: demand * 3, // Request 3x buffer amount
type: good.type
type: good.type,
target: this.name,
})
}
@ -138,7 +148,7 @@ export class Planet {
}
get offeredGoods(): TradeInstance[] {
return this.getAllGoods().filter(g => g.productionRate && g.amount).map(g => { return { type: g.type, amount: g.amount}})
return this.getAllGoods().filter(g => g.productionRate && g.amount).map(g => { return { type: g.type, amount: g.amount, target: this.name }})
}
// request(ship: ShipUi) {
@ -282,6 +292,17 @@ export class Planet {
console.log('wartend: ',this.shipsWaitingForDocking.map(d => d.name).join(','))
}
get goodsInTransit(): TradeInstance[] {
return this.gameService.ships
.flatMap(ship => ship.cargoSpace)
.filter(item => item.target === this.name);
}
upgradeHarbour() {
this.dockCapacity++;
}
}
export interface PlanetInit {
@ -296,4 +317,5 @@ export interface PlanetInit {
export interface TradeInstance {
type: GoodType;
amount: number;
target: string;
}

View File

@ -46,6 +46,10 @@ export class TradeRoute {
}
return demands;
}
get planetNames(): string[] {
return this.route.map(r => r.target.name);
}
}
interface ITradePlanet {

View File

@ -159,27 +159,6 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
}
}
loadCargo(cargo: TradeInstance): number {
const loaded = this.model.cargoSpace.reduce((acc, succ) => acc + succ.amount, 0);
if (loaded >= this.model.cargoSize) { return 0; }
const remaining = this.model.cargoSize - loaded;
const load = Math.min(remaining, cargo.amount);
const exists = this.model.cargoSpace.find(c => c.type == cargo.type);
if (exists) {
exists.amount += load
} else {
this.model.cargoSpace.push({
amount: load,
type: cargo.type
})
}
console.log(`Eingeladen: ${cargo.type}: ${load}`)
return load;
}
activateRoute() {
if (!this.model.route) { return; }

View File

@ -1,3 +1,4 @@
import { Good } from "../goods/good.interface";
import { Planet, TradeInstance } from "../planet.model";
import { TradeRoute } from "../routes/trade-route.model";
@ -6,11 +7,11 @@ export class Ship {
public maxSpeed = 100;
public currentSpeed = 0;
public cargoSize = 100;
public cargoSize = 50;
cargoSpace: TradeInstance[] = [];
public route: TradeRoute | undefined = new TradeRoute([])
public name = "Pioneer-01-" + Math.round(Math.random() * 100);
public loadingSpeed = 1.5;
public loadingSpeed = 3.5;
public status: 'loading' | 'unloading' | 'waiting' | 'idle' | 'traveling' = 'idle';
public flightMode: FlightMode = FlightMode.Normal;
@ -38,22 +39,15 @@ export class Ship {
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';
const delivering = this.cargoSpace.filter(cargo => cargo.target == planet.name);
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);
for (let dgood of delivering) {
const good = planet.getGood(dgood.type);
if (!good) { continue; }
await this.removeFromCargoSpace({type: offer.type, amount: transfer});
good.amount += transfer;
await this.removeFromCargoSpace({type: dgood.type, amount: dgood.amount, target: dgood.target}, good);
}
this.cargoSpace = this.cargoSpace.filter(c => c.amount != 0)
this.cargoSpace = this.cargoSpace.filter(c => c.amount != 0 && c.amount != undefined)
return Promise.resolve(null);
}
@ -77,7 +71,7 @@ export class Ship {
demand.amount = Math.max(demand.amount, 0)
if (demand.amount == 0) { continue; }
const received = planet.request(demand);
await this.addToCargoSpace({type: demand.type, amount: received})
await this.addToCargoSpace({type: demand.type, amount: received, target: demand.target})
}
return Promise.resolve(null)
@ -87,13 +81,14 @@ export class Ship {
return this.cargoSize - this.cargoSpace.reduce((acc, succ) => acc + succ.amount, 0)
}
private async removeFromCargoSpace(cargo: TradeInstance) {
private async removeFromCargoSpace(cargo: TradeInstance, to: Good) {
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);
to.amount += (cargo.amount / steps);
}
await this.waitForLoading(1)
}
@ -112,7 +107,8 @@ export class Ship {
} else {
this.cargoSpace.push({
type: cargo.type,
amount: cargo.amount / steps
amount: cargo.amount / steps,
target: cargo.target
});
}

View File

@ -106,6 +106,7 @@ export class MapScene extends Phaser.Scene {
this.ships.push(s)
this.physics.world.enable(s);
s.activateRoute();
this.gameService.ships.push(s.model)
}
override update(time: number, delta: number): void {
@ -120,7 +121,7 @@ export class MapScene extends Phaser.Scene {
}
private buildPlanets() {
for (let config of PLANETCONFIGS) {
const planet = new PlanetUi(this, config.x, config.y, config.texture, config.config);
const planet = new PlanetUi(this, config.x, config.y, config.texture, config.config, this.gameService);
planet.rightClick.subscribe(planet => {
this.ship.moveTo(planet);
this.isDragging = false;
@ -130,6 +131,7 @@ export class MapScene extends Phaser.Scene {
this.isDragging = false;
});
this.planets.push(planet);
this.gameService.planets.push(planet.model);
}
}

View File

@ -11,6 +11,9 @@ export class GameService {
public showPlanetInfo: Planet | undefined;
public showShipInfo: Ship | undefined;
public ships: Ship[] = [];
public planets: Planet[] = [];
constructor() {}
showDialog(planet: Planet) {

View File

@ -2,6 +2,7 @@ import { EventEmitter } from "@angular/core";
import { interval } from "rxjs";
import { Planet } from "../model/planet.model";
import { PlanetStatus } from "./planet-status.ui";
import { GameService } from "../service/game.service";
export class PlanetUi extends Phaser.Physics.Arcade.Sprite {
@ -12,12 +13,12 @@ export class PlanetUi extends Phaser.Physics.Arcade.Sprite {
private updateInterval = interval(1000)
constructor(scene: Phaser.Scene, x: number, y: number, texture: string, config: any) {
constructor(scene: Phaser.Scene, x: number, y: number, texture: string, config: any, gameService: GameService) {
super(scene, x, y, texture);
// this.setDisplaySize(200, 200);
this.model = new Planet(config);
this.model = new Planet(config, gameService);
scene.add.existing(this);
this.setInteractive({ useHandCursor: true });

View File

@ -95,7 +95,7 @@ $font-size-base: 14px;
.ui-section {
padding: 16px;
border-top: 1px solid #202d3e;
ul {
margin: 8px 0 0 16px;
@ -114,3 +114,7 @@ $font-size-base: 14px;
display: flex;
justify-content: space-between;
}
.ui-body > .ui-section {
border-top: 1px solid #202d3e;
}