This commit is contained in:
Bastian Wagner 2025-04-26 22:31:08 +02:00
parent cb000d29aa
commit 3dd86fa224
26 changed files with 292 additions and 175 deletions

View File

@ -1,59 +1,3 @@
# StellarLines
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.9.
## Development server
To start a local development server, run:
```bash
ng serve
```
Once the server is running, open your browser and navigate to `http://localhost:4200/`. The application will automatically reload whenever you modify any of the source files.
## Code scaffolding
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
```bash
ng generate component component-name
```
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
```bash
ng generate --help
```
## Building
To build the project run:
```bash
ng build
```
This will compile your project and store the build artifacts in the `dist/` directory. By default, the production build optimizes your application for performance and speed.
## Running unit tests
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
```bash
ng test
```
## Running end-to-end tests
For end-to-end (e2e) testing, run:
```bash
ng e2e
```
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
## Additional Resources
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
Docker:
- docker build -t bastianwagner/stellar_lines_client:latest .
- docker push bastianwagner/stellar_lines_client:latest

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 903 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 737 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 148 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

View File

@ -55,7 +55,7 @@ export class AppComponent {
physics: {
default: 'arcade',
arcade: {
debug: true,
debug: false,
timeScale: 1
}
}

View File

@ -8,7 +8,7 @@
<div class="ui-body">
@if (planet.hasHarbour) {
<div class="ui-text-secondary" style="padding: 16px;">👥 Bevölkerung: {{ population }} 🚀</div>
<div class="ui-text-secondary" style="padding: 16px;">👥 Bevölkerung: {{ population }} {{ planet.isGrowing ? '🚀' : '⬇️' }}</div>
<div class="ui-section">
<div>Landebuchten: {{ planet.dockCapacity }}</div>
</div>
@ -16,7 +16,12 @@
<div>🏭 Produktion:</div>
<ul>
@for (item of producedItems; track $index) {
<li>{{ item.type }}: +{{ item.productionRate | number:'0.0-2' }}/s</li>
<li>
<div class="flex">
<div>{{ item.type }}: +{{ getProductionAmount(item) | number:'0.0-2' }}/s</div>
<div>Angebot: {{ getOfferedAmount(item) | number:'0.0-0'}}</div>
</div>
</li>
}
</ul>
</div>
@ -41,6 +46,15 @@
</ul>
</div>
<!-- <div class="ui-section">
<div>📦 Anfrage:</div>
<ul>
@for (item of requested; track $index) {
<li>{{ item.type }}: {{ item.amount | number:'0.0-1' }}/s</li>
}
</ul>
</div> -->
@if (goodsInTransit.length > 0) {
<div class="ui-section">
<div>📦 In Lieferung:</div>
@ -59,7 +73,11 @@
<div>🏭 Produktion:</div>
<ul>
@for (item of producedItems; track $index) {
<li>{{ item.type }}: +{{ item.productionRate | number:'0.0-2' }}/s</li>
<li >
<div class="flex">
<div>{{ item.type }}: +{{ getProductionAmount(item) | number:'0.0-2' }}/s</div>
</div>
</li>
}
</ul>
</div>
@ -70,7 +88,10 @@
@if (planet.hasHarbour) {
<button class="button" (click)="upgradeHarbour()"
matTooltip="Stellt eine zusätzliche Landebucht zur Verfügung. Pro Landebucht kann ein Raumschiff verladen werden. Das Upgrade kostet allerdings Geld."
>Raumhafen upgraden</button>
>Raumhafen aufwerten</button>
<button class="button" (click)="upgradeProduction()" [disabled]="!canUpgradeProduction"
matTooltip="Kosten: {{this.planet.productionLvlUpgradeCost | number}} Credits">Produktion aufwerten</button>
} @else {
<button class="button" (click)="buildHarbour()"
matTooltip="Baue einen Raumhafen um den Planeten anfliegen zu können."

View File

@ -35,7 +35,7 @@ export class PlanetDialogComponent {
}
get storedItems(): Good[] {
return this.planet.getAllGoods()
return this.planet.getAllGoods().filter(item => item.demandRate || item.amount)
}
get consumedItems(): Good[] {
@ -51,7 +51,11 @@ export class PlanetDialogComponent {
}
getFillPercentange(item: Good): number {
return (item.amount / (item.demandRate * this.planet.population * 30)) * 100;
const val = (item.amount / (item.demandRate * this.planet.population * this.planet.demandSecondsBuffer)) * 100;
if (isNaN(val)) {
return 0;
}
return Math.min(Math.floor(val), 100);
}
@ -72,5 +76,28 @@ export class PlanetDialogComponent {
this.planet.buildHarbour()
}
getOfferedAmount(item: Good): number {
const offers = this.planet.offeredGoods;
return offers.find(o => o.type == item.type)?.amount ?? 0;
}
upgradeProduction() {
this.planet.upgradeProduction();
}
getProductionAmount(item: Good): number {
if (!item.productionRate) { return 0; }
return this.planet.getProductionLvl(item) * item.productionRate;
}
get canUpgradeProduction(): boolean {
return this.gameService.money > this.planet.productionLvlUpgradeCost;
}
get requested(): TradeInstance[] {
return this.planet.requestedGoods;
}
}

View File

@ -1,7 +1,7 @@
<div class="ui-panel" (click)="onClick($event)">
<div class="ui-title" cdkDragHandle>
<div class="image"><img [src]="'sprites/ships/01-starter.png'" alt=""></div>
<div class="image"><img [src]="'sprites/ships/' + ship.texture +'.png'" alt=""></div>
<div>{{ ship.name }}</div>
</div>
@ -44,6 +44,10 @@
<div>Ladegeschwindigkeit: </div>
<div>{{ ship.loadingSpeed | number:'0.0-2' }} t/s</div>
</li>
<li class="flex">
<div>Balance:</div>
<div>{{ ship.balance | number:'0.0-2' }} Credits</div>
</li>
</ul>
<div>

View File

@ -45,5 +45,6 @@ export class ShipDialogComponent {
sell() {
this.gameService.sellShip(this.ship);
this.close();
}
}

View File

@ -4,25 +4,32 @@
</div>
<div class="ui-section">
<div>🚀 Neues Schiff: Pioneer-1</div>
<div style="margin-top: 12px; font-size: 12px;">{{ config.desciption }}</div>
<div>
<select name="selectship" id="slship" [(ngModel)]="selectedModel">
<option value="1" selected>Pioneer-01</option>
<option value="2">Colony Carrier</option>
<option value="3">Industrial Tanker</option>
</select>
</div>
<div>🚀 Neues Schiff: {{ selectedShip.name }}</div>
<div style="margin-top: 12px; font-size: 12px;">{{ selectedShip.desciption }}</div>
<ul>
<li class="flex">
<div>Kosten: </div>
<div>{{ config.buyCost | number:'0.0-2'}} Credits</div>
<div>{{ selectedShip.buyCost | number:'0.0-2'}} Credits</div>
</li>
<li class="flex">
<div>Frachtraum: </div>
<div>{{ config.cargoSize | number: '0.0-2'}} t</div>
<div>{{ selectedShip.cargoSize | number: '0.0-2'}} t</div>
</li>
<li class="flex">
<div>Max Geschwindigkeit: </div>
<div>{{ config.maxSpeed | number: '0.0-2'}} km/s</div>
<div>{{ selectedShip.maxSpeed | number: '0.0-2'}} km/s</div>
</li>
<li class="flex">
<div>Unterhalt: </div>
<div>{{ config.cost | number: '0.0-2'}} Credits</div>
<div>{{ selectedShip.cost | number: '0.0-2'}} Credits</div>
</li>
</ul>
</div>

View File

@ -4,10 +4,11 @@ import { GameService } from '../../../service/game.service';
import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
import { Planet } from '../../../model/planet.model';
import { ShipConfig } from '../../../model/ships/ship.model';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-buy',
imports: [CommonModule, CdkDropList, CdkDrag, CdkDragHandle],
imports: [CommonModule, CdkDropList, CdkDrag, CdkDragHandle, FormsModule],
templateUrl: './buy.component.html',
styleUrl: './buy.component.scss'
})
@ -19,13 +20,53 @@ export class BuyComponent {
config: ShipConfig = {
name: 'Pioneer-01',
acceleration: 500,
cargoSize: 10,
cargoSize: 20,
cost: 0.6,
loadingSpeed: 25,
maxSpeed: 500,
loadingSpeed: 15,
maxSpeed: 300,
planetRoute: [],
buyCost: 2000,
desciption: 'Ein kleines, schnelles Schiff. Es hat wenig Platz für Ladung, lädt aber schnell und ist sehr wendig.'
desciption: 'Ein kleines, schnelles Schiff. Es hat wenig Platz für Ladung, lädt aber schnell und ist sehr wendig.',
texture: 'swift-hauler'
}
config2: ShipConfig = {
name: 'Colony Carrier',
acceleration: 200,
cargoSize: 50,
cost: 1.6,
loadingSpeed: 20,
maxSpeed: 200,
planetRoute: [],
buyCost: 4000,
desciption: 'Eine größere Version von der Pioneer-01. Der größere Frachtraum geht zu Lasten der Beschleunigung und Maximalgeschwindigkeit.',
texture: 'colony-carrier'
}
config3: ShipConfig = {
name: 'Industrial Tanker',
acceleration: 5,
cargoSize: 300,
cost: 3.8,
loadingSpeed: 5,
maxSpeed: 600,
planetRoute: [],
buyCost: 8000,
desciption: 'Ein großes behäbiges Schiff. Es wird durchaus schnell, beschleunigt aber sehr langsam und erreicht die Spitzengeschwindigkeit nur selten.',
texture: 'industrial-tanker'
}
selectedModel = '1';
get selectedShip(): ShipConfig {
if (this.selectedModel == '1') {
return this.config;
} else if (this.selectedModel == '3') {
return this.config3
}
return this.config2;
}
canAffordShip() {
@ -35,7 +76,7 @@ export class BuyComponent {
buyShip() {
if (!this.canAffordShip()) return;
this.gameService.createShip({
...this.config,
...this.selectedShip,
planetRoute: this.selectedPlanets
})
this.close();
@ -57,4 +98,5 @@ export class BuyComponent {
);
}
}
}

View File

@ -1,8 +1,8 @@
<div (click)="onClick($event)" (mousedown)="onClick($event)" class="flex gamebar">
<div class="gold">
Credits: {{gameService.money | number:'0.0-0'}}
{{gameService.money | number:'0.0-0'}} Credits
</div>
<button class="button" (click)="toggleBuy()" >Schiffe</button>
<button class="button" (click)="toggleBuy()" >Route anlegen</button>
</div>

View File

@ -3,97 +3,97 @@ import { PlanetInit } from "../model/planet.model";
export const PLANETCONFIGS: { x: number, y: number, texture: string, config: PlanetInit}[] = [
{
x: 600,
y: 800,
x: 900,
y: 950,
texture: 'terra-nova',
config: {
name: 'Terra Nova',
initialGoods: [
{ type: GoodType.Wasser, amount: 15 },
{ type: GoodType.Nahrung, amount: 8, productionBonus: 1.3 },
{ type: GoodType.Wasser, amount: 10 },
{ type: GoodType.Nahrung, amount: 10, productionBonus: 1.3 },
]
}
},
{
x: 3000,
y: 900,
x: 4000,
y: 1500,
texture: 'mechanica-prime',
config: {
name: 'Mechanica Prime',
initialGoods: [
{ type: GoodType.Wasser, amount: 120 },
{ type: GoodType.Nahrung, amount: 80 },
{ type: GoodType.Metall, amount: 50, productionBonus: 1.5 },
{ type: GoodType.Bauteile, amount: 20, productionBonus: 1.3 },
{ type: GoodType.Wasser, amount: 10 },
{ type: GoodType.Nahrung, amount: 10 },
{ type: GoodType.Metall, amount: 10, productionBonus: 1.5 },
{ type: GoodType.Bauteile, amount: 10, productionBonus: 1.3 },
{ type: GoodType.Elektronik, amount: 10 }
]
}
},
{
x: 1800,
y: 2800,
y: 3800,
texture: 'aqualis',
config: {
name: 'Aqualis',
initialGoods: [
{ type: GoodType.Wasser, amount: 30, productionBonus: 2.0 },
{ type: GoodType.Nahrung, amount: 15 },
{ type: GoodType.Wasser, amount: 200, productionBonus: 2.0 },
{ type: GoodType.Nahrung, amount: 10 },
{ type: GoodType.Treibstoff, amount: 10 }
]
}
},
{
x: 3900,
y: 2500,
x: 4500,
y: 5500,
texture: 'planet',
config: {
name: 'Ferron',
initialGoods: [
{ type: GoodType.Wasser, amount: 120 },
{ type: GoodType.Nahrung, amount: 80 },
{ type: GoodType.Erz, amount: 200, productionBonus: 1.8 },
{ type: GoodType.Metall, amount: 40 },
{ type: GoodType.Treibstoff, amount: 20 }
{ type: GoodType.Wasser, amount: 10 },
{ type: GoodType.Nahrung, amount: 10 },
{ type: GoodType.Erz, amount: 10, productionBonus: 1.8 },
{ type: GoodType.Metall, amount: 10 },
{ type: GoodType.Treibstoff, amount: 10 }
]
}
},
{
x: 5400,
y: 1400,
x: 7400,
y: 2400,
texture: 'novus-reach',
config: {
name: 'Novus Reach',
initialGoods: [
{ type: GoodType.Nahrung, amount: 90, productionBonus: 1.5 },
{ type: GoodType.Wasser, amount: 50 },
{ type: GoodType.Bauteile, amount: 15 }
{ type: GoodType.Nahrung, amount: 10, productionBonus: 1.5 },
{ type: GoodType.Wasser, amount: 10 },
{ type: GoodType.Bauteile, amount: 10 }
]
}
}
,
{
x: 3700,
y: 4600,
texture: 'novus-reach',
y: 7600,
texture: 'volaris',
config: {
name: 'Novus Reach 2',
name: 'Volaris',
initialGoods: [
{ type: GoodType.Nahrung, amount: 90, productionBonus: 1.5 },
{ type: GoodType.Wasser, amount: 50 },
{ type: GoodType.Bauteile, amount: 15 }
{ type: GoodType.Nahrung, amount: 10 },
{ type: GoodType.Wasser, amount: 10, productionBonus: 1.1 },
{ type: GoodType.Bauteile, amount: 10 }
]
}
},
{
x: 6000,
y: 3600,
texture: 'terra-nova',
x: 8000,
y: 6600,
texture: 'ignis-prime',
config: {
name: 'Terra Nova 2',
name: 'Ignis Prime',
initialGoods: [
{ type: GoodType.Wasser, amount: 120 },
{ type: GoodType.Nahrung, amount: 80, productionBonus: 1.3 },
{ type: GoodType.Erz, amount: 100 }
{ type: GoodType.Wasser, amount: 10 },
{ type: GoodType.Nahrung, amount: 10 },
{ type: GoodType.Treibstoff, amount: 10, productionBonus: 0.8 }
]
}
}

View File

@ -8,11 +8,11 @@ export interface GoodConfig {
}
export const GOODS_DATA: Record<GoodType, GoodConfig> = {
[GoodType.Erz]: { baseProduction: 1.0, baseDemand: 0, storageLimit: 500, isRawResource: true },
[GoodType.Erz]: { baseProduction: 1.0, baseDemand: 0.001, storageLimit: 500, isRawResource: true },
[GoodType.Wasser]: { baseProduction: 1, baseDemand: 0.0015, storageLimit: 300, isRawResource: true },
[GoodType.Nahrung]: { baseProduction: 1, baseDemand: 0.001, storageLimit: 200, isRawResource: true },
[GoodType.Metall]: { baseProduction: 1, baseDemand: 0, storageLimit: 300, isRawResource: false },
[GoodType.Metall]: { baseProduction: 1, baseDemand: 0.001, storageLimit: 300, isRawResource: false },
[GoodType.Treibstoff]: { baseProduction: 1, baseDemand: 0, storageLimit: 150, isRawResource: false },
[GoodType.Elektronik]: { baseProduction: 1, baseDemand: 0, storageLimit: 100, isRawResource: false },
[GoodType.Bauteile]: { baseProduction: 1, baseDemand: 0, storageLimit: 100, isRawResource: false }
[GoodType.Elektronik]: { baseProduction: 1, baseDemand: 0.001, storageLimit: 100, isRawResource: false },
[GoodType.Bauteile]: { baseProduction: 1, baseDemand: 0.001, storageLimit: 100, isRawResource: false }
};

View File

@ -11,12 +11,12 @@ export class Planet {
public image: string;
private goods: Map<string, Good> = new Map();
private updateSubscription = interval(5000).subscribe(() => {this.update(5)}); // alle 5s
private updateSubscription = interval(1000).subscribe(() => {this.update(1)}); // alle 5s
public isGrowing: boolean = false;
private populationGrowthRate = 0.002; // Basiswachstum pro Tick (%)
private populationDeclineRate = 0.005; // Basisrückgang bei Mangel (%)
demandSecondsBuffer = 150; // Anfrage immer mindestens 30 Sekunden überleben
public demandSecondsBuffer = 150; // Anfrage immer mindestens 30 Sekunden überleben
private productionLevel: Map<GoodType, number> = new Map();
private dockedShips: Ship[] = [];
@ -60,13 +60,56 @@ export class Planet {
this.dockCapacity = 1;
}, 10000)
}
adjustPopulationDemands(good: Good) {
switch(good.type) {
case GoodType.Erz:
if (this.population > 250) {
good.demandRate = GOODS_DATA.Erz.baseDemand
} else {
good.demandRate = 0;
}
break;
case GoodType.Bauteile:
if (this.population > 500) {
good.demandRate = GOODS_DATA.Bauteile.baseDemand
} else {
good.demandRate = 0;
}
break;
case GoodType.Elektronik:
if (this.population > 700) {
good.demandRate = GOODS_DATA.Elektronik.baseDemand
} else {
good.demandRate = 0;
}
break;
case GoodType.Metall:
if (this.population > 750) {
good.demandRate = GOODS_DATA.Metall.baseDemand
} else {
good.demandRate = 0;
}
break;
case GoodType.Treibstoff:
if (this.population > 900) {
good.demandRate = GOODS_DATA.Treibstoff.baseDemand
} else {
good.demandRate = 0;
}
break;
}
}
private update(seconds: number): void {
this.goods.forEach((good: Good, key: string) => {
this.adjustPopulationDemands(good)
const lvlMultiplier = this.productionLevel.get(good.type) ?? 1;
good.amount += good.productionRate * seconds * lvlMultiplier;
good.amount -= good.demandRate * seconds;
// Min 0
good.amount = Math.max(0, good.amount);
@ -77,23 +120,11 @@ export class Planet {
this.updatePopulation(seconds)
return;
// Debug-Ausgabe (später ersetzen durch Events/Callback/Service)
console.log(`[${this.name}] Wirtschaft aktualisiert:`);
this.goods.forEach(good => {
console.log(` ${good.type}: ${good.amount.toFixed(2)}`);
});
console.log("Angeboten:")
for (let good of this.offeredGoods) {
console.log(` ${good.type}: ${good.amount.toFixed(2)}`)
}
console.log("Nachgefragt:")
for (let good of this.requestedGoods) {
console.log(` ${good.type}: ${good.amount.toFixed(2)}`)
}
@ -134,9 +165,8 @@ export class Planet {
const inTransit = this.goodsInTransit.filter(g => g.type == good.type).reduce((acc, succ) => acc + succ.amount, 0);
if (demand < good.amount + inTransit) {
console.log(`[${this.name}] Skipping request for ${good.type}: ${inTransit} in transit + ${good.amount} > ${demand}`);
continue; // Es werden genug geliefert.
}
@ -151,19 +181,9 @@ export class Planet {
}
get offeredGoods(): TradeInstance[] {
return this.getAllGoods().filter(g => g.productionRate && g.amount).map(g => { return { type: g.type, amount: g.amount, target: this.name }})
return this.getAllGoods().filter(g => g.productionRate && g.amount).map(g => { return { type: g.type, amount: g.amount - (g.demandRate * this.population * this.demandSecondsBuffer), target: this.name }}).filter(g => g.amount > 0)
}
// request(ship: ShipUi) {
// const offers = this.offeredGoods;
// if (offers.length == 0) { return; }
// const loaded = ship.loadCargo(offers[0]);
// offers[0].amount -= loaded;
// const reduce = this.goods.get(offers[0].type)
// if (!reduce) { return; }
// reduce.amount = Math.max(0, reduce.amount - loaded);
// }
request(demandedGood: {type: GoodType, amount: number}) {
const offers = this.offeredGoods;
if (offers.length == 0) { return 0; }
@ -225,14 +245,18 @@ export class Planet {
*/
private calculateNaturalDemand(seconds: number): Map<GoodType, number> {
const demand = new Map<GoodType, number>();
for (const goodType in GOODS_DATA) {
const config = GOODS_DATA[goodType as GoodType];
if (config.baseDemand > 0) {
demand.set(goodType as GoodType, this.population * config.baseDemand * seconds);
}
for (let good of this.getAllGoods()) {
demand.set(good.type ,this.population * good.demandRate * seconds )
}
// for (const goodType in GOODS_DATA) {
// const config = GOODS_DATA[goodType as GoodType];
// if (config.baseDemand > 0) {
// demand.set(goodType as GoodType, this.population * config.baseDemand * seconds);
// }
// }
return demand;
}
@ -280,9 +304,7 @@ export class Planet {
dock(ship: Ship) {
console.log("DOCK:", ship.name)
if (!this.dockedShips.includes(ship)) {
console.log("DOCK:", ship.name)
this.dockedShips.push(ship);
this.shipsWaitingForDocking = this.shipsWaitingForDocking.filter(s => s != ship); // aus warteschlange entfernen
}
@ -309,6 +331,36 @@ export class Planet {
this.gameService.money -= 3000;
}
upgradeProduction() {
if (this.gameService.money < this.productionLvlUpgradeCost) { return; }
this.gameService.money -= this.productionLvlUpgradeCost;
this.getAllGoods().filter(g => g.productionRate).forEach(good => {
const lvl = this.productionLevel.get(good.type);
if (lvl) {
this.productionLevel.set(good.type, lvl + 1);
} else {
this.productionLevel.set(good.type, 2)
}
if (good.productionStorage) {
good.productionStorage = good.productionStorage * 1.5;
}
})
}
getProductionLvl(good: Good): number {
return this.productionLevel.get(good.type) ?? 1;
}
get productionLvlUpgradeCost(): number {
const lvls = Array.from(this.productionLevel.values());
lvls.push(1); // falls es leer ist
const lvl = Math.max(...lvls);
return lvl * 1000;
}
}
export interface PlanetInit {

View File

@ -1,7 +1,6 @@
import { MapScene } from "../scene/map.scene";
import { GameService } from "../service/game.service";
import { PlanetUi } from "../ui/planet.ui";
import { TradeInstance } from "./planet.model";
import { FlightMode, Ship } from "./ships/ship.model";
export class ShipUi extends Phaser.Physics.Arcade.Sprite {
@ -16,7 +15,7 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
private orbitSpeed: number = Math.PI / 25; // Eine Runde in 2 Sekunden
constructor(scene: MapScene, x: number, y: number, gameService: GameService, ship: Ship) {
super(scene, x, y, 'ship');
super(scene, x, y, ship.texture);
this.gameService = gameService;
this.model = ship;

View File

@ -14,6 +14,7 @@ export interface ShipConfig {
planetRoute: Planet[];
buyCost: number;
desciption: string;
texture: string;
}
export class Ship {
@ -29,6 +30,10 @@ export class Ship {
public cost = 0.5
public buyCost = 0;
public description: string = "";
texture: string;
public totalCost: number = 0;
public totalEarnings: number = 0;
private updateInterval = interval(1000).subscribe(() => {
this.update();
@ -44,7 +49,10 @@ export class Ship {
this.cost = config.cost;
this.buyCost = config.buyCost;
this.description = config.desciption;
this.texture = config.texture;
this.route = new TradeRoute(config.planetRoute)
this.name = config.name + ' - ' + Math.round(Math.random() * 100);
this.totalCost = config.buyCost;
}
@ -80,10 +88,10 @@ export class Ship {
for (let dgood of delivering) {
const good = planet.getGood(dgood.type);
if (!good) { continue; }
await this.removeFromCargoSpace({type: dgood.type, amount: dgood.amount, target: dgood.target}, good);
await this.removeFromCargoSpace(dgood, good);
}
this.cargoSpace = this.cargoSpace.filter(c => c.amount != 0 && c.amount != undefined)
this.cargoSpace = this.cargoSpace.filter(c => c.amount != 0 && c.amount != undefined && c.amount > 0);
return Promise.resolve(null);
}
@ -101,7 +109,7 @@ export class Ship {
for (let demand of demands) {
// requested amount: demand - storage
const stored = this.cargoSpace.find(c => c.type == demand.type);
const stored = this.cargoSpace.find(c => c.type == demand.type && demand.target == c.target);
if (stored) { demand.amount -= stored.amount; };
demand.amount = Math.min(demand.amount, this.freeCargoSpace);
demand.amount = Math.max(demand.amount, 0)
@ -118,18 +126,21 @@ export class Ship {
}
private async removeFromCargoSpace(cargo: TradeInstance, to: Good) {
const steps = Math.ceil(cargo.amount)
const steps = Math.ceil(cargo.amount);
const transferPerStep = cargo.amount / steps;
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);
this.gameService.money += 5;
if (cargo) {
cargo.amount -= transferPerStep;
to.amount += transferPerStep;
this.gameService.money += 18 * transferPerStep;
this.totalEarnings += 18 * transferPerStep;
}
await this.waitForLoading(1)
}
to.amount += cargo.amount;
cargo.amount = 0;
return Promise.resolve(null)
}
@ -138,7 +149,7 @@ export class Ship {
const steps = Math.ceil(cargo.amount)
for (let i = 1; i <= steps; i++) {
const existing = this.cargoSpace.find(c => c.type == cargo.type);
const existing = this.cargoSpace.find(c => c.type == cargo.type && cargo.target == c.target);
if (existing) {
existing.amount += (cargo.amount / steps);
} else {
@ -166,12 +177,17 @@ export class Ship {
update() {
this.gameService.money -= this.cost;
this.totalCost += this.cost;
}
sell() {
this.updateInterval.unsubscribe();
}
get balance(): number {
return this.totalEarnings - this.totalCost;
}
}
export enum FlightMode {

View File

@ -21,10 +21,14 @@ export class MapScene extends Phaser.Scene {
}
preload() {
this.load.image('ship', 'sprites/ships/swift-hauler.png');
this.load.image('swift-hauler', 'sprites/ships/swift-hauler.png');
this.load.image('colony-carrier', 'sprites/ships/colony-carrier.png');
this.load.image('industrial-tanker', 'sprites/ships/industrial-tanker.png');
this.load.image('harbour', 'sprites/buildings/harbour.png');
this.load.image('planet', 'sprites/planets/planet-1.png');
this.load.image('terra-nova', 'sprites/planets/terra-nova.png');
this.load.image('volaris', 'sprites/planets/volaris.png');
this.load.image('ignis-prime', 'sprites/planets/ignis-prime.png');
this.load.image('mechanica-prime', 'sprites/planets/mechanica-prime.png');
this.load.image('novus-reach', 'sprites/planets/novus-reach.png');
this.load.image('aqualis', 'sprites/planets/aqualis.png');
@ -47,7 +51,7 @@ export class MapScene extends Phaser.Scene {
for (let i = 0; i< 1000; i++) {
const x = Phaser.Math.Between(0, 10000);
const y = Phaser.Math.Between(0, 10000);
this.add.circle(x, y, Phaser.Math.Between(1, 3), 0x88ccff)
this.add.circle(x, y, Phaser.Math.Between(2, 10), 0x88ccff)
}
// Beispiel: ein paar Kreise (Planeten) zeichnen

View File

@ -15,7 +15,7 @@ export class GameService {
showTutorial = true;
public money = 12000;
public money = 12500;
onShipCreate: EventEmitter<Ship> = new EventEmitter();
onShipDestroy: EventEmitter<Ship> = new EventEmitter();