✨ Integrated Home comp with the game comp
This commit is contained in:
+11
-6
@@ -7,7 +7,8 @@ import { useState } from 'react';
|
|||||||
// ---------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// ----------------------------------------------------- Context -------------------------------------------------------
|
// ----------------------------------------------------- Context -------------------------------------------------------
|
||||||
import { RecoilRoot } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
import { gameStateAtom } from './contexts/gameState';
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// --------------------------------------------------- Components ------------------------------------------------------
|
// --------------------------------------------------- Components ------------------------------------------------------
|
||||||
@@ -28,9 +29,13 @@ import LeaderBoard from './components/Leaderboard/leaderboard';
|
|||||||
const App = () => {
|
const App = () => {
|
||||||
const [helpDisplayed, displayHelp] = useState(false);
|
const [helpDisplayed, displayHelp] = useState(false);
|
||||||
|
|
||||||
|
const [gameState] = useRecoilState(gameStateAtom);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='App'>
|
<div className='App'>
|
||||||
{/* <RecoilRoot>
|
{gameState.status === 'settings' && <Home />}
|
||||||
|
{(gameState.status === 'idle' || gameState.status === 'playing') && (
|
||||||
|
<>
|
||||||
<div className='stats'>
|
<div className='stats'>
|
||||||
<Timer />
|
<Timer />
|
||||||
<Logo className={'logo'} />
|
<Logo className={'logo'} />
|
||||||
@@ -44,16 +49,16 @@ const App = () => {
|
|||||||
<Question />
|
<Question />
|
||||||
<span>Comment jouer</span>
|
<span>Comment jouer</span>
|
||||||
</button>
|
</button>
|
||||||
</RecoilRoot>
|
|
||||||
{helpDisplayed && (
|
{helpDisplayed && (
|
||||||
<Help
|
<Help
|
||||||
onClose={() => {
|
onClose={() => {
|
||||||
displayHelp(false);
|
displayHelp(false);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)} */}
|
)}
|
||||||
<Home />
|
</>
|
||||||
{/* <LeaderBoard /> */}
|
)}
|
||||||
|
{gameState.status === 'board' && <LeaderBoard />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,10 +22,10 @@ import Flag from '../../assets/flag.png';
|
|||||||
import './styles.scss';
|
import './styles.scss';
|
||||||
// ---------------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
const Grid = () => {
|
||||||
const [gameState, setGameState] = useRecoilState(gameStateAtom);
|
const [gameState, setGameState] = useRecoilState(gameStateAtom);
|
||||||
|
|
||||||
const [grid, setGrid] = useState(genGrid(size));
|
const [grid, setGrid] = useState(genGrid(gameState.gridSize));
|
||||||
|
|
||||||
const [, updateGrid] = useState({});
|
const [, updateGrid] = useState({});
|
||||||
const forceUpdate = useCallback(() => updateGrid({}), []);
|
const forceUpdate = useCallback(() => updateGrid({}), []);
|
||||||
@@ -37,7 +37,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
|||||||
if (grid[rowIndex][colIndex].hidden && !grid[rowIndex][colIndex].flag) {
|
if (grid[rowIndex][colIndex].hidden && !grid[rowIndex][colIndex].flag) {
|
||||||
setGrid((prev) => {
|
setGrid((prev) => {
|
||||||
if (gameState.status === 'idle') {
|
if (gameState.status === 'idle') {
|
||||||
const { grid: newGrid, bombsCount } = startGame(prev, difficulty as Difficulty, true, rowIndex, colIndex);
|
const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, true, rowIndex, colIndex);
|
||||||
prev = newGrid;
|
prev = newGrid;
|
||||||
|
|
||||||
setGameState((prevGameState) => ({
|
setGameState((prevGameState) => ({
|
||||||
@@ -59,7 +59,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
|||||||
if (grid[rowIndex][colIndex].hidden) {
|
if (grid[rowIndex][colIndex].hidden) {
|
||||||
setGrid((prev) => {
|
setGrid((prev) => {
|
||||||
if (gameState.status === 'idle') {
|
if (gameState.status === 'idle') {
|
||||||
const { grid: newGrid, bombsCount } = startGame(prev, difficulty as Difficulty, false);
|
const { grid: newGrid, bombsCount } = startGame(prev, gameState.difficulty as Difficulty, false);
|
||||||
prev = newGrid;
|
prev = newGrid;
|
||||||
|
|
||||||
setGameState((prevGameState) => ({
|
setGameState((prevGameState) => ({
|
||||||
@@ -97,7 +97,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
|||||||
<div
|
<div
|
||||||
className='grid'
|
className='grid'
|
||||||
style={{
|
style={{
|
||||||
gridTemplateRows: `repeat(${size}, var(--size))`,
|
gridTemplateRows: `repeat(${gameState.gridSize}, var(--size))`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{grid.map((row, rowIndex) => (
|
{grid.map((row, rowIndex) => (
|
||||||
@@ -105,7 +105,7 @@ const Grid = ({ size = 12, difficulty = 'beginner' }) => {
|
|||||||
key={`row${rowIndex}`}
|
key={`row${rowIndex}`}
|
||||||
className='row'
|
className='row'
|
||||||
style={{
|
style={{
|
||||||
gridTemplateColumns: `repeat(${size}, var(--size))`,
|
gridTemplateColumns: `repeat(${gameState.gridSize}, var(--size))`,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{row.map((cell, cellIndex) => {
|
{row.map((cell, cellIndex) => {
|
||||||
|
|||||||
@@ -1,27 +1,79 @@
|
|||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
//! Imports
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// ----------------------------------------------------- Styles --------------------------------------------------------
|
||||||
|
import { useRef } from 'react';
|
||||||
import './styles.scss';
|
import './styles.scss';
|
||||||
|
import { useRecoilState } from 'recoil';
|
||||||
|
import { gameStateAtom } from '../../contexts/gameState';
|
||||||
|
// ---------------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
const Home = () => {
|
const Home = () => {
|
||||||
|
const difficultyRef = useRef<HTMLSelectElement>(null);
|
||||||
|
const sizeRef = useRef<HTMLSelectElement>(null);
|
||||||
|
|
||||||
|
const [, setGameState] = useRecoilState(gameStateAtom);
|
||||||
|
|
||||||
|
const onClick = () => {
|
||||||
|
if (difficultyRef.current !== null && sizeRef.current !== null) {
|
||||||
|
const difficulty = difficultyRef.current.value;
|
||||||
|
const size = sizeRef.current.value;
|
||||||
|
|
||||||
|
setGameState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
difficulty: difficulty,
|
||||||
|
gridSize: parseInt(size),
|
||||||
|
status: 'idle',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='gameContainer'>
|
<div className='gameContainer'>
|
||||||
<h1 className='gameTitle'>Démineur</h1>
|
<h1 className='title'>Démineur</h1>
|
||||||
|
|
||||||
<div className='settingsContainer'>
|
<div className='settingsContainer'>
|
||||||
<div className='selectorBox'>
|
<div className='selectorBox'>
|
||||||
<p className='chooseTitle'>Choisissez la taille de la grille</p>
|
<p className='settingLabel'>Taille de la grille</p>
|
||||||
<select className='parameterBox'>
|
<select
|
||||||
<option value='little'>Petit</option>
|
ref={sizeRef}
|
||||||
<option value='medium'>Moyen</option>
|
className='select'
|
||||||
<option value='big'>Grand</option>
|
>
|
||||||
|
<option
|
||||||
|
value='12'
|
||||||
|
selected
|
||||||
|
>
|
||||||
|
Petit
|
||||||
|
</option>
|
||||||
|
<option value='16'>Moyen</option>
|
||||||
|
<option value='20'>Grand</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='selectorBox'>
|
<div className='selectorBox'>
|
||||||
<p className='chooseTitle'>Choisissez votre niveau</p>
|
<p className='settingLabel'>Difficulté</p>
|
||||||
<select className='parameterBox'>
|
<select
|
||||||
<option value='easy'>Facile</option>
|
ref={difficultyRef}
|
||||||
<option value='medium'>Moyen</option>
|
className='select'
|
||||||
<option value='hard'>Difficile</option>
|
>
|
||||||
|
<option
|
||||||
|
value='beginner'
|
||||||
|
selected
|
||||||
|
>
|
||||||
|
Facile
|
||||||
|
</option>
|
||||||
|
<option value='intermediate'>Moyen</option>
|
||||||
|
<option value='expert'>Difficile</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<button className='startGameBtn'>Commencer</button>
|
|
||||||
|
<button
|
||||||
|
className='startButton'
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
Commencer
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,47 +1,64 @@
|
|||||||
.gameContainer {
|
.gameContainer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
height: 100vh;
|
align-items: stretch;
|
||||||
}
|
gap: 30px;
|
||||||
|
width: 95svw;
|
||||||
|
max-width: 500px;
|
||||||
|
|
||||||
.gameTitle {
|
& > .title {
|
||||||
font-size: 2rem;
|
font-size: 2em;
|
||||||
font-weight: bold;
|
font-weight: 600;
|
||||||
}
|
text-align: center;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
.settingsContainer {
|
& > .settingsContainer {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-rows: repeat(2, 1fr);
|
flex-direction: column;
|
||||||
margin: 1rem 0 1rem 0;
|
gap: 20px;
|
||||||
gap: 10px;
|
padding: 20px;
|
||||||
}
|
border: 2px solid #f39440;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #ffdccb;
|
||||||
|
|
||||||
.selectorBox {
|
& > .selectorBox {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
gap: 20px;
|
gap: 20px;
|
||||||
}
|
|
||||||
|
|
||||||
.chooseTitle{
|
& > .settingLabel {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
color: #f39440;
|
||||||
|
}
|
||||||
|
|
||||||
.parameterBox {
|
& > .select {
|
||||||
font-size: 1rem;
|
|
||||||
border-radius: 5px;
|
|
||||||
padding: 2.5px 5px;
|
padding: 2.5px 5px;
|
||||||
}
|
border: 1px solid #f39440;
|
||||||
|
border-radius: 5px;
|
||||||
.startGameBtn {
|
background-color: #ffdccb;
|
||||||
margin: 1rem 0 1rem 0;
|
font-size: 1rem;
|
||||||
padding: 0.7rem 1rem;
|
color: #f39440;
|
||||||
border-radius: 10px;
|
outline: none;
|
||||||
font-size: 1.2rem;
|
|
||||||
font-weight: bold;
|
|
||||||
background-color: #333;
|
|
||||||
color: #FFF;
|
|
||||||
border: #FFF 0.5px solid;
|
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
& > .startButton {
|
||||||
|
padding: 10px;
|
||||||
|
border: 2px solid #f39440;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: #ffdccb;
|
||||||
|
font-size: 1.2em;
|
||||||
|
color: #f39440;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.3s ease, color 0.3s ease;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: #f39440;
|
||||||
|
color: #ffdccb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -3,8 +3,10 @@ import { atom } from 'recoil';
|
|||||||
export const gameStateAtom = atom({
|
export const gameStateAtom = atom({
|
||||||
key: 'gameState',
|
key: 'gameState',
|
||||||
default: {
|
default: {
|
||||||
|
status: 'settings',
|
||||||
|
difficulty: 'begginer',
|
||||||
|
gridSize: 20,
|
||||||
bombs: 0,
|
bombs: 0,
|
||||||
placedFlags: 0,
|
placedFlags: 0,
|
||||||
status: 'idle',
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
+6
-1
@@ -5,12 +5,17 @@
|
|||||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
user-select: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#root {
|
#root {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
width: 100svw;
|
width: 100svw;
|
||||||
height: 100svh;
|
height: 100svh;
|
||||||
background: #598b8e;
|
background: #598b8e;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
color: #fff;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ import React from 'react';
|
|||||||
import ReactDOM from 'react-dom/client';
|
import ReactDOM from 'react-dom/client';
|
||||||
import './index.scss';
|
import './index.scss';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
import { RecoilRoot } from 'recoil';
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
|
||||||
|
|
||||||
root.render(
|
root.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
<RecoilRoot>
|
||||||
<App />
|
<App />
|
||||||
|
</RecoilRoot>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user