Skip to content

Commit 222a0d3

Browse files
Fix IA weights modifications and New IA Hard Game
1 parent 3b1caac commit 222a0d3

26 files changed

+710
-274
lines changed

.DS_Store

6 KB
Binary file not shown.

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
flappy-bird-neural-network
2+
.vscode

README.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1-
#flappy-bird-neural-network WIP
1+
# Flappy Bird Neural Network
2+
3+
![Menu](screenshot.png)
4+
5+
![Game](screenshot1.png)

assets/.DS_Store

6 KB
Binary file not shown.

assets/bird16.png

6.51 KB
Loading

assets/wall.png

1.34 KB
Loading

components/bird.go

+60-50
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,47 @@ package components
22

33
import (
44
"math"
5+
"time"
56

67
"github.com/faiface/pixel"
78
"github.com/faiface/pixel/pixelgl"
89
)
910

11+
// BirdHeight is the height of the bird sprite
1012
const BirdHeight = 46
13+
14+
// BirdWidth is the width of the bird sprite
1115
const BirdWidth = 54
12-
const gravity = 20.0
16+
17+
// BirdX is the inicial position X of the bird
1318
const BirdX = WindowWidth/2 - WindowWidth*0.2
19+
const gravity = 20.0
1420

15-
var maxSpeed = gravity / 5
21+
var maxSpeed = gravity / 4
1622

1723
// Bird component
1824
type Bird struct {
19-
x float64
20-
y float64
21-
speed float64
22-
sprite *pixel.Sprite
23-
points int64
24-
death bool
25-
enable bool
25+
x float64
26+
y float64
27+
speed float64
28+
sprite *pixel.Sprite
29+
points int64
30+
death bool
31+
enableGhost bool
32+
ghost bool
2633
}
2734

2835
// NewBird creates a new bird component
2936
func NewBird(x float64, sprite *pixel.Sprite) *Bird {
3037
return &Bird{
31-
x: x,
32-
y: WindowHeight / 2,
33-
speed: 2,
34-
sprite: sprite,
35-
points: 0,
36-
death: false,
37-
enable: true,
38+
x: x,
39+
y: WindowHeight / 2,
40+
speed: 2,
41+
sprite: sprite,
42+
points: 0,
43+
death: false,
44+
enableGhost: true,
45+
ghost: false,
3846
}
3947
}
4048

@@ -50,10 +58,6 @@ func (b *Bird) GetPoints() int64 {
5058
return b.points
5159
}
5260

53-
func (b *Bird) Enable() {
54-
b.enable = true
55-
}
56-
5761
func (b *Bird) IsDeath() bool {
5862
return b.death
5963
}
@@ -63,50 +67,33 @@ func (b *Bird) Death() {
6367
}
6468

