Skip to content

Commit

Permalink
chore: Refactor code for improved performance and readability
Browse files Browse the repository at this point in the history
  • Loading branch information
jinhuid committed Jun 8, 2024
1 parent 7c7bbfb commit e972f21
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 122 deletions.
87 changes: 41 additions & 46 deletions src/brick/index.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { drawBrick } from "../draw"
import { gameParam } from "../gameConfig"
import {
BinaryString,
BrickColor,
BrickStruct,
Bricks,
IBrick,
} from "../types/brick"
import { BrickColor, BrickStruct, Bricks, IBrick } from "../types/brick"
import { bricks } from "./brickConfig"

const getY = (structure: BinaryString<BrickStruct>) => {
const index = structure.findLastIndex((s) => +s !== 0)
const getY = (structure: Readonly<number[]>) => {
const index = structure.findLastIndex((s) => s !== 0)
if (index === -1) return -structure.length
return -index - 1
}

const getStructureVal = (structure: BrickStruct): number[] => {
return structure.map((s) => parseInt(s, 2))
}

const eliminateTarget = 2 ** gameParam.column - 1

export class Brick implements IBrick {
static readonly height = gameParam.brickHeight
static readonly width = gameParam.brickWidth
readonly color: BrickColor
readonly width: number
readonly height: number
structure: BinaryString<BrickStruct>
structure: Readonly<number[]>
x: number
y: number
isRecycle = false
Expand All @@ -31,7 +32,7 @@ export class Brick implements IBrick {
this.color = bricks[this.letter].color
this.width = Brick.width
this.height = Brick.height
this.structure = bricks[this.letter].struct
this.structure = getStructureVal(bricks[this.letter].struct)
this.x = gameParam.column / 2 - 1
this.y = getY(this.structure)
}
Expand Down Expand Up @@ -86,49 +87,42 @@ export class Brick implements IBrick {
return true
}
rotate(mapBinary: number[]) {
const len = this.structure[0].length
let newStructure: string[][] | BinaryString<BrickStruct> = Array.from(
{ length: len },
() => new Array(len)
)
for (let i = 0; i < this.structure.length; i++) {
for (let j = 0; j < this.structure[i].length; j++) {
let x = i,
y = len - 1 - j
const len = this.structure.length
const newStructure: number[] = new Array(len).fill(0)
let i = 0,
j = 0
while (i < len) {
if (this.structure[i] & (1 << (len - 1 - j))) {
const x = i
const y = len - 1 - j
//边界检测
if (
this.structure[i][j] === "1" &&
(x + this.x >= gameParam.column ||
x + this.x < 0 ||
y + this.y >= gameParam.row)
)
x + this.x >= gameParam.column ||
x + this.x < 0 ||
y + this.y >= gameParam.row
) {
return
newStructure[y][x] = this.structure[i][j]
}
newStructure[y] += 1 << (len - 1 - x)
}
j++
if (j === len) {
i++
j = 0
}
}
newStructure = newStructure.map((s) =>
s.join("")
) as unknown as BinaryString<BrickStruct>
const newBinary = this.getBinary(newStructure)
if (this.isOverlap(mapBinary, newBinary)) return
this.structure = newStructure
}
getBinary(
structure: BinaryString<BrickStruct> = this.structure,
x: number = this.x
) {
const binary: number[] = []
const len = structure[0].length
const carry = gameParam.column - x - len
for (let i = len - 1; i >= 0; i--) {
let r
getBinary(structure = this.structure, x: number = this.x) {
const carry = gameParam.column - x - structure.length
return structure.map((v) => {
if (carry >= 0) {
r = parseInt(structure[i], 2) << carry
} else {
r = parseInt(structure[i], 2) >> -carry
return v << carry
}
binary.unshift(r)
}
return binary
return v >> -carry
})
}
correctLastTime(time: number) {
this.lastTime = time
Expand Down Expand Up @@ -157,7 +151,8 @@ export class Brick implements IBrick {
}
for (let i = binary.length - 1; i >= 0; i--) {
if (y + i < 0) continue
if (binary[i] & (mapBinary[y + i] ?? 2 ** gameParam.column - 1)) {
//mapBinary[y + i] 可能的情况为0 或者 undefined(因为brick.structure有全0排列)
if (binary[i] & (mapBinary[y + i] ?? eliminateTarget)) {
return true
}
}
Expand All @@ -170,7 +165,7 @@ export class Brick implements IBrick {
*/
private isAtBorder(direction: "left" | "right") {
const binary = this.getBinary()
const maxBorderBinaryValue = { left: 2 ** (gameParam.column - 1), right: 1 }
const maxBorderBinaryValue = { left: (eliminateTarget + 1) / 2, right: 1 }
for (let i = binary.length - 1; i >= 0; i--) {
if (binary[i] & maxBorderBinaryValue[direction]) {
return true
Expand Down
14 changes: 9 additions & 5 deletions src/draw/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ export const drawBrick = (
ctx: CanvasRenderingContext2D,
{ x, y, width, height, color, structure }: IBrick
) => {
for (let i = 0; i < structure.length; i++) {
for (let j = 0; j < structure[i].length; j++) {
if (structure[i][j] == "0") continue
let i = 0,
j = 0
while (i < structure.length) {
if (structure[i] & (1 << (structure.length - 1 - j))) {
drawBrickPiece(ctx, {
x: (x + j) * width,
y: (y + i) * height,
Expand All @@ -16,7 +17,10 @@ export const drawBrick = (
color,
} as IBrick)
}
j++
if (j === structure.length) {
j = 0
i++
}
}
}


104 changes: 50 additions & 54 deletions src/types/brick.ts
Original file line number Diff line number Diff line change
@@ -1,74 +1,70 @@
import { Binary, isBinaryString } from "./helper";


export type BinaryString<T extends BrickStruct> = {
[K in keyof T]: isBinaryString<T[K]>;
};
// type a = BinaryString<("00" | "10" | "01" | "11")[]>
export type Binary<
T extends number,
R extends string = "",
Arr extends string[] = []
> = Arr["length"] extends T ? R : Binary<T, `${R}${"0" | "1"}`, [...Arr, ""]>

export type Struct<
T extends number,
R extends any[] = []
> = R["length"] extends T ? R : Struct<T, [...R, Binary<T>]>;
> = R["length"] extends T ? R : Struct<T, [...R, Binary<T>]>

export type BrickLetter = keyof Bricks;

export type BrickColor = Bricks[BrickLetter]["color"];

export type BrickStruct = Bricks[BrickLetter]["struct"];
export type BrickLetter = keyof Bricks

export type BrickColor = Bricks[BrickLetter]["color"]

export type BrickStruct = Bricks[BrickLetter]["struct"]

export type Bricks = {
[key: string]: {
color: string;
struct: Readonly<Struct<1> | Struct<2> | Struct<3> | Struct<4>>;
};
color: string
struct: Readonly<Struct<1> | Struct<2> | Struct<3> | Struct<4>>
}
o: {
color: "#FADADD";
struct: Readonly<Struct<2>>;
};
color: "#FADADD"
struct: Readonly<Struct<2>>
}
i: {
color: "#F7E9D4";
struct: Readonly<Struct<4>>;
};
color: "#F7E9D4"
struct: Readonly<Struct<4>>
}
s: {
color: "#C8E6C9";
struct: Readonly<Struct<3>>;
};
color: "#C8E6C9"
struct: Readonly<Struct<3>>
}
z: {
color: "#B3E5FC";
struct: Readonly<Struct<3>>;
};
color: "#B3E5FC"
struct: Readonly<Struct<3>>
}
l: {
color: "#FFCC80";
struct: Readonly<Struct<3>>;
};
color: "#FFCC80"
struct: Readonly<Struct<3>>
}
j: {
color: "#FFEE58";
struct: Readonly<Struct<3>>;
};
color: "#FFEE58"
struct: Readonly<Struct<3>>
}
t: {
color: "#CE93D8";
struct: Readonly<Struct<3>>;
};
};
color: "#CE93D8"
struct: Readonly<Struct<3>>
}
}

export interface IBrick {
letter: BrickLetter;
x: number;
y: number;
width: number;
height: number;
color: BrickColor;
structure: BinaryString<BrickStruct>;
isRecycle: boolean;
draw(ctx: CanvasRenderingContext2D): void;
update(time: number, mapBinary: number[]): boolean;
getBinary(): number[];
left(mapBinary: number[]): void;
right(mapBinary: number[]): void;
downOne(mapBinary: number[]): boolean;
downToBottom(mapBinary: number[]): boolean;
rotate(mapBinary: number[]): void;
letter: BrickLetter
x: number
y: number
width: number
height: number
color: BrickColor
structure: Readonly<number[]>
isRecycle: boolean
draw(ctx: CanvasRenderingContext2D): void
update(time: number, mapBinary: number[]): boolean
getBinary(): number[]
left(mapBinary: number[]): void
right(mapBinary: number[]): void
downOne(mapBinary: number[]): boolean
downToBottom(mapBinary: number[]): boolean
rotate(mapBinary: number[]): void
}
17 changes: 0 additions & 17 deletions src/types/helper.ts

This file was deleted.

0 comments on commit e972f21

Please sign in to comment.