Skip to content

Commit c15fda5

Browse files
committed
Extract controls component
1 parent 5580db1 commit c15fda5

File tree

3 files changed

+136
-121
lines changed

3 files changed

+136
-121
lines changed

components/GameBoard.js

Lines changed: 46 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -38,60 +38,30 @@ const GameOverScreen = ({ gameover }) => (
3838
</div>
3939
)
4040

41-
const GameBox = ({ width, children }) => {
42-
console.log(arguments)
43-
return (
41+
const GameBox = ({ width, children }) => (
42+
<div
43+
style={{
44+
position: 'relative',
45+
border: '1px solid #ddd',
46+
width: `${width}px`,
47+
maxWidth: '100%',
48+
background: '#fff'
49+
}}
50+
>
4451
<div
4552
style={{
46-
display: 'flex',
47-
alignItems: 'center',
48-
justifyContent: 'center',
49-
position: 'fixed',
50-
background: '#f5f5f5',
51-
margin: 0,
52-
top: 0,
53-
bottom: 0,
54-
left: 0,
55-
right: 0
53+
position: 'relative',
54+
width: '100%',
55+
paddingBottom: '100%',
56+
height: 0
5657
}}
57-
>
58-
<div
59-
style={{
60-
position: 'relative',
61-
border: '1px solid #ddd',
62-
width: `${width}px`,
63-
maxWidth: '100%',
64-
background: '#fff'
65-
}}
66-
>
67-
<div
68-
style={{
69-
position: 'relative',
70-
width: '100%',
71-
paddingBottom: '100%',
72-
height: 0
73-
}}
74-
/>
75-
{children}
76-
</div>
77-
</div>
78-
)
79-
}
80-
81-
export default ({
82-
width,
83-
colors,
84-
score,
85-
highScore,
86-
gameover,
87-
level,
88-
balls
89-
}) => (
90-
<GameBox width={width}>
91-
<Score score={score} highScore={highScore} />
92-
<GameOverScreen gameover={gameover} />
93-
<Levels colors={colors} current={level} />
58+
/>
59+
{children}
60+
</div>
61+
)
9462

63+
const Balls = ({ colors, balls }) => (
64+
<TransitionGroup>
9565
<style jsx global>{`
9666
.ball-enter {
9767
transform: scale(1.7);
@@ -119,16 +89,31 @@ export default ({
11989
transition: 0.4s !important;
12090
}
12191
`}</style>
122-
<TransitionGroup>
123-
{balls.map(params => (
124-
<CSSTransition
125-
key={params.key}
126-
classNames='ball'
127-
timeout={{ enter: 300, exit: 400 }}
128-
>
129-
<Ball colors={colors} {...params} />
130-
</CSSTransition>
131-
))}
132-
</TransitionGroup>
92+
{balls.map(params => (
93+
<CSSTransition
94+
key={params.key}
95+
classNames='ball'
96+
timeout={{ enter: 300, exit: 400 }}
97+
>
98+
<Ball colors={colors} {...params} />
99+
</CSSTransition>
100+
))}
101+
</TransitionGroup>
102+
)
103+
104+
export default ({
105+
width,
106+
colors,
107+
score,
108+
highScore,
109+
gameover,
110+
level,
111+
balls
112+
}) => (
113+
<GameBox width={width}>
114+
<Score score={score} highScore={highScore} />
115+
<GameOverScreen gameover={gameover} />
116+
<Levels colors={colors} current={level} />
117+
<Balls balls={balls} colors={colors} />
133118
</GameBox>
134119
)

components/GameControls.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import KeyHandler, { KEYDOWN } from 'react-key-handler'
2+
import Swipeable from 'react-swipeable'
3+
4+
function isCloseToAngle (target) {
5+
return angle => {
6+
const tolerance = 0.6
7+
return target - tolerance < angle && angle < target + tolerance
8+
}
9+
}
10+
11+
const isLeftSwipe = isCloseToAngle(0)
12+
const isRightSwipe = isCloseToAngle(Math.PI)
13+
const isUpSwipe = isCloseToAngle(Math.PI / 2)
14+
const isDownSwipe = isCloseToAngle(-Math.PI / 2)
15+
16+
export default ({ children, left, right, up, down }) => {
17+
return (
18+
<Swipeable onSwiped={(e, deltaX, deltaY, isFlick, velocity) => {
19+
if (!isFlick) return
20+
e.preventDefault()
21+
22+
const angle = Math.atan2(deltaY, deltaX)
23+
24+
if (isLeftSwipe(angle)) {
25+
left()
26+
} else if (isRightSwipe(angle)) {
27+
right()
28+
} else if (isUpSwipe(angle)) {
29+
up()
30+
} else if (isDownSwipe(angle)) {
31+
down()
32+
}
33+
}}>
34+
<KeyHandler
35+
keyEventName={KEYDOWN}
36+
keyValue='ArrowDown'
37+
onKeyHandle={down}
38+
/>
39+
<KeyHandler
40+
keyEventName={KEYDOWN}
41+
keyValue='ArrowLeft'
42+
onKeyHandle={left}
43+
/>
44+
<KeyHandler
45+
keyEventName={KEYDOWN}
46+
keyValue='ArrowRight'
47+
onKeyHandle={right}
48+
/>
49+
<KeyHandler
50+
keyEventName={KEYDOWN}
51+
keyValue='ArrowUp'
52+
onKeyHandle={up}
53+
/>
54+
{children}
55+
</Swipeable>
56+
)
57+
}

pages/index.js

Lines changed: 33 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,29 @@
1-
import KeyHandler, { KEYDOWN } from 'react-key-handler'
21
import React from 'react'
3-
import Swipeable from 'react-swipeable'
42
import Head from 'next/head'
53
import game from '../lib/game'
64
import GameBoard from '../components/GameBoard'
5+
import GameControls from '../components/GameControls'
76

87
export default class Page extends React.Component {
9-
constructor (props) {
8+
constructor () {
109
super()
1110
this.game = game()
1211
this.game.onUpdate(s => this.setState(s))
1312
}
1413

1514
componentDidMount () {
16-
this.loadHighScore()
17-
}
18-
19-
loadHighScore () {
2015
if (typeof window === 'undefined') return
2116
this.game.setHighScore(window.localStorage['score'] || 0)
2217
}
2318

24-
isCloseToAngle (angle, target) {
25-
const tolerance = 0.6
26-
return target - tolerance < angle && angle < target + tolerance
27-
}
28-
29-
swiped (e, deltaX, deltaY, isFlick, velocity) {
30-
if (!isFlick) return
31-
e.preventDefault()
32-
33-
const angle = Math.atan2(deltaY, deltaX)
34-
console.log(angle)
35-
if (this.isCloseToAngle(angle, 0)) {
36-
this.game.moveDotsLeft()
37-
} else if (this.isCloseToAngle(angle, Math.PI)) {
38-
this.game.moveDotsRight()
39-
} else if (this.isCloseToAngle(angle, Math.PI / 2)) {
40-
this.game.rotateDots()
41-
} else if (this.isCloseToAngle(angle, -Math.PI / 2)) {
42-
this.game.pushDots()
43-
}
44-
}
45-
4619
render () {
4720
return (
48-
<Swipeable onSwiped={this.swiped.bind(this)}>
49-
<KeyHandler
50-
keyEventName={KEYDOWN}
51-
keyValue='ArrowDown'
52-
onKeyHandle={() => this.game.pushDots()}
53-
/>
54-
<KeyHandler
55-
keyEventName={KEYDOWN}
56-
keyValue='ArrowLeft'
57-
onKeyHandle={() => this.game.moveDotsLeft()}
58-
/>
59-
<KeyHandler
60-
keyEventName={KEYDOWN}
61-
keyValue='ArrowRight'
62-
onKeyHandle={() => this.game.moveDotsRight()}
63-
/>
64-
<KeyHandler
65-
keyEventName={KEYDOWN}
66-
keyValue='ArrowUp'
67-
onKeyHandle={() => this.game.rotateDots()}
68-
/>
21+
<GameControls
22+
up={this.game.rotateDots}
23+
down={this.game.pushDots}
24+
left={this.game.moveDotsLeft}
25+
right={this.game.moveDotsRight}
26+
>
6927
<Head>
7028
<title>Combine!</title>
7129
<meta charSet='utf-8' />
@@ -75,16 +33,31 @@ export default class Page extends React.Component {
7533
/>
7634
</Head>
7735

78-
<GameBoard
79-
width={500}
80-
colors={this.game.colors()}
81-
score={this.game.score()}
82-
highScore={this.game.highScore()}
83-
gameover={this.game.gameover()}
84-
level={this.game.level()}
85-
balls={this.game.balls()}
86-
/>
87-
</Swipeable>
36+
<div
37+
style={{
38+
display: 'flex',
39+
alignItems: 'center',
40+
justifyContent: 'center',
41+
position: 'fixed',
42+
background: '#f5f5f5',
43+
margin: 0,
44+
top: 0,
45+
bottom: 0,
46+
left: 0,
47+
right: 0
48+
}}
49+
>
50+
<GameBoard
51+
width={500}
52+
colors={this.game.colors()}
53+
score={this.game.score()}
54+
highScore={this.game.highScore()}
55+
gameover={this.game.gameover()}
56+
level={this.game.level()}
57+
balls={this.game.balls()}
58+
/>
59+
</div>
60+
</GameControls>
8861
)
8962
}
9063
}

0 commit comments

Comments
 (0)