@@ -6,6 +6,11 @@ import { GAME_WIDTH, GAME_HEIGHT, BIRD_COUNT, PIPE_DISTANCE, GAME_SPEED, PIPE_WI
6
6
import Pipe from './components/pipe'
7
7
import Bird from './components/bird'
8
8
9
+ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
10
+ import { faRecordVinyl , faDove , faAward , faChevronCircleRight } from '@fortawesome/free-solid-svg-icons'
11
+ import { faEarlybirds } from '@fortawesome/free-brands-svg-icons'
12
+
13
+
9
14
10
15
class Game extends Component {
11
16
@@ -16,10 +21,10 @@ class Game extends Component {
16
21
birds
17
22
18
23
// Find best bird and train others
19
- bestBird1
20
- bestBird2
24
+ bestBirds
21
25
22
26
//
27
+ loopNumber
23
28
frameCount
24
29
state
25
30
@@ -34,13 +39,19 @@ class Game extends Component {
34
39
constructor ( props ) {
35
40
super ( props )
36
41
42
+ this . loopNumber = 0
37
43
this . recordFlyTime = - 1
44
+ this . bestBirds = [ ]
38
45
39
46
this . state = {
40
47
gameSpeed : GAME_SPEED ,
41
48
birdCount : BIRD_COUNT ,
42
49
pipeWidth : PIPE_WIDTH ,
43
- pipeDistance : PIPE_DISTANCE
50
+ pipeDistance : PIPE_DISTANCE ,
51
+ bestBirds : [ ] ,
52
+ recordFlyTime : 0 ,
53
+ currentFlyTime : 0 ,
54
+ loopNumber : 0
44
55
}
45
56
}
46
57
@@ -59,12 +70,19 @@ class Game extends Component {
59
70
60
71
this . pipeIndex = 0
61
72
this . frameCount = 0
73
+ this . loopNumber += 1
74
+
75
+ // set current best fly time
76
+ this . setState ( {
77
+ currentFlyTime : 0 ,
78
+ loopNumber : this . loopNumber
79
+ } )
62
80
}
63
81
64
82
// Restart Game
65
83
restart ( ) {
66
84
this . reset ( )
67
-
85
+
68
86
// generate birds before starting
69
87
this . generateBirds ( )
70
88
@@ -102,23 +120,35 @@ class Game extends Component {
102
120
// if all birds are dead
103
121
if ( aliveBirds . length === 0 ) {
104
122
// sort all dead birds by fly time and take best bird
105
- this . birds . forEach ( bird => {
106
- if ( this . recordFlyTime < bird . flyTime ) {
107
- this . recordFlyTime = bird . flyTime
108
- this . bestBird2 = this . bestBird1
109
- this . bestBird1 = bird
110
- }
123
+ this . birds . push ( this . bestBirds )
124
+ this . birds . sort ( ( a , b ) => a . flyTime < b . flyTime )
125
+
126
+ this . bestBirds = [ ]
127
+ for ( let i = 0 ; i < 4 ; i ++ ) {
128
+ this . bestBirds . push ( this . birds [ i ] )
129
+ }
130
+
131
+ console . log ( this . bestBirds )
132
+ this . setState ( {
133
+ recordFlyTime : this . birds [ 0 ] . flyTime ,
134
+ bestBirds : this . bestBirds
111
135
} )
112
136
137
+ // reset unnecessary data
113
138
this . reset ( )
114
139
115
140
// make mutation using best bird brain
116
- this . bestBird1 . mutate ( )
141
+ this . bestBirds [ 0 ] . mutate ( )
117
142
// generate new birds using best bird
118
- this . generateBirds ( this . bestBird1 , this . bestBird2 )
143
+ this . generateBirds ( this . bestBirds )
119
144
120
145
// start game and train again
121
146
this . start ( )
147
+ } else {
148
+ // set current best fly time
149
+ this . setState ( {
150
+ currentFlyTime : aliveBirds [ 0 ] . flyTime
151
+ } )
122
152
}
123
153
}
124
154
@@ -127,9 +157,9 @@ class Game extends Component {
127
157
this . birds = [ ]
128
158
for ( let i = 0 ; i < this . state . birdCount ; i ++ ) {
129
159
if ( bestBirds && bestBirds . length && Math . random ( ) < 0.8 ) {
130
- this . birds . push ( new Bird ( bestBirds [ i % bestBirds . length ] . brain ) )
160
+ this . birds . push ( new Bird ( i + 1 , this . loopNumber , bestBirds [ i % bestBirds . length ] . brain ) )
131
161
} else {
132
- this . birds . push ( new Bird ( ) )
162
+ this . birds . push ( new Bird ( i + 1 , this . loopNumber ) )
133
163
}
134
164
}
135
165
}
@@ -165,75 +195,132 @@ class Game extends Component {
165
195
render ( ) {
166
196
return (
167
197
< div className = "App" >
168
- < h1 > FlappyBird - Self Learning</ h1 >
169
- < div className = "Game" >
170
- < div className = "Game-left" >
171
- < section >
172
- < h2 > Statistics</ h2 >
173
- < div >
174
- < h3 > Record</ h3 >
175
- < p > Best: < span > { this . state . gameSpeed } </ span > </ p >
176
- < p > Current: < span > { this . state . gameSpeed } </ span > </ p >
177
- </ div >
178
- < div >
179
- < h3 > Best Bird 1</ h3 >
180
- < p > ID: < span > { this . state . gameSpeed } </ span > </ p >
181
- < p > Fly Time: < span > { this . state . gameSpeed } </ span > </ p >
198
+ < div className = "App-header" >
199
+ < div className = "site-logo container" >
200
+ < div className = "logo" >
201
+ < FontAwesomeIcon icon = { faDove } />
202
+ </ div >
203
+ < h2 > FlappyBird - Self Learning</ h2 >
204
+ </ div >
205
+ </ div >
206
+ < div className = "App-content container" >
207
+ < section className = "statistics" >
208
+ < div className = "card" >
209
+ < div className = "card-header" >
210
+ < h2 > Statistics</ h2 >
182
211
</ div >
183
- < div >
184
- < h3 > Best Bird 2</ h3 >
185
- < p > ID: < span > { this . state . gameSpeed } </ span > </ p >
186
- < p > Fly Time: < span > { this . state . gameSpeed } </ span > </ p >
212
+ < div className = "card-body" >
213
+ < div className = "card-item" >
214
+ < h3 > Loop Number</ h3 >
215
+ < div >
216
+ < div className = "item-icon txt-info" >
217
+ < FontAwesomeIcon icon = { faChevronCircleRight } />
218
+ </ div >
219
+ < div className = "item-data" >
220
+ < p > Loop: < span > { this . state . loopNumber } </ span > </ p >
221
+ </ div >
222
+ </ div >
223
+ </ div >
224
+ < div className = "card-item" >
225
+ < h3 > Record</ h3 >
226
+ < div >
227
+ < div className = "item-icon txt-primary" >
228
+ < FontAwesomeIcon icon = { faRecordVinyl } />
229
+ </ div >
230
+ < div className = "item-data" >
231
+ < p > Best: < span > { this . state . recordFlyTime } </ span > </ p >
232
+ < p > Current: < span > { this . state . currentFlyTime } </ span > </ p >
233
+ </ div >
234
+ { this . state . currentFlyTime > this . state . recordFlyTime ? (
235
+ < div className = "record-icon txt-success" >
236
+ < FontAwesomeIcon icon = { faAward } />
237
+ </ div >
238
+ ) : ( < span > </ span > )
239
+ }
240
+ </ div >
241
+ </ div >
242
+ { this . state . bestBirds . map ( function ( bird , index ) {
243
+ return (
244
+ < div className = "card-item" >
245
+ < h3 > Best Bird { index + 1 } </ h3 >
246
+ < div >
247
+ < div className = "item-icon txt-info" >
248
+ < FontAwesomeIcon icon = { faEarlybirds } />
249
+ </ div >
250
+ < div className = "item-data" >
251
+ < p > Name: < span > { bird ? bird . getName ( ) : "" } </ span > </ p >
252
+ < p > Current: < span > { bird . flyTime } </ span > </ p >
253
+ </ div >
254
+ </ div >
255
+ </ div >
256
+ ) ;
257
+ } ) }
187
258
</ div >
188
- </ section >
189
- </ div >
190
- < div className = "Game-center " >
191
- < React . Fragment >
192
- < canvas id = "gameCanvas" width = { GAME_WIDTH } height = { GAME_HEIGHT } className = "Game -canvas" >
259
+ </ div >
260
+ </ section >
261
+ < section className = "game-panel " >
262
+ < div className = "card-game" >
263
+ < canvas id = "gameCanvas" width = { GAME_WIDTH } height = { GAME_HEIGHT } className = "game -canvas" >
193
264
Your browser does not support the HTML canvas tag.
194
265
</ canvas >
195
- </ React . Fragment >
196
- < section >
197
- < h2 > Live Configuration</ h2 >
198
- < div >
199
- < div >
200
- < h3 > Game Speed</ h3 >
201
- < p > { this . state . gameSpeed } </ p >
202
- < input type = "range" min = "10" max = "300"
203
- value = { this . state . gameSpeed }
204
- onChange = { this . changeGameSpeed } />
266
+ </ div >
267
+ < div className = "live-confg" >
268
+ < div className = "card" >
269
+ < div className = "card-header" >
270
+ < h2 > Game Speed</ h2 >
271
+ </ div >
272
+ < div className = "card-body" >
273
+ < div className = "card-item" >
274
+ < p > { this . state . gameSpeed } </ p >
275
+ < input type = "range" min = "10" max = "300"
276
+ value = { this . state . gameSpeed }
277
+ onChange = { this . changeGameSpeed } />
278
+ </ div >
205
279
</ div >
206
280
</ div >
207
- </ section >
208
- </ div >
209
- < div className = "Game-right" >
210
- < section >
211
- < h2 > Initial Configuration</ h2 >
212
- < div >
213
- < div >
281
+ </ div >
282
+ </ section >
283
+ < section className = "configurations" >
284
+ < div className = "card" >
285
+ < div className = "card-header" >
286
+ < h2 > Configuration</ h2 >
287
+ </ div >
288
+ < div className = "card-body" >
289
+ < div className = "card-item" >
214
290
< h3 > Bird Count</ h3 >
215
- < p > { this . state . birdCount } </ p >
216
- < input type = "number" value =
217
- { this . state . birdCount }
218
- onChange = { this . changeBirdCount } />
291
+ < div >
292
+ < p > { this . state . birdCount } </ p >
293
+ < input type = "number" value =
294
+ { this . state . birdCount }
295
+ onChange = { this . changeBirdCount } />
296
+ </ div >
219
297
</ div >
220
- < div >
298
+ < div className = "card-item" >
221
299
< h3 > Pipe Width</ h3 >
222
- < p > { this . state . pipeWidth } </ p >
223
- < input type = "range" min = "10" max = "80"
224
- value = { this . state . pipeWidth }
225
- onChange = { this . changePipeWidth } />
300
+ < div >
301
+ < p > { this . state . pipeWidth } </ p >
302
+ < input type = "range" min = "10" max = "80"
303
+ value = { this . state . pipeWidth }
304
+ onChange = { this . changePipeWidth } />
305
+ </ div >
226
306
</ div >
227
- < div >
307
+ < div className = "card-item" >
228
308
< h3 > Pipe Distance</ h3 >
229
- < p > { this . state . pipeDistance } </ p >
230
- < input type = "range" min = "40" max = "240"
231
- value = { this . state . pipeDistance }
232
- onChange = { this . changePipeDistance } />
309
+ < div >
310
+ < p > { this . state . pipeDistance } </ p >
311
+ < input type = "range" min = "40" max = "240"
312
+ value = { this . state . pipeDistance }
313
+ onChange = { this . changePipeDistance } />
314
+ </ div >
315
+ </ div >
316
+ < div className = "card-item" >
317
+ < div >
318
+ < button className = "btn bg-primary txt-white" > Restart Game</ button >
319
+ </ div >
233
320
</ div >
234
321
</ div >
235
- </ section >
236
- </ div >
322
+ </ div >
323
+ </ section >
237
324
</ div >
238
325
</ div >
239
326
) ;
0 commit comments