Skip to content

Commit

Permalink
refactor: improve board & pieces physics accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
Neosoulink committed Aug 21, 2024
1 parent 288962c commit 1b5ed07
Show file tree
Hide file tree
Showing 6 changed files with 95 additions and 102 deletions.
19 changes: 13 additions & 6 deletions apps/web/src/common/models/piece.model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { InstancedMesh, Matrix4 } from "three";
import { InstancedMesh, Matrix4, Vector3, Vector3Like } from "three";
import { Subject } from "rxjs";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";

import type { BoardCoords, PieceId } from "../interfaces";
import { ColorVariant, PieceType } from "../enums";
import { MATRIX, QUATERNION, SCALE, VECTOR } from "../constants";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";

export class PieceModel<
T extends PieceType = PieceType,
Expand All @@ -15,11 +15,12 @@ export class PieceModel<
public readonly update$$ = new Subject<typeof this>();
public readonly coords: BoardCoords = { col: 0, row: 0 };

public physics!: PhysicsProperties;

constructor(
public readonly id: PieceId,
public readonly type: T,
public readonly color: C,
public readonly physics: PhysicsProperties,
public readonly promotedFromType?: PieceType
) {
super();
Expand All @@ -33,15 +34,21 @@ export class PieceModel<
this._index = Number(value);
}

public setCoords(board: InstancedMesh, coords: BoardCoords, yOffset = 0) {
public setCoords(
board: InstancedMesh,
coords: BoardCoords,
offset: Vector3Like = new Vector3()
) {
this.coords.col = coords.col;
this.coords.row = coords.row;

board.getMatrixAt(coords.col + coords.row * board.count ** 0.5, MATRIX);
MATRIX.decompose(VECTOR, QUATERNION, SCALE);
VECTOR.setY(VECTOR.y + yOffset);
VECTOR.add(offset);

this.physics.rigidBody.setTranslation(VECTOR, true);
this.physics.rigidBody.setAngvel({ x: 0, y: 0, z: 0 }, true);
this.physics.rigidBody.setLinvel({ x: 0, y: 0, z: 0 }, true);
this.physics.rigidBody.setTranslation(VECTOR.add(board.position), true);
this.update$$.next(this);
}
}
37 changes: 19 additions & 18 deletions apps/web/src/common/models/pieces-group.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ export class PiecesGroupModel<
public readonly pieceMoved$$ = new Subject<PieceModel<type, color>>();

