Refactoring global key listeners into appropriate components.

master
Ben Burlingham 9 years ago
parent 43a0a09314
commit 778c1678a9
  1. 12
      actions/board/troggle.actions.js
  2. 170
      components/board/board.component.js
  3. 17
      components/board/message.component.js
  4. 20
      components/board/muncher.component.js
  5. 4
      reducers/board/troggle.reducer.js
  6. 7
      sass/board/message.scss

@ -1,8 +1,6 @@
export const TROGGLE_ACTION = 'TROGGLE_ACTION'; export const TROGGLE_ACTION = 'TROGGLE_ACTION';
export const CREATE = 'CREATE'; export const CREATE = 'CREATE';
export const MOVE = 'MOVE'; export const MOVE = 'MOVE';
export const FREEZE_ALL = 'FREEZE_ALL';
export const UNFREEZE_ALL = 'UNFREEZE_ALL';
export const CLEAR_ALL = 'CLEAR_ALL'; export const CLEAR_ALL = 'CLEAR_ALL';
export const create = (x, y) => ({ export const create = (x, y) => ({
@ -20,16 +18,6 @@ export const move = (index, x, y) => ({
y: y y: y
}); });
export const freezeAll = () => ({
type: TROGGLE_ACTION,
action: FREEZE_ALL
});
export const unfreezeAll = () => ({
type: TROGGLE_ACTION,
action: UNFREEZE_ALL
});
export const clearAll = () => ({ export const clearAll = () => ({
type: TROGGLE_ACTION, type: TROGGLE_ACTION,
action: CLEAR_ALL action: CLEAR_ALL

@ -26,127 +26,115 @@ const troggleCreateTimers = [];
let listener = null; let listener = null;
export default class Board extends Component { export default class Board extends Component {
refocus() {
this.props.dispatch(MessageActions.hide());
ReactDOM.findDOMNode(this.refs.muncher).focus();
};
componentDidMount() { componentDidMount() {
listener = this.keydown.bind(this); ReactDOM.findDOMNode(this.refs.muncher).focus();
window.addEventListener('keydown', listener); listener = this.refocus.bind(this);
window.addEventListener('click', listener);
this.nextLevel(); this.nextLevel();
}; };
componentWillUnmount() { componentWillUnmount() {
this.clearTroggleTimers(); // this.clearTroggleTimers();
window.removeEventListener('keydown', listener); window.removeEventListener('keydown', listener);
}; };
nextLevel() { nextLevel() {
this.props.dispatch(BoardActions.nextLevel()); this.props.dispatch(BoardActions.nextLevel());
this.props.dispatch(TroggleActions.clearAll()); // this.props.dispatch(TroggleActions.clearAll());
this.clearTroggleTimers(); // this.clearTroggleTimers();
this.createTroggles(); // this.createTroggles();
};
clearTroggleTimers() {
troggleMoveTimers.forEach((timer) => {
clearTimeout(timer);
});
troggleCreateTimers.forEach((timer) => {
clearTimeout(timer);
});
}; };
createTroggle(index) { // clearTroggleTimers() {
const newCoords = TroggleAI.create(); // troggleMoveTimers.forEach((timer) => {
this.props.dispatch(TroggleActions.create(newCoords.x, newCoords.y)); // clearTimeout(timer);
troggleMoveTimers.push(setTimeout(this.moveTroggle.bind(this, index), 1000)); // });
//
// troggleCreateTimers.forEach((timer) => {
// clearTimeout(timer);
// });
// };
//
// createTroggle(index) {
// const newCoords = TroggleAI.create();
// this.props.dispatch(TroggleActions.create(newCoords.x, newCoords.y));
// troggleMoveTimers.push(setTimeout(this.moveTroggle.bind(this, index), 1000));
// };
//
// createTroggles() {
// const troggleCount = 3; //Math.min(Math.ceil(this.props.board.level / 2), 5);
// for (let i = 0; i < troggleCount; i++) {
// setTimeout(this.createTroggle.bind(this, i), (i + 1) * 5000);
// }
// };
//
// moveTroggle(index) {
// const newCoords = TroggleAI.move(
// this.props.troggles[index].x,
// this.props.troggles[index].y,
// this.props.muncher.x,
// this.props.muncher.y
// );
//
// if (newCoords.x === this.props.muncher.x && newCoords.y === this.props.muncher.y) {
// this.props.dispatch(MessageActions.show("You've been eaten by a troggle!"));
// this.props.dispatch(TroggleActions.clearAll());
// }
// else {
// this.props.dispatch(TroggleActions.move(index, newCoords.x, newCoords.y));
// clearTimeout(troggleMoveTimers[index]);
// troggleMoveTimers[index] = setTimeout(this.moveTroggle.bind(this, index), 1000);
// }
// };
messageNext() {
this.props.dispatch(MessageActions.hide());
ReactDOM.findDOMNode(this.refs.muncher).focus();
}; };
createTroggles() { muncherNext(x, y) {
const troggleCount = 3; //Math.min(Math.ceil(this.props.board.level / 2), 5); const index = y * SETTINGS.GRID_WIDTH + x;
for (let i = 0; i < troggleCount; i++) {
setTimeout(this.createTroggle.bind(this, i), (i + 1) * 5000);
}
};
moveTroggle(index) { if (this.props.values[index].valid) {
const newCoords = TroggleAI.move( this.props.dispatch(BoardActions.hideValue(index));
this.props.troggles[index].x, this.props.dispatch(ScorebarActions.munchSucceeded());
this.props.troggles[index].y,
this.props.muncher.x,
this.props.muncher.y
);
if (newCoords.x === this.props.muncher.x && newCoords.y === this.props.muncher.y) {
this.props.dispatch(MessageActions.show('Eaten by a troggle!'));
this.props.dispatch(TroggleActions.clearAll());
} }
else { else {
this.props.dispatch(TroggleActions.move(index, newCoords.x, newCoords.y)); const msg = Values.getError(this.props.values[index].value, this.props.level);
clearTimeout(troggleMoveTimers[index]); this.props.dispatch(MessageActions.show(msg));
troggleMoveTimers[index] = setTimeout(this.moveTroggle.bind(this, index), 1000); this.props.dispatch(ScorebarActions.munchFailed());
} ReactDOM.findDOMNode(this.refs.message).focus();
};
// Keydown listener for spacebar, since it is bound to munch event and
// message hide event. Couldn't find a more modular way to do this.
keydown(e) {
if (e.keyCode !== 32) {
return;
} }
if (this.props.message.hidden === false) { // if (Values.checkComplete(this.props.values, this.props.level)) {
this.props.dispatch(MessageActions.hide()); // this.props.dispatch(MessageActions.exclaim());
this.props.dispatch(MuncherActions.unfreeze()); // }
if (Values.checkComplete(this.props.board.values, this.props.board.level)) {
console.warn("NEXT LEVEL")
}
}
else {
const index = this.props.muncher.y * SETTINGS.GRID_HEIGHT + this.props.muncher.x
const { board, dispatch } = this.props;
if (board.values[index].valid) {
dispatch(BoardActions.hideValue(index));
dispatch(ScorebarActions.munchSucceeded());
}
else {
const msg = Values.getError(board.values[index].value, board.level);
dispatch(MessageActions.show(msg));
dispatch(ScorebarActions.munchFailed());
dispatch(MuncherActions.freeze());
}
if (Values.checkComplete(this.props.board.values, board.level)) {
dispatch(MessageActions.exclaim());
}
}
}; };
render() { render() {
const { board, message, troggles } = this.props; // const troggleElements = [];
const troggleElements = []; // for (let i = 0; i < troggles.length; i++) {
for (let i = 0; i < troggles.length; i++) { // troggleElements[i] = <Troggle x={troggles[i].x} y={troggles[i].y} key={i} />;
troggleElements.push(<Troggle x={troggles[i].x} y={troggles[i].y} key={i} />); // }
} // {troggleElements}
return (<div className='board'> return (<div className='board'>
<Scorebar /> <Scorebar />
<Titlebar title={board.title} /> <Titlebar title={this.props.title} />
<Message hidden={message.hidden} message={message.message} /> <Message ref='message' next={this.messageNext.bind(this)} />
<Muncher /> <Grid values={this.props.values} />
{troggleElements} <Muncher ref='muncher' next={this.muncherNext.bind(this)} />
<Grid values={board.values} />
</div>); </div>);
}; };
}; };
const select = (state) => { const select = (state) => {
return { return state.board;
board: state.board,
muncher: state.muncher,
message: state.message,
troggles: state.troggles
};
} }
export default connect(select)(Board); export default connect(select)(Board);

@ -1,8 +1,15 @@
require('../../sass/board/message.scss'); require('../../sass/board/message.scss');
import { Component } from 'react'; import { Component } from 'react';
import { connect } from 'react-redux';
export class Message extends Component {
keydown(e) {
if (e.keyCode === 32) {
this.props.next();
}
};
export default class Message extends Component {
render() { render() {
var classname = ['message']; var classname = ['message'];
@ -11,7 +18,7 @@ export default class Message extends Component {
} }
return ( return (
<div className={classname.join(' ')}> <div className={classname.join(' ')} tabIndex='1' onKeyDown={this.keydown.bind(this)}>
{this.props.message} {this.props.message}
<br /> <br />
Press Spacebar to continue. Press Spacebar to continue.
@ -19,3 +26,9 @@ export default class Message extends Component {
); );
}; };
}; };
const select = (state) => {
return state.message;
}
export default connect(select)(Message);

@ -5,27 +5,15 @@ import { connect } from 'react-redux';
import * as MuncherActions from '../../actions/board/muncher.actions'; import * as MuncherActions from '../../actions/board/muncher.actions';
import { SETTINGS } from '../../App'; import { SETTINGS } from '../../App';
let listener = null;
export class Muncher extends Component { export class Muncher extends Component {
componentDidMount() {
listener = this.keydown.bind(this);
window.addEventListener('keydown', listener);
};
componentWillUnmount() {
window.removeEventListener('keydown', listener);
};
keydown(e) { keydown(e) {
if (this.props.frozen === true) {
return;
}
const x = this.props.x; const x = this.props.x;
const y = this.props.y; const y = this.props.y;
switch (e.keyCode) { switch (e.keyCode) {
case 32:
this.props.next(x, y);
break;
case 37: case 37:
if (x !== 0) { if (x !== 0) {
this.props.dispatch(MuncherActions.moveLeft()); this.props.dispatch(MuncherActions.moveLeft());
@ -56,7 +44,7 @@ export class Muncher extends Component {
const classname = ['muncher', 'x' + this.props.x, 'y' + this.props.y]; const classname = ['muncher', 'x' + this.props.x, 'y' + this.props.y];
return ( return (
<div className={classname.join(' ')}></div> <div className={classname.join(' ')} tabIndex='1' onKeyDown={this.keydown.bind(this)}></div>
); );
}; };
}; };

@ -18,10 +18,6 @@ const reducer = (state = initial, action) => {
case TroggleActions.CREATE: case TroggleActions.CREATE:
return Immutable.List(state).push({ x: action.x, y: action.y }).toArray(); return Immutable.List(state).push({ x: action.x, y: action.y }).toArray();
case TroggleActions.FREEZE_ALL:
case TroggleActions.UNFREEZE_ALL:
case TroggleActions.CLEAR_ALL: case TroggleActions.CLEAR_ALL:
return Immutable.List().toArray(); return Immutable.List().toArray();
}; };

@ -1,6 +1,7 @@
.message { .message {
background:#fff; background:#fff;
border:1px solid #000; border:1px solid #000;
cursor: default;
font-size:14px; font-size:14px;
line-height:40px; line-height:40px;
margin:150px 5%; margin:150px 5%;
@ -10,7 +11,11 @@
width:90%; width:90%;
z-index:1000; z-index:1000;
* {
cursor:default;
}
&.hidden { &.hidden {
display:none; opacity:0;
} }
} }

Loading…
Cancel
Save