From 7bfab9163b2c286f03fed8540255658253333cf5 Mon Sep 17 00:00:00 2001 From: Ben Burlingham Date: Tue, 26 Apr 2016 06:40:02 -0700 Subject: [PATCH] Starting split of high score entry screen and welcome screen. --- actions/mode.actions.js | 7 +- actions/welcome/welcome.actions.js | 7 -- components/high-score/high-score.component.js | 63 +++++++++++ .../initials.component.js | 5 + ...core.component.js => hof-row.component.js} | 2 +- components/welcome/welcome.component.js | 30 ++--- .../high-score/high-score.controller.js | 71 ++++++++++++ .../initials.controller.js | 28 +---- controllers/welcome/welcome.controller.js | 47 +++----- index.js | 1 + readme.md | 2 + reducers/high-score/high-score.reducer.js | 30 +++++ reducers/welcome/welcome.reducer.js | 24 +--- sass/blink.scss | 16 +++ sass/high-score/high-score.scss | 104 ++++++++++++++++++ sass/welcome/welcome.scss | 103 +++++------------ 16 files changed, 362 insertions(+), 178 deletions(-) create mode 100644 components/high-score/high-score.component.js rename components/{welcome => high-score}/initials.component.js (89%) rename components/welcome/{high-score.component.js => hof-row.component.js} (85%) create mode 100644 controllers/high-score/high-score.controller.js rename controllers/{welcome => high-score}/initials.controller.js (68%) create mode 100644 reducers/high-score/high-score.reducer.js create mode 100644 sass/blink.scss create mode 100644 sass/high-score/high-score.scss diff --git a/actions/mode.actions.js b/actions/mode.actions.js index dd2df06..8c84ad6 100644 --- a/actions/mode.actions.js +++ b/actions/mode.actions.js @@ -1,7 +1,7 @@ -// Game mode actions and action creators. export const MODE_ACTION = 'MODE_ACTION'; export const WELCOME = 'MODE_WELCOME'; export const OPTIONS = 'MODE_OPTIONS'; +export const HIGHSCORE = 'MODE_HIGH_SCORE'; export const BOARD = 'MODE_BOARD'; export const welcome = () => ({ @@ -14,6 +14,11 @@ export const options = () => ({ action: OPTIONS }); +export const highscore = () => ({ + type: MODE_ACTION, + action: HIGHSCORE +}); + export const board = () => ({ type: MODE_ACTION, action: BOARD diff --git a/actions/welcome/welcome.actions.js b/actions/welcome/welcome.actions.js index 521bcbc..313f8c5 100644 --- a/actions/welcome/welcome.actions.js +++ b/actions/welcome/welcome.actions.js @@ -1,15 +1,8 @@ export const WELCOME_ACTION = 'WELCOME_ACTION'; export const UPDATE_SCORES = 'WELCOME_UPDATE_SCORES'; -export const UPDATE_INITIALS = 'WELCOME_UDPATE_INITIALS'; export const updateScores = (scores) => ({ type: WELCOME_ACTION, action: UPDATE_SCORES, scores: scores }); - -export const updateInitials = (initials) => ({ - type: WELCOME_ACTION, - action: UPDATE_INITIALS, - initials: initials -}); diff --git a/components/high-score/high-score.component.js b/components/high-score/high-score.component.js new file mode 100644 index 0000000..cacea5d --- /dev/null +++ b/components/high-score/high-score.component.js @@ -0,0 +1,63 @@ +require('../../sass/high-score/high-score.scss'); + +import { Component } from 'react'; +import { connect } from 'react-redux'; +import Initials from './initials.component'; + +import * as ModeActions from '../../actions/mode.actions'; +import HighScoreCtrl from '../../controllers/high-score/high-score.controller'; + +let listener; + +export class Welcome extends Component { + componentDidMount() { + listener = HighScoreCtrl.keydown.bind(HighScoreCtrl); + window.addEventListener('keydown', listener); + + // HighScoreCtrl.setDispatch(this.props.dispatch); + // HighScoreCtrl.retrieveScores(); + // HighScoreCtrl.updateScores(ScorebarCtrl.currentScore); + }; + + componentWillUnmount() { + window.removeEventListener('keydown', listener); + }; + + render() { + // var entries = []; + // this.props.values.map(function(v, i) { + // entries.push(); + // }); + + if (WelcomeCtrl.isHighScore() > 0) { + return ( +
+ +
+
New high score!
+
Enter your initials:
+ +
+ ); + } + else { + return ( +
+ +
Press Spacebar for new game
+ high scores here +
+ ); + } + + + }; +}; + +const select = (state) => { + return { + values: state.welcome.scores + } +}; + +export default connect(select)(Welcome); diff --git a/components/welcome/initials.component.js b/components/high-score/initials.component.js similarity index 89% rename from components/welcome/initials.component.js rename to components/high-score/initials.component.js index d108c4c..c9f28ba 100644 --- a/components/welcome/initials.component.js +++ b/components/high-score/initials.component.js @@ -6,9 +6,14 @@ import InitialsCtrl from '../../controllers/welcome/initials.controller'; export class Initials extends Component { componentDidMount() { InitialsCtrl.setDispatch(this.props.dispatch); + InitialsCtrl.update(); }; render() { + if (this.props.initials.length === 0) { + return
; + } + const class1 = ['initial']; const class2 = ['initial']; const class3 = ['initial']; diff --git a/components/welcome/high-score.component.js b/components/welcome/hof-row.component.js similarity index 85% rename from components/welcome/high-score.component.js rename to components/welcome/hof-row.component.js index 0f9884c..10b8133 100644 --- a/components/welcome/high-score.component.js +++ b/components/welcome/hof-row.component.js @@ -1,6 +1,6 @@ import { Component } from 'react'; -export default class HighScoreEntry extends Component { +export default class HofRow extends Component { render() { return (
diff --git a/components/welcome/welcome.component.js b/components/welcome/welcome.component.js index 2385d95..b748765 100644 --- a/components/welcome/welcome.component.js +++ b/components/welcome/welcome.component.js @@ -2,21 +2,18 @@ require('../../sass/welcome/welcome.scss'); import { Component } from 'react'; import { connect } from 'react-redux'; -import Initials from './initials.component'; -import * as ModeActions from '../../actions/mode.actions'; import WelcomeCtrl from '../../controllers/welcome/welcome.controller'; - +import HofRow from '../../components/welcome/hof-row.component'; let listener; export class Welcome extends Component { componentDidMount() { + WelcomeCtrl.setDispatch(this.props.dispatch); + WelcomeCtrl.updateFromLocalStorage(); + listener = WelcomeCtrl.keydown.bind(WelcomeCtrl); window.addEventListener('keydown', listener); - - // HighScoreCtrl.setDispatch(this.props.dispatch); - // HighScoreCtrl.retrieveScores(); - // HighScoreCtrl.updateScores(ScorebarCtrl.currentScore); }; componentWillUnmount() { @@ -24,27 +21,24 @@ export class Welcome extends Component { }; render() { - // var entries = []; - // this.props.values.map(function(v, i) { - // entries.push(); - // }); + const entries = []; + this.props.scores.map(function(v, i) { + entries.push(); + }); return (
-
Press Spacebar for new game
-
New high score!
-
Enter your initials:
- +
Press Spacebar for new game
+
+ {entries}
); }; }; const select = (state) => { - return { - values: state.welcome.scores - } + return state.welcome; }; export default connect(select)(Welcome); diff --git a/controllers/high-score/high-score.controller.js b/controllers/high-score/high-score.controller.js new file mode 100644 index 0000000..9be48ab --- /dev/null +++ b/controllers/high-score/high-score.controller.js @@ -0,0 +1,71 @@ +import * as WelcomeActions from '../../actions/welcome/welcome.actions'; +import InitialsCtrl from './initials.controller'; +import SETTINGS from '../../AppSettings'; + +let dispatch; + +let finalScore = 800; + +const scores = [ + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, +]; + +const WelcomeCtrl = { + setDispatch: (d) => dispatch = d, + + isHighScore: () => finalScore > 0, + + gameOver: (score) => { + let found = -1; + finalScore = -1; + + for (let i = 0; i < scores.length; i++) { + if (scores[i].score < score) { + found = i; + } + } + + finalScore = -1; + if (found > -1) { + // scores.splice(found, { initials: 'ZZZ', score: score }); + // scores.pop(); + finalScore = score; + } + }, + + update: () => { + const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY); + + if (scores !== null) { + dispatch(WelcomeActions.updateScores(scores)); + } + }, + + keydown: (e) => { + if ((gameOverFlag === true && e.keyCode === 13) || (gameOverFlag === true && e.keyCode === 32)) { + } + else if (gameOverFlag === true) { + InitialsCtrl.keydown(e); + } + else if (e.keyCode === 32) { + this.props.dispatch(ModeActions.options()); + } + }, + + doTheThing: () => { + const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY); + + if (scores !== null) { + return scores[0].score; + } + + return 0; + // localStorage.setItem(SETTINGS.LOCAL_STORAGE_KEY, scores); + }, +}; + +export default WelcomeCtrl; diff --git a/controllers/welcome/initials.controller.js b/controllers/high-score/initials.controller.js similarity index 68% rename from controllers/welcome/initials.controller.js rename to controllers/high-score/initials.controller.js index 4dd736c..12cc392 100644 --- a/controllers/welcome/initials.controller.js +++ b/controllers/high-score/initials.controller.js @@ -16,15 +16,12 @@ const InitialsCtrl = { keydown: function(e) { switch (e.keyCode) { - case 13: - case 32: - break; case 37: active--; if (active === -1) { active = initials.length - 1; } - this.updateInitials(); + this.update(); break; case 38: code = initials[active].initial.charCodeAt(0); @@ -33,14 +30,14 @@ const InitialsCtrl = { code = 90; } initials[active].initial = String.fromCharCode(code); - this.updateInitials(); + this.update(); break; case 39: active++; if (active === initials.length) { active = 0; } - this.updateInitials(); + this.update(); break; case 40: code = initials[active].initial.charCodeAt(0); @@ -49,7 +46,7 @@ const InitialsCtrl = { code = 65; } initials[active].initial = String.fromCharCode(code); - this.updateInitials(); + this.update(); break; } @@ -59,11 +56,11 @@ const InitialsCtrl = { if (active < initials.length - 1) { active++; } - this.updateInitials(); + this.update(); } }, - updateInitials: () => { + update: () => { initials = initials.map((v) => { v.active = false; return v; @@ -72,19 +69,6 @@ const InitialsCtrl = { initials[active].active = true; dispatch(WelcomeActions.updateInitials(initials)); - }, - - updateScores: (scores) => { - // [ - // { initials: "ABA", score: "219283", rank: "1" }, - // { initials: "ABA", score: "107112", rank: "2" }, - // { initials: "ABA", score: "81091", rank: "3" }, - // { initials: "ABA", score: "67747", rank: "4" }, - // { initials: "ABA", score: "9283", rank: "5" }, - // { initials: "ABA", score: "928", rank: "6" } - // ]; - - // localStorage.setItem(SETTINGS.LOCAL_STORAGE_KEY, scores); } }; diff --git a/controllers/welcome/welcome.controller.js b/controllers/welcome/welcome.controller.js index 50f5a9f..808c6e1 100644 --- a/controllers/welcome/welcome.controller.js +++ b/controllers/welcome/welcome.controller.js @@ -1,43 +1,30 @@ import * as WelcomeActions from '../../actions/welcome/welcome.actions'; -import InitialsCtrl from './initials.controller'; +import * as ModeActions from '../../actions/mode.actions'; import SETTINGS from '../../AppSettings'; let dispatch; -let update = true; -const HighScoreCtrl = { - setDispatch: (d) => dispatch = d, - - keydown: (e) => { - if (update === true) { - InitialsCtrl.keydown(e); - } - else if (e.keyCode === 32) { - this.props.dispatch(ModeActions.options()); - } - }, - - getHighScore: () => { - const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY); +const emptyScores = [ + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, + { initials: "AAA", score: "0" }, +]; - if (scores !== null) { - return scores[0].score; - } - - return 0; - }, - - gameOver: (score) => { +const WelcomeCtrl = { + setDispatch: (d) => dispatch = d, + updateFromLocalStorage: () => { + const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY) || emptyScores; + dispatch(WelcomeActions.updateScores(scores)); }, - retrieveScores: () => { - const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY); - - if (scores !== null) { - dispatch(WelcomeActions.updateScores(scores)); + keydown: (e) => { + if (e.keyCode === 32) { + dispatch(ModeActions.options()); } } }; -export default HighScoreCtrl; +export default WelcomeCtrl; diff --git a/index.js b/index.js index fe96ca2..6a2cf20 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,5 @@ require('./sass/reset.scss'); +require('./sass/blink.scss'); import { render } from 'react-dom'; import { createStore, combineReducers } from 'redux' diff --git a/readme.md b/readme.md index 193cd1a..b4d5923 100644 --- a/readme.md +++ b/readme.md @@ -10,4 +10,6 @@ Run `npm install` to install the required Node packages. Run `npm run dev` in the project root to start the [webpack dev server](https://webpack.github.io/docs/webpack-dev-server.html). +Run `npm run prod` in the project root to assemble prod bundles. + Navigate to http://localhost:8080/. diff --git a/reducers/high-score/high-score.reducer.js b/reducers/high-score/high-score.reducer.js new file mode 100644 index 0000000..7a42328 --- /dev/null +++ b/reducers/high-score/high-score.reducer.js @@ -0,0 +1,30 @@ +const Immutable = require('immutable'); + +import * as WelcomeActions from '../../actions/welcome/welcome.actions'; + +const initial = { + scores: [], + initials: [] +}; + +const reducer = (state = initial, action) => { + if (action.type !== WelcomeActions.WELCOME_ACTION) { + return state; + } + + switch (action.action) { + case WelcomeActions.UPDATE_SCORES: + return Immutable.Map(state) + .set('scores', action.scores) + .toObject(); + + case WelcomeActions.UPDATE_INITIALS: + return Immutable.Map(state) + .set('initials', action.initials) + .toObject(); + } + + return state; +}; + +export default reducer; diff --git a/reducers/welcome/welcome.reducer.js b/reducers/welcome/welcome.reducer.js index 79a1ddc..d4b8f76 100644 --- a/reducers/welcome/welcome.reducer.js +++ b/reducers/welcome/welcome.reducer.js @@ -2,35 +2,17 @@ const Immutable = require('immutable'); import * as WelcomeActions from '../../actions/welcome/welcome.actions'; -const initial = { - scores: [ - { initials: "AAA", score: "0", rank: "1" }, - { initials: "AAA", score: "0", rank: "1" }, - { initials: "AAA", score: "0", rank: "1" }, - { initials: "AAA", score: "0", rank: "1" }, - { initials: "AAA", score: "0", rank: "1" }, - { initials: "AAA", score: "0", rank: "1" } - ], - - initials: [ - { initial: 'A', active: true }, - { initial: 'A', active: false }, - { initial: 'A', active: false } - ] -}; +const initial = { scores: [] }; const reducer = (state = initial, action) => { if (action.type !== WelcomeActions.WELCOME_ACTION) { return state; } - // if (action.action === WelcomeActions.UPDATE_SCORES) { - // return action.scores; - // } switch (action.action) { - case WelcomeActions.UPDATE_INITIALS: + case WelcomeActions.UPDATE_SCORES: return Immutable.Map(state) - .set('initials', action.initials) + .set('scores', action.scores) .toObject(); } diff --git a/sass/blink.scss b/sass/blink.scss new file mode 100644 index 0000000..115b063 --- /dev/null +++ b/sass/blink.scss @@ -0,0 +1,16 @@ +@keyframes blink { + 50% { + opacity: 0.6; + } +} + +@-webkit-keyframes blink { + 50% { + opacity: 0.6; + } +} + +.blink { + animation: blink 1s step-start 0s infinite; + -webkit-animation: blink 1s step-start 0s infinite; +} diff --git a/sass/high-score/high-score.scss b/sass/high-score/high-score.scss new file mode 100644 index 0000000..36ed6f2 --- /dev/null +++ b/sass/high-score/high-score.scss @@ -0,0 +1,104 @@ +.high-score { + $w: 350px; + + padding:20px; + text-align:center; + + img { + width:$w; + } + + .line { + line-height:30px; + } + + .spacer { + height:100px; + } + + @keyframes blink { + 50% { + opacity: 0.6; + } + } + + @-webkit-keyframes blink { + 50% { + opacity: 0.6; + } + } + + .blink { + animation: blink 1s step-start 0s infinite; + -webkit-animation: blink 1s step-start 0s infinite; + } + + .initial { + display:inline-block; + } + + // .highscores { + // margin:0 auto; + // width:350px; + // } + // + // .newgame { + // margin:20px 0; + // transition:opacity 0.1s ease; + // + // &.hidden { + // opacity: 0.5; + // } + // } +} +// +// .highscores { +// $w: 350px; +// +// font-size: 0; +// +// hr { +// border:0; +// border-top:1px solid #ccc; +// margin:20px auto; +// width: $w; +// } +// +// .blink { +// animation: blinker 1s none infinite; +// } +// +// @keyframes blinker { +// 50% { opacity: 0.6; } +// } +// +// .line { +// font-size:16px; +// line-height:30px; +// margin: 10px auto; +// text-align:center; +// width:$w; +// }; +// +// .entry { +// font-size:16px; +// line-height:40px; +// } +// +// .rank { +// display:inline-block; +// text-align:left; +// width:50px; +// } +// +// .initials { +// display:inline-block; +// width:100px; +// } +// +// .score { +// display:inline-block; +// text-align:right; +// width:200px; +// } +// } diff --git a/sass/welcome/welcome.scss b/sass/welcome/welcome.scss index a36a045..5078eec 100644 --- a/sass/welcome/welcome.scss +++ b/sass/welcome/welcome.scss @@ -1,5 +1,6 @@ .welcome { - $w: 350px; + $fs: 14px; + $w: 400px; padding:20px; text-align:center; @@ -9,92 +10,38 @@ } .line { - line-height:30px; + font-size:14px; + line-height:70px; + margin:0 auto; + width: $w; } - @keyframes blink { - 50% { - opacity: 0.6; - } + hr { + border:0; + border-top:1px solid #ccc; + margin:20px auto; + width: $w; } - @-webkit-keyframes blink { - 50% { - opacity: 0.6; - } + .entry { + font-size:16px; + line-height:40px; } - .blink { - animation: blink 1s step-start 0s infinite; - -webkit-animation: blink 1s step-start 0s infinite; + .rank { + display:inline-block; + text-align:left; + width:50px; } - .initial { + .initials { display:inline-block; + width:100px; } - // .highscores { - // margin:0 auto; - // width:350px; - // } - // - // .newgame { - // margin:20px 0; - // transition:opacity 0.1s ease; - // - // &.hidden { - // opacity: 0.5; - // } - // } + .score { + display:inline-block; + text-align:right; + width:200px; + } } -// -// .highscores { -// $w: 350px; -// -// font-size: 0; -// -// hr { -// border:0; -// border-top:1px solid #ccc; -// margin:20px auto; -// width: $w; -// } -// -// .blink { -// animation: blinker 1s none infinite; -// } -// -// @keyframes blinker { -// 50% { opacity: 0.6; } -// } -// -// .line { -// font-size:16px; -// line-height:30px; -// margin: 10px auto; -// text-align:center; -// width:$w; -// }; -// -// .entry { -// font-size:16px; -// line-height:40px; -// } -// -// .rank { -// display:inline-block; -// text-align:left; -// width:50px; -// } -// -// .initials { -// display:inline-block; -// width:100px; -// } -// -// .score { -// display:inline-block; -// text-align:right; -// width:200px; -// } -// }