Skip to content

Commit

Permalink
Merge pull request #23 from shibisuriya/feat/replay
Browse files Browse the repository at this point in the history
feat: added the ability to pause + revamped the grid
  • Loading branch information
shibisuriya authored Nov 9, 2023
2 parents 187c771 + 9e230f3 commit 5f51ef1
Show file tree
Hide file tree
Showing 12 changed files with 336 additions and 255 deletions.
1 change: 1 addition & 0 deletions packages/game-client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"webpack-dev-server": "^4.15.1"
},
"dependencies": {
"antd": "^5.11.0",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0"
Expand Down
114 changes: 47 additions & 67 deletions packages/game-client/src/App.jsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,54 @@
import React, { useState } from 'react';
import { defaultDirections } from './constants';
import { initialSnakesState, initialFoodState } from './computed';
import { useDirection, useFood, useTicks, useSnakes, useInput, useSocket } from './hooks';
import Grid from './Grid';
import styles from './app.module.css';

// function App() {
// const [mounted, setMounted] = useState(true);
// return (
// <div>
// <div>
// <button onClick={() => setMounted((prev) => !prev)}>Mount / Unmount</button>
// </div>
// <div>{mounted && <Game />}</div>
// </div>
// );
// }
import React, { Fragment, useState } from 'react';
import Game from './Game';
import { Button } from 'antd';
import { Divider, Space, Checkbox, Switch } from 'antd';
import { stringToBoolean } from './utils';

function App() {
const [snakeId, setSnakeId] = useState(1);

// Keep the direction of the snakes inside useRef since we don't
// want to force rerender of the component when the user changes
// the direction.
const { getDirection, onLeft, onRight, onUp, onDown, setDirection } = useDirection(defaultDirections, 1);

useInput({ snakes, onUp, onDown, onLeft, onRight, snakeId });

const getSnakeCells = () => allSnakeCells();

const { food, getFood, removeFood, spawnFood, isFood, setFood } = useFood({ initialFoodState, getSnakeCells });

const getTracks = () => {
return { addSnakeToTrack, removeSnakeFromTracks, resetSnakeTrack };
};

// Don't keep direction of the snakes inside of useState()...
const {
snakes,
moveForward,
getSnakeCells: allSnakeCells,
getAllSnakeIds,
} = useSnakes({
initialSnakesState,
getDirection,
getFood,
removeFood,
setDirection,
isFood,
setFood,
getTracks,
});

const { addSnakeToTrack, removeSnakeFromTracks, resetSnakeTrack } = useTicks({
moveForward,
spawnFood,
getAllSnakeIds,
});
const [recordInLocalStorage, setRecordInLocalStorage] = useState(
stringToBoolean(localStorage.getItem('recordInLocalStorage')) ?? false,
);

const [isGamePaused, setIsGamePaused] = useState(stringToBoolean(localStorage.getItem('isGamePaused') ?? true));
const [showCellId, setShowCellId] = useState(stringToBoolean(localStorage.getItem('showCellId')) ?? false);
return (
<div className={styles.game}>
{/* <select value={snakeId} onChange={(e) => setSnakeId(e.target.value)}>
{Object.keys(snakes).map((snakeId, index) => (
<option value={snakeId} key={index}>
{snakeId}
</option>
))}
</select> */}
<Grid snakes={snakes} food={food} />
</div>
<Fragment>
<Space>
<Checkbox
checked={isGamePaused}
onChange={(e) => {
const val = e.target.checked;
localStorage.setItem('isGamePaused', val);
setIsGamePaused(val);
}}
>
Is Game paused?
</Checkbox>
<Checkbox
checked={recordInLocalStorage}
onChange={(e) => {
const val = Boolean(e.target.checked);
localStorage.setItem('recordInLocalStorage', val);
setRecordInLocalStorage(val);
}}
>
Record game in localStorage?
</Checkbox>
<Checkbox
checked={showCellId}
onChange={(e) => {
const val = Boolean(e.target.checked);
localStorage.setItem('showCellId', val);
setShowCellId(val);
}}
>
Show cell ID?
</Checkbox>
</Space>

<Divider dashed />
<Game showCellId={showCellId} isGamePaused={isGamePaused} />
</Fragment>
);
}

Expand Down
77 changes: 77 additions & 0 deletions packages/game-client/src/Game.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import React, { Fragment, useState } from 'react';
import { defaultDirections } from './constants';
import { initialSnakesState, initialFoodState } from './computed';
import { useDirection, useFood, useTicks, useSnakes, useInput, useSocket } from './hooks';
import Grid from './Grid';
import styles from './app.module.css';

// function App() {
// const [mounted, setMounted] = useState(true);
// return (
// <div>
// <div>
// <button onClick={() => setMounted((prev) => !prev)}>Mount / Unmount</button>
// </div>
// <div>{mounted && <Game />}</div>
// </div>
// );
// }

function Game(props) {
const { showCellId, isGamePaused } = props;
const [snakeId, setSnakeId] = useState(1);

// Keep the direction of the snakes inside useRef since we don't
// want to force rerender of the component when the user changes
// the direction.
const { getDirection, onLeft, onRight, onUp, onDown, setDirection } = useDirection(defaultDirections, 1);

useInput({ snakes, onUp, onDown, onLeft, onRight, snakeId });

const getSnakeCells = () => allSnakeCells();

const { food, getFood, removeFood, spawnFood, isFood, setFood } = useFood({ initialFoodState, getSnakeCells });

const getTracks = () => {
return { addSnakeToTrack, removeSnakeFromTracks, resetSnakeTrack };
};

// Don't keep direction of the snakes inside of useState()...
const {
snakes,
moveForward,
getSnakeCells: allSnakeCells,
getAllSnakeIds,
} = useSnakes({
initialSnakesState,
getDirection,
getFood,
removeFood,
setDirection,
isFood,
setFood,
getTracks,
});

const { addSnakeToTrack, removeSnakeFromTracks, resetSnakeTrack } = useTicks({
moveForward,
spawnFood,
getAllSnakeIds,
isGamePaused,
});

return (
<div className={styles.game}>
{/* <select value={snakeId} onChange={(e) => setSnakeId(e.target.value)}>
{Object.keys(snakes).map((snakeId, index) => (
<option value={snakeId} key={index}>
{snakeId}
</option>
))}
</select> */}
<Grid snakes={snakes} food={food} showCellId={showCellId} />
</div>
);
}

export default Game;
49 changes: 23 additions & 26 deletions packages/game-client/src/Grid.jsx
Original file line number Diff line number Diff line change
@@ -1,54 +1,51 @@
import React from 'react';
import styles from './grid.module.css';
import { CELL_DIMENSION, GRID_HEIGHT, GRID_WIDTH } from './constants';
import { CELL_DIMENSION, GRID_HEIGHT, GRID_WIDTH, FOOD_TYPES } from './constants';
import animation from './animations.module.css';

function Cell({ x, y, color }) {
function Cell({ x, y, color, showCellId, animationClass }) {
return (
<div
className={styles.cell}
className={`${styles.cell} ${animation[animationClass]}`}
style={{
top: `${x * CELL_DIMENSION}px`,
left: `${y * CELL_DIMENSION}px`,
height: `${CELL_DIMENSION}px`,
width: `${CELL_DIMENSION}px`,
backgroundColor: color,
}}
></div>
);
}

function Food({ x, y, type }) {
return (
<div
className={`${styles.cell} ${styles.food} ${styles[type.toLowerCase()]}`}
style={{
top: `${x * CELL_DIMENSION}px`,
left: `${y * CELL_DIMENSION}px`,
height: `${CELL_DIMENSION}px`,
width: `${CELL_DIMENSION}px`,
}}
></div>
>
{showCellId && `${x}-${y}`}
</div>
);
}

function Grid({ snakes, food }) {
function Grid({ snakes, food, showCellId }) {
return (
<div className={styles.grid} style={{ width: `${GRID_WIDTH}px`, height: `${GRID_HEIGHT}px` }}>
{Object.values(snakes).map((snake) => {
const { hash, headColor, bodyColor } = snake;
const [headKey] = snake.list;
return Object.entries(hash).map(([key, value]) => {
const { x, y } = value;
if (key == headKey) {
return <Cell x={x} y={y} key={key} color={headColor} />;
} else {
return <Cell x={x} y={y} key={key} color={bodyColor} />;
}
return (
<Cell
x={x}
y={y}
key={key}
color={key == headKey ? headColor : bodyColor}
showCellId={showCellId}
type="snake"
/>
);
});
})}
{Object.entries(food).map(([key, value]) => {
const { x, y, type } = value;
return <Food x={x} y={y} key={key} type={type} />;
const { x, y, type: foodType } = value;
const { color, animationClass } = FOOD_TYPES[foodType];
return (
<Cell x={x} y={y} key={key} color={color} showCellId={showCellId} animationClass={animationClass} />
);
})}
</div>
);
Expand Down
Loading

0 comments on commit 5f51ef1

Please sign in to comment.