-
Notifications
You must be signed in to change notification settings - Fork 1
/
draw.go
151 lines (103 loc) · 3.4 KB
/
draw.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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// here we do our drawing of said snek
package main
import (
"github.com/hajimehoshi/ebiten"
"image/color"
"math"
"math/rand"
)
type Drawable interface {
//this the image for the edible
avatar() *ebiten.Image
//this is used for drawing
position() Vector2
}
// does the level animation, where the snake flips out
func DoLevelAnimation(game *GameState, screen *ebiten.Image) {
//we are responsible for all drawing in the coroutine- Update
//is not handling that anymore
DrawBackground(screen)
//now we handle the shrink
percentageRemaining := float64(game.tick-game.coroutineStart) / 180.0
if percentageRemaining > 1 {
percentageRemaining = 1
}
//find the closest value of 2, using the ticks to completion as a %
//first calculate the difference of max and start using the percentage,
//when there are all ticks reminaing, this is 0 ( the snake is the biggest ),
//and when there are no ticks, it is 0 ( snake is smol )
sizeDiffAsFloat := (maxSize - startSize) * percentageRemaining
//now take the floor of the difference
sizeDiffAsInt := int(math.Floor(sizeDiffAsFloat))
//now find the nearest power of 2 of the difference
sizeDiff := (2 - sizeDiffAsInt%2) + sizeDiffAsInt
//now actually subtract it from the max size, getting our new size,
//divisible by 2 and between max size and start size
newSize := maxSize - sizeDiff
//sometimes we can go over, depending on how accurate our frame
//emulation is via ticks
if newSize < startSize {
newSize = startSize
}
i := 0
shrunkImage := game.snake.GetImageForSize(newSize)
//new color for the shrunken image
randomColor := color.NRGBA{
uint8(rand.Intn(255)),
uint8(rand.Intn(255)),
uint8(rand.Intn(255)),
255}
shrunkImage.Fill(randomColor)
//do the "wobble animation"
for segment := range game.snake.GetTail() {
i++
//find the value of cos/sin at game.tick + i(offset) multiplied by a radian
//this creates a circular motion in which the segments appear to wobble
diffX := math.Cos(float64(game.tick+i)*(math.Pi/24)) * (5 - (4 * percentageRemaining))
diffY := math.Sin(float64(game.tick+i)*(math.Pi/24)) * (5 - (4 * percentageRemaining))
newPosition := Vector2{
diffX + segment.x,
diffY + segment.y}
//we create a new segment here, really only using the position of
//the old segment
newSegment := SnakeSegment{
&game.snake,
newPosition,
float64(newSize),
shrunkImage}
//and draw the segment
DrawObject(newSegment, screen)
}
}
//draw does not take a pointer to state, so we do not modifiy it
//i had this throw an error for the parent to collect,
//but i am no longer doing that. unsure if i want to remove it
func Draw(game GameState, screen *ebiten.Image) error {
DrawBackground(screen)
//this might be a real data object someday
drawable := make([]Drawable, len(game.edibles))
for i, edible := range game.edibles {
drawable[i] = edible
DrawObject(drawable[i], screen)
}
for drawObject := range game.snake.GetDrawTail() {
DrawObject(drawObject, screen)
}
return nil
}
func DrawBackground(screen *ebiten.Image) {
//background draw
screen.Fill(color.NRGBA{0xff, 0x00, 0x00, 0xff})
}
func DrawObject(drawable Drawable, screen *ebiten.Image) {
if drawable == nil {
return
}
if drawable.avatar() == nil {
return
}
position := drawable.position()
opts := &ebiten.DrawImageOptions{}
opts.GeoM.Translate(position.x, position.y)
screen.DrawImage(drawable.avatar(), opts)
}