-
Notifications
You must be signed in to change notification settings - Fork 2
/
Worm.h
169 lines (151 loc) · 3.93 KB
/
Worm.h
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
#include <Adafruit_NeoPixel.h>
//ARDUINO
// const int STRIP_PIN = 6; // Digital pin connected to DIN on the led strip
// const int NUM_PIXELS = 20; // How many individual LEDs are connected on the strip
//ESP32
const int STRIP_PIN = 32; // Digital pin connected to DIN on the led strip
const int NUM_PIXELS = 144; // How many individual LEDs are connected on the strip
const int NUM_MAX_WORMS = 10; // How many worms can be active on the strip at once
Adafruit_NeoPixel pixels(NUM_PIXELS, STRIP_PIN, NEO_GRB + NEO_KHZ800); //set up pixels object
uint32_t red = pixels.Color(100, 0, 0); // rgb(100,0,0)
uint32_t orange = pixels.Color(100, 50, 0); // rgb(100,50,0)
uint32_t yellow = pixels.Color(100, 100, 0); // rgb(100,100,0)
uint32_t green = pixels.Color(0, 100, 0); // rgb(0,100,0)
uint32_t light_blue = pixels.Color(0, 0, 100); // rgb(0,100,100)
uint32_t blue = pixels.Color(0, 0, 100); // rgb(0,0,100)
uint32_t indigo = pixels.Color(150, 0, 150); // rgb(50,0,100)
uint32_t magenta = pixels.Color(150, 0, 150); // rgb(100,0,100)
uint32_t unlit = pixels.Color(0, 0, 0); // rgb(0,0,0)
const int NUM_COLOURS = 8;
uint32_t colorList[NUM_COLOURS]{red, orange, yellow, green, light_blue, blue, indigo, magenta};
/**
* returns a random colour from a pre-defined list
*/
uint32_t getRandomColor()
{
int index = random(NUM_COLOURS);
return colorList[index];
}
class Worm
{
private:
int head = -1;
uint32_t color = unlit;
int length = 4;
public:
/**
* Returns the worm's head position
*/
int getHead()
{
return head;
}
/**
* Returns the worm's color
*/
uint32_t getColor()
{
return color;
}
/**
* Returns the worm's length
*/
uint32_t getLength()
{
return length;
}
/**
* Returns whether the worm is currently on the strip
*/
bool isOnStrip()
{
return head >= 0;
}
/**
* Returns whether the worm is past the strip
*/
bool isPastStrip()
{
return (head - length) >= NUM_PIXELS;
}
/**
* Positions the worm to start wriggling, and assigns a color
*/
void start()
{
head = 0;
color = getRandomColor();
length = random(4, 12);
}
/**
* Moves the worm forward one space
*/
void wriggle()
{
head += 1;
}
/**
* Resets the worm position off the strip
*/
void reset()
{
head = -1;
}
};
Worm worms[NUM_MAX_WORMS] = {};
volatile int lastStart = 0;
/**
* Handles settings a worm head to pixel 0 and assigning it a new colour.
* Uses a debounce implementation to prevent starting worms too close together
* as a result of fluctuating triggers.
*/
void startWorm()
{
if (millis() - lastStart <= 300)
{
return;
}
// find the first worm not on the strip and add it to the strip
for (int i = 0; i < NUM_MAX_WORMS; i++)
{
if (!worms[i].isOnStrip())
{
worms[i].start();
break;
}
}
lastStart = millis();
}
/**
* Fills a worm based on the provided head index and colour
*/
void fillWorm(int headIdx, int length, uint32_t color)
{
int count = headIdx < length - 1 ? headIdx + 1 : length;
int theoreticalWormTail = headIdx - length + 1;
int wormTail = theoreticalWormTail < 0 ? 0 : theoreticalWormTail;
if (wormTail - 1 >= 0)
{
pixels.setPixelColor(wormTail - 1, 0, 0, 0);
}
pixels.fill(color, wormTail, count);
}
/**
* Handles checking each worm to fill, and incrementing the worm where necessary.
*/
void tickWorms()
{
for (int i = 0; i < NUM_MAX_WORMS; i++)
{
if (worms[i].isOnStrip())
{
fillWorm(worms[i].getHead(), worms[i].getLength(), worms[i].getColor());
worms[i].wriggle();
}
if (worms[i].isPastStrip())
{
worms[i].reset();
}
}
pixels.show();
}