constructor(
private readonly physics: Physics,
public readonly piecesType: type,
public readonly piecesColor: color,
count: PieceId,
Expand All @@ -27,28 +26,14 @@ export class PiecesGroupModel<
) {
super(geometry, undefined, count);

const physicsProperties = this.physics.addToWorld(
this,
1
) as PhysicsProperties[];

this.instanceMatrix.setUsage(DynamicDrawUsage);

(pieces ? Object.keys(pieces) : Array.from(Array(this.count))).forEach(
(pieceKey: number, i) => {
const oldPiece = pieces?.[pieceKey];
const piecePhysicsProperties = physicsProperties[
i
] as PhysicsProperties;

const piece =
oldPiece ??
new PieceModel(
i,
this.piecesType,
this.piecesColor,
piecePhysicsProperties
);
oldPiece ?? new PieceModel(i, this.piecesType, this.piecesColor);
piece.index = i;

this.setMatrixAt(i, piece);
Expand Down Expand Up @@ -78,20 +63,36 @@ export class PiecesGroupModel<
this.update();
}

public initPhysics(physics: Physics) {
const physicsProperties = physics.addToWorld(
this,
1
) as PhysicsProperties[];

physicsProperties.forEach((_, i) => {
const piecePhysicsProperties = physicsProperties[i] as PhysicsProperties;
if (this.pieces[i]) this.pieces[i].physics = piecePhysicsProperties;
});
}

public setPieceCoords(
id: PieceId,
board: InstancedMesh,
coords: BoardCoords
) {
if (this?.geometry.attributes.position) {
this.geometry.computeBoundingBox();

const boundingBox = this.geometry.boundingBox;

if (boundingBox) {
// const width = boundingBox.max.x - boundingBox.min.x;
const height = boundingBox.max.y - boundingBox.min.y;

this.pieces[id]?.setCoords(board, coords, height / 2 + 2);
this.pieces[id]?.setCoords(board, coords, {
x: 0,
y: height / 2 + 2,
z: 0
});
}
}

Expand Down
58 changes: 54 additions & 4 deletions apps/web/src/core/chess-board/chess-board.component.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
import "reflect-metadata";

import { inject, singleton } from "tsyringe";
import { Color, InstancedMesh, PlaneGeometry } from "three";
import {
DynamicDrawUsage,
Euler,
Color,
InstancedMesh,
PlaneGeometry
} from "three";
import { PhysicsProperties } from "@chess-d/rapier-physics/dist/types";
import { Physics } from "@chess-d/rapier-physics";

import { BoardCell } from "../../common";

import {
BoardCoords,
BoardCell,
MATRIX,
QUATERNION,
SCALE,
VECTOR
} from "../../common";
@singleton()
export class ChessBoardComponent {
public readonly cellSize = 1;
Expand Down Expand Up @@ -35,7 +47,43 @@ export class ChessBoardComponent {

constructor(@inject(Physics) private readonly _physics: Physics) {}

public init() {
public initCells() {
const _QUATERNION = QUATERNION.clone().setFromEuler(
new Euler(Math.PI / -2, 0, Math.PI / -2)
);
let isBlack = false;

this.board.position.set(this.halfSize, 0, -this.halfSize);
this.board.instanceMatrix.setUsage(DynamicDrawUsage);

for (let i = 0; i < this.board.count; i++) {
const coords: BoardCoords = {
col: Math.floor(i % this.cellsRangeCount) + 1,
row: Math.floor(i / this.cellsRangeCount) + 1
};

if (!this.cells[coords.row - 1]) {
isBlack = !isBlack;
this.cells.push([]);
}

this.board.getMatrixAt(i, MATRIX);

VECTOR.set(-(coords.col * this.cellSize), 0, coords.row * this.cellSize);
MATRIX.compose(VECTOR, _QUATERNION, SCALE);

this.board.setMatrixAt(i, MATRIX);
this.board.setColorAt(i, isBlack ? this.blackAccent : this.whiteAccent);
this.cells[coords.row - 1]?.push({
col: coords.col,
row: coords.row,
isBlack
});
isBlack = !isBlack;
}
}

public initPhysics() {
this.board.name = ChessBoardComponent.name;

this.board.userData = {
Expand All @@ -44,5 +92,7 @@ export class ChessBoardComponent {
};

this.physics = this._physics?.addToWorld(this.board) as PhysicsProperties;

this.physics.rigidBody.setTranslation({ x: 0, y: 0, z: 0 }, true);
}
}
62 changes: 4 additions & 58 deletions apps/web/src/core/chess-board/chess-board.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { inject, singleton } from "tsyringe";
import { DynamicDrawUsage, Euler } from "three";

import { AppModule, Module } from "@quick-threejs/reactive";

import { BoardCoords, MATRIX, QUATERNION, SCALE, VECTOR } from "../../common";
import { CoreComponent } from "../core.component";
import { ChessBoardComponent } from "./chess-board.component";
import { ChessBoardController } from "./chess-board.controller";

Expand All @@ -13,66 +11,14 @@ export class ChessBoardModule implements Module {
@inject(AppModule) private readonly appModule: AppModule,
@inject(ChessBoardComponent)
private readonly component: ChessBoardComponent,
@inject(CoreComponent) private readonly coreComponent: CoreComponent,
@inject(ChessBoardController)
private readonly controller: ChessBoardController
) {}

public init() {
this.component.init();

this.component.board.position.set(
this.component.halfSize,
0,
-this.component.halfSize
);

this.component.physics?.rigidBody.setTranslation(
{ x: this.component.halfSize, y: 0, z: -this.component.halfSize },
true
);

this.component.board.instanceMatrix.setUsage(DynamicDrawUsage);

const _QUATERNION = QUATERNION.clone().setFromEuler(
new Euler(Math.PI / -2, 0, 0)
);
let isBlack = false;

for (let i = 0; i < this.component.board.count; i++) {
const coords: BoardCoords = {
col: Math.floor(i % this.component.cellsRangeCount) + 1,
row: Math.floor(i / this.component.cellsRangeCount) + 1
};

if (!this.component.cells[coords.row - 1]) {
isBlack = !isBlack;
this.component.cells.push([]);
}

this.component.board.getMatrixAt(i, MATRIX);

VECTOR.set(
-(coords.col * this.component.cellSize),
0,
coords.row * this.component.cellSize
);
MATRIX.compose(VECTOR, _QUATERNION, SCALE);

this.component.board.setMatrixAt(i, MATRIX);
this.component.board.setColorAt(
i,
isBlack ? this.component.blackAccent : this.component.whiteAccent
);
this.component.cells[coords.row - 1]?.push({
col: coords.col,
row: coords.row,
isBlack
});
isBlack = !isBlack;
this.component.initCells();
this.component.initPhysics();

this.appModule.world.scene().add(this.component.board);
}
this.appModule.world.scene().add(this.component.board);
}

public dispose() {}
Expand Down
18 changes: 4 additions & 14 deletions apps/web/src/core/pieces/pieces.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export class PiecesComponent {
this.chessBoardComponent.cellsRangeCount,
this.resourceComponent.getGeometryByPieceType(PieceType.pawn)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey, index) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand All @@ -55,7 +54,6 @@ export class PiecesComponent {
2,
this.resourceComponent.getGeometryByPieceType(PieceType.rock)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey, index) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand Down Expand Up @@ -83,7 +81,6 @@ export class PiecesComponent {
2,
this.resourceComponent.getGeometryByPieceType(PieceType.bishop)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey, index) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand Down Expand Up @@ -112,7 +109,6 @@ export class PiecesComponent {
2,
this.resourceComponent.getGeometryByPieceType(PieceType.knight)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey, index) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand Down Expand Up @@ -141,7 +137,6 @@ export class PiecesComponent {
1,
this.resourceComponent.getGeometryByPieceType(PieceType.queen)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand All @@ -164,7 +159,6 @@ export class PiecesComponent {
1,
this.resourceComponent.getGeometryByPieceType(PieceType.king)
);
group.position.copy(this.chessBoardComponent.board.position);

Object.keys(group.pieces).forEach((pieceKey) => {
const piece = group.pieces[parseInt(pieceKey)];
Expand All @@ -187,14 +181,10 @@ export class PiecesComponent {
geometry: BufferGeometry,
pieces?: PiecesGroupModel<Type, Color>["pieces"]
) {
return new PiecesGroupModel(
this._physics,
type,
color,
count,
geometry,
pieces
);
const group = new PiecesGroupModel(type, color, count, geometry, pieces);
group.initPhysics(this._physics);

return group;
}

public initPieces() {
Expand Down
3 changes: 1 addition & 2 deletions apps/web/src/core/pieces/pieces.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export class PiecesModule implements Module {
init() {
this.component.initPieces();

if (this.component.groups) {
if (this.component.groups)
[...Object.keys(this.component.groups[ColorVariant.black])].forEach(
(key) => {
const blackGroup =
Expand All @@ -66,7 +66,6 @@ export class PiecesModule implements Module {
if (whiteGroup) this.appModule.world.scene().add(whiteGroup);
}
);
}
}

dispose() {}
Expand Down

0 comments on commit 1b5ed07

Please sign in to comment.