From 44620c2a3fc09a7145b851d823ae1b98c8e61d30 Mon Sep 17 00:00:00 2001 From: Ben Burlingham Date: Sat, 23 Apr 2016 20:10:14 -0700 Subject: [PATCH] Troggles complete. --- actions/board/message.actions.js | 10 +--- actions/board/scorebar.actions.js | 12 ++--- actions/board/troggle.actions.js | 16 ++++--- components/board/troggles.component.js | 5 +- controllers/board.controller.js | 60 +++++++++++++++++------- controllers/message.controller.js | 65 +++++++++++++++++++++++++- controllers/muncher.controller.js | 10 ++-- controllers/scorebar.controller.js | 43 +++++++++++++++++ controllers/troggle.controller.js | 55 +++++++++++++++------- reducers/board/message.reducer.js | 22 --------- reducers/board/scorebar.reducer.js | 22 ++++----- reducers/board/troggle.reducer.js | 18 ++++--- 12 files changed, 231 insertions(+), 107 deletions(-) create mode 100644 controllers/scorebar.controller.js diff --git a/actions/board/message.actions.js b/actions/board/message.actions.js index 59048e5..5ee2331 100644 --- a/actions/board/message.actions.js +++ b/actions/board/message.actions.js @@ -1,7 +1,6 @@ export const MESSAGE_ACTION = 'MESSAGE_ACTION'; -export const SHOW = 'SHOW'; -export const HIDE = 'HIDE'; -export const EXCLAIM = 'EXCLAIM'; +export const SHOW = 'MESSAGE_SHOW'; +export const HIDE = 'MESSAGE_HIDE'; export const show = (message) => ({ type: MESSAGE_ACTION, @@ -9,11 +8,6 @@ export const show = (message) => ({ message: message }); -export const exclaim = () => ({ - type: MESSAGE_ACTION, - action: EXCLAIM -}); - export const hide = () => ({ type: MESSAGE_ACTION, action: HIDE diff --git a/actions/board/scorebar.actions.js b/actions/board/scorebar.actions.js index bd442ce..c78d4b0 100644 --- a/actions/board/scorebar.actions.js +++ b/actions/board/scorebar.actions.js @@ -1,13 +1,7 @@ export const SCOREBAR_ACTION = 'SCOREBAR_ACTION'; -export const MUNCH_SUCCEEDED = 'SCOREBAR_MUNCH_SUCCEEDED'; -export const MUNCH_FAILED = 'SCOREBAR_MUNCH_FAILED'; +export const UPDATE = 'SCOREBAR_UPDATE'; -export const munchSucceeded = () => ({ +export const update = () => ({ type: SCOREBAR_ACTION, - action: MUNCH_SUCCEEDED, -}); - -export const munchFailed = () => ({ - type: SCOREBAR_ACTION, - action: MUNCH_FAILED + action: UPDATE }); diff --git a/actions/board/troggle.actions.js b/actions/board/troggle.actions.js index b31247b..4738155 100644 --- a/actions/board/troggle.actions.js +++ b/actions/board/troggle.actions.js @@ -1,18 +1,22 @@ export const TROGGLE_ACTION = 'TROGGLE_ACTION'; export const CREATE = 'TROGGLE_CREATE'; -export const MOVE = 'TROGGLE_MOVE'; +export const UPDATE = 'TROGGLE_UPDATE'; export const CLEAR_ALL = 'TROGGLE_CLEAR_ALL'; -export const create = (index) => ({ +export const create = (index, x, y) => ({ type: TROGGLE_ACTION, action: CREATE, - index: index + index: index, + x: x, + y: y }); -export const move = (index) => ({ +export const update = (index, x, y) => ({ type: TROGGLE_ACTION, - action: MOVE, - index: index + action: UPDATE, + index: index, + x: x, + y: y }); export const clearAll = () => ({ diff --git a/components/board/troggles.component.js b/components/board/troggles.component.js index 184c32a..50dfeb0 100644 --- a/components/board/troggles.component.js +++ b/components/board/troggles.component.js @@ -15,7 +15,7 @@ export class Troggles extends Component { const { troggles, muncher } = this.props; const troggleElements = Array.from(Array(troggles.length), (v, i) => { - return ; + return ; }); return
{troggleElements}
@@ -24,8 +24,7 @@ export class Troggles extends Component { const select = (state) => { return { - troggles: state.troggles, - muncher: state.muncher + troggles: state.troggles }; } diff --git a/controllers/board.controller.js b/controllers/board.controller.js index 3b5cfd1..5499537 100644 --- a/controllers/board.controller.js +++ b/controllers/board.controller.js @@ -1,15 +1,14 @@ import { SETTINGS } from '../App.js'; -import * as ScorebarActions from '../actions/board/scorebar.actions'; -import * as MessageActions from '../actions/board/message.actions'; - import TroggleCtrl from './troggle.controller'; import MessageCtrl from './message.controller'; import MuncherCtrl from './muncher.controller'; import GridCtrl from './grid.controller'; import TitlebarCtrl from './titlebar.controller'; +import ScorebarCtrl from './scorebar.controller'; let level = -1; +let collision = false; let dispatch; const BoardCtrl = { @@ -18,30 +17,51 @@ const BoardCtrl = { GridCtrl.setDispatch(d); MuncherCtrl.setDispatch(d); TitlebarCtrl.setDispatch(d); + ScorebarCtrl.setDispatch(d); + MessageCtrl.setDispatch(d); + TroggleCtrl.setDispatch(d); }, + isCollision: () => collision, + munch() { const index = MuncherCtrl.getY() * SETTINGS.GRID_WIDTH + MuncherCtrl.getX(); if (GridCtrl.getValues()[index].valid) { GridCtrl.hideValue(index); + ScorebarCtrl.munchSucceeded(); if (GridCtrl.isCompleted() === true) { - dispatch(MessageActions.exclaim()); + MessageCtrl.goodNews('Level complete!'); } } else { - dispatch(MessageActions.show(`Uh oh - ${GridCtrl.getValues()[index].value} is not a match.`)); + TroggleCtrl.freeze(); + MessageCtrl.badNews(`${GridCtrl.getValues()[index].value} is not a match.`); + ScorebarCtrl.munchFailed(); } }, keyListener(e) { - if (e.keyCode === 32 && GridCtrl.isCompleted() === true) { + if (e.keyCode === 32 && ScorebarCtrl.getLives() === 0) { + MessageCtrl.show("Game over!"); + } + else if (e.keyCode === 32 && GridCtrl.isCompleted() === true) { this.nextLevel(); - dispatch(MessageActions.hide()); + ScorebarCtrl.levelUp(level); + MessageCtrl.hide(); + } + else if (e.keyCode === 32 && BoardCtrl.isCollision() === true) { + collision = false; + TroggleCtrl.clearTroggles(); + TroggleCtrl.createTroggles(level); + TroggleCtrl.unfreeze(); + ScorebarCtrl.eatenByTroggle(); + MessageCtrl.hide(); } else if (e.keyCode === 32 && MessageCtrl.isShowing() === true) { - dispatch(MessageActions.hide()); + TroggleCtrl.unfreeze(); + MessageCtrl.hide(); } else if (e.keyCode === 32 && MessageCtrl.isShowing() === false) { this.munch(); @@ -55,16 +75,24 @@ const BoardCtrl = { level++; GridCtrl.generateValues(level); TitlebarCtrl.setTitle(level); - // TroggleCtrl.clearAll(this.props.dispatch); - // TroggleCtrl.createTroggles(this.props.dispatch); + TroggleCtrl.clearTroggles(); + TroggleCtrl.createTroggles(level); }, - // if (troggles[i].x === muncher.x && troggles[i].y === muncher.y) { - // this.props.dispatch(MessageActions.show("You've been eaten by a troggle!")); - // this.props.dispatch(ScorebarActions.munchFailed()); - // TroggleCtrl.frozen = true; - // ReactDOM.findDOMNode(this.refs.message).focus(); - // } + checkCollision() { + const x = MuncherCtrl.getX(); + const y = MuncherCtrl.getY(); + + const troggles = TroggleCtrl.getTroggles(); + for (let i = 0; i < troggles.length; i++) { + if (troggles[i].x === x && troggles[i].y === y) { + collision = true; + TroggleCtrl.freeze(); + MessageCtrl.badNews("You've been eaten by a troggle!"); + break; + } + } + } }; export default BoardCtrl; diff --git a/controllers/message.controller.js b/controllers/message.controller.js index 35d7db5..6c4046d 100644 --- a/controllers/message.controller.js +++ b/controllers/message.controller.js @@ -1,8 +1,69 @@ +import * as MessageActions from '../actions/board/message.actions'; + +const positives = [ + 'All finished!', + 'Boom!', + 'Capital!', + 'Congratulations!', + 'Great job!', + 'Huzzah!', + 'Hooray!', + 'Hot dog!', + 'Marvelous!', + 'Nice work!', + 'Shazam!', + 'Spot on!', + 'Whee!', + 'Wonderful!', + 'Woohoo!', + 'Yippee!' +]; + +const negatives = [ + 'Cripes!', + 'Darn it!', + 'Doggone it!', + 'Drat!', + 'Fiddlesticks!', + 'Good grief!', + 'Oh dear!', + 'Oh no!', + 'Rats!', + 'Shazbot!', + 'Shoot!', + 'Shucks!', + 'Too bad!', + 'Uh oh!' +]; + +let dispatch; let show = false; const MessageCtrl = { - hide: () => show = false, - show: () => show = true, + setDispatch: (d) => dispatch = d, + + hide: () => { + show = false; + dispatch(MessageActions.hide()); + }, + + show: (msg) => { + show = true; + dispatch(MessageActions.show(`${msg}`)); + }, + + goodNews: (msg) => { + show = true; + const exclaim = positives[Math.floor(positives.length * Math.random())]; + dispatch(MessageActions.show(`${exclaim} ${msg}`)); + }, + + badNews: (msg) => { + show = true; + const exclaim = negatives[Math.floor(negatives.length * Math.random())]; + dispatch(MessageActions.show(`${exclaim} ${msg}`)); + }, + isShowing: () => show }; diff --git a/controllers/muncher.controller.js b/controllers/muncher.controller.js index dde9342..e73e838 100644 --- a/controllers/muncher.controller.js +++ b/controllers/muncher.controller.js @@ -1,4 +1,5 @@ import * as MuncherActions from '../actions/board/muncher.actions'; +import BoardCtrl from './board.controller'; import { SETTINGS } from '../App'; let x = 0; @@ -15,31 +16,32 @@ const MuncherCtrl = { case 37: if (x !== 0) { x -= 1; - dispatch(MuncherActions.update()); } break; case 38: if (y !== 0) { y -= 1; - dispatch(MuncherActions.update()); } break; case 39: if (x !== SETTINGS.GRID_WIDTH - 1) { x += 1; - dispatch(MuncherActions.update()); } break; case 40: if (y !== SETTINGS.GRID_HEIGHT - 1) { y += 1; - dispatch(MuncherActions.update()); } break; } + + if (e.keyCode >= 37 || e.keyCode <= 40) { + dispatch(MuncherActions.update()); + BoardCtrl.checkCollision(); + } } }; diff --git a/controllers/scorebar.controller.js b/controllers/scorebar.controller.js new file mode 100644 index 0000000..273478e --- /dev/null +++ b/controllers/scorebar.controller.js @@ -0,0 +1,43 @@ +import * as ScorebarActions from '../actions/board/scorebar.actions'; +import { SETTINGS } from '../App'; + +let dispatch; +let lives = 3; +let currentScore = 0; +let highScore = 7; + +const ScorebarCtrl = { + setDispatch: d => dispatch = d, + + getCurrentScore: () => currentScore, + getHighScore: () => highScore, + getLives: () => lives, + + munchSucceeded: () => { + currentScore += 10; + dispatch(ScorebarActions.update()); + }, + + munchFailed: () => { + lives--; + currentScore -= 5; + dispatch(ScorebarActions.update()); + }, + + eatenByTroggle: () => { + lives--; + dispatch(ScorebarActions.update()); + }, + + levelUp: (level) => { + currentScore += 25; + dispatch(ScorebarActions.update()); + }, + + reset: () => { + lives = SETTINGS.LIVES; + currentScore = 0; + } +}; + +export default ScorebarCtrl; diff --git a/controllers/troggle.controller.js b/controllers/troggle.controller.js index 57221de..3643798 100644 --- a/controllers/troggle.controller.js +++ b/controllers/troggle.controller.js @@ -1,16 +1,30 @@ import { SETTINGS } from '../App'; import * as TroggleActions from '../actions/board/troggle.actions'; +import MuncherCtrl from './muncher.controller'; +import BoardCtrl from './board.controller'; +const troggles = []; const troggleMoveTimers = []; const troggleCreateTimers = []; +let frozen = false; +let dispatch; + const TroggleCtrl = { - frozen: false, + setDispatch: (d) => dispatch = d, + + getTroggles: () => troggles, + + freeze: () => frozen = true, + unfreeze: () => frozen = false, + isFrozen: () => frozen, - clearAll(dispatch) { + clearTroggles() { dispatch(TroggleActions.clearAll()); + troggles.length = 0; + troggleMoveTimers.forEach((timer) => { clearTimeout(timer); }); @@ -20,41 +34,50 @@ const TroggleCtrl = { }); }, - createTroggle(index, dispatch) { - dispatch(TroggleActions.create(index)); + createTroggle(index) { + const coords = this.getStartingCoords(); + troggles[index] = { x: coords.x, y: coords.y }; + dispatch(TroggleActions.create(index, coords.x, coords.y)); - const ref = this.moveTroggle.bind(this, index, dispatch); + const ref = this.moveTroggle.bind(this, index); troggleMoveTimers[index] = setTimeout(ref, 1000); }, - createTroggles(dispatch, level) { + createTroggles(level) { // const count = Math.min(Math.ceil((level + 1) / 2), 5); const count = 3; for (let index = 0; index < count; index++) { - const ref = this.createTroggle.bind(this, index, dispatch); + const ref = this.createTroggle.bind(this, index); troggleCreateTimers[index] = setTimeout(ref, (index) * 1000); // troggleCreateTimers[index] = setTimeout(ref, (index + 1) * 5000); } }, - moveTroggle(index, dispatch) { - if (this.frozen === false) { - dispatch(TroggleActions.move(index)); + moveTroggle(index) { + if (frozen === false) { + const coords = this.getMoveCoords(troggles[index].x, troggles[index].y); + troggles[index].x = coords.x; + troggles[index].y = coords.y; + + BoardCtrl.checkCollision(); + dispatch(TroggleActions.update(index, coords.x, coords.y)); } - const ref = this.moveTroggle.bind(this, index, dispatch); + const ref = this.moveTroggle.bind(this, index); troggleMoveTimers[index] = setTimeout(ref, 1000); }, - getMoveCoords(currX, currY, muncherX, muncherY) { - // Randomize movement with boolean flags. - const moveToAttack = Boolean(Math.round(Math.random())); - const moveAlongXAxis = Boolean(Math.round(Math.random())); - const moveInPositiveDirection = Boolean(Math.round(Math.random())); + getMoveCoords(currX, currY) { + // Randomize movement with boolean flags. Aggression can be controlled here. + const moveToAttack = Boolean(Math.random() > 0.35); + const moveAlongXAxis = Boolean(Math.random() > 0.5); + const moveInPositiveDirection = Boolean(Math.random() > 0.5); let newX = currX; let newY = currY; + let muncherX = MuncherCtrl.getX(); + let muncherY = MuncherCtrl.getY(); // DO NOT CONSOLIDATE. Attack first, ask questions later. if (moveAlongXAxis === true) { diff --git a/reducers/board/message.reducer.js b/reducers/board/message.reducer.js index fc9328c..0db98dc 100644 --- a/reducers/board/message.reducer.js +++ b/reducers/board/message.reducer.js @@ -1,18 +1,6 @@ const Immutable = require('immutable'); import * as MessageActions from '../../actions/board/message.actions'; -import MessageCtrl from '../../controllers/message.controller'; - -const exclamations = [ - 'Congratulations!', - 'Yippee!', - 'Woohoo!', - 'Nice work!', - 'Great job!', - 'Boom!', - 'All finished!', - 'Shazam!' -]; const initial = { message: '', hidden: true }; @@ -22,23 +10,13 @@ const reducer = (state = initial, action) => { } switch (action.action) { - case MessageActions.EXCLAIM: - MessageCtrl.show(); - const msg = exclamations[Math.floor(Math.random() * exclamations.length)]; - return Immutable.Map(state) - .set('hidden', false) - .set('message', msg) - .toObject(); - case MessageActions.SHOW: - MessageCtrl.show(); return Immutable.Map(state) .set('hidden', false) .set('message', action.message) .toObject(); case MessageActions.HIDE: - MessageCtrl.hide(); return Immutable.Map(state) .set('hidden', true) .toObject(); diff --git a/reducers/board/scorebar.reducer.js b/reducers/board/scorebar.reducer.js index 17ca7c6..9f4108b 100644 --- a/reducers/board/scorebar.reducer.js +++ b/reducers/board/scorebar.reducer.js @@ -1,24 +1,24 @@ const Immutable = require('immutable'); import * as ScorebarActions from '../../actions/board/scorebar.actions'; -import { SETTINGS } from '../../App'; +import ScorebarCtrl from '../../controllers/scorebar.controller.js'; -const initial = { current: 0, high: 999, lives: SETTINGS.LIVES }; +const initial = { + current: ScorebarCtrl.getCurrentScore(), + high: ScorebarCtrl.getHighScore(), + lives: ScorebarCtrl.getLives() +}; const reducer = (state = initial, action) => { if (action.type !== ScorebarActions.SCOREBAR_ACTION) { return state; } - switch (action.action) { - case ScorebarActions.MUNCH_SUCCEEDED: - return Immutable.Map(state).set('current', state.current + 10).toObject(); - - case ScorebarActions.MUNCH_FAILED: - return Immutable.Map(state).set('lives', state.lives - 1).toObject(); - } - - return state; + return Immutable.Map(state) + .set('current', ScorebarCtrl.getCurrentScore()) + .set('high', ScorebarCtrl.getHighScore()) + .set('lives', ScorebarCtrl.getLives()) + .toObject(); }; export default reducer; diff --git a/reducers/board/troggle.reducer.js b/reducers/board/troggle.reducer.js index cc1ec85..1493d61 100644 --- a/reducers/board/troggle.reducer.js +++ b/reducers/board/troggle.reducer.js @@ -1,7 +1,6 @@ const Immutable = require('immutable'); import * as TroggleActions from '../../actions/board/troggle.actions'; -import TroggleCtrl from '../../controllers/troggle.controller'; const initial = []; @@ -11,21 +10,20 @@ const reducer = (state = initial, action) => { } switch (action.action) { - case TroggleActions.MOVE: - const t = state[action.index]; - const coords1 = TroggleCtrl.getMoveCoords(t.x, t.y, t.mx, t.my); - + case TroggleActions.UPDATE: return Immutable.fromJS(state) - .setIn([action.index, 'x'], coords1.x) - .setIn([action.index, 'y'], coords1.y) + .setIn([action.index, 'x'], action.x) + .setIn([action.index, 'y'], action.y) .toJS(); case TroggleActions.CREATE: - const coords2 = TroggleCtrl.getStartingCoords(); - return Immutable.List(state).set(action.index, { x: coords2.x, y: coords2.y }).toArray(); + return Immutable.List(state) + .set(action.index, { x: action.x, y: action.y }) + .toArray(); case TroggleActions.CLEAR_ALL: - return Immutable.List().toArray(); + return Immutable.List() + .toArray(); }; return state;