-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbird.go
119 lines (93 loc) · 1.83 KB
/
bird.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
package main
import (
"fmt"
"sync"
"github.com/veandco/go-sdl2/img"
"github.com/veandco/go-sdl2/sdl"
)
const (
gravity = 0.1
jumpSpeed = 5
)
type bird struct {
mu sync.RWMutex
time int
textures []*sdl.Texture
x, y int32
w, h int32
speed float64
dead bool
}
func newBird(r *sdl.Renderer) (*bird, error) {
var textures []*sdl.Texture
for i := 1; i <= 4; i++ {
path := fmt.Sprintf("res/imgs/bird_frame_%d.png", i)
texture, err := img.LoadTexture(r, path)
if err != nil {
return nil, fmt.Errorf("could not load background image: %v", err)
}
textures = append(textures, texture)
}
return &bird{textures: textures, x: 10, y: 300, w: 50, h: 43}, nil
}
func (b *bird) update() {
b.mu.Lock()
defer b.mu.Unlock()
b.time++
b.y -= int32(b.speed)
if b.y < 0 {
b.dead = true
}
b.speed += gravity
}
func (b *bird) paint(r *sdl.Renderer) error {
b.mu.RLock()
defer b.mu.RUnlock()
rect := &sdl.Rect{W: b.w, H: b.h, X: b.x, Y: 600 - b.y - b.h/2}
i := b.time / 10 % len(b.textures)
if err := r.Copy(b.textures[i], nil, rect); err != nil {
return fmt.Errorf("could not copy bird: %v", err)
}
return nil
}
func (b *bird) restart() {
b.mu.Lock()
defer b.mu.Unlock()
b.y = 300
b.speed = 0
b.dead = false
}
func (b *bird) destroy() {
b.mu.Lock()
defer b.mu.Unlock()
for _, b := range b.textures {
b.Destroy()
}
}
func (b *bird) isDead() bool {
b.mu.RLock()
defer b.mu.RUnlock()
return b.dead
}
func (b *bird) jump() {
b.mu.Lock()
defer b.mu.Unlock()
b.speed = -jumpSpeed
}
func (b *bird) touch(p *pipe) {
b.mu.Lock()
defer b.mu.Unlock()
if p.x > b.x+b.w { // too far right
return
}
if p.x+p.w < b.x { // too far left
return
}
if !p.inverted && p.h < b.y-b.h/2 { // pipe is too low
return
}
if p.inverted && 600-p.h > b.y+b.h/2 { // height is too high
return
}
b.dead = true
}