Emulate the "Flame effect" of the game DOOM. Based on: https://github.com/filipedeschamps/doom-fire-algorithm

Dependencies:   LCD_DISCO_F429ZI mbed BSP_DISCO_F429ZI STM32F4_RNG

Committer:
agaelema
Date:
Thu Jan 24 01:30:04 2019 +0000
Revision:
0:5d90a43149b1
Child:
1:739609be634c
Emulate in realtime the "Flame effect" of the game DOOM.; ; Based on: https://github.com/filipedeschamps/doom-fire-algorithm

Who changed what in which revision?

UserRevisionLine numberNew contents of line
agaelema 0:5d90a43149b1 1 /*********************************************************************
agaelema 0:5d90a43149b1 2 * Based on: https://github.com/filipedeschamps/doom-fire-algorithm
agaelema 0:5d90a43149b1 3 * modified by: Haroldo Amaral - http://bit.ly/haroldo_github
agaelema 0:5d90a43149b1 4 *********************************************************************/
agaelema 0:5d90a43149b1 5
agaelema 0:5d90a43149b1 6 #include "mbed.h"
agaelema 0:5d90a43149b1 7 #include "LCD_DISCO_F429ZI.h"
agaelema 0:5d90a43149b1 8 #include "STM32F4_RNG.h"
agaelema 0:5d90a43149b1 9
agaelema 0:5d90a43149b1 10 LCD_DISCO_F429ZI lcd; // declare lcd class
agaelema 0:5d90a43149b1 11
agaelema 0:5d90a43149b1 12 STM32F4_RNG rnd; // declare random number class (use internal HW)
agaelema 0:5d90a43149b1 13
agaelema 0:5d90a43149b1 14 DigitalOut led1(LED1); // declare GPIO class (output)
agaelema 0:5d90a43149b1 15
agaelema 0:5d90a43149b1 16 Serial pc(USBTX, USBRX); // declare serial class (UART)
agaelema 0:5d90a43149b1 17
agaelema 0:5d90a43149b1 18 //#define ENABLE_DEBUGMATRIX // uncomment to enable matrix debug via UART
agaelema 0:5d90a43149b1 19
agaelema 0:5d90a43149b1 20
agaelema 0:5d90a43149b1 21 #define PALETTESIZE (sizeof(ColorPalette)/sizeof(uint32_t))
agaelema 0:5d90a43149b1 22
agaelema 0:5d90a43149b1 23 #define ROWS 40 // numeber of lines
agaelema 0:5d90a43149b1 24 #define COLS 40 // number of columns
agaelema 0:5d90a43149b1 25 #define MATRIXSIZE (ROWS*COLS) // number os vector (cells)
agaelema 0:5d90a43149b1 26
agaelema 0:5d90a43149b1 27 #define PIXELSIZE 4 // size of pixel
agaelema 0:5d90a43149b1 28
agaelema 0:5d90a43149b1 29 uint8_t FlameMatrix[ROWS*COLS];
agaelema 0:5d90a43149b1 30
agaelema 0:5d90a43149b1 31 uint32_t ColorPalette[] =
agaelema 0:5d90a43149b1 32 {
agaelema 0:5d90a43149b1 33 0xFF070707, //{"r":7,"g":7,"b":7}
agaelema 0:5d90a43149b1 34 0xFF1F0707, //{"r":31,"g":7,"b":7}
agaelema 0:5d90a43149b1 35 0xFF2F0F07, //{"r":47,"g":15,"b":7}
agaelema 0:5d90a43149b1 36 0xFF470F07, //{"r":71,"g":15,"b":7}
agaelema 0:5d90a43149b1 37 0xFF571707, //{"r":87,"g":23,"b":7}
agaelema 0:5d90a43149b1 38 0xFF671F07, //{"r":103,"g":31,"b":7}
agaelema 0:5d90a43149b1 39 0xFF771F07, //{"r":119,"g":31,"b":7}
agaelema 0:5d90a43149b1 40 0xFF8F2707, //{"r":143,"g":39,"b":7}
agaelema 0:5d90a43149b1 41 0xFF9F2F07, //{"r":159,"g":47,"b":7}
agaelema 0:5d90a43149b1 42 0xFFAF3F07, //{"r":175,"g":63,"b":7}
agaelema 0:5d90a43149b1 43 0xFFBF4707, //{"r":191,"g":71,"b":7}
agaelema 0:5d90a43149b1 44 0xFFC74707, //{"r":199,"g":71,"b":7}
agaelema 0:5d90a43149b1 45 0xFFDF4707, //{"r":223,"g":79,"b":7}
agaelema 0:5d90a43149b1 46 0xFFDF5707, //{"r":223,"g":87,"b":7}
agaelema 0:5d90a43149b1 47 0xFFDF5707, //{"r":223,"g":87,"b":7}
agaelema 0:5d90a43149b1 48 0xFFD75F07, //{"r":215,"g":95,"b":7}
agaelema 0:5d90a43149b1 49 0xFFD75F07, //{"r":215,"g":95,"b":7}
agaelema 0:5d90a43149b1 50 0xFFD7670F, //{"r":215,"g":103,"b":15}
agaelema 0:5d90a43149b1 51 0xFFCF6F0F, //{"r":207,"g":111,"b":15}
agaelema 0:5d90a43149b1 52 0xFFCF770F, //{"r":207,"g":119,"b":15}
agaelema 0:5d90a43149b1 53 0xFFCF7F0F, //{"r":207,"g":127,"b":15}
agaelema 0:5d90a43149b1 54 0xFFCF8717, //{"r":207,"g":135,"b":23}
agaelema 0:5d90a43149b1 55 0xFFC78717, //{"r":199,"g":135,"b":23}
agaelema 0:5d90a43149b1 56 0xFFC78F17, //{"r":199,"g":143,"b":23}
agaelema 0:5d90a43149b1 57 0xFFC7971F, //{"r":199,"g":151,"b":31}
agaelema 0:5d90a43149b1 58 0xFFBF9F1F, //{"r":191,"g":159,"b":31}
agaelema 0:5d90a43149b1 59 0xFFBF9F1F, //{"r":191,"g":159,"b":31}
agaelema 0:5d90a43149b1 60 0xFFBFA727, //{"r":191,"g":167,"b":39}
agaelema 0:5d90a43149b1 61 0xFFBFA727, //{"r":191,"g":167,"b":39}
agaelema 0:5d90a43149b1 62 0xFFBFAF2F, //{"r":191,"g":175,"b":47}
agaelema 0:5d90a43149b1 63 0xFFB7AF2F, //{"r":183,"g":175,"b":47}
agaelema 0:5d90a43149b1 64 0xFFB7B72F, //{"r":183,"g":183,"b":47}
agaelema 0:5d90a43149b1 65 0xFFB7B737, //{"r":183,"g":183,"b":55}
agaelema 0:5d90a43149b1 66 0xFFCFCF6F, //{"r":207,"g":207,"b":111}
agaelema 0:5d90a43149b1 67 0xFFDFDF9F, //{"r":223,"g":223,"b":159}
agaelema 0:5d90a43149b1 68 0xFFEFEFC7, //{"r":239,"g":239,"b":199}
agaelema 0:5d90a43149b1 69 0xFFFFFFFF, //{"r":255,"g":255,"b":255}
agaelema 0:5d90a43149b1 70 };
agaelema 0:5d90a43149b1 71
agaelema 0:5d90a43149b1 72
agaelema 0:5d90a43149b1 73 /*********************************************************************
agaelema 0:5d90a43149b1 74 * Prototype of functions
agaelema 0:5d90a43149b1 75 *********************************************************************/
agaelema 0:5d90a43149b1 76 void fillWithZeros(uint8_t *ptrMatrix, uint32_t size);
agaelema 0:5d90a43149b1 77 void createFireSource(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, uint32_t fireIntensity);
agaelema 0:5d90a43149b1 78 void drawFlames(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, uint32_t pixelSize);
agaelema 0:5d90a43149b1 79 void calculateFirePropagation(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, int32_t randAtt, int32_t wind);
agaelema 0:5d90a43149b1 80
agaelema 0:5d90a43149b1 81 void debugMatrix(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols);
agaelema 0:5d90a43149b1 82
agaelema 0:5d90a43149b1 83
agaelema 0:5d90a43149b1 84 int main()
agaelema 0:5d90a43149b1 85 {
agaelema 0:5d90a43149b1 86 led1 = 1; // set LED
agaelema 0:5d90a43149b1 87
agaelema 0:5d90a43149b1 88 uint8_t *matrixPtr; // pointer to matrix
agaelema 0:5d90a43149b1 89 matrixPtr = FlameMatrix;
agaelema 0:5d90a43149b1 90
agaelema 0:5d90a43149b1 91 lcd.Clear(LCD_COLOR_BLACK); // fill lcd with black color
agaelema 0:5d90a43149b1 92
agaelema 0:5d90a43149b1 93 fillWithZeros(matrixPtr, MATRIXSIZE); // fill matrix with zeros
agaelema 0:5d90a43149b1 94 #if defined (ENABLE_DEBUGMATRIX)
agaelema 0:5d90a43149b1 95 debugMatrix(matrixPtr, ROWS, COLS);
agaelema 0:5d90a43149b1 96 #endif
agaelema 0:5d90a43149b1 97
agaelema 0:5d90a43149b1 98 /*
agaelema 0:5d90a43149b1 99 * create firesource
agaelema 0:5d90a43149b1 100 * - matrix -> pointer to fire matrix
agaelema 0:5d90a43149b1 101 * - rows -> number of lines
agaelema 0:5d90a43149b1 102 * - cols -> number of columns
agaelema 0:5d90a43149b1 103 * - fireIntensity -> intensity of source
agaelema 0:5d90a43149b1 104 */
agaelema 0:5d90a43149b1 105 createFireSource(matrixPtr, ROWS, COLS, 36);
agaelema 0:5d90a43149b1 106 #if defined (ENABLE_DEBUGMATRIX)
agaelema 0:5d90a43149b1 107 debugMatrix(matrixPtr, ROWS, COLS);
agaelema 0:5d90a43149b1 108 #endif
agaelema 0:5d90a43149b1 109
agaelema 0:5d90a43149b1 110 while(1)
agaelema 0:5d90a43149b1 111 {
agaelema 0:5d90a43149b1 112 /*
agaelema 0:5d90a43149b1 113 * merge functions "calculateFirePropagation" and "updateFireIntensityPerPixel"
agaelema 0:5d90a43149b1 114 * - matrix -> pointer to fire matrix
agaelema 0:5d90a43149b1 115 * - rows -> number of lines
agaelema 0:5d90a43149b1 116 * - cols -> number of columns
agaelema 0:5d90a43149b1 117 * - randAtt -> attenuation of randomness
agaelema 0:5d90a43149b1 118 * - wind -> negative number (left), positive (right), zero (no wind)
agaelema 0:5d90a43149b1 119 */
agaelema 0:5d90a43149b1 120 calculateFirePropagation(matrixPtr, ROWS, COLS, 3 , -3);
agaelema 0:5d90a43149b1 121
agaelema 0:5d90a43149b1 122 drawFlames(matrixPtr, ROWS, COLS, PIXELSIZE);
agaelema 0:5d90a43149b1 123
agaelema 0:5d90a43149b1 124 wait(0.05);
agaelema 0:5d90a43149b1 125 led1 = (led1 ^ 1);
agaelema 0:5d90a43149b1 126 }
agaelema 0:5d90a43149b1 127 }
agaelema 0:5d90a43149b1 128
agaelema 0:5d90a43149b1 129
agaelema 0:5d90a43149b1 130
agaelema 0:5d90a43149b1 131
agaelema 0:5d90a43149b1 132 void fillWithZeros(uint8_t *ptrMatrix, uint32_t size)
agaelema 0:5d90a43149b1 133 {
agaelema 0:5d90a43149b1 134 uint32_t counter;
agaelema 0:5d90a43149b1 135
agaelema 0:5d90a43149b1 136 for (counter = 0; counter < size; counter++)
agaelema 0:5d90a43149b1 137 {
agaelema 0:5d90a43149b1 138 *(ptrMatrix+counter) = 0;
agaelema 0:5d90a43149b1 139 // pc.printf("Cl = %u \r\n", counter);
agaelema 0:5d90a43149b1 140 }
agaelema 0:5d90a43149b1 141 }
agaelema 0:5d90a43149b1 142
agaelema 0:5d90a43149b1 143 void createFireSource(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, uint32_t fireIntensity)
agaelema 0:5d90a43149b1 144 {
agaelema 0:5d90a43149b1 145 uint32_t lasRow = rows*cols - cols;
agaelema 0:5d90a43149b1 146 uint32_t counter;
agaelema 0:5d90a43149b1 147
agaelema 0:5d90a43149b1 148 if (fireIntensity > 36) fireIntensity = 36;
agaelema 0:5d90a43149b1 149
agaelema 0:5d90a43149b1 150 for (counter = 0; counter < cols; counter++) // in each cell
agaelema 0:5d90a43149b1 151 {
agaelema 0:5d90a43149b1 152 ptrMatrix[lasRow + counter] = fireIntensity;
agaelema 0:5d90a43149b1 153 // pc.printf("Fs %u = %u \r\n", lasRow + counter, fireIntensity);
agaelema 0:5d90a43149b1 154 }
agaelema 0:5d90a43149b1 155 }
agaelema 0:5d90a43149b1 156
agaelema 0:5d90a43149b1 157 void drawFlames(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, uint32_t pixelSize)
agaelema 0:5d90a43149b1 158 {
agaelema 0:5d90a43149b1 159 uint32_t rowCounter = 0;
agaelema 0:5d90a43149b1 160 uint32_t colCounter = 0;
agaelema 0:5d90a43149b1 161
agaelema 0:5d90a43149b1 162 for (rowCounter = 0; rowCounter < rows; rowCounter++) // in each line
agaelema 0:5d90a43149b1 163 {
agaelema 0:5d90a43149b1 164 for (colCounter = 0; colCounter < cols; colCounter++) // in each column
agaelema 0:5d90a43149b1 165 {
agaelema 0:5d90a43149b1 166 lcd.SetTextColor( ColorPalette[*(ptrMatrix + rowCounter*cols + colCounter)] );
agaelema 0:5d90a43149b1 167 lcd.FillRect(pixelSize*colCounter, pixelSize*rowCounter, pixelSize, pixelSize);
agaelema 0:5d90a43149b1 168 }
agaelema 0:5d90a43149b1 169 }
agaelema 0:5d90a43149b1 170 }
agaelema 0:5d90a43149b1 171
agaelema 0:5d90a43149b1 172 void calculateFirePropagation(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols, int32_t randAtt, int32_t wind)
agaelema 0:5d90a43149b1 173 {
agaelema 0:5d90a43149b1 174 uint32_t rowCounter = 0;
agaelema 0:5d90a43149b1 175 uint32_t colCounter = 0;
agaelema 0:5d90a43149b1 176 int32_t currentIndex;
agaelema 0:5d90a43149b1 177
agaelema 0:5d90a43149b1 178 for (colCounter = 0; colCounter < cols; colCounter++) // in each column
agaelema 0:5d90a43149b1 179 {
agaelema 0:5d90a43149b1 180 for (rowCounter = 0; rowCounter < rows - 1; rowCounter++) // in each line
agaelema 0:5d90a43149b1 181 {
agaelema 0:5d90a43149b1 182 float random = (float)rnd.Get()/0xFFFFFFFF; // calculate a random number between 0-1
agaelema 0:5d90a43149b1 183 int32_t decay = (int32_t)(random * randAtt); // calculate decay
agaelema 0:5d90a43149b1 184
agaelema 0:5d90a43149b1 185 /*
agaelema 0:5d90a43149b1 186 * calculate the current index considering the randomness
agaelema 0:5d90a43149b1 187 */
agaelema 0:5d90a43149b1 188 currentIndex = rowCounter*cols + colCounter + (int32_t)(random * wind);
agaelema 0:5d90a43149b1 189 if (currentIndex < 0) currentIndex = 0; // avoid exit the matrix
agaelema 0:5d90a43149b1 190
agaelema 0:5d90a43149b1 191 int32_t temp = *(ptrMatrix + (rowCounter+1)*cols + colCounter) - decay;
agaelema 0:5d90a43149b1 192 *(ptrMatrix + currentIndex) = (temp <=0) ? 0 : temp; // avoid nonexistent palette color
agaelema 0:5d90a43149b1 193 }
agaelema 0:5d90a43149b1 194 }
agaelema 0:5d90a43149b1 195 }
agaelema 0:5d90a43149b1 196
agaelema 0:5d90a43149b1 197
agaelema 0:5d90a43149b1 198 void debugMatrix(uint8_t *ptrMatrix, uint32_t rows, uint32_t cols)
agaelema 0:5d90a43149b1 199 {
agaelema 0:5d90a43149b1 200 uint32_t rowCounter = 0;
agaelema 0:5d90a43149b1 201 uint32_t colCounter = 0;
agaelema 0:5d90a43149b1 202
agaelema 0:5d90a43149b1 203 pc.printf("\r\n debug matrix linear \r\n");
agaelema 0:5d90a43149b1 204
agaelema 0:5d90a43149b1 205 for (colCounter = 0; colCounter < cols*rows; colCounter++)
agaelema 0:5d90a43149b1 206 {
agaelema 0:5d90a43149b1 207 pc.printf("%02d ", *(ptrMatrix + colCounter));
agaelema 0:5d90a43149b1 208 }
agaelema 0:5d90a43149b1 209 pc.printf("\r\n");
agaelema 0:5d90a43149b1 210
agaelema 0:5d90a43149b1 211 pc.printf("\r\n debug matrix form \r\n");
agaelema 0:5d90a43149b1 212 for (rowCounter = 0; rowCounter < rows; rowCounter++)
agaelema 0:5d90a43149b1 213 {
agaelema 0:5d90a43149b1 214 for (colCounter = 0; colCounter < cols; colCounter++)
agaelema 0:5d90a43149b1 215 {
agaelema 0:5d90a43149b1 216 pc.printf("%02d-%02d-%02d ", *(ptrMatrix + rowCounter*cols + colCounter), rowCounter*cols, colCounter);
agaelema 0:5d90a43149b1 217 }
agaelema 0:5d90a43149b1 218 pc.printf("\r\n");
agaelema 0:5d90a43149b1 219 }
agaelema 0:5d90a43149b1 220 }