Extracted all components in their own files.
This commit is contained in:
17
src/components/Apple.js
Normal file
17
src/components/Apple.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
export const Apple = styled.div.attrs({ role: "img", "aria-label": "apple" })`
|
||||||
|
width: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
height: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 1.8rem;
|
||||||
|
padding-left: 0.0625rem;
|
||||||
|
&:after {
|
||||||
|
content: "${props => (!props.died ? "🍎" : "🐛")}";
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Apple;
|
||||||
29
src/components/SnakePart.js
Normal file
29
src/components/SnakePart.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import styled, { css } from "styled-components";
|
||||||
|
|
||||||
|
export const SnakePart = styled.div`
|
||||||
|
width: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
height: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
display: inline-block;
|
||||||
|
font-size: 1.3rem;
|
||||||
|
vertical-align: top;
|
||||||
|
line-height: 1.8rem;
|
||||||
|
padding-left: 0.0625rem;
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
!props.died
|
||||||
|
? css`
|
||||||
|
background-color: ${props => props.value && `hsl(340, ${props.value.brightness}%, 65%)`};
|
||||||
|
box-shadow: 1px 1px 2px #ddd inset, -1px -1px 2px gray inset;
|
||||||
|
`
|
||||||
|
: css`
|
||||||
|
background-color: ${props => props.value && `hsl(0, 0%, ${100 - props.value.brightness}% )`};
|
||||||
|
box-shadow: 1px 1px 2px #ddd inset, -1px -1px 2px gray inset;
|
||||||
|
|
||||||
|
&:after {
|
||||||
|
content: "${props => props.value && props.value.index === 0 && "💀"}";
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default SnakePart;
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
import React from "react";
|
||||||
|
import styled from "styled-components";
|
||||||
|
|
||||||
|
const Row = styled.div`
|
||||||
|
white-space: nowrap;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Cell = styled.div`
|
||||||
|
width: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
height: ${({ theme }) => theme.snake.cell.size};
|
||||||
|
border: ${({ theme }) => theme.snake.cell.border};
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 1px 1px 4px gray inset, -1px -1px 4px #fff inset;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Stage = ({ data, children }) => (
|
||||||
|
<div>
|
||||||
|
{data.map((r, y) => (
|
||||||
|
<Row key={`y${y}`}>
|
||||||
|
{r.map((c, x) => (
|
||||||
|
<Cell key={`x${x}y${y}`}>{children(c)}</Cell>
|
||||||
|
))}
|
||||||
|
</Row>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default Stage;
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ import {
|
|||||||
/* Components */
|
/* Components */
|
||||||
import ControlPanel from "../components/ControlPanel.js";
|
import ControlPanel from "../components/ControlPanel.js";
|
||||||
import Scoreboard from "../components/Scoreboard.js";
|
import Scoreboard from "../components/Scoreboard.js";
|
||||||
|
import Stage from "../components/Stage.js";
|
||||||
|
import SnakePart from "../components/SnakePart.js";
|
||||||
|
import Apple from "../components/Apple.js";
|
||||||
|
|
||||||
const Layout = styled.div`
|
const Layout = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -29,74 +32,6 @@ const SidePanel = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Row = styled.div`
|
|
||||||
white-space: nowrap;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Cell = styled.div`
|
|
||||||
width: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
height: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
border: ${({ theme }) => theme.snake.cell.border};
|
|
||||||
display: inline-block;
|
|
||||||
vertical-align: top;
|
|
||||||
text-align: center;
|
|
||||||
background-color: ${props => props.theme.snake.cellColors[" "]};
|
|
||||||
box-shadow: 1px 1px 4px gray inset, -1px -1px 4px #fff inset;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const SnakePart = styled.div`
|
|
||||||
width: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
height: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
background-color: ${props => props.value && `hsl(340, ${props.value.brightness}%, 65%)`};
|
|
||||||
box-shadow: 1px 1px 2px #ddd inset, -1px -1px 2px gray inset;
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Apple = styled.div.attrs({ role: "img", "aria-label": "apple" })`
|
|
||||||
width: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
height: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
vertical-align: top;
|
|
||||||
line-height: 1.8rem;
|
|
||||||
padding-left: 0.0625rem;
|
|
||||||
&:after {
|
|
||||||
content: "${props => (!props.died ? "🍎" : "🐛")}";
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Skull = styled.div.attrs({ role: "img", "aria-label": "skull" })`
|
|
||||||
width: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
height: ${({ theme }) => theme.snake.cell.size};
|
|
||||||
display: inline-block;
|
|
||||||
font-size: 1.3rem;
|
|
||||||
vertical-align: top;
|
|
||||||
line-height: 1.8rem;
|
|
||||||
background-color: ${props => props.value && `hsl(0, 0%, ${100 - props.value.brightness}% )`};
|
|
||||||
padding-left: 0.0625rem;
|
|
||||||
box-shadow: 1px 1px 2px #ddd inset, -1px -1px 2px gray inset;
|
|
||||||
&:after {
|
|
||||||
content: "${props => props.value && props.value.index === 0 && "💀"}";
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
const Grid = ({ data, died }) => (
|
|
||||||
<div>
|
|
||||||
{data.map((r, y) => (
|
|
||||||
<Row key={`y${y}`}>
|
|
||||||
{r.map((c, x) => (
|
|
||||||
<Cell key={`x${x}y${y}`} died={died}>
|
|
||||||
{c.type === "apple" && <Apple died={died} />}
|
|
||||||
{!died && c.type === "snake" && <SnakePart value={c} />}
|
|
||||||
{died && c.type === "snake" && <Skull value={c} />}
|
|
||||||
</Cell>
|
|
||||||
))}
|
|
||||||
</Row>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
class Snake extends React.Component {
|
class Snake extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@@ -132,7 +67,12 @@ class Snake extends React.Component {
|
|||||||
return (
|
return (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<Layout>
|
<Layout>
|
||||||
<Grid data={grid} died={died} />
|
<Stage data={grid}>
|
||||||
|
{cell =>
|
||||||
|
(cell.type === "apple" && <Apple died={died} />) ||
|
||||||
|
(cell.type === "snake" && <SnakePart value={cell} died={died} />)
|
||||||
|
}
|
||||||
|
</Stage>
|
||||||
<SidePanel>
|
<SidePanel>
|
||||||
<Scoreboard score={score} zoom={2} />
|
<Scoreboard score={score} zoom={2} />
|
||||||
<ControlPanel
|
<ControlPanel
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
export default class GameLoop {
|
|
||||||
-_isRunning = false;
|
|
||||||
-_handler = null;
|
|
||||||
|
|
||||||
constructor(handler) {
|
|
||||||
this._handler = handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
get isRunning() {
|
|
||||||
return this._isRunning;
|
|
||||||
}
|
|
||||||
|
|
||||||
start() {
|
|
||||||
this._isRunning = true;
|
|
||||||
}
|
|
||||||
stop() {
|
|
||||||
this._isRunning = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user