alpha
This commit is contained in:
parent
9007d94b0d
commit
a5767a2c79
BIN
public/sprites/ships/swift-hauler.png
Normal file
BIN
public/sprites/ships/swift-hauler.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 125 KiB |
@ -1,7 +1,17 @@
|
||||
<div #gameContainer class="game-container"></div>
|
||||
@if (gameService.showShipInfo) {
|
||||
<app-ship-dialog cdkDrag cdkDragBoundary="html"/>
|
||||
<app-ship-dialog cdkDrag cdkDragBoundary="html" (click)="stopPropagation($event)" (mousedown)="stopPropagation($event)"/>
|
||||
}
|
||||
@if (gameService.showPlanetInfo) {
|
||||
<app-planet-dialog cdkDrag cdkDragBoundary="html"></app-planet-dialog>
|
||||
<app-planet-dialog cdkDrag cdkDragBoundary="html" (click)="stopPropagation($event)" (mousedown)="stopPropagation($event)"></app-planet-dialog>
|
||||
}
|
||||
|
||||
@if (gameService.showBuyShip) {
|
||||
<app-buy cdkDrag (click)="stopPropagation($event)" (mousedown)="stopPropagation($event)"/>
|
||||
}
|
||||
|
||||
<app-status-bar class="ui-panel" (click)="stopPropagation($event)" (mousedown)="stopPropagation($event)"/>
|
||||
|
||||
@if (gameService.showTutorial) {
|
||||
<app-welcome (click)="stopPropagation($event)" (mousedown)="stopPropagation($event)" />
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, ElementRef, inject, ViewChild } from '@angular/core';
|
||||
import { Component, ElementRef, inject, LOCALE_ID, ViewChild } from '@angular/core';
|
||||
import Phaser from 'phaser';
|
||||
import { MapScene } from './scene/map.scene';
|
||||
import { MatDialog, MatDialogModule } from '@angular/material/dialog';
|
||||
@ -6,10 +6,20 @@ import { GameService } from './service/game.service';
|
||||
import { ShipDialogComponent } from './components/dialog/ship-dialog/ship-dialog.component';
|
||||
import { PlanetDialogComponent } from './components/dialog/planet-dialog/planet-dialog.component';
|
||||
import { DragDropModule } from '@angular/cdk/drag-drop';
|
||||
import { StatusBarComponent } from './components/status-bar/status-bar.component';
|
||||
import { BuyComponent } from './components/ships/buy/buy.component';
|
||||
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import localeDe from '@angular/common/locales/de';
|
||||
import localeDeExtra from '@angular/common/locales/extra/de';
|
||||
import { WelcomeComponent } from './components/tutorial/welcome/welcome.component';
|
||||
|
||||
registerLocaleData(localeDe, 'de-DE', localeDeExtra);
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
imports: [MatDialogModule, ShipDialogComponent, PlanetDialogComponent, DragDropModule],
|
||||
imports: [MatDialogModule, ShipDialogComponent, PlanetDialogComponent, DragDropModule, StatusBarComponent, BuyComponent, WelcomeComponent],
|
||||
providers: [{ provide: LOCALE_ID, useValue: 'de-DE' }],
|
||||
templateUrl: './app.component.html',
|
||||
styleUrl: './app.component.scss'
|
||||
})
|
||||
@ -53,4 +63,8 @@ export class AppComponent {
|
||||
|
||||
const game = new Phaser.Game(config);
|
||||
}
|
||||
|
||||
stopPropagation(event: any) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<div class="ui-panel">
|
||||
<div class="ui-title">
|
||||
<div class="ui-title" cdkDragHandle>
|
||||
<div class="image"><img [src]="'sprites/planets/sm/'+ planet.image +'.png'" alt=""></div>
|
||||
<div>{{ planet.name }}</div>
|
||||
</div>
|
||||
@ -7,7 +7,8 @@
|
||||
|
||||
|
||||
<div class="ui-body">
|
||||
<div class="ui-text-secondary" style="padding: 16px;">👥 Bevölkerung: {{ population }} 🚀</div>
|
||||
@if (planet.hasHarbour) {
|
||||
<div class="ui-text-secondary" style="padding: 16px;">👥 Bevölkerung: {{ population }} 🚀</div>
|
||||
<div class="ui-section">
|
||||
<div>Landebuchten: {{ planet.dockCapacity }}</div>
|
||||
</div>
|
||||
@ -21,7 +22,9 @@
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<div>📦 Vorräte:</div>
|
||||
<div style="display: inline-block;"
|
||||
matTooltip="Jeder Planet braucht ausreichend Vorräte. Hat er genug Vorräte, ziehen Menschen in die Stadt des Raumhafens. Existieren nicht genug Rohstoffe, verlassen Menschen die Stadt. Je mehr Menschen hier leben, desto höher wird ihr Verbrauch."
|
||||
>📦 Vorräte:</div>
|
||||
@for (item of storedItems; track $index) {
|
||||
<div class="ui-progress-bar" [ngClass]="item.type.toLowerCase()">
|
||||
<div class="progress-fill" [style.width.%]="getFillPercentange(item)">{{ item.type }}: {{ item.amount | number:'0.0-1' }}</div>
|
||||
@ -38,19 +41,42 @@
|
||||
</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>
|
||||
@if (goodsInTransit.length > 0) {
|
||||
<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>
|
||||
}
|
||||
|
||||
|
||||
} @else {
|
||||
<div class="ui-text-secondary" style="padding: 16px;">Baue einen Raumhafen um diesen Planeten zu erschließen, und auf die Ressourcen zuzugreifen. Es bildet sich eine kleine Siedlung um den Raumhafen. Je besser diese versorgt ist, desto mehr Menschen ziehen hin. Gibt es zu wenig Rohstoffe, verlassen die Menschen die Siedlung und ziehen ins Umland um sich selbst zu versorgen.</div>
|
||||
<div class="ui-section">
|
||||
<div>🏭 Produktion:</div>
|
||||
<ul>
|
||||
@for (item of producedItems; track $index) {
|
||||
<li>{{ item.type }}: +{{ item.productionRate | number:'0.0-2' }}/s</li>
|
||||
}
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<button class="button" (click)="upgradeHarbour()" >Raumhafen upgraden</button>
|
||||
<button class="button">Siedeln</button>
|
||||
<div class="ui-section flex">
|
||||
@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>
|
||||
} @else {
|
||||
<button class="button" (click)="buildHarbour()"
|
||||
matTooltip="Baue einen Raumhafen um den Planeten anfliegen zu können."
|
||||
>Raumhafen bauen</button>
|
||||
|
||||
}
|
||||
<button class="button" (click)="close()" >Schließen</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -4,4 +4,10 @@
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
@ -5,11 +5,12 @@ import { CommonModule } from '@angular/common';
|
||||
import { Good } from '../../../model/goods/good.interface';
|
||||
import { GoodType } from '../../../model/goods/good-type.enum';
|
||||
import { GameService } from '../../../service/game.service';
|
||||
import {DragDropModule} from '@angular/cdk/drag-drop';
|
||||
import {CdkDragHandle, DragDropModule} from '@angular/cdk/drag-drop';
|
||||
import {MatTooltipModule} from '@angular/material/tooltip';
|
||||
|
||||
@Component({
|
||||
selector: 'app-planet-dialog',
|
||||
imports: [CommonModule, MatDialogModule, DragDropModule],
|
||||
imports: [CommonModule, MatDialogModule, DragDropModule, MatTooltipModule, CdkDragHandle],
|
||||
templateUrl: './planet-dialog.component.html',
|
||||
styleUrl: './planet-dialog.component.scss'
|
||||
})
|
||||
@ -17,7 +18,6 @@ export class PlanetDialogComponent {
|
||||
public gameService: GameService = inject(GameService)
|
||||
|
||||
ngOnInit() {
|
||||
console.log(this.planet)
|
||||
}
|
||||
|
||||
|
||||
@ -67,5 +67,10 @@ export class PlanetDialogComponent {
|
||||
this.planet.upgradeHarbour()
|
||||
}
|
||||
|
||||
|
||||
buildHarbour() {
|
||||
this.planet.buildHarbour()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<div class="ui-panel" (click)="onClick($event)">
|
||||
|
||||
<div class="ui-title">
|
||||
<div class="ui-title" cdkDragHandle>
|
||||
<div class="image"><img [src]="'sprites/ships/01-starter.png'" alt=""></div>
|
||||
<div>{{ ship.name }}</div>
|
||||
</div>
|
||||
@ -70,7 +70,7 @@
|
||||
|
||||
|
||||
</div>
|
||||
<div class="ui-section">
|
||||
<div class="ui-section flex">
|
||||
<button class="button">Produktion upgraden</button>
|
||||
<button class="button">Siedeln</button>
|
||||
<button class="button" (click)="onClick($event); close();" >Schließen</button>
|
||||
|
||||
@ -2,12 +2,12 @@ import { CommonModule } from '@angular/common';
|
||||
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';
|
||||
import { CdkDragHandle } from '@angular/cdk/drag-drop';
|
||||
|
||||
@Component({
|
||||
selector: 'app-ship-dialog',
|
||||
imports: [CommonModule],
|
||||
imports: [CommonModule, CdkDragHandle],
|
||||
templateUrl: './ship-dialog.component.html',
|
||||
styleUrl: './ship-dialog.component.scss'
|
||||
})
|
||||
|
||||
86
src/app/components/ships/buy/buy.component.html
Normal file
86
src/app/components/ships/buy/buy.component.html
Normal file
@ -0,0 +1,86 @@
|
||||
<div class="ui-panel">
|
||||
<div class="ui-title" cdkDragHandle>
|
||||
Raumschiff einsetzen
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<div>🚀 Neues Schiff: Pioneer-1</div>
|
||||
<ul>
|
||||
<li class="flex">
|
||||
<div>Kosten: </div>
|
||||
<div>{{ config.buyCost | number:'0.0-2'}} Credits</div>
|
||||
</li>
|
||||
<li class="flex">
|
||||
<div>Frachtraum: </div>
|
||||
<div>{{ config.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>
|
||||
</li>
|
||||
|
||||
<li class="flex">
|
||||
<div>Unterhalt: </div>
|
||||
<div>{{ config.cost | number: '0.0-2'}} Credits</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<div>🛣️ Route festlegen:</div>
|
||||
@if (availablePlanets.length == 0) {
|
||||
<div style="margin-top: 12px;">
|
||||
Um Planeten anfliegen zu können, musst du einen Weltraumhafen bauen.
|
||||
</div>
|
||||
}
|
||||
<div class="flex route-containers">
|
||||
<div class="route-column">
|
||||
<div class="route-header">Ausgewählte Planeten</div>
|
||||
<div class="route-selection" cdkDropList #selected="cdkDropList"
|
||||
[cdkDropListData]="selectedPlanets"
|
||||
[cdkDropListConnectedTo]="[available]"
|
||||
(cdkDropListDropped)="drop($event)">
|
||||
@for (planet of selectedPlanets; track planet.name) {
|
||||
<div class="planet-option" cdkDrag>
|
||||
{{ planet.name }}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="route-column">
|
||||
<div class="route-header">Verfügbare Planeten</div>
|
||||
|
||||
<div class="route-selection" cdkDropList #available="cdkDropList"
|
||||
[cdkDropListData]="availablePlanets"
|
||||
[cdkDropListConnectedTo]="[selected]"
|
||||
(cdkDropListDropped)="drop($event)">
|
||||
@for (planet of availablePlanets; track planet.name) {
|
||||
<div class="planet-option" cdkDrag>
|
||||
{{ planet.name }}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<div>Ausgewählte Route:</div>
|
||||
<div class="flex route">
|
||||
@for (planet of selectedPlanets; track planet.name) {
|
||||
<div>{{ planet.name }}</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui-section flex">
|
||||
|
||||
<button class="button"
|
||||
[disabled]="selectedPlanets.length < 2 || !canAffordShip()"
|
||||
(click)="buyShip()">
|
||||
Schiff kaufen
|
||||
</button>
|
||||
<button class="button" (click)="close()">Abbrechen</button>
|
||||
</div>
|
||||
</div>
|
||||
56
src/app/components/ships/buy/buy.component.scss
Normal file
56
src/app/components/ships/buy/buy.component.scss
Normal file
@ -0,0 +1,56 @@
|
||||
:host {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
// width: 240px;
|
||||
// height: 240px;
|
||||
// background-color: var(--background-color);
|
||||
// color: var(--primary-color);
|
||||
width: 600px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.route-containers {
|
||||
gap: 16px;
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.route-column {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.route-header {
|
||||
font-size: 14px;
|
||||
color: var(--secundary-color);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.route-selection {
|
||||
min-height: 100px;
|
||||
border: 1px solid #202d3e;
|
||||
border-radius: 8px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.planet-option {
|
||||
padding: 8px;
|
||||
margin: 4px 0;
|
||||
background-color: #1c243b;
|
||||
border-radius: 4px;
|
||||
cursor: move;
|
||||
|
||||
&:hover {
|
||||
background-color: #3c8dbc;
|
||||
}
|
||||
}
|
||||
|
||||
.route {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
border: 1px solid #202d3e;
|
||||
border-radius: 4px;
|
||||
}
|
||||
23
src/app/components/ships/buy/buy.component.spec.ts
Normal file
23
src/app/components/ships/buy/buy.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { BuyComponent } from './buy.component';
|
||||
|
||||
describe('BuyComponent', () => {
|
||||
let component: BuyComponent;
|
||||
let fixture: ComponentFixture<BuyComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [BuyComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(BuyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
59
src/app/components/ships/buy/buy.component.ts
Normal file
59
src/app/components/ships/buy/buy.component.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, inject } from '@angular/core';
|
||||
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';
|
||||
|
||||
@Component({
|
||||
selector: 'app-buy',
|
||||
imports: [CommonModule, CdkDropList, CdkDrag, CdkDragHandle],
|
||||
templateUrl: './buy.component.html',
|
||||
styleUrl: './buy.component.scss'
|
||||
})
|
||||
export class BuyComponent {
|
||||
private gameService: GameService = inject(GameService);
|
||||
|
||||
availablePlanets: Planet[] = this.gameService.planets.filter(p => p.hasHarbour);
|
||||
selectedPlanets: Planet[] = [];
|
||||
config: ShipConfig = {
|
||||
name: 'Pioneer-01',
|
||||
acceleration: 500,
|
||||
cargoSize: 10,
|
||||
cost: 0.6,
|
||||
loadingSpeed: 25,
|
||||
maxSpeed: 500,
|
||||
planetRoute: [],
|
||||
buyCost: 2000
|
||||
}
|
||||
|
||||
canAffordShip() {
|
||||
return this.gameService.money >= 3000;
|
||||
}
|
||||
|
||||
buyShip() {
|
||||
if (!this.canAffordShip()) return;
|
||||
this.gameService.createShip({
|
||||
...this.config,
|
||||
planetRoute: this.selectedPlanets
|
||||
})
|
||||
this.close();
|
||||
}
|
||||
|
||||
close() {
|
||||
this.gameService.showBuyShip = false;
|
||||
}
|
||||
|
||||
drop(event: CdkDragDrop<Planet[]>) {
|
||||
if (event.previousContainer === event.container) {
|
||||
moveItemInArray(event.container.data, event.previousIndex, event.currentIndex);
|
||||
} else {
|
||||
transferArrayItem(
|
||||
event.previousContainer.data,
|
||||
event.container.data,
|
||||
event.previousIndex,
|
||||
event.currentIndex,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
8
src/app/components/status-bar/status-bar.component.html
Normal file
8
src/app/components/status-bar/status-bar.component.html
Normal file
@ -0,0 +1,8 @@
|
||||
<div (click)="onClick($event)" (mousedown)="onClick($event)" class="flex gamebar">
|
||||
|
||||
<div class="gold">
|
||||
Credits: {{gameService.money | number:'0.0-0'}}
|
||||
</div>
|
||||
|
||||
<button class="button" (click)="toggleBuy()" >Schiffe</button>
|
||||
</div>
|
||||
11
src/app/components/status-bar/status-bar.component.scss
Normal file
11
src/app/components/status-bar/status-bar.component.scss
Normal file
@ -0,0 +1,11 @@
|
||||
:host {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 40%;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.gamebar {
|
||||
align-items: center;
|
||||
}
|
||||
23
src/app/components/status-bar/status-bar.component.spec.ts
Normal file
23
src/app/components/status-bar/status-bar.component.spec.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { StatusBarComponent } from './status-bar.component';
|
||||
|
||||
describe('StatusBarComponent', () => {
|
||||
let component: StatusBarComponent;
|
||||
let fixture: ComponentFixture<StatusBarComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [StatusBarComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(StatusBarComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
26
src/app/components/status-bar/status-bar.component.ts
Normal file
26
src/app/components/status-bar/status-bar.component.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { GameService } from '../../service/game.service';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
@Component({
|
||||
selector: 'app-status-bar',
|
||||
imports: [CommonModule],
|
||||
templateUrl: './status-bar.component.html',
|
||||
styleUrl: './status-bar.component.scss'
|
||||
})
|
||||
export class StatusBarComponent {
|
||||
public gameService: GameService = inject(GameService);
|
||||
|
||||
|
||||
onClick(event: any) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
print() {
|
||||
console.log("PRI")
|
||||
}
|
||||
|
||||
toggleBuy() {
|
||||
this.gameService.showBuyShip = !this.gameService.showBuyShip;
|
||||
}
|
||||
}
|
||||
57
src/app/components/tutorial/welcome/welcome.component.html
Normal file
57
src/app/components/tutorial/welcome/welcome.component.html
Normal file
@ -0,0 +1,57 @@
|
||||
<div class="ui-panel welcome-container">
|
||||
<div class="ui-title">
|
||||
<h1>🚀 Willkommen bei StellarLines</h1>
|
||||
</div>
|
||||
|
||||
<div class="ui-body">
|
||||
<div class="ui-section">
|
||||
<h2>Deine interplanetare Handelsgesellschaft</h2>
|
||||
<p>
|
||||
Willkommen im Jahr 2184!
|
||||
<br>
|
||||
<br>
|
||||
Als aufstrebender Unternehmer ist es deine Aufgabe,
|
||||
ein florierendes Handelsnetzwerk zwischen den Planeten aufzubauen. Gründe ein
|
||||
interplanetares Frachtunternehmen, transportiere wichtige Güter zwischen den
|
||||
Kolonien und erwirtschafte Profite mit jedem erfolgreichen Transport.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<h3>🎯 Deine Ziele:</h3>
|
||||
<ul>
|
||||
<li>Errichte Raumhäfen auf verschiedenen Planeten</li>
|
||||
<li>Baue Handelsrouten zwischen den Planeten auf</li>
|
||||
<li>Versorge die Siedlungen mit wichtigen Gütern</li>
|
||||
<li>Erweitere deine Handelsflotte</li>
|
||||
<li>Schaffe prosperierende Kolonien</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<h3>🎮 So spielst du:</h3>
|
||||
<ol>
|
||||
<li>Wähle einen Planeten und baue einen Raumhafen</li>
|
||||
<li>Kaufe dein erstes Handelsschiff (Hierfür brauchst du 2 Planeten)</li>
|
||||
<li>Lege Handelsrouten zwischen Planeten fest</li>
|
||||
<li>Versorge die Siedlungen mit Rohstoffen</li>
|
||||
<li>Erwirtschafte Gewinne durch geschickten Handel</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="ui-section tips">
|
||||
<h3>💡 Tipp:</h3>
|
||||
<p>
|
||||
Achte auf die Bedürfnisse der Siedlungen. Gut versorgte Kolonien wachsen und
|
||||
erhöhen ihren Bedarf an Waren. Bei Mangel wandern die Siedler ab! Für den Anfang benötigen die Kolonien nur Nahrung und Wasser. Mit wachsender Bevölkerung steigt auch der Bedarf an weiteren Rohstoffen.
|
||||
<br><br>
|
||||
Du beginnst mit 10.000 Credits. Gib sie weise aus, Schiffe und Raumhäfen kosten Unterhalt. Je mehr Waren du transportierst, desto mehr Geld verdienst du auch. Planeten kaufen allerdings nur Waren, die sie auch brauchen.
|
||||
Schiffe auf Handelsrouten fliegen die Planeten ab, und versorgen sie automatisch mit den Gütern die sie benötigen.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="ui-section">
|
||||
<button class="button" (click)="close()" >Spiel starten</button>
|
||||
</div>
|
||||
</div>
|
||||
20
src/app/components/tutorial/welcome/welcome.component.scss
Normal file
20
src/app/components/tutorial/welcome/welcome.component.scss
Normal file
@ -0,0 +1,20 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 24px;
|
||||
right: 24px;
|
||||
bottom: 24px;
|
||||
}
|
||||
|
||||
.ui-body{
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ui-panel {
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { WelcomeComponent } from './welcome.component';
|
||||
|
||||
describe('WelcomeComponent', () => {
|
||||
let component: WelcomeComponent;
|
||||
let fixture: ComponentFixture<WelcomeComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [WelcomeComponent]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
fixture = TestBed.createComponent(WelcomeComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
18
src/app/components/tutorial/welcome/welcome.component.ts
Normal file
18
src/app/components/tutorial/welcome/welcome.component.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { GameService } from '../../../service/game.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-welcome',
|
||||
imports: [],
|
||||
templateUrl: './welcome.component.html',
|
||||
styleUrl: './welcome.component.scss'
|
||||
})
|
||||
export class WelcomeComponent {
|
||||
|
||||
gameService = inject(GameService);
|
||||
|
||||
|
||||
close() {
|
||||
this.gameService.showTutorial = false;
|
||||
}
|
||||
}
|
||||
@ -3,21 +3,20 @@ import { PlanetInit } from "../model/planet.model";
|
||||
|
||||
export const PLANETCONFIGS: { x: number, y: number, texture: string, config: PlanetInit}[] = [
|
||||
{
|
||||
x: 200,
|
||||
y: 300,
|
||||
x: 600,
|
||||
y: 800,
|
||||
texture: 'terra-nova',
|
||||
config: {
|
||||
name: 'Terra Nova',
|
||||
initialGoods: [
|
||||
{ type: GoodType.Wasser, amount: 120 },
|
||||
{ type: GoodType.Nahrung, amount: 80, productionBonus: 1.3 },
|
||||
{ type: GoodType.Erz, amount: 100 }
|
||||
{ type: GoodType.Wasser, amount: 15 },
|
||||
{ type: GoodType.Nahrung, amount: 8, productionBonus: 1.3 },
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
x: 600,
|
||||
y: 200,
|
||||
x: 3000,
|
||||
y: 900,
|
||||
texture: 'mechanica-prime',
|
||||
config: {
|
||||
name: 'Mechanica Prime',
|
||||
@ -31,21 +30,21 @@ export const PLANETCONFIGS: { x: number, y: number, texture: string, config: Pla
|
||||
}
|
||||
},
|
||||
{
|
||||
x: 400,
|
||||
y: 700,
|
||||
x: 1800,
|
||||
y: 2800,
|
||||
texture: 'aqualis',
|
||||
config: {
|
||||
name: 'Aqualis',
|
||||
initialGoods: [
|
||||
{ type: GoodType.Wasser, amount: 300, productionBonus: 2.0 },
|
||||
{ type: GoodType.Nahrung, amount: 60 },
|
||||
{ type: GoodType.Wasser, amount: 30, productionBonus: 2.0 },
|
||||
{ type: GoodType.Nahrung, amount: 15 },
|
||||
{ type: GoodType.Treibstoff, amount: 10 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
x: 900,
|
||||
y: 500,
|
||||
x: 3900,
|
||||
y: 2500,
|
||||
texture: 'planet',
|
||||
config: {
|
||||
name: 'Ferron',
|
||||
@ -59,8 +58,8 @@ export const PLANETCONFIGS: { x: number, y: number, texture: string, config: Pla
|
||||
}
|
||||
},
|
||||
{
|
||||
x: 800,
|
||||
y: 800,
|
||||
x: 5400,
|
||||
y: 1400,
|
||||
texture: 'novus-reach',
|
||||
config: {
|
||||
name: 'Novus Reach',
|
||||
@ -71,4 +70,31 @@ export const PLANETCONFIGS: { x: number, y: number, texture: string, config: Pla
|
||||
]
|
||||
}
|
||||
}
|
||||
,
|
||||
{
|
||||
x: 3700,
|
||||
y: 4600,
|
||||
texture: 'novus-reach',
|
||||
config: {
|
||||
name: 'Novus Reach 2',
|
||||
initialGoods: [
|
||||
{ type: GoodType.Nahrung, amount: 90, productionBonus: 1.5 },
|
||||
{ type: GoodType.Wasser, amount: 50 },
|
||||
{ type: GoodType.Bauteile, amount: 15 }
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
x: 6000,
|
||||
y: 3600,
|
||||
texture: 'terra-nova',
|
||||
config: {
|
||||
name: 'Terra Nova 2',
|
||||
initialGoods: [
|
||||
{ type: GoodType.Wasser, amount: 120 },
|
||||
{ type: GoodType.Nahrung, amount: 80, productionBonus: 1.3 },
|
||||
{ type: GoodType.Erz, amount: 100 }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
@ -9,8 +9,8 @@ export interface GoodConfig {
|
||||
|
||||
export const GOODS_DATA: Record<GoodType, GoodConfig> = {
|
||||
[GoodType.Erz]: { baseProduction: 1.0, baseDemand: 0, storageLimit: 500, isRawResource: true },
|
||||
[GoodType.Wasser]: { baseProduction: 1, baseDemand: 0.015, storageLimit: 300, isRawResource: true },
|
||||
[GoodType.Nahrung]: { baseProduction: 1, baseDemand: 0.01, storageLimit: 200, 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.Treibstoff]: { baseProduction: 1, baseDemand: 0, storageLimit: 150, isRawResource: false },
|
||||
[GoodType.Elektronik]: { baseProduction: 1, baseDemand: 0, storageLimit: 100, isRawResource: false },
|
||||
|
||||
@ -1,8 +1,7 @@
|
||||
import { interval, Subscription } from "rxjs";
|
||||
import { interval } from "rxjs";
|
||||
import { GoodType } from "./goods/good-type.enum";
|
||||
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";
|
||||
|
||||
@ -17,7 +16,7 @@ export class Planet {
|
||||
public isGrowing: boolean = false;
|
||||
private populationGrowthRate = 0.002; // Basiswachstum pro Tick (%)
|
||||
private populationDeclineRate = 0.005; // Basisrückgang bei Mangel (%)
|
||||
demandSecondsBuffer = 30; // Anfrage immer mindestens 30 Sekunden überleben
|
||||
demandSecondsBuffer = 150; // Anfrage immer mindestens 30 Sekunden überleben
|
||||
|
||||
private productionLevel: Map<GoodType, number> = new Map();
|
||||
private dockedShips: Ship[] = [];
|
||||
@ -26,6 +25,8 @@ export class Planet {
|
||||
|
||||
private gameService: GameService;
|
||||
|
||||
hasHarbour = false;
|
||||
|
||||
|
||||
constructor(config: PlanetInit, gameService: GameService) {
|
||||
this.name = config.name;
|
||||
@ -133,12 +134,14 @@ 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.
|
||||
}
|
||||
|
||||
result.push({
|
||||
amount: demand * 3, // Request 3x buffer amount
|
||||
amount: demand * 5, // Request 3x buffer amount
|
||||
type: good.type,
|
||||
target: this.name,
|
||||
})
|
||||
@ -286,10 +289,7 @@ export class Planet {
|
||||
}
|
||||
|
||||
undock(ship: Ship) {
|
||||
console.log("undock", ship.name)
|
||||
this.dockedShips = this.dockedShips.filter(d => d != ship);
|
||||
console.log('Angedockt: ',this.dockedShips.map(d => d.name).join(','))
|
||||
console.log('wartend: ',this.shipsWaitingForDocking.map(d => d.name).join(','))
|
||||
}
|
||||
|
||||
get goodsInTransit(): TradeInstance[] {
|
||||
@ -303,6 +303,12 @@ export class Planet {
|
||||
this.dockCapacity++;
|
||||
}
|
||||
|
||||
|
||||
buildHarbour() {
|
||||
this.hasHarbour = true;
|
||||
this.gameService.money -= 3000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export interface PlanetInit {
|
||||
|
||||
@ -8,23 +8,23 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
|
||||
private velocity = new Phaser.Math.Vector2(0, 0);
|
||||
private target: PlanetUi | null = null;
|
||||
private targetVector: Phaser.Math.Vector2 | null = null; // Später Planet!
|
||||
public model: Ship = new Ship();
|
||||
public model: Ship;
|
||||
public gameService: GameService;
|
||||
|
||||
private orbitAngle: number = 0;
|
||||
private orbitRadius: number = 120;
|
||||
private orbitSpeed: number = Math.PI / 25; // Eine Runde in 2 Sekunden
|
||||
|
||||
constructor(scene: MapScene, x: number, y: number, gameService: GameService) {
|
||||
constructor(scene: MapScene, x: number, y: number, gameService: GameService, ship: Ship) {
|
||||
super(scene, x, y, 'ship');
|
||||
this.gameService = gameService;
|
||||
|
||||
this.model = ship;
|
||||
|
||||
scene.add.existing(this);
|
||||
scene.physics.add.existing(this);
|
||||
this.setOrigin(0.5);
|
||||
this.setScale(1); // oder z. B. 0.5 je nach Bildgröße
|
||||
this.setDisplaySize(32, 32)
|
||||
this.setDisplaySize(96, 128)
|
||||
this.setCollideWorldBounds(true);
|
||||
const conf: Phaser.Types.Input.InputConfiguration = {
|
||||
useHandCursor: true
|
||||
@ -62,7 +62,7 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
|
||||
|
||||
switch (this.model.flightMode) {
|
||||
case FlightMode.Normal:
|
||||
if (distance < 150) {
|
||||
if (distance < (this.target.height / 2) + 100) {
|
||||
this.startOrbit(this.target);
|
||||
return;
|
||||
}
|
||||
@ -73,7 +73,7 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
|
||||
break;
|
||||
case FlightMode.Docking:
|
||||
this.flyDirectlyToTarget(to, dt);
|
||||
if (distance < 5) {
|
||||
if (distance < 150) {
|
||||
this.land();
|
||||
}
|
||||
break;
|
||||
@ -104,21 +104,21 @@ export class ShipUi extends Phaser.Physics.Arcade.Sprite {
|
||||
|
||||
this.velocity.set(Math.cos(angle) * this.model.currentSpeed, Math.sin(angle) * this.model.currentSpeed);
|
||||
this.body.setVelocity(this.velocity.x, this.velocity.y);
|
||||
this.setRotation(this.velocity.angle() + Phaser.Math.DegToRad(180));
|
||||
this.setRotation(this.velocity.angle() + Phaser.Math.DegToRad(90));
|
||||
}
|
||||
|
||||
private updateOrbit(center: Phaser.Math.Vector2, dt: number): void {
|
||||
if (!(this.body instanceof Phaser.Physics.Arcade.Body)) { return; }
|
||||
this.orbitAngle += this.orbitSpeed * dt;
|
||||
|
||||
const targetX = center.x + Math.cos(this.orbitAngle) * this.orbitRadius;
|
||||
const targetY = center.y + Math.sin(this.orbitAngle) * this.orbitRadius;
|
||||
const targetX = center.x + Math.cos(this.orbitAngle) * this.target!.height / 2;
|
||||
const targetY = center.y + Math.sin(this.orbitAngle) * this.target!.height / 2;
|
||||
|
||||
const desiredVelocityX = (targetX - this.getWorldPoint().x) * 5;
|
||||
const desiredVelocityY = (targetY - this.getWorldPoint().y) * 5;
|
||||
this.body.setVelocity(desiredVelocityX, desiredVelocityY);
|
||||
|
||||
this.setRotation(this.body.velocity.angle() + Phaser.Math.DegToRad(180));
|
||||
this.setRotation(this.body.velocity.angle() + Phaser.Math.DegToRad(90));
|
||||
|
||||
// Umdrehungen zählen
|
||||
if (this.orbitAngle >= Math.PI * 2) {
|
||||
|
||||
@ -1,17 +1,49 @@
|
||||
import { interval } from "rxjs";
|
||||
import { Good } from "../goods/good.interface";
|
||||
import { Planet, TradeInstance } from "../planet.model";
|
||||
import { TradeRoute } from "../routes/trade-route.model";
|
||||
import { GameService } from "../../service/game.service";
|
||||
|
||||
export interface ShipConfig {
|
||||
name: string;
|
||||
cargoSize: number;
|
||||
acceleration: number;
|
||||
maxSpeed: number;
|
||||
loadingSpeed: number;
|
||||
cost: number;
|
||||
planetRoute: Planet[];
|
||||
buyCost: number;
|
||||
}
|
||||
|
||||
export class Ship {
|
||||
public acceleration = 10; // Pixel pro Sekunde²
|
||||
public maxSpeed = 100;
|
||||
public acceleration = 20; // Pixel pro Sekunde²
|
||||
public maxSpeed = 500;
|
||||
public currentSpeed = 0;
|
||||
|
||||
public cargoSize = 50;
|
||||
public cargoSize = 10;
|
||||
cargoSpace: TradeInstance[] = [];
|
||||
public route: TradeRoute | undefined = new TradeRoute([])
|
||||
public name = "Pioneer-01-" + Math.round(Math.random() * 100);
|
||||
public loadingSpeed = 3.5;
|
||||
public cost = 0.5
|
||||
|
||||
private updateInterval = interval(1000);
|
||||
private gameService: GameService;
|
||||
|
||||
constructor(gameService: GameService, config: ShipConfig) {
|
||||
this.gameService = gameService;
|
||||
this.acceleration = config.acceleration;
|
||||
this.cargoSize = config.cargoSize;
|
||||
this.maxSpeed = config.maxSpeed;
|
||||
this.loadingSpeed = config.loadingSpeed;
|
||||
this.cost = config.cost;
|
||||
this.route = new TradeRoute(config.planetRoute)
|
||||
|
||||
this.updateInterval.subscribe(() => {
|
||||
this.update();
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
public status: 'loading' | 'unloading' | 'waiting' | 'idle' | 'traveling' = 'idle';
|
||||
public flightMode: FlightMode = FlightMode.Normal;
|
||||
@ -89,6 +121,7 @@ export class Ship {
|
||||
if (existing) {
|
||||
existing.amount -= (cargo.amount / steps);
|
||||
to.amount += (cargo.amount / steps);
|
||||
this.gameService.money += 5;
|
||||
}
|
||||
await this.waitForLoading(1)
|
||||
}
|
||||
@ -126,6 +159,10 @@ export class Ship {
|
||||
}, amount * 1000 / this.loadingSpeed)
|
||||
})
|
||||
}
|
||||
|
||||
update() {
|
||||
this.gameService.money -= this.cost;
|
||||
}
|
||||
}
|
||||
|
||||
export enum FlightMode {
|
||||
|
||||
@ -21,14 +21,14 @@ export class MapScene extends Phaser.Scene {
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.image('ship', 'sprites/ships/01-starter.png');
|
||||
this.load.image('ship', 'sprites/ships/swift-hauler.png');
|
||||
this.load.image('harbour', 'sprites/buildings/harbour.png');
|
||||
this.load.image('planet', 'sprites/planets/sm/planet-1.png');
|
||||
this.load.image('terra-nova', 'sprites/planets/sm/terra-nova.png');
|
||||
this.load.image('mechanica-prime', 'sprites/planets/sm/mechanica-prime.png');
|
||||
this.load.image('novus-reach', 'sprites/planets/sm/novus-reach.png');
|
||||
this.load.image('aqualis', 'sprites/planets/sm/aqualis.png');
|
||||
this.load.image('ferron', 'sprites/planets/sm/ferron.png');
|
||||
this.load.image('planet', 'sprites/planets/planet-1.png');
|
||||
this.load.image('terra-nova', 'sprites/planets/terra-nova.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');
|
||||
this.load.image('ferron', 'sprites/planets/ferron.png');
|
||||
}
|
||||
|
||||
create() {
|
||||
@ -79,7 +79,7 @@ export class MapScene extends Phaser.Scene {
|
||||
const now = Date.now();
|
||||
if (now - this.lastZoomTime < 50) return; // nur alle 100ms
|
||||
this.lastZoomTime = now;
|
||||
const factor = 1.05;
|
||||
const factor = 1.1;
|
||||
if (deltaY > 0) {
|
||||
this.camera.setZoom(this.camera.zoom / factor);
|
||||
} else {
|
||||
@ -91,23 +91,20 @@ export class MapScene extends Phaser.Scene {
|
||||
this.camera.setZoom(Phaser.Math.Clamp(this.camera.zoom, minScale, 1));
|
||||
});
|
||||
|
||||
this.createShip();
|
||||
setTimeout(() => {
|
||||
this.createShip();
|
||||
}, 100)
|
||||
this.camera.setZoom(0.4)
|
||||
|
||||
|
||||
|
||||
this.gameService.onShipCreate.subscribe(ship => {
|
||||
const ui = new ShipUi(this, 100, 100, this.gameService, ship);
|
||||
ui.activateRoute();
|
||||
this.physics.world.enable(ui);
|
||||
this.ships.push(ui);
|
||||
})
|
||||
// this.enableMouseLogging();
|
||||
|
||||
}
|
||||
|
||||
createShip() {
|
||||
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))
|
||||
this.ships.push(s)
|
||||
this.physics.world.enable(s);
|
||||
s.activateRoute();
|
||||
this.gameService.ships.push(s.model)
|
||||
}
|
||||
|
||||
override update(time: number, delta: number): void {
|
||||
if (this.ship) {
|
||||
@ -132,6 +129,7 @@ export class MapScene extends Phaser.Scene {
|
||||
});
|
||||
this.planets.push(planet);
|
||||
this.gameService.planets.push(planet.model);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -146,4 +144,20 @@ export class MapScene extends Phaser.Scene {
|
||||
getPlanetUiByName(name: string) {
|
||||
return this.planets.find(p => p.model.name == name);
|
||||
}
|
||||
|
||||
enableMouseLogging() {
|
||||
let mouseText: Phaser.GameObjects.Text;
|
||||
|
||||
this.input.on('pointermove', (pointer: Phaser.Input.Pointer) => {
|
||||
if (!mouseText) {
|
||||
mouseText = this.add.text(30, 30, '', {
|
||||
fontSize: '160px',
|
||||
color: '#00ff00',
|
||||
backgroundColor: '#000000',
|
||||
padding: { x: 5, y: 2 }
|
||||
}).setScrollFactor(0).setDepth(9999);
|
||||
}
|
||||
mouseText.setText(`X: ${pointer.worldX.toFixed(0)}\nY: ${pointer.worldY.toFixed(0)}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import { MatDialog, MatDialogRef } from "@angular/material/dialog";
|
||||
import { PlanetDialogComponent } from "../components/dialog/planet-dialog/planet-dialog.component";
|
||||
import { EventEmitter, Injectable } from "@angular/core";
|
||||
import { Planet } from "../model/planet.model";
|
||||
import { Ship } from "../model/ships/ship.model";
|
||||
import { Ship, ShipConfig } from "../model/ships/ship.model";
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
@ -10,10 +8,17 @@ import { Ship } from "../model/ships/ship.model";
|
||||
export class GameService {
|
||||
public showPlanetInfo: Planet | undefined;
|
||||
public showShipInfo: Ship | undefined;
|
||||
public showBuyShip = false;
|
||||
|
||||
public ships: Ship[] = [];
|
||||
public planets: Planet[] = [];
|
||||
|
||||
showTutorial = true;
|
||||
|
||||
public money = 10000;
|
||||
|
||||
onShipCreate: EventEmitter<Ship> = new EventEmitter();
|
||||
|
||||
constructor() {}
|
||||
|
||||
showDialog(planet: Planet) {
|
||||
@ -27,4 +32,15 @@ export class GameService {
|
||||
get canDrag(): boolean {
|
||||
return this.showShipInfo == undefined && this.showPlanetInfo == undefined;
|
||||
}
|
||||
|
||||
|
||||
createShip(config: ShipConfig) {
|
||||
if (this.money < config.buyCost) {
|
||||
return;
|
||||
}
|
||||
this.money -= config.buyCost;
|
||||
const ship = new Ship(this, config);
|
||||
this.ships.push(ship);
|
||||
this.onShipCreate.emit(ship);
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,7 @@ export class PlanetStatus {
|
||||
}
|
||||
|
||||
update() {
|
||||
this.container.setScale(1 / this.scene.cameras.main.zoom)
|
||||
const population = Math.floor(this.getPopulation());
|
||||
const growth = this.getGrowthState();
|
||||
const criticalGoods = this.getCriticalGoods();
|
||||
@ -41,7 +42,13 @@ export class PlanetStatus {
|
||||
criticalText = ' 🛑 ' + criticalGoods.map(g => g.toString().substring(0, 2)).join(',');
|
||||
}
|
||||
|
||||
this.text.setText(`${this.planetSprite.model.name}, 👥 ${population} ${growthSymbol}${criticalText}`);
|
||||
let text = `${this.planetSprite.model.name}`;
|
||||
|
||||
if (this.planetSprite.model.hasHarbour) {
|
||||
text += `, 👥 ${population} ${growthSymbol}${criticalText}`
|
||||
}
|
||||
|
||||
this.text.setText(text);
|
||||
|
||||
// Position immer über Planet aktualisieren
|
||||
this.container.setPosition(this.planetSprite.x, this.planetSprite.y - (this.planetSprite.height / 2) - 5);
|
||||
|
||||
@ -10,6 +10,7 @@ export class PlanetUi extends Phaser.Physics.Arcade.Sprite {
|
||||
public rightClick: EventEmitter<PlanetUi> = new EventEmitter();
|
||||
public model: Planet;
|
||||
private status: PlanetStatus | undefined;
|
||||
private harbourImage!: any;
|
||||
|
||||
private updateInterval = interval(1000)
|
||||
|
||||
@ -41,8 +42,11 @@ export class PlanetUi extends Phaser.Physics.Arcade.Sprite {
|
||||
this.updateInterval.subscribe(() => this.update())
|
||||
|
||||
|
||||
const image = this.scene.add.image(this.getWorldPoint().x, this.getWorldPoint().y, 'harbour')
|
||||
image.setDisplaySize(64, 96);
|
||||
this.harbourImage = this.scene.add.image(this.getWorldPoint().x, this.getWorldPoint().y, 'harbour')
|
||||
this.harbourImage.setDisplaySize(164, 256);
|
||||
this.harbourImage.setVisible(false);
|
||||
|
||||
// this.setScale(0.5)
|
||||
|
||||
// this.setInteractive(new Phaser.Geom.Circle(x, y, 200), Phaser.Geom.Circle.Contains);
|
||||
}
|
||||
@ -65,6 +69,8 @@ export class PlanetUi extends Phaser.Physics.Arcade.Sprite {
|
||||
}
|
||||
|
||||
this.status?.update();
|
||||
this.harbourImage.setVisible(this.model.hasHarbour)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,9 +5,13 @@ $color-background: #0b1120;
|
||||
$color-panel: #1c243b;
|
||||
$color-text-primary: #e0f0ff;
|
||||
$color-text-secondary: #a0b8d8;
|
||||
$color-water: #4fc1e9;
|
||||
$color-food: #f7c06b;
|
||||
$color-water: #137092;
|
||||
$color-food: #a87f41;
|
||||
$color-ore: #c1543a;
|
||||
$color-metal: #4d4d4d;
|
||||
$color-fuel: #2e5c2d;
|
||||
$color-electronics: #4d2d6b;
|
||||
$color-workparts: #441631;
|
||||
$color-success: #4CAF50;
|
||||
$color-error: #f44336;
|
||||
$color-button: #1c243b;
|
||||
@ -86,6 +90,10 @@ $font-size-base: 14px;
|
||||
&.wasser .progress-fill { background-color: $color-water; }
|
||||
&.nahrung .progress-fill { background-color: $color-food; }
|
||||
&.erz .progress-fill { background-color: $color-ore; }
|
||||
&.metall .progress-fill { background-color: $color-metal; }
|
||||
&.treibstoff .progress-fill { background-color: $color-fuel; }
|
||||
&.elektronik .progress-fill { background-color: $color-electronics; }
|
||||
&.bauteile .progress-fill { background-color: $color-workparts; }
|
||||
}
|
||||
|
||||
.button {
|
||||
@ -113,6 +121,7 @@ $font-size-base: 14px;
|
||||
.flex {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.ui-body > .ui-section {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user