Skip to content

Commit

Permalink
fix: tile ownership changes
Browse files Browse the repository at this point in the history
  • Loading branch information
keshav2010 committed Jul 24, 2024
1 parent 95fa884 commit f64b485
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 53 deletions.
3 changes: 2 additions & 1 deletion gameserver/commands/OnSpawnPointSelectCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ export class OnSpawnPointSelectCommand extends Command<
return;
}
const player = this.state.getPlayer(client.id);
player?.updatePosition(requestedPoint.x, requestedPoint.y);
if(!player) return;
player.updatePosition(requestedPoint.x, requestedPoint.y);
this.state.tilemap.updateOwnershipMap(this.state.getPlayers());
}
}
1 change: 0 additions & 1 deletion gameserver/schema/PlayerState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,6 @@ export class PlayerState extends Schema implements ISceneItem {

sessionState.onCaptureFlagRemoved(flagId);
this.resourceGrowthRateHz = 2 * (1 + 0.2 * this.captureFlags.length);
sessionState.tilemap.updateOwnershipMap(sessionState.getPlayers());
}
removeBulkCaptureFlag(
flagIds: string[],
Expand Down
6 changes: 1 addition & 5 deletions gameserver/schema/SessionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,7 @@ export class SessionState extends Schema {
return this.players.get(sessionId);
}
public getPlayers() {
let playersArr = [];
for (let player of this.players.entries()) {
playersArr.push(player[1]);
}
return playersArr;
return this.players;
}

onCaptureFlagAdded(flagId: string, parentId: string) {
Expand Down
23 changes: 13 additions & 10 deletions gameserver/schema/SoldierState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,18 +391,21 @@ export class SoldierState extends Schema implements ISceneItem, IBoidAgent {
flagQuatree.id
);
if (!flagOwnerId) return;
const flag = sessionState
.getPlayer(flagOwnerId)
?.captureFlags.toArray()

const flagOwner = sessionState.getPlayer(flagOwnerId);
if (!flagOwner) return;

const [flag] = sessionState
.getPlayer(flagOwnerId)!
.captureFlags.toArray()
.filter((flag) => flag.id === flagQuatree.id);

if (flag && flag?.[0]) {
flag[0].setHealth(flag[0].health - 0.5 * delta);
if(flag[0].health === 0)
sessionState
.getPlayer(flagOwnerId)
?.removeCaptureFlag(flag[0].id, sessionState, stateManager);
}
if (!flag) return;

flag.setHealth(flag.health - 0.5 * delta);
if (flag.health > 0) return;
flagOwner.removeCaptureFlag(flag.id, sessionState, stateManager);
sessionState.tilemap.updateOwnershipMap(sessionState.getPlayers());
});

this.stateMachine.tick({ delta, stateManager, soldier: this });
Expand Down
88 changes: 56 additions & 32 deletions gameserver/schema/TilemapState.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Schema, type, ArraySchema } from "@colyseus/schema";
import { Schema, type, MapSchema, ArraySchema } from "@colyseus/schema";
import { createNoise2D } from "simplex-noise";
import { PlayerState } from "./PlayerState";
import SAT from "sat";