6569
func (b *Bird) Update() {
66-
if b.death == true || b.enable == true {
67-
if b.speed < maxSpeed {
68-
b.speed += gravity * Delta
69-
}
70+
if b.speed < maxSpeed {
71+
b.speed += gravity * Delta
7072
}
7173

7274
if b.death == true {
7375
b.x -= XSpeed * Delta
76+
7477
if b.y > 80 {
7578
b.y -= b.speed
7679
}
77-
} else {
78-
if b.enable && b.y > 80 {
79-
b.y -= b.speed
80-
} else {
81-
if b.y >= WindowHeight/2+20 {
82-
b.speed = 2
83-
} else if b.y < WindowHeight/2-20 {
84-
b.speed = -2
85-
}
8680

87-
b.y -= b.speed
88-
}
81+
return
8982
}
90-
}
91-
92-
func (b *Bird) Draw(win *pixelgl.Window) error {
93-
mat := pixel.IM
9483

95-
if b.enable && b.speed > 0 {
96-
if b.speed > -5 && b.speed < 3 {
97-
mat = mat.Rotated(pixel.V(0, 0), b.speed*-15*math.Pi/180)
98-
} else {
99-
mat = mat.Rotated(pixel.V(0, 0), -45*math.Pi/180)
100-
}
101-
} else if b.enable == false {
102-
mat = mat.Rotated(pixel.V(0, 0), -18*math.Pi/180)
103-
}
84+
b.y -= b.speed
85+
}
10486

87+
func (b *Bird) Draw(win *pixelgl.Window) {
88+
mat := pixel.IM.Rotated(pixel.V(0, 0), Min(15*math.Pi/180, b.speed*-8*math.Pi/180))
10589
mat = mat.Moved(pixel.V(b.x, b.y))
10690

107-
b.sprite.Draw(win, mat)
91+
sprite := b.sprite
92+
if b.ghost {
93+
sprite = Sprites["bird16"]
94+
}
10895

109-
return nil
96+
sprite.Draw(win, mat)
11097
}
11198

11299
func (b *Bird) Jump() {
@@ -116,3 +103,26 @@ func (b *Bird) Jump() {
116103
func (b *Bird) IncreasePoint() {
117104
b.points++
118105
}
106+
107+
func (b *Bird) Ghost() bool {
108+
return b.ghost
109+
}
110+
111+
func (b *Bird) IsEnableGhost() bool {
112+
return b.enableGhost
113+
}
114+
115+
func (b *Bird) UseGhost() {
116+
if b.enableGhost {
117+
b.ghost = true
118+
b.enableGhost = false
119+
120+
time.AfterFunc(2*time.Second, func() {
121+
b.ghost = false
122+
})
123+
124+
time.AfterFunc(7*time.Second, func() {
125+
b.enableGhost = true
126+
})
127+
}
128+
}

components/individual.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package components
2+
3+
import (
4+
"github.com/andersondalmina/flappy-bird-neural-network/neuralnetwork"
5+
)
6+
7+
// Individual component
8+
type Individual struct {
9+
bird *Bird
10+
neural *neuralnetwork.NeuralNetwork
11+
inputs []float64
12+
}
13+
14+
// NewIndividual create a new individual
15+
func NewIndividual(b *Bird, n *neuralnetwork.NeuralNetwork) *Individual {
16+
i := Individual{
17+
bird: b,
18+
neural: n,
19+
inputs: make([]float64, 2),
20+
}
21+
22+
return &i
23+
}
24+
25+
// Bird return the individual bird
26+
func (i *Individual) Bird() *Bird {
27+
return i.bird
28+
}
29+
30+
// Inputs return the inputs
31+
func (i *Individual) Inputs() []float64 {
32+
return i.inputs
33+
}
34+
35+
// SetInputs set the inputs
36+
func (i *Individual) SetInputs(inputs []float64) {
37+
i.inputs = inputs
38+
}
39+
40+
// Neural return the neural
41+
func (i *Individual) Neural() *neuralnetwork.NeuralNetwork {
42+
return i.neural
43+
}

components/pipe.go

+64-11
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,39 @@ package components
22

33
import (
44
"math"
5+
"math/rand"
56

67
"github.com/faiface/pixel"
78
"github.com/faiface/pixel/pixelgl"
89
)
910

11+
// PipeHeight is the width of the pipe sprite
1012
const PipeHeight = 40.0
1113

12-
// Pipe component
14+
// PipeWidth is the width of the pipe sprite
15+
const PipeWidth = 86.0
16+
17+
// Obstacle component interface
18+
type Obstacle interface {
19+
GetX() float64
20+
GetY() float64
21+
Draw(win *pixelgl.Window)
22+
Update()
23+
IsDefeated() bool
24+
Defeat()
25+
CheckCrash(b Bird) bool
26+
GetType() float64
27+
}
28+
29+
// Pipe type of obstacle
1330
type Pipe struct {
1431
x float64
1532
y float64
1633
defeated bool
1734
speed float64
1835
spriteUp *pixel.Sprite
1936
spriteDown *pixel.Sprite
37+
direction int
2038
}
2139

2240
// NewPipe creates a new pipe component
@@ -28,26 +46,37 @@ func NewPipe(x float64, y float64) *Pipe {
2846
speed: 0,
2947
spriteUp: Sprites["pipeUp"],
3048
spriteDown: Sprites["pipeDown"],
49+
direction: rand.Intn(1),
3150
}
3251
}
3352

34-
func (b *Pipe) GetX() float64 {
35-
return b.x
53+
// GetType return the type of obstacle
54+
func (p *Pipe) GetType() float64 {
55+
return 1
3656
}
3757

38-
func (b *Pipe) GetY() float64 {
39-
return b.y
58+
// GetX return X position
59+
func (p *Pipe) GetX() float64 {
60+
return p.x
4061
}
4162

42-
func (b *Pipe) IsDefeated() bool {
43-
return b.defeated
63+
// GetY return Y position
64+
func (p *Pipe) GetY() float64 {
65+
return p.y
4466
}
4567

46-
func (b *Pipe) Defeat() {
47-
b.defeated = true
68+
// IsDefeated return if the wall is defeat
69+
func (p *Pipe) IsDefeated() bool {
70+
return p.defeated
4871
}
4972

50-
func (p *Pipe) Draw(win *pixelgl.Window) error {
73+
// Defeat mask this wall as defeat
74+
func (p *Pipe) Defeat() {
75+
p.defeated = true
76+
}
77+
78+
// Draw the wall on window
79+
func (p *Pipe) Draw(win *pixelgl.Window) {
5180
// Draw down part of pipe
5281
p.spriteUp.Draw(win, pixel.IM.Moved(pixel.V(p.x, p.y-100)))
5382
for i := p.y - 100 - PipeHeight; i > 0; i -= PipeHeight {
@@ -61,6 +90,30 @@ func (p *Pipe) Draw(win *pixelgl.Window) error {
6190
}
6291

6392
p.x -= XSpeed * Delta
93+
}
94+
95+
// Update the pipe
96+
func (p *Pipe) Update() {
97+
if p.direction == 1 {
98+
p.y++
99+
} else {
100+
p.y--
101+
}
102+
103+
if p.y > WindowHeight-150 {
104+
p.direction = 0
105+
} else if p.y < 200 {
106+
p.direction = 1
107+
}
108+
}
109+
110+
// CheckCrash check if a bird crash on the pipe
111+
func (p *Pipe) CheckCrash(b Bird) bool {
112+
if b.GetX() >= p.GetX()-50 && b.GetX() <= p.GetX()+50 {
113+
if b.GetY() <= (p.GetY()-55) || b.GetY() >= (p.GetY()+55) {
114+
return true
115+
}
116+
}
64117

65-
return nil
118+
return false
66119
}

neuralnetwork/population.go components/population.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package neuralnetwork
1+
package components
22

33
// Number of individuals of each population
44
const iNum = 100

components/sprites.go

+12
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,12 @@ func loadSprites() map[string]*pixel.Sprite {
6161
}
6262
result["bird15"] = pixel.NewSprite(picBird, picBird.Bounds())
6363

64+
picBird, err = loadPicture("./assets/bird16.png")
65+
if err != nil {
66+
panic(err)
67+
}
68+
result["bird16"] = pixel.NewSprite(picBird, picBird.Bounds())
69+
6470
picUp, err := loadPicture("./assets/pipeup.png")
6571
if err != nil {
6672
panic(err)
@@ -73,6 +79,12 @@ func loadSprites() map[string]*pixel.Sprite {
7379
}
7480
result["pipeDown"] = pixel.NewSprite(picDown, picDown.Bounds())
7581

82+
pic, err := loadPicture("./assets/wall.png")
83+
if err != nil {
84+
panic(err)
85+
}
86+
result["wall"] = pixel.NewSprite(pic, pic.Bounds())
87+
7688
return result
7789
}
7890

components/text.go

+3
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,21 @@ import (
1313
"golang.org/x/image/font"
1414
)
1515

16+
// Text component
1617
type Text struct {
1718
txt string
1819
color color.RGBA
1920
}
2021

22+
// CreateTextLine create a net text component
2123
func CreateTextLine(txt string, color color.RGBA) Text {
2224
return Text{
2325
txt: txt,
2426
color: color,
2527
}
2628
}
2729

30+
// WriteText draw the text on the window
2831
func WriteText(txt []Text, color color.RGBA, win *pixelgl.Window, mat pixel.Matrix) {
2932
face, err := loadTTF("./assets/font.ttf", 14)
3033
if err != nil {

0 commit comments

Comments
 (0)