parent
d35d0792c4
commit
9ebdfe6e97
24 changed files with 406 additions and 162 deletions
@ -1,7 +1,8 @@ |
|||||||
const SETTINGS = { |
const SETTINGS = { |
||||||
GRID_WIDTH: 6, |
GRID_WIDTH: 6, |
||||||
GRID_HEIGHT: 5, |
GRID_HEIGHT: 5, |
||||||
LIVES: 3 |
LIVES: 3, |
||||||
|
LOCAL_STORAGE_KEY: 'number-munchers-high-scores' |
||||||
}; |
}; |
||||||
|
|
||||||
export default SETTINGS; |
export default SETTINGS; |
||||||
|
@ -1,8 +0,0 @@ |
|||||||
// New game component actions and action creators.
|
|
||||||
export const NEWGAME_ACTION = 'NEWGAME_ACTION'; |
|
||||||
export const BLINK = 'BLINK'; |
|
||||||
|
|
||||||
export const blink = () => ({ |
|
||||||
type: NEWGAME_ACTION, |
|
||||||
action: BLINK |
|
||||||
}); |
|
@ -0,0 +1,15 @@ |
|||||||
|
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 |
||||||
|
}); |
@ -1,26 +0,0 @@ |
|||||||
require('../../sass/welcome/highscores.scss'); |
|
||||||
|
|
||||||
import { Component } from 'react'; |
|
||||||
import HighScoreEntry from './high-score-entry.component'; |
|
||||||
|
|
||||||
export default class HighScores extends Component { |
|
||||||
render() { |
|
||||||
const vals = [ |
|
||||||
{ 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" } |
|
||||||
]; |
|
||||||
|
|
||||||
var entries = []; |
|
||||||
vals.map(function(v, i) { |
|
||||||
entries.push(<HighScoreEntry initials={v.initials} score={v.score} rank={v.rank} key={i} />); |
|
||||||
}); |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className='highscores'>{entries}</div> |
|
||||||
); |
|
||||||
} |
|
||||||
}; |
|
@ -0,0 +1,42 @@ |
|||||||
|
import { Component } from 'react'; |
||||||
|
import { connect } from 'react-redux'; |
||||||
|
|
||||||
|
import InitialsCtrl from '../../controllers/welcome/initials.controller'; |
||||||
|
|
||||||
|
export class Initials extends Component { |
||||||
|
componentDidMount() { |
||||||
|
InitialsCtrl.setDispatch(this.props.dispatch); |
||||||
|
}; |
||||||
|
|
||||||
|
render() { |
||||||
|
const class1 = ['initial']; |
||||||
|
const class2 = ['initial']; |
||||||
|
const class3 = ['initial']; |
||||||
|
|
||||||
|
if (this.props.initials[0].active === true) { |
||||||
|
class1.push('blink'); |
||||||
|
} |
||||||
|
if (this.props.initials[1].active === true) { |
||||||
|
class2.push('blink'); |
||||||
|
} |
||||||
|
if (this.props.initials[2].active === true) { |
||||||
|
class3.push('blink'); |
||||||
|
} |
||||||
|
|
||||||
|
return ( |
||||||
|
<div className='initials'> |
||||||
|
<div className={class1.join(' ')}>{this.props.initials[0].initial}</div> |
||||||
|
<div className={class2.join(' ')}>{this.props.initials[1].initial}</div> |
||||||
|
<div className={class3.join(' ')}>{this.props.initials[2].initial}</div> |
||||||
|
</div> |
||||||
|
); |
||||||
|
}; |
||||||
|
}; |
||||||
|
|
||||||
|
const select = (state) => { |
||||||
|
return { |
||||||
|
initials: state.welcome.initials |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default connect(select)(Initials); |
@ -1,51 +0,0 @@ |
|||||||
import { Component } from 'react'; |
|
||||||
import { connect } from 'react-redux'; |
|
||||||
|
|
||||||
import * as ModeActions from '../../actions/mode.actions'; |
|
||||||
import * as NewGameActions from '../../actions/welcome/new-game.actions'; |
|
||||||
|
|
||||||
let blinkTimer = null; |
|
||||||
let newgameListener = null; |
|
||||||
|
|
||||||
const toggleTimeout = function() { |
|
||||||
var hidden = this.props.blink; |
|
||||||
this.props.dispatch(NewGameActions.blink()); |
|
||||||
blinkTimer = setTimeout(toggleTimeout.bind(this), 600); |
|
||||||
}; |
|
||||||
|
|
||||||
export default class NewGame extends Component { |
|
||||||
componentDidMount() { |
|
||||||
newgameListener = this.handleKeydown.bind(this); |
|
||||||
window.addEventListener('keydown', newgameListener); |
|
||||||
toggleTimeout.call(this); |
|
||||||
}; |
|
||||||
|
|
||||||
componentWillUnmount() { |
|
||||||
window.removeEventListener('keydown', newgameListener); |
|
||||||
clearTimeout(blinkTimer); |
|
||||||
}; |
|
||||||
|
|
||||||
handleKeydown(e) { |
|
||||||
if (e.keyCode === 32) { |
|
||||||
this.props.dispatch(ModeActions.options()); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
render() { |
|
||||||
const classname = ['newgame']; |
|
||||||
|
|
||||||
if (this.props.hidden === true) { |
|
||||||
classname.push('hidden'); |
|
||||||
} |
|
||||||
|
|
||||||
return ( |
|
||||||
<div className={classname.join(' ')}>Press Space Bar To Play</div> |
|
||||||
); |
|
||||||
}; |
|
||||||
}; |
|
||||||
|
|
||||||
const select = (state) => { |
|
||||||
return state.newgame; |
|
||||||
}; |
|
||||||
|
|
||||||
export default connect(select)(NewGame); |
|
@ -1,18 +1,50 @@ |
|||||||
require('../../sass/welcome/welcome.scss'); |
require('../../sass/welcome/welcome.scss'); |
||||||
|
|
||||||
import { Component } from 'react'; |
import { Component } from 'react'; |
||||||
|
import { connect } from 'react-redux'; |
||||||
|
import Initials from './initials.component'; |
||||||
|
|
||||||
import NewGame from './new-game.component'; |
import * as ModeActions from '../../actions/mode.actions'; |
||||||
import HighScores from './high-scores.component'; |
import WelcomeCtrl from '../../controllers/welcome/welcome.controller'; |
||||||
|
|
||||||
|
let listener; |
||||||
|
|
||||||
|
export class Welcome extends Component { |
||||||
|
componentDidMount() { |
||||||
|
listener = WelcomeCtrl.keydown.bind(WelcomeCtrl); |
||||||
|
window.addEventListener('keydown', listener); |
||||||
|
|
||||||
|
// HighScoreCtrl.setDispatch(this.props.dispatch);
|
||||||
|
// HighScoreCtrl.retrieveScores();
|
||||||
|
// HighScoreCtrl.updateScores(ScorebarCtrl.currentScore);
|
||||||
|
}; |
||||||
|
|
||||||
|
componentWillUnmount() { |
||||||
|
window.removeEventListener('keydown', listener); |
||||||
|
}; |
||||||
|
|
||||||
export default class Welcome extends Component { |
|
||||||
render() { |
render() { |
||||||
|
// var entries = [];
|
||||||
|
// this.props.values.map(function(v, i) {
|
||||||
|
// entries.push(<HighScoreEntry initials={v.initials} score={v.score} rank={v.rank} key={i} />);
|
||||||
|
// });
|
||||||
|
|
||||||
return ( |
return ( |
||||||
<div className='welcome'> |
<div className='welcome'> |
||||||
<img src="res/title.png" /> |
<img src="res/title.png" /> |
||||||
<NewGame /> |
<div className='line'>Press Spacebar for new game</div> |
||||||
<HighScores /> |
<div className='line'>New high score!</div> |
||||||
|
<div className='line'>Enter your initials:</div> |
||||||
|
<Initials /> |
||||||
</div> |
</div> |
||||||
); |
); |
||||||
}; |
}; |
||||||
}; |
}; |
||||||
|
|
||||||
|
const select = (state) => { |
||||||
|
return { |
||||||
|
values: state.welcome.scores |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default connect(select)(Welcome); |
||||||
|
@ -0,0 +1,91 @@ |
|||||||
|
import * as WelcomeActions from '../../actions/welcome/welcome.actions'; |
||||||
|
|
||||||
|
let dispatch; |
||||||
|
|
||||||
|
let initials = [ |
||||||
|
{ initial: 'A', active: true }, |
||||||
|
{ initial: 'A', active: false }, |
||||||
|
{ initial: 'A', active: false } |
||||||
|
]; |
||||||
|
|
||||||
|
let active = 0; |
||||||
|
let code; |
||||||
|
|
||||||
|
const InitialsCtrl = { |
||||||
|
setDispatch: (d) => dispatch = d, |
||||||
|
|
||||||
|
keydown: function(e) { |
||||||
|
switch (e.keyCode) { |
||||||
|
case 13: |
||||||
|
case 32: |
||||||
|
break; |
||||||
|
case 37: |
||||||
|
active--; |
||||||
|
if (active === -1) { |
||||||
|
active = initials.length - 1; |
||||||
|
} |
||||||
|
this.updateInitials(); |
||||||
|
break; |
||||||
|
case 38: |
||||||
|
code = initials[active].initial.charCodeAt(0); |
||||||
|
code--; |
||||||
|
if (code === 64) { |
||||||
|
code = 90; |
||||||
|
} |
||||||
|
initials[active].initial = String.fromCharCode(code); |
||||||
|
this.updateInitials(); |
||||||
|
break; |
||||||
|
case 39: |
||||||
|
active++; |
||||||
|
if (active === initials.length) { |
||||||
|
active = 0; |
||||||
|
} |
||||||
|
this.updateInitials(); |
||||||
|
break; |
||||||
|
case 40: |
||||||
|
code = initials[active].initial.charCodeAt(0); |
||||||
|
code++; |
||||||
|
if (code === 91) { |
||||||
|
code = 65; |
||||||
|
} |
||||||
|
initials[active].initial = String.fromCharCode(code); |
||||||
|
this.updateInitials(); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
if (e.keyCode >= 65 && e.keyCode <= 90) { |
||||||
|
initials[active].initial = String.fromCharCode(e.keyCode); |
||||||
|
|
||||||
|
if (active < initials.length - 1) { |
||||||
|
active++; |
||||||
|
} |
||||||
|
this.updateInitials(); |
||||||
|
} |
||||||
|
}, |
||||||
|
|
||||||
|
updateInitials: () => { |
||||||
|
initials = initials.map((v) => { |
||||||
|
v.active = false; |
||||||
|
return v; |
||||||
|
}); |
||||||
|
|
||||||
|
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);
|
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default InitialsCtrl; |
@ -0,0 +1,43 @@ |
|||||||
|
import * as WelcomeActions from '../../actions/welcome/welcome.actions'; |
||||||
|
import InitialsCtrl from './initials.controller'; |
||||||
|
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); |
||||||
|
|
||||||
|
if (scores !== null) { |
||||||
|
return scores[0].score; |
||||||
|
} |
||||||
|
|
||||||
|
return 0; |
||||||
|
}, |
||||||
|
|
||||||
|
gameOver: (score) => { |
||||||
|
|
||||||
|
}, |
||||||
|
|
||||||
|
retrieveScores: () => { |
||||||
|
const scores = localStorage.getItem(SETTINGS.LOCAL_STORAGE_KEY); |
||||||
|
|
||||||
|
if (scores !== null) { |
||||||
|
dispatch(WelcomeActions.updateScores(scores)); |
||||||
|
} |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
export default HighScoreCtrl; |
@ -1,16 +0,0 @@ |
|||||||
import * as NewGameActions from '../../actions/welcome/new-game.actions'; |
|
||||||
|
|
||||||
const initial = { hidden: false }; |
|
||||||
const reducer = (state = initial, action) => { |
|
||||||
if (action.type !== NewGameActions.NEWGAME_ACTION) { |
|
||||||
return state; |
|
||||||
} |
|
||||||
|
|
||||||
if (action.action === NewGameActions.BLINK) { |
|
||||||
return (state.hidden ? { hidden: false } : { hidden: true }); |
|
||||||
} |
|
||||||
|
|
||||||
return state; |
|
||||||
}; |
|
||||||
|
|
||||||
export default reducer; |
|
@ -0,0 +1,40 @@ |
|||||||
|
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 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: |
||||||
|
return Immutable.Map(state) |
||||||
|
.set('initials', action.initials) |
||||||
|
.toObject(); |
||||||
|
} |
||||||
|
|
||||||
|
return state; |
||||||
|
}; |
||||||
|
|
||||||
|
export default reducer; |
@ -1,25 +0,0 @@ |
|||||||
.highscores { |
|
||||||
font-size: 0; |
|
||||||
|
|
||||||
.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; |
|
||||||
} |
|
||||||
} |
|
@ -1,22 +1,100 @@ |
|||||||
.welcome { |
.welcome { |
||||||
|
$w: 350px; |
||||||
|
|
||||||
padding:20px; |
padding:20px; |
||||||
text-align:center; |
text-align:center; |
||||||
|
|
||||||
img { |
img { |
||||||
width:350px; |
width:$w; |
||||||
} |
} |
||||||
|
|
||||||
.highscores { |
.line { |
||||||
margin:0 auto; |
line-height:30px; |
||||||
width:350px; |
|
||||||
} |
} |
||||||
|
|
||||||
.newgame { |
@keyframes blink { |
||||||
margin:20px 0; |
50% { |
||||||
transition:opacity 0.1s ease; |
opacity: 0.6; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
&.hidden { |
@-webkit-keyframes blink { |
||||||
opacity: 0.5; |
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; |
||||||
|
// } |
||||||
|
// } |
||||||
|
Loading…
Reference in new issue