You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Game of Life Memory Leak Fix + Other Changes
Fixed memory leak using new. Removed gameoflife struct and reverted back to using pointers to segenv.data (similar to starLeds version).
Added Blur slider. Blurs dead cells slowly to bgColor depending on slider instead of immediately dying. Doesn't effect game logic.
Removed confusing pauseFrames, uses .step to pause now.
Keeps track of last palette used and immediately recolors cells if new palette/color selected. Can be improved.
Changes gameSpeed slider to be more consistent. Speed = updates/second now in increments of 4.
// create game of life struct to hold cells and future cells
5168
-
structgameOfLife {
5169
-
uint8_t* cells;
5170
-
uint8_t* futureCells;
5171
-
uint8_t gliderLength;
5172
-
uint16_t oscillatorCRC;
5173
-
uint16_t spaceshipCRC;
5174
-
};
5167
+
5175
5168
uint16_tmode_2Dgameoflife(void) { // Written by Ewoud Wijma, inspired by https://natureofcode.com/book/chapter-7-cellular-automata/
5176
5169
// and https://github.com/DougHaber/nlife-color , Modified By: Brandon Butler
5177
5170
if (!strip.isMatrix) returnmode_static(); // not a 2D set-up
5178
5171
5179
5172
constuint16_t cols = SEGMENT.virtualWidth();
5180
5173
constuint16_t rows = SEGMENT.virtualHeight();
5181
-
constsize_t dataSize = (SEGMENT.length() / 8) + (((SEGMENT.length() % 8) != 0) ? 1 : 0); // add one byte when extra bits needed (length not a multiple of 8)
elseif ((!alive || aliveBgColor) && !overlayBG && !bgBlendMode) SEGMENT.setPixelColorXY(x,y, cellColor); // Redraw dead cells/alive off cells for default overlayFG
5259
+
elseif (!alive && !overlayBG && generation == 1) SEGMENT.setPixelColorXY(x,y, color_blend(cellColor, bgColor, 16)); // Fade dead cells (bgBlendMode) on generation 1
5252
5260
}
5261
+
5262
+
if (SEGENV.step > strip.now || strip.now - SEGENV.step < 1000 / (uint32_t)map(SEGMENT.speed,0,255,1,64)) return FRAMETIME; //skip if not enough time has passed (1-64 updates/sec)
5263
+
5253
5264
//Update Game of Life
5254
5265
bool cellChanged = false; // Detect still live and dead grids
5255
-
//cell index and coordinates
5256
-
uint16_t cIndex;
5266
+
//cell coordinates
5257
5267
uint16_t cX;
5258
5268
uint16_t cY;
5259
5269
//Loop through all cells. Count neighbors, apply rules, setPixel
5260
5270
for (int x = 0; x < cols; x++) for (int y = 0; y < rows; y++) {
5261
5271
byte neighbors = 0;
5262
5272
byte colorCount = 0; //track number of valid colors
5263
-
CRGB nColors[3]; // track 3 colors, dying cells may overwrite but this wont be used
5273
+
uint32_t nColors[3]; // track 3 colors, dying cells may overwrite but this wont be used
5264
5274
5265
5275
for (int i = -1; i <= 1; i++) for (int j = -1; j <= 1; j++) { // iterate through 3*3 matrix
5266
-
if (i==0 && j==0) continue; // ignore itself
5267
-
if (!SEGMENT.check3 || generation % 1500 == 0) { //no wrap disable wrap every 1500 generations to prevent undetected repeats
5268
-
cX = x+i;
5269
-
cY = y+j;
5276
+
if (i == 0 && j == 0) continue; // ignore itself
5277
+
if (!wrap || generation % 1500 == 0 || aliveCount == 5) { //no wrap, disable wrap every 1500 generations to prevent undetected repeats
5278
+
cX = x + i;
5279
+
cY = y + j;
5270
5280
if (cX < 0 || cY < 0 || cX >= cols || cY >= rows) continue; //skip if out of bounds
5271
5281
} else { //wrap around
5272
-
cX = (x+i+cols) % cols;
5273
-
cY = (y+j+rows) % rows;
5282
+
cX = (x + i + cols) % cols;
5283
+
cY = (y + j + rows) % rows;
5274
5284
}
5275
-
cIndex = cY * cols + cX;
5285
+
cIndex = cY * cols + cX;//neighbor cell index
5276
5286
// count neighbors and store upto 3 neighbor colors
5277
-
if (getBitValue(gol->cells, cIndex)) { //if alive
5287
+
if (getBitValue(cells, cIndex)) { //if alive
5278
5288
neighbors++;
5289
+
if (!getBitValue(futureCells, cIndex) || SEGMENT.getPixelColorXY(cX,cY) == bgColor) continue; //parent just died, color lost
5279
5290
color = SEGMENT.getPixelColorXY(cX, cY);
5280
-
if (color == backgroundColor) continue; //parent just died, color lost
5281
-
nColors[colorCount%3] = color;
5291
+
nColors[colorCount % 3] = color;
5282
5292
colorCount++;
5283
5293
}
5284
5294
}
5285
5295
5286
5296
// Rules of Life
5287
-
bool cellValue = getBitValue(gol->cells, y * cols + x);
if (!cellChanged || crc == gol->oscillatorCRC || crc == gol->spaceshipCRC) repetition = true; //check if cell changed this gen and compare previous stored crc values
5335
+
if (!cellChanged || crc == *oscillatorCRC || crc == *spaceshipCRC) repetition = true; //check if cell changed this gen and compare previous stored crc values
5324
5336
if (repetition) {
5325
-
generation = 0; // reset on next call
5326
-
pauseFrames = 50;
5337
+
generation = 0; // reset on next call
5338
+
SEGENV.step += 1000; // pause final generation for 1 second
5327
5339
return FRAMETIME;
5328
5340
}
5329
5341
// Update CRC values
5330
-
if (generation % 16 == 0) gol->oscillatorCRC = crc;
5331
-
if (generation % gol->gliderLength == 0) gol->spaceshipCRC = crc;
0 commit comments