diff --git a/src/brick/index.ts b/src/brick/index.ts index 83bda46..4efb335 100644 --- a/src/brick/index.ts +++ b/src/brick/index.ts @@ -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) => { - const index = structure.findLastIndex((s) => +s !== 0) +const getY = (structure: Readonly) => { + 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 + structure: Readonly x: number y: number isRecycle = false @@ -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) } @@ -86,49 +87,42 @@ export class Brick implements IBrick { return true } rotate(mapBinary: number[]) { - const len = this.structure[0].length - let newStructure: string[][] | BinaryString = 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 const newBinary = this.getBinary(newStructure) if (this.isOverlap(mapBinary, newBinary)) return this.structure = newStructure } - getBinary( - structure: BinaryString = 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 @@ -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 } } @@ -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 diff --git a/src/draw/index.ts b/src/draw/index.ts index 201942a..6dcaee1 100644 --- a/src/draw/index.ts +++ b/src/draw/index.ts @@ -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, @@ -16,7 +17,10 @@ export const drawBrick = ( color, } as IBrick) } + j++ + if (j === structure.length) { + j = 0 + i++ + } } } - - diff --git a/src/types/brick.ts b/src/types/brick.ts index f40eb19..433f972 100644 --- a/src/types/brick.ts +++ b/src/types/brick.ts @@ -1,74 +1,70 @@ -import { Binary, isBinaryString } from "./helper"; - - -export type BinaryString = { - [K in keyof T]: isBinaryString; -}; -// 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 export type Struct< T extends number, R extends any[] = [] -> = R["length"] extends T ? R : Struct]>; +> = R["length"] extends T ? R : Struct]> -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<2> | Struct<3> | Struct<4>>; - }; + color: string + struct: Readonly | Struct<2> | Struct<3> | Struct<4>> + } o: { - color: "#FADADD"; - struct: Readonly>; - }; + color: "#FADADD" + struct: Readonly> + } i: { - color: "#F7E9D4"; - struct: Readonly>; - }; + color: "#F7E9D4" + struct: Readonly> + } s: { - color: "#C8E6C9"; - struct: Readonly>; - }; + color: "#C8E6C9" + struct: Readonly> + } z: { - color: "#B3E5FC"; - struct: Readonly>; - }; + color: "#B3E5FC" + struct: Readonly> + } l: { - color: "#FFCC80"; - struct: Readonly>; - }; + color: "#FFCC80" + struct: Readonly> + } j: { - color: "#FFEE58"; - struct: Readonly>; - }; + color: "#FFEE58" + struct: Readonly> + } t: { - color: "#CE93D8"; - struct: Readonly>; - }; -}; + color: "#CE93D8" + struct: Readonly> + } +} export interface IBrick { - letter: BrickLetter; - x: number; - y: number; - width: number; - height: number; - color: BrickColor; - structure: BinaryString; - 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 + 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 } diff --git a/src/types/helper.ts b/src/types/helper.ts deleted file mode 100644 index 556924c..0000000 --- a/src/types/helper.ts +++ /dev/null @@ -1,17 +0,0 @@ -export type NoneBinary = T extends `${"1" | "0"}${infer R}` - ? NoneBinary - : T extends "" - ? _T - : never - -export type isBinaryString = NoneBinary extends never ? never : T - -export type Binary< - T extends number, - R extends string = "", - Arr extends string[] = [] -> = Arr["length"] extends T ? R : Binary - -// export type OptionalKeys = { -// [K in keyof T]-?: {} extends Pick ? K : never -// }[keyof T] \ No newline at end of file