diff --git a/src/channels/minesweeper/Face.tsx b/src/channels/minesweeper/Face.tsx index 0557396..86c837d 100644 --- a/src/channels/minesweeper/Face.tsx +++ b/src/channels/minesweeper/Face.tsx @@ -1,9 +1,12 @@ import { css } from '@emotion/react'; + import { FACE_DIMENSION, FACE_ORDER } from './constants'; +import type { FaceType } from './types'; import faces from './assets/faces.png'; -export type FaceType = (typeof FACE_ORDER)[number]; +const SPRITES_PER_ROW = 5; +const SPRITESHEET_ROWS = 1; function getFaceOffset(face: FaceType) { const faceIndex = FACE_ORDER.indexOf(face); @@ -18,11 +21,11 @@ export function Face({ face }: FaceProps) { return (
); diff --git a/src/channels/minesweeper/Tile.tsx b/src/channels/minesweeper/Tile.tsx index 62c232d..c93f4dd 100644 --- a/src/channels/minesweeper/Tile.tsx +++ b/src/channels/minesweeper/Tile.tsx @@ -1,13 +1,12 @@ import { css } from '@emotion/react'; + import { TILE_DIMENSION } from './constants'; +import type { TileData } from './types'; import tiles from './assets/tiles.png'; -export type TileData = { - id: string; - tileType: readonly [number, number]; - isMine: boolean; -}; +const SPRITES_PER_ROW = 8; +const SPRITESHEET_ROWS = 2; export function Tile({ tileType }: TileData) { const [x, y] = tileType; @@ -15,10 +14,11 @@ export function Tile({ tileType }: TileData) { return (
); diff --git a/src/channels/minesweeper/constants.ts b/src/channels/minesweeper/constants.ts index 038fb6a..c6db45b 100644 --- a/src/channels/minesweeper/constants.ts +++ b/src/channels/minesweeper/constants.ts @@ -1,12 +1,14 @@ -export const FACE_DIMENSION = 24; +import type { TileData } from './types'; + +export const FACE_DIMENSION = 36; export const FACE_ORDER = ['smile', 'smile_pressed', 'open_mouth', 'sunglasses', 'heart_eyes'] as const; export const MINE_CHANCE = 0.17; export const GRID_ROWS = 16; -export const GRID_COLUMNS = 67; +export const GRID_COLUMNS = 66; -export const TILE_DIMENSION = 16; +export const TILE_DIMENSION = 16.24; export const TILE_MAP = { HIDDEN: [0, 0], @@ -35,8 +37,8 @@ export const mineNumberTiles = [ TILE_MAP.EIGHT, ]; -export const MIN_REVEAL_DONATION = 20; +export const MIN_REVEAL_DONATION = 25; /** maximum donation amount for determining reveal threshold */ export const REVEAL_DONATION_CAP = 500; export const MIN_REVEALED_TILES = 1; -export const MAX_REVEALED_TILES = 25; +export const MAX_REVEALED_TILES = 15; diff --git a/src/channels/minesweeper/index.tsx b/src/channels/minesweeper/index.tsx index 7c2bc83..b130102 100644 --- a/src/channels/minesweeper/index.tsx +++ b/src/channels/minesweeper/index.tsx @@ -6,24 +6,19 @@ import { ChannelProps, registerChannel } from '../channels'; import { useListenFor, useReplicant } from 'use-nodecg'; import type { Event, FormattedDonation, Total } from '@gdq/types/tracker'; -import { Face, FaceType } from './Face'; -import { Tile, TileData } from './Tile'; +import { Face } from './Face'; +import { Tile } from './Tile'; import { TILE_DIMENSION, GRID_COLUMNS, GRID_ROWS, TILE_MAP, MINE_CHANCE, MIN_REVEAL_DONATION } from './constants'; import { createTileCluster, getTileRevealThreshold, random, randomFromArray, splitTileIndex } from './utils'; import { usePreloadedReplicant } from '@gdq/lib/hooks/usePreloadedReplicant'; import { cloneDeep } from 'lodash'; +import type { FaceType, GridState, TileData } from './types'; registerChannel('Minesweeper', 132, Minesweeper, { position: 'bottomRight', handle: 'rshig', }); -type GridState = { - grid: TileData[][]; - mines: string[]; - nonMines: string[]; -}; - function generateInitialGridState(): GridState { const state: GridState = { grid: [], mines: [], nonMines: [] }; for (let i = 0; i < GRID_ROWS; i++) { @@ -182,8 +177,8 @@ export function Minesweeper(props: ChannelProps) { const flagTimeoutRef = useRef>(); useEffect(() => { function flagTiles(timeoutMS: number) { - // Add a question mark every 5-10 seconds - const newTimeout = random(5_000, 10_000); + // Add a question mark every 10-20 seconds + const newTimeout = random(10_000, 20_000); flagTimeoutRef.current = setTimeout(() => { dispatch({ type: actions.QUESTION_TILE }); flagTiles(newTimeout); @@ -248,11 +243,11 @@ const Container = styled.div` const Wrapper = styled.div` position: relative; display: flex; - gap: 5px; + gap: 4px; flex-direction: column; height: 100%; background-color: #bdbdbd; - padding: 5px; + padding: 4px 5px; border-left: 3px solid #fff; border-top: 3px solid #fff; `; @@ -261,7 +256,7 @@ const Header = styled.header` display: flex; justify-content: space-between; align-items: center; - padding: 0 5px; + padding: 0 4px; height: 50px; border: 2px solid; border-color: #7d7d7d #fff #fff #7d7d7d; @@ -284,11 +279,13 @@ const LCDContainer = styled.div` const LCDText = styled.div` font-family: minesweeper; - font-size: 32px; + font-size: 38px; text-transform: uppercase; - color: #ea3323; + color: hsl(4.82deg 82.57% 58%); background: #000; border: 1px solid; border-color: #808080 #fff #fff #808080; - padding: 1px; + padding: 4px; + line-height: 0.8; + letter-spacing: 0.025rem; `; diff --git a/src/channels/minesweeper/types.d.ts b/src/channels/minesweeper/types.d.ts new file mode 100644 index 0000000..1aa90c1 --- /dev/null +++ b/src/channels/minesweeper/types.d.ts @@ -0,0 +1,15 @@ +import { FACE_ORDER } from './constants'; + +export type FaceType = (typeof FACE_ORDER)[number]; + +export type TileData = { + id: string; + tileType: readonly [number, number]; + isMine: boolean; +}; + +export type GridState = { + grid: TileData[][]; + mines: string[]; + nonMines: string[]; +}; diff --git a/src/channels/minesweeper/utils.ts b/src/channels/minesweeper/utils.ts index 36bae3d..525e12c 100644 --- a/src/channels/minesweeper/utils.ts +++ b/src/channels/minesweeper/utils.ts @@ -1,4 +1,3 @@ -import { TileData } from './Tile'; import { REVEAL_DONATION_CAP, GRID_COLUMNS, @@ -8,6 +7,7 @@ import { MIN_REVEALED_TILES, mineNumberTiles, } from './constants'; +import type { TileData } from './types'; export function random(min: number, max: number) { return Math.floor(Math.random() * (max - min)) + min;