mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-26 09:14:36 +00:00
hit space bar for alternate view
This commit is contained in:
@@ -243,14 +243,16 @@
|
||||
* store and archive player cookies DONE 12/17/2024
|
||||
* make ips less precise for user safety DONE 12/17/2024
|
||||
* send client logs back to server DONE 12/18/2024
|
||||
* render more info in info overlay
|
||||
* render more info in info overlay DONE 12/19/2024
|
||||
* create alternate view for freinds enemies DONE 12/19/2024
|
||||
* give naval units health
|
||||
* create more prominant discord link
|
||||
* right click brings up player info menu
|
||||
* create new view for enemies & personal units
|
||||
* send client logs back to server DONE 12/17/2024
|
||||
* make info panel merge with X, display more info
|
||||
* right click brings up player info menu
|
||||
* seperate server config from client config
|
||||
* give naval units health
|
||||
* bug: player names not updating sometimes
|
||||
* make player editeable configs
|
||||
* couldn't scroll left on build menu to deploy bombs (mobile)
|
||||
|
||||
@@ -44,6 +44,10 @@ export class DragEvent implements GameEvent {
|
||||
) { }
|
||||
}
|
||||
|
||||
export class AlternateViewEvent implements GameEvent {
|
||||
constructor(public readonly alternateView: boolean) { }
|
||||
}
|
||||
|
||||
export class InputHandler {
|
||||
|
||||
private lastPointerX: number = 0;
|
||||
@@ -58,6 +62,8 @@ export class InputHandler {
|
||||
|
||||
private pointerDown: boolean = false
|
||||
|
||||
private alternateView = false
|
||||
|
||||
constructor(private canvas: HTMLCanvasElement, private eventBus: EventBus) { }
|
||||
|
||||
initialize() {
|
||||
@@ -72,6 +78,25 @@ export class InputHandler {
|
||||
this.eventBus.emit(new MouseMoveEvent(e.clientX, e.clientY))
|
||||
});
|
||||
this.pointers.clear()
|
||||
|
||||
|
||||
window.addEventListener('keydown', (e) => {
|
||||
if (e.code === 'Space') {
|
||||
e.preventDefault(); // Prevent page scrolling
|
||||
if (!this.alternateView) {
|
||||
this.alternateView = true
|
||||
this.eventBus.emit(new AlternateViewEvent(true))
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener('keyup', (e) => {
|
||||
if (e.code === 'Space') {
|
||||
e.preventDefault();
|
||||
this.alternateView = false
|
||||
this.eventBus.emit(new AlternateViewEvent(false))
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private onPointerDown(event: PointerEvent) {
|
||||
|
||||
@@ -75,7 +75,7 @@ export function createRenderer(canvas: HTMLCanvasElement, game: Game, eventBus:
|
||||
new TerrainLayer(game),
|
||||
new TerritoryLayer(game, eventBus),
|
||||
new StructureLayer(game, eventBus),
|
||||
new UnitLayer(game, eventBus),
|
||||
new UnitLayer(game, eventBus, clientID),
|
||||
new NameLayer(game, game.config().theme(), transformHandler, clientID),
|
||||
new UILayer(eventBus, game, clientID, transformHandler),
|
||||
eventsDisplay,
|
||||
|
||||
@@ -1,10 +1,17 @@
|
||||
import { Colord } from "colord";
|
||||
import { Theme } from "../../../core/configuration/Config";
|
||||
import { Unit, UnitEvent, Cell, Game, Tile, UnitType } from "../../../core/game/Game";
|
||||
import { Unit, UnitEvent, Cell, Game, Tile, UnitType, Player } from "../../../core/game/Game";
|
||||
import { bfs, dist, euclDist } from "../../../core/Util";
|
||||
import { Layer } from "./Layer";
|
||||
import { EventBus } from "../../../core/EventBus";
|
||||
import { consolex } from "../../../core/Consolex";
|
||||
import { AlternateViewEvent } from "../../InputHandler";
|
||||
import { ClientID } from "../../../core/Schemas";
|
||||
|
||||
enum Relationship {
|
||||
Self,
|
||||
Ally,
|
||||
Enemy
|
||||
}
|
||||
|
||||
export class UnitLayer implements Layer {
|
||||
private canvas: HTMLCanvasElement;
|
||||
@@ -14,7 +21,12 @@ export class UnitLayer implements Layer {
|
||||
|
||||
private theme: Theme = null;
|
||||
|
||||
constructor(private game: Game, private eventBus: EventBus) {
|
||||
private alternateView = false
|
||||
|
||||
private myPlayer: Player | null = null
|
||||
|
||||
|
||||
constructor(private game: Game, private eventBus: EventBus, private clientID: ClientID) {
|
||||
this.theme = game.config().theme();
|
||||
}
|
||||
|
||||
@@ -24,6 +36,9 @@ export class UnitLayer implements Layer {
|
||||
}
|
||||
|
||||
tick() {
|
||||
if (this.myPlayer == null) {
|
||||
this.myPlayer = this.game.playerByClientID(this.clientID)
|
||||
}
|
||||
}
|
||||
|
||||
init(game: Game) {
|
||||
@@ -34,6 +49,7 @@ export class UnitLayer implements Layer {
|
||||
this.canvas.height = this.game.height();
|
||||
|
||||
this.eventBus.on(UnitEvent, e => this.onUnitEvent(e));
|
||||
this.eventBus.on(AlternateViewEvent, e => this.onAlternativeViewEvent(e))
|
||||
}
|
||||
|
||||
renderLayer(context: CanvasRenderingContext2D) {
|
||||
@@ -46,6 +62,31 @@ export class UnitLayer implements Layer {
|
||||
);
|
||||
}
|
||||
|
||||
onAlternativeViewEvent(event: AlternateViewEvent) {
|
||||
this.alternateView = event.alternateView
|
||||
this.redraw()
|
||||
}
|
||||
|
||||
|
||||
redraw() {
|
||||
for (const unit of this.game.units()) {
|
||||
this.onUnitEvent(new UnitEvent(unit, unit.tile()))
|
||||
}
|
||||
}
|
||||
|
||||
private relationship(unit: Unit): Relationship {
|
||||
if (this.myPlayer == null) {
|
||||
return Relationship.Enemy
|
||||
}
|
||||
if (this.myPlayer == unit.owner()) {
|
||||
return Relationship.Self
|
||||
}
|
||||
if (this.myPlayer.isAlliedWith(unit.owner())) {
|
||||
return Relationship.Ally
|
||||
}
|
||||
return Relationship.Enemy
|
||||
}
|
||||
|
||||
onUnitEvent(event: UnitEvent) {
|
||||
switch (event.unit.type()) {
|
||||
case UnitType.TransportShip:
|
||||
@@ -71,6 +112,7 @@ export class UnitLayer implements Layer {
|
||||
}
|
||||
|
||||
private handleDestroyerEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 4)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
@@ -78,12 +120,13 @@ export class UnitLayer implements Layer {
|
||||
return
|
||||
}
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), 4))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 3))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
|
||||
private handleBattleshipEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 6)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
@@ -91,48 +134,52 @@ export class UnitLayer implements Layer {
|
||||
return
|
||||
}
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), 5))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 4))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
|
||||
private handleShellEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
this.clearCell(event.oldTile.cell())
|
||||
if (!event.unit.isActive()) {
|
||||
return
|
||||
}
|
||||
this.paintCell(event.unit.tile().cell(), this.theme.borderColor(event.unit.owner().info()), 255)
|
||||
this.paintCell(event.unit.tile().cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255)
|
||||
}
|
||||
|
||||
|
||||
private handleNuke(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 2)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
if (event.unit.isActive()) {
|
||||
bfs(event.unit.tile(), euclDist(event.unit.tile(), 2))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private handleTradeShipEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
bfs(event.oldTile, euclDist(event.oldTile, 3)).forEach(t => {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
if (event.unit.isActive()) {
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 2))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
if (event.unit.isActive()) {
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
}
|
||||
}
|
||||
|
||||
private handleBoatEvent(event: UnitEvent) {
|
||||
const rel = this.relationship(event.unit)
|
||||
if (!this.boatToTrail.has(event.unit)) {
|
||||
this.boatToTrail.set(event.unit, new Set<Tile>());
|
||||
}
|
||||
@@ -142,30 +189,36 @@ export class UnitLayer implements Layer {
|
||||
this.clearCell(t.cell());
|
||||
});
|
||||
if (event.unit.isActive()) {
|
||||
try {
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 4)).forEach(
|
||||
t => {
|
||||
if (trail.has(t)) {
|
||||
this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 150);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch {
|
||||
consolex.log('uh oh')
|
||||
for (const t of trail) {
|
||||
this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 150);
|
||||
}
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 2))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.borderColor(event.unit.owner().info()), 255));
|
||||
bfs(event.unit.tile(), dist(event.unit.tile(), 1))
|
||||
.forEach(t => this.paintCell(t.cell(), this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
.forEach(t => this.paintCell(t.cell(), rel, this.theme.territoryColor(event.unit.owner().info()), 255));
|
||||
} else {
|
||||
trail.forEach(t => this.clearCell(t.cell()));
|
||||
this.boatToTrail.delete(event.unit);
|
||||
}
|
||||
}
|
||||
|
||||
paintCell(cell: Cell, color: Colord, alpha: number) {
|
||||
paintCell(cell: Cell, relationship: Relationship, color: Colord, alpha: number) {
|
||||
this.clearCell(cell)
|
||||
this.context.fillStyle = color.alpha(alpha / 255).toRgbString();
|
||||
if (this.alternateView) {
|
||||
switch (relationship) {
|
||||
case Relationship.Self:
|
||||
this.context.fillStyle = this.theme.selfColor().toRgbString()
|
||||
break
|
||||
case Relationship.Ally:
|
||||
this.context.fillStyle = this.theme.allyColor().toRgbString()
|
||||
break
|
||||
case Relationship.Enemy:
|
||||
this.context.fillStyle = this.theme.enemyColor().toRgbString()
|
||||
break
|
||||
}
|
||||
} else {
|
||||
this.context.fillStyle = color.alpha(alpha / 255).toRgbString();
|
||||
}
|
||||
this.context.fillRect(cell.x, cell.y, 1, 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -84,5 +84,9 @@ export interface Theme {
|
||||
backgroundColor(): Colord;
|
||||
falloutColor(): Colord
|
||||
font(): string;
|
||||
// unit color for alternate view
|
||||
selfColor(): Colord
|
||||
allyColor(): Colord
|
||||
enemyColor(): Colord
|
||||
}
|
||||
|
||||
|
||||
@@ -25,9 +25,9 @@ export const devConfig = new class extends DefaultConfig {
|
||||
lobbyLifetime(): number {
|
||||
return 10 * 1000
|
||||
}
|
||||
// tradeShipSpawnRate(): number {
|
||||
// return 10
|
||||
// }
|
||||
tradeShipSpawnRate(): number {
|
||||
return 10
|
||||
}
|
||||
boatMaxDistance(): number {
|
||||
return 5000
|
||||
}
|
||||
|
||||
@@ -122,6 +122,11 @@ export const pastelTheme = new class implements Theme {
|
||||
colord({ r: 170, g: 150, b: 170 }) // Dusty Rose
|
||||
];
|
||||
|
||||
private _selfColor = colord({ r: 0, g: 255, b: 0 })
|
||||
private _allyColor = colord({ r: 255, g: 255, b: 0 })
|
||||
private _enemyColor = colord({ r: 255, g: 0, b: 0 })
|
||||
|
||||
|
||||
playerInfoColor(id: PlayerID): Colord {
|
||||
return colord({ r: 50, g: 50, b: 50 })
|
||||
}
|
||||
@@ -199,4 +204,14 @@ export const pastelTheme = new class implements Theme {
|
||||
font(): string {
|
||||
return "Overpass, sans-serif";
|
||||
}
|
||||
|
||||
selfColor(): Colord {
|
||||
return this._selfColor
|
||||
}
|
||||
allyColor(): Colord {
|
||||
return this._allyColor
|
||||
}
|
||||
enemyColor(): Colord {
|
||||
return this._enemyColor
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user