tmemory
Version:
A terminal-based Memory card game built with React Ink. Features multiple grid sizes, AI opponent, and high scores.
127 lines (126 loc) • 5.47 kB
JavaScript
import { Box, Text, useInput } from 'ink';
import BigText from 'ink-big-text';
import Gradient from 'ink-gradient';
import React from 'react';
import { GameLayout } from '../../components/layout/GameLayout.js';
import { COLORS } from '../../constants/colors.js';
import { ALL_PRESET_GRIDS, isValidGrid } from '../../constants/gridPresets.js';
import { useGame } from '../../context/GameContext/index.js';
import { useHighScores } from '../../context/HighScoreContext/index.js';
import { Controls } from './components/Controls.js';
import { GameModeSelect } from './components/GameModeSelect.js';
import { GridSizeConfig } from './components/GridSizeConfig.js';
import { HighScoreDisplay } from './components/HighScoreDisplay.js';
export const MainMenu = () => {
const { onlineEnabled, setOnlineEnabled } = useHighScores();
const { state, dispatch } = useGame();
useInput((input, key) => {
if (input === 'm' || input === 'M') {
dispatch({
type: 'SET_GRID_SELECTION_MODE',
payload: state.gridSelectionMode === 'preset' ? 'custom' : 'preset',
});
return;
}
if (input.toLowerCase() === 'l') {
dispatch({ type: 'SET_GAME_STATE', payload: 'leaderboard' });
return;
}
if (input.toLowerCase() === 'o') {
setOnlineEnabled(!onlineEnabled);
return;
}
if (input === 'g' || input === 'G') {
const nextMode = (() => {
switch (state.gameMode) {
case 'single':
return 'vs-player';
case 'vs-player':
return 'vs-ai';
case 'vs-ai':
return 'single';
}
})();
dispatch({ type: 'SET_GAME_MODE', payload: nextMode });
return;
}
if (state.gridSelectionMode === 'preset') {
if (key.upArrow &&
state.currentPresetIndex < ALL_PRESET_GRIDS.length - 1) {
const nextIndex = state.currentPresetIndex + 1;
const nextGrid = ALL_PRESET_GRIDS[nextIndex];
if (nextGrid) {
dispatch({ type: 'SET_CURRENT_PRESET_INDEX', payload: nextIndex });
dispatch({ type: 'SET_GRID_DIMENSION', payload: nextGrid });
}
}
else if (key.downArrow && state.currentPresetIndex > 0) {
const nextIndex = state.currentPresetIndex - 1;
const nextGrid = ALL_PRESET_GRIDS[nextIndex];
if (nextGrid) {
dispatch({ type: 'SET_CURRENT_PRESET_INDEX', payload: nextIndex });
dispatch({ type: 'SET_GRID_DIMENSION', payload: nextGrid });
}
}
}
else {
// Custom mode
if (key.leftArrow) {
const next = {
...state.gridDimension,
cols: Math.max(state.gridDimension.cols - 1, 1),
};
if (isValidGrid(next)) {
dispatch({ type: 'SET_GRID_DIMENSION', payload: next });
}
}
else if (key.rightArrow) {
const next = {
...state.gridDimension,
cols: Math.min(state.gridDimension.cols + 1, 12),
};
if (isValidGrid(next)) {
dispatch({ type: 'SET_GRID_DIMENSION', payload: next });
}
}
else if (key.upArrow) {
const next = {
...state.gridDimension,
rows: Math.min(state.gridDimension.rows + 1, 12),
};
if (isValidGrid(next)) {
dispatch({ type: 'SET_GRID_DIMENSION', payload: next });
}
}
else if (key.downArrow) {
const next = {
...state.gridDimension,
rows: Math.max(state.gridDimension.rows - 1, 1),
};
if (isValidGrid(next)) {
dispatch({ type: 'SET_GRID_DIMENSION', payload: next });
}
}
}
if (input === ' ' || key.return) {
dispatch({ type: 'START_NEW_GAME' });
}
});
const { gameMode, gridDimension, gridSelectionMode } = state;
return (React.createElement(GameLayout, null,
React.createElement(Box, { height: 6 },
React.createElement(Gradient, { name: "mind" },
React.createElement(BigText, { text: "Memory" }))),
React.createElement(GameModeSelect, { currentMode: gameMode }),
React.createElement(GridSizeConfig, { gridDimension: gridDimension, selectionMode: gridSelectionMode }),
React.createElement(HighScoreDisplay, { gameMode: gameMode, gridDimension: gridDimension }),
React.createElement(Controls, { gridSelectionMode: gridSelectionMode, onlineEnabled: onlineEnabled }),
React.createElement(Box, { marginTop: 1 },
React.createElement(Text, { color: COLORS.dim },
"Press",
' ',
React.createElement(Gradient, { name: "cristal" },
React.createElement(Text, { bold: true }, "Space")),
' ',
"to begin!"))));
};