This commit is contained in:
Kai Moseley 2016-09-20 23:52:23 +01:00
parent db9b46ec09
commit 0ca9f5c64a
8 changed files with 28 additions and 16 deletions

View File

@ -1,4 +1,4 @@
{
"presets": ["es2015", "react"],
"plugins": ["transform-object-rest-spread", "syntax-async-functions", "transform-async-to-generator", "transform-flow-strip-types"]
"plugins": ["transform-object-rest-spread", "transform-flow-strip-types"]
}

View File

@ -24,13 +24,14 @@
"eslint-plugin-react": "^6.0.0",
"flow-bin": "^0.32.0",
"jest": "^15.1.1",
"lodash": "^4.16.1",
"node-sass": "^3.8.0",
"react": "^15.3.1",
"react-dom": "^15.3.1",
"react-motion": "^0.4.4",
"sass-loader": "^4.0.0",
"style-loader": "^0.13.1",
"webpack": "^1.13.2",
"webpack-dev-server": "^1.16.1",
"react-motion": "^0.4.4"
"webpack-dev-server": "^1.16.1"
}
}

View File

@ -17,8 +17,6 @@ type GameProps = {
shuffled: boolean,
}
type onClick = (event: Object) => void
export const Game = (props: GameProps) => (
<div>
<div className={ styles.board } style={{ width: 10 + (props.shells.length * 110) }}>

View File

@ -7,6 +7,7 @@ import {
randomizeArrayOrder,
} from '../utils/gameUtils';
import { Game } from './Game';
import { isEqual } from 'lodash';
//=====================
// Flow types
@ -34,9 +35,11 @@ type Shell = {
// Game component
//======================
export class GameContainer extends Component {
//Flow types
state: GameContainerState;
props: GameContainerProps;
selectRandomShell: ?() => number;
shufflingTimeout: ?number;
_initializeGame: (numberOfShells: number) => void;
_startGame: () => void;
_setWinningShell: () => void;
@ -55,6 +58,7 @@ export class GameContainer extends Component {
output: `Click on 'Play' to begin!`,
};
this.selectRandomShell = null;
this.shufflingTimeout = null;
//In general it's a good idea to bind methods which refer to this in the
//constructor. It means, amongst other things, that the functions can be
@ -97,6 +101,7 @@ export class GameContainer extends Component {
}
_setWinningShell(): void {
//Randomly determine the winning shell (this is the shell which has the ball at the beginning of a round)
if (!this.selectRandomShell) throw new Error('selectRandomShell not properly initialized!');
this.setState({
ballShellId: this.selectRandomShell(),
@ -133,9 +138,9 @@ export class GameContainer extends Component {
shuffling: shuffleCount < this.props.shuffles,
});
if (this.state.shuffled) return res(true);
return setTimeout(shuffle, 1000);
this.shufflingTimeout = setTimeout(shuffle, 1000);
};
setTimeout(shuffle, 1000);
this.shufflingTimeout = setTimeout(shuffle, 1000);
});
}
@ -145,7 +150,9 @@ export class GameContainer extends Component {
}
componentWillReceiveProps(newProps: GameContainerProps) {
if(newProps.numberOfShells !== this.props.numberOfShells) {
if(!isEqual(newProps, this.props)) {
//If the input properties change mid shuffle, cancel the shuffling function
if (this.shufflingTimeout) clearTimeout(this.shufflingTimeout);
this._initializeGame(newProps.numberOfShells);
}
}

View File

@ -11,7 +11,7 @@ type ShellProps = {
}
export const Shell = (props: ShellProps) =>
<Motion style={{x: spring(props.position, { stiffness: 300, damping: 15 })}}>
<Motion style={{x: spring(props.position, { stiffness: 276, damping: 26 })}}>
{ ({ x }) => (
<div>
<div
@ -21,8 +21,8 @@ export const Shell = (props: ShellProps) =>
className={ styles.shell }
onClick={ props.onClick }
>
{ props.containsBall && props.displayBall &&
<div className={ styles.ball } /> }
{ props.containsBall && props.displayBall &&
<div className={ styles.ball } /> }
</div>
</div>
)}

View File

@ -20,6 +20,7 @@ export class ShellGameAppContainer extends Component {
this._handleInputUpdate = this._handleInputUpdate.bind(this);
}
//Simple form handler (takes the name and value of an input and adds it to the state if preset).
_handleInputUpdate(e: Object): void {
if (!this.state.hasOwnProperty(e.target.name)) throw new Error('Form input name should be on the GameShellAppContainer state');
this.setState({

View File

@ -4,5 +4,6 @@ import ReactDOM from 'react-dom';
import { ShellGameAppContainer } from './components';
ReactDOM.render(
<ShellGameAppContainer />
, document.getElementById('react-shell-game'));
<ShellGameAppContainer />,
document.getElementById('react-shell-game'
));

View File

@ -5,11 +5,14 @@ type Shell = {
//======================
// Utility functions
//======================
//Generate a random number generator which will return values within a given range.
export function createRandomNumberFn(minimum: number, maximum: number): () => number {
return () => minimum + Math.floor(Math.random() * ((maximum-minimum) + 1));
}
export function randomizeArrayOrder(array: Shell[]): Shell[] {
//Create a randomized array based on an input array.
export function randomizeArrayOrder(array: []): [] {
let oldArray = [ ...array ];
let newArr = [];
@ -20,10 +23,11 @@ export function randomizeArrayOrder(array: Shell[]): Shell[] {
return newArr;
}
export function createShells(numberOfShells: number): Shell[] {
/* The shell containing the ball will be tracked independently of shells, but
in order to properly animate the shells later, a fixed id is desirable.
*/
in order to properly keep track of components (particularly useful with certain animation libraries),
a fixed id is desirable. */
let newShellArr = [];
for (let i=0; i<numberOfShells; i++) {
newShellArr = [ ...newShellArr, {