export enum ETileType {
DIRT = "dirt",
GRASS = "grass",
Expand Down Expand Up @@ -50,62 +49,87 @@ export class TilemapState extends Schema {
return new SAT.Vector(col, row);
}

getTileTypeAt(index: number) {
getTileTypeAt(index: number) : ETileType {
const tileId = this.tilemap1D.at(index);
return TilesTypeById[tileId];
}

updateOwnershipMap(players: PlayerState[]) {
updateOwnershipMap(players: MapSchema<PlayerState, string>) {
for (
let tileIndex1D = 0;
tileIndex1D < this.ownershipTilemap1D.length;
tileIndex1D++
) {
const tileType = this.getTileTypeAt(tileIndex1D);
if (tileType === "water") continue;

const currentOwner = this.ownershipTilemap1D.at(tileIndex1D);
const newOwner = this.selectTileOwner(tileIndex1D, players);
if (tileType === ETileType.WATER) continue;

if (newOwner !== "NONE" && currentOwner !== "NONE") {
continue;
}
if (newOwner === currentOwner) continue;
this.ownershipTilemap1D[tileIndex1D] = newOwner;
this.ownershipTilemap1D[tileIndex1D] = this.getTileOwner(
tileIndex1D,
players
);
}
}

private selectTileOwner(
tileIndex: number,
players: PlayerState[]
private isTileWithinPlayerReach(
player: PlayerState | undefined,
tile1DIndex: number
): boolean {
if (!player) return false;
const minDistance = TilemapState.TILE_INFLUENCE_DISTANCE;
let isValidOwner = false;
const castleAndCaptureFlagPos = player.captureFlags.map((flag) =>
flag.pos.getVector()
);
castleAndCaptureFlagPos.push(player.pos.getVector());

const tilePos = this.get2DIndex(tile1DIndex);
for (const pos of castleAndCaptureFlagPos) {
pos.x = Math.floor(pos.x / this.tilewidth);
pos.y = Math.floor(pos.y / this.tileheight);
const distanceFromTile = pos.sub(tilePos).len();
if (distanceFromTile >= minDistance) continue;
isValidOwner = true;
break;
}

return isValidOwner;
}
private getTileOwner(
tile1DIndex: number,
players: MapSchema<PlayerState, string>
): string | "NONE" {
let ownerId = "NONE";
const currentOwner = this.ownershipTilemap1D.at(tile1DIndex);
let ownerId = players.has(currentOwner) ? currentOwner : "NONE";
let isTileWithinCurrentOwnerReach = this.isTileWithinPlayerReach(
players.get(ownerId),
tile1DIndex
);

// if tile currently has an active owner that satisfies the ownership creteria
if (isTileWithinCurrentOwnerReach) return ownerId;

ownerId = 'NONE';
let minDistance = TilemapState.TILE_INFLUENCE_DISTANCE;

for (const player of players) {
const captureFlagPos = player.captureFlags.map((flag) =>
let hasOwner: boolean = false;
for (const [_, player] of players) {
const castleAndCaptureFlagPos = player.captureFlags.map((flag) =>
flag.pos.getVector()
);
const territoryFlagPositions = [
player.pos.getVector(),
...captureFlagPos,
];
castleAndCaptureFlagPos.push(player.pos.getVector());

territoryFlagPositions.forEach((pos) => {
// Convert to tile coordinates
const tilePos = this.get2DIndex(tile1DIndex);
for (const pos of castleAndCaptureFlagPos) {
pos.x = Math.floor(pos.x / this.tilewidth);
pos.y = Math.floor(pos.y / this.tileheight);

const tilePos = this.get2DIndex(tileIndex);

const distanceFromTile = pos.sub(tilePos).len();
if (distanceFromTile >= minDistance) return;

if (distanceFromTile >= minDistance) continue;
hasOwner = true;
minDistance = distanceFromTile;
ownerId = player.id;
});
}
}
return ownerId;
return hasOwner ? ownerId : "NONE";
}

async generateTilemap() {
Expand Down
3 changes: 2 additions & 1 deletion public/gameObjects/CaptureFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ export class CaptureFlag
y: number,
radius: number
) {
this.circleOfInfluence = scene.add.graphics();
if(!this.circleOfInfluence)
this.circleOfInfluence = scene.add.graphics();
this.circleOfInfluence.lineStyle(3, 0xffffff);
this.circleOfInfluence.strokeCircle(x, y, radius);
}
Expand Down
5 changes: 2 additions & 3 deletions public/scenes/GameScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,8 +459,8 @@ export class GameScene extends BaseScene {
// update tilemap for every tile update received.
this.AddStateChangeListener(
GameSessionState.tilemap.ownershipTilemap1D.onChange(
(owner, tileIndex) => {
this.updateTilemap(networkManager, owner, tileIndex);
(owner, tile1DIndex) => {
this.updateTilemap(networkManager, owner, tile1DIndex);
}
)
);
Expand Down Expand Up @@ -531,7 +531,6 @@ export class GameScene extends BaseScene {

this.AddSceneEvent(
GAMEEVENTS.DELETE_SELECTED_OBJECTS, () => {
console.log('requested to delete seelcted objects');
const selectedObjectsMap = this.data.get(
DataKey.SELECTED_OBJECTS_MAP
) as Map<string, BaseSoldier | CaptureFlag>;
Expand Down

0 comments on commit f64b485

Please sign in to comment.