Skip to content

Commit

Permalink
formation grid's center should be at selected pos
Browse files Browse the repository at this point in the history
  • Loading branch information
keshav2010 committed Apr 26, 2024
1 parent 6fcdbbb commit 95f5f58
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 23 deletions.
47 changes: 35 additions & 12 deletions gameserver/commands/OnSoldierMoveCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,34 +15,57 @@ export class OnSoldierMoveCommand extends Command<SessionRoom, CommandPayload> {
expectedPositionX: number;
expectedPositionY: number;
}>) {
const sceneSize = gameManager?.scene.getDimension();
if (!sceneSize) return;

const soldierObjects = message.soldierIds
.map((id) => this.state.getPlayer(client.sessionId)?.getSoldier(id))
.filter(Boolean) as SoldierState[];
if (soldierObjects.length === 0) {
return;
}

if (soldierObjects.length === 0) return;

// leader selection for group movement
const leader = soldierObjects[0];
for (let i = 1; i < soldierObjects.length; i++) {
soldierObjects[i].setGroupLeaderId(leader.id);
}

// update relative position of group units (leader will be assigned center slot in group grid)
// create formation centered at expectedPosition
const matrixRows = Math.ceil(Math.sqrt(soldierObjects.length));
const offset = 80;
const offset = 96;
let expectedPosition = new SAT.Vector(
message.expectedPositionX,
message.expectedPositionY
);

const boundingBoxWidth = matrixRows * offset;
const boundingBoxHeight = boundingBoxWidth;

const formationBoundingBox = new SAT.Box(
expectedPosition,
boundingBoxWidth,
boundingBoxHeight
)
.toPolygon()
.translate(
expectedPosition.x - boundingBoxWidth + offset / 2,
expectedPosition.y - boundingBoxHeight + offset / 2
);
console.log(matrixRows);
expectedPosition = formationBoundingBox.getCentroid();

const soldiersOffset = new Map<string, SAT.Vector>();
soldierObjects.forEach((soldier, i) => {
const offsetX = (i % matrixRows) * offset;
const offsetY = Math.floor(i / matrixRows) * offset;
soldier.offsetFromPosition = new SAT.Vector(offsetX, offsetY);
const row = Math.floor(i / matrixRows) * offset;
const col = (i % matrixRows) * offset;
soldiersOffset.set(soldier.id, new SAT.Vector(col, row));
});

// expected position will also be assigned in an order to maintain group formation
soldierObjects.forEach((soldier) => {
const targetPos = new SAT.Vector(
message.expectedPositionX + soldier.offsetFromPosition.x,
message.expectedPositionY + soldier.offsetFromPosition.y
);
const targetPos = expectedPosition
.clone()
.add(soldiersOffset.get(soldier.id)!);
soldier.setTargetPosition(targetPos);
});
}
Expand Down
23 changes: 19 additions & 4 deletions gameserver/commands/OnSpawnPointSelectCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,31 @@ import { Command } from "@colyseus/command";
import { SessionRoom } from "../SessionRoom";
import { Client } from "colyseus";
import { CommandPayload } from "./CommandPayloadType";
export class OnSpawnPointSelectCommand extends Command<
SessionRoom,
CommandPayload
> {
import SAT from 'sat';
export class OnSpawnPointSelectCommand extends Command<SessionRoom, CommandPayload> {
execute({
client,
message,
gameManager,
}: CommandPayload<{ spawnX: number; spawnY: number }>) {
const { spawnX, spawnY } = message;
const requestedPoint = new SAT.Vector(spawnX, spawnY);

const castleSize = 64;

const dimensions = gameManager?.scene.getDimension();
if (!dimensions) return;

const sceneBoundingBox = new SAT.Box(
new SAT.Vector(0, 0).add(new SAT.Vector(castleSize, castleSize)),
dimensions.x - castleSize * 2,
dimensions.y - castleSize * 2
);

const pointInPolygon = SAT.pointInPolygon(requestedPoint, sceneBoundingBox.toPolygon())
if (!pointInPolygon) {
return;
}
const player = this.state.getPlayer(client.id);
player?.updatePosition(spawnX, spawnY);
}
Expand Down
8 changes: 4 additions & 4 deletions gameserver/core/GameStateManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export class GameStateManager<PlayerSchema extends IDfied> {
) {
this.GameStarted = false;
this.scene = new Scene({
width: 15,
height: 15,
width: 1920,
height: 1920,
});
this.playerMap = new Map();
this.countdown = SERVER_CONFIG.COUNTDOWN;
Expand Down Expand Up @@ -61,8 +61,8 @@ export class GameStateManager<PlayerSchema extends IDfied> {
this.stateMachine.tick(args);
}

addSceneItem(item: ISceneItem) {
this.scene.addSceneItem(item);
addSceneItem(item: ISceneItem, doObserve: boolean = true) {
this.scene.addSceneItem(item, doObserve);
}
removeSceneItem(itemId: string) {
this.scene.removeSceneItem(itemId);
Expand Down
8 changes: 8 additions & 0 deletions gameserver/core/Scene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { ISceneItem } from "./types/ISceneItem"
import { SceneObjectType } from "./types/SceneObject";
export class Scene extends Quadtree<TypeQuadtreeItem> {
sceneItemMap: Map<string, ISceneItem>;
width: number;
height: number;

constructor(opts: {
x?: number;
Expand All @@ -14,9 +16,15 @@ export class Scene extends Quadtree<TypeQuadtreeItem> {
maxElements?: number;
}) {
super(opts);
this.width = opts.width;
this.height = opts.height;
this.sceneItemMap = new Map<string, ISceneItem>();
}

getDimension() {
return new SAT.Vector(this.width, this.height);
}

removeSceneItem(itemId: string) {
if (!this.sceneItemMap.has(itemId)) {
console.log(`item ${itemId} not found in scene`);
Expand Down
1 change: 0 additions & 1 deletion gameserver/core/types/IBoidAgent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export interface IBoidAgent {
getVelocityVector: (...args: any) => SAT.Vector;

groupLeaderId?: string | null;
offsetFromPosition: SAT.Vector;
setGroupLeaderId: (arg: string) => void;
getGroupLeaderId: () => string | undefined | null;

Expand Down
2 changes: 0 additions & 2 deletions gameserver/schema/SoldierState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ export class SoldierState extends Schema implements ISceneItem, IBoidAgent {
}>(SoldierStateMachineJSON, soldierStateBehaviours);

groupLeaderId?: string | null;
offsetFromPosition: SAT.Vector = new SAT.Vector(0, 0);
constructor(
playerId: string,
soldierType: SoldierType,
Expand Down Expand Up @@ -287,7 +286,6 @@ export class SoldierState extends Schema implements ISceneItem, IBoidAgent {
?.getSoldier(this.groupLeaderId);
if (!groupLeaderRef) {
this.groupLeaderId = null;
this.offsetFromPosition = new SAT.Vector(0, 0);
}
stateManager.scene.checkCollisionOnObject(
this,
Expand Down
Binary file modified public/assets/groundtiles.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions public/scenes/BaseScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ export class BaseScene extends Phaser.Scene {
T extends
| Phaser.GameObjects.Graphics
| PlayerCastle
| Phaser.Cameras.Controls.SmoothedKeyControl
| Phaser.GameObjects.Text
| Phaser.GameObjects.DOMElement
| Phaser.GameObjects.Image
Expand Down

0 comments on commit 95f5f58

Please sign in to comment.