Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: LCD_DISCO_F429ZI mbed TS_DISCO_F429ZI mbed-os BSP_DISCO_F429ZI
SecurityUnlockDemo-Animation.cpp@5:5c507689ae66, 2019-06-05 (annotated)
- Committer:
- Damotclese
- Date:
- Wed Jun 05 02:27:51 2019 +0000
- Revision:
- 5:5c507689ae66
- Parent:
- 4:5c70a30d6757
I put a pizza BMP on the screen;
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| Damotclese | 1:316582aec4fb | 1 | |
| Damotclese | 1:316582aec4fb | 2 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 3 | // SecurityUnlockDemo-Animation.cpp |
| Damotclese | 1:316582aec4fb | 4 | // |
| Damotclese | 1:316582aec4fb | 5 | // Fredric L. Rice, June 2019 |
| Damotclese | 1:316582aec4fb | 6 | // |
| Damotclese | 2:444eeedb41f0 | 7 | // This module draws a mushroom on the display and then animates it as |
| Damotclese | 2:444eeedb41f0 | 8 | // the mushroom moves around "randomly." Every 10 moves or so it will |
| Damotclese | 2:444eeedb41f0 | 9 | // "teleport" to a "random" place on the screen. |
| Damotclese | 2:444eeedb41f0 | 10 | // |
| Damotclese | 2:444eeedb41f0 | 11 | // The random number generator provided by mbed is not very good |
| Damotclese | 2:444eeedb41f0 | 12 | // so we attempt to use the analog inputs on PF_3, PF_4, PF_5 to help |
| Damotclese | 2:444eeedb41f0 | 13 | // drive some randomness. |
| Damotclese | 2:444eeedb41f0 | 14 | // |
| Damotclese | 3:0e554d8d5a19 | 15 | // Conceivably more than one sprite could be animated merely by |
| Damotclese | 3:0e554d8d5a19 | 16 | // making some of the data elements arrays -- and of course using C++ |
| Damotclese | 3:0e554d8d5a19 | 17 | // to instantiate objects and then animating them is the correct way |
| Damotclese | 3:0e554d8d5a19 | 18 | // to do such things. This is a concept demonstration projjct, so we |
| Damotclese | 3:0e554d8d5a19 | 19 | // do not expect to make a proper class and allow any number of them |
| Damotclese | 3:0e554d8d5a19 | 20 | // to be instantiated and get automated. |
| Damotclese | 3:0e554d8d5a19 | 21 | // |
| Damotclese | 3:0e554d8d5a19 | 22 | // That would be neat but that's something for another project. |
| Damotclese | 3:0e554d8d5a19 | 23 | // |
| Damotclese | 1:316582aec4fb | 24 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 25 | |
| Damotclese | 1:316582aec4fb | 26 | #include "mbed.h" // The mbed operating system |
| Damotclese | 1:316582aec4fb | 27 | #include "LCD_DISCO_F429ZI.h" // For controlling the LCD |
| Damotclese | 1:316582aec4fb | 28 | #include "TS_DISCO_F429ZI.h" // For controlling the touch screen |
| Damotclese | 1:316582aec4fb | 29 | #include "SecurityUnlockDemo-Main.h" // For the main module's prototypes |
| Damotclese | 1:316582aec4fb | 30 | #include "SecurityUnlockDemo-Animation.h" // Always include our own header |
| Damotclese | 1:316582aec4fb | 31 | |
| Damotclese | 1:316582aec4fb | 32 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 33 | // Describe data which is defined externally that we may access |
| Damotclese | 1:316582aec4fb | 34 | // |
| Damotclese | 1:316582aec4fb | 35 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 36 | |
| Damotclese | 1:316582aec4fb | 37 | // We may be accessing the LCD |
| Damotclese | 1:316582aec4fb | 38 | extern LCD_DISCO_F429ZI st_lcd; |
| Damotclese | 1:316582aec4fb | 39 | |
| Damotclese | 1:316582aec4fb | 40 | // We may be accessing the touch screen |
| Damotclese | 1:316582aec4fb | 41 | extern TS_DISCO_F429ZI st_touchScreen; |
| Damotclese | 1:316582aec4fb | 42 | |
| Damotclese | 1:316582aec4fb | 43 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 44 | // Define local data storage |
| Damotclese | 1:316582aec4fb | 45 | // |
| Damotclese | 1:316582aec4fb | 46 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 47 | |
| Damotclese | 1:316582aec4fb | 48 | // We define a "sprite" like entity consisting of a bit map showing |
| Damotclese | 1:316582aec4fb | 49 | // the colors of pixes that will display a mushroom which we will |
| Damotclese | 1:316582aec4fb | 50 | // move around the screen. The sprite consists of 22 pixes across |
| Damotclese | 1:316582aec4fb | 51 | // and 17 pixels down so it's a small graphic. The letters describe |
| Damotclese | 1:316582aec4fb | 52 | // the color of each pixel. |
| Damotclese | 1:316582aec4fb | 53 | static char * pau8_mushroomMap[SPRITE_HEIGHT_IN_PIXELS] = |
| Damotclese | 1:316582aec4fb | 54 | { // 1234567890123456789012 |
| Damotclese | 1:316582aec4fb | 55 | "wwwwwwwwwbbbbbbwwwwwww", // 1 |
| Damotclese | 1:316582aec4fb | 56 | "wwwwwwwbbbwggwbbbwwwww", // 2 |
| Damotclese | 1:316582aec4fb | 57 | "wwwwwwbbwwggwwwbbwwwww", // 3 |
| Damotclese | 1:316582aec4fb | 58 | "wwwwwbbgwwggggwwbbwwww", // 4 |
| Damotclese | 1:316582aec4fb | 59 | "wwwwwbwgggggggggggbwww", // 5 |
| Damotclese | 1:316582aec4fb | 60 | "wwwwbbwwggwwwwggwwbbww", // 6 |
| Damotclese | 1:316582aec4fb | 61 | "wwwwbwwwgwwwwwwgwwwbww", // 7 |
| Damotclese | 1:316582aec4fb | 62 | "wwwwbwwwgwwwwwwgwwwbww", // 8 |
| Damotclese | 1:316582aec4fb | 63 | "wwwwbwwggwwwwwwwggwwbw", // 9 |
| Damotclese | 1:316582aec4fb | 64 | "wwwwbwwggwwwwwwwggwwbw", // 10 |
| Damotclese | 1:316582aec4fb | 65 | "wwwwbgggggwwwwwgggggbw", // 11 |
| Damotclese | 1:316582aec4fb | 66 | "wwwwbggbbbbbbbbbbbggbw", // 12 |
| Damotclese | 1:316582aec4fb | 67 | "wwwwbbbbwwbwwbwwbbbbbw", // 13 |
| Damotclese | 1:316582aec4fb | 68 | "wwwwwwbwwwbwwbwwwwbwww", // 14 |
| Damotclese | 1:316582aec4fb | 69 | "wwwwwwbwwwwwwwwwwwbwww", // 15 |
| Damotclese | 1:316582aec4fb | 70 | "wwwwwwbbwwwwwwwwwbbwww", // 16 |
| Damotclese | 1:316582aec4fb | 71 | "wwwwwwwbbbbbbbbbbbwwww" |
| Damotclese | 1:316582aec4fb | 72 | } ; |
| Damotclese | 1:316582aec4fb | 73 | |
| Damotclese | 1:316582aec4fb | 74 | // There are 8 different directions that this animation supports, |
| Damotclese | 1:316582aec4fb | 75 | // the coordinate offsets to add/subtract from the current pixel |
| Damotclese | 1:316582aec4fb | 76 | // position depending upon the direction is mapped here. |
| Damotclese | 1:316582aec4fb | 77 | // |
| Damotclese | 1:316582aec4fb | 78 | // Directions: |
| Damotclese | 1:316582aec4fb | 79 | // 1 2 3 Left up, Up, Right Up |
| Damotclese | 1:316582aec4fb | 80 | // 4 6 Left, N/A, Right |
| Damotclese | 1:316582aec4fb | 81 | // 7 8 9 Right Down, Down, Right Down |
| Damotclese | 1:316582aec4fb | 82 | static int8_t i8_movementMatrix[3][6] = |
| Damotclese | 1:316582aec4fb | 83 | { |
| Damotclese | 1:316582aec4fb | 84 | -1, -1, -1, 0, -1, 1, |
| Damotclese | 1:316582aec4fb | 85 | -1, 0, 0, 0, 1, 0, |
| Damotclese | 1:316582aec4fb | 86 | -1, 1, 0, 1, 1, 1 |
| Damotclese | 1:316582aec4fb | 87 | } ; |
| Damotclese | 1:316582aec4fb | 88 | |
| Damotclese | 1:316582aec4fb | 89 | // We maintain local data indicating where the sprite was last drawn |
| Damotclese | 1:316582aec4fb | 90 | static uint16_t u16_spriteCurrentX; |
| Damotclese | 1:316582aec4fb | 91 | static uint16_t u16_spriteCurrentY; |
| Damotclese | 1:316582aec4fb | 92 | static uint8_t u8_spriteCurrentDirection; |
| Damotclese | 1:316582aec4fb | 93 | |
| Damotclese | 1:316582aec4fb | 94 | // When we are first asked to start animation, we launch |
| Damotclese | 1:316582aec4fb | 95 | // a thread to continue the animation forever |
| Damotclese | 1:316582aec4fb | 96 | static Thread st_animationThread; |
| Damotclese | 1:316582aec4fb | 97 | |
| Damotclese | 1:316582aec4fb | 98 | // To know whether animation is running, we maintain this boolean |
| Damotclese | 1:316582aec4fb | 99 | static bool b_animationThreadRunning; |
| Damotclese | 1:316582aec4fb | 100 | |
| Damotclese | 1:316582aec4fb | 101 | // After every 10 movements along a given direction, rather than |
| Damotclese | 1:316582aec4fb | 102 | // pick a direction and then move toward it we will "teleport" |
| Damotclese | 1:316582aec4fb | 103 | // the sprite to a "random" location on the screen and maintain |
| Damotclese | 1:316582aec4fb | 104 | // the direction -- unless we're up against a boundary, then a |
| Damotclese | 1:316582aec4fb | 105 | // new direction will be selected |
| Damotclese | 1:316582aec4fb | 106 | static uint8_t u8_teleportCounter; |
| Damotclese | 1:316582aec4fb | 107 | |
| Damotclese | 1:316582aec4fb | 108 | // When we teleport, we display a message indicating that/ |
| Damotclese | 1:316582aec4fb | 109 | // After about 1 second we want to remove that message from |
| Damotclese | 1:316582aec4fb | 110 | // the screen so we maintain this count down timer |
| Damotclese | 1:316582aec4fb | 111 | static uint16_t u16_teleportMessageRemovalCountDown; |
| Damotclese | 2:444eeedb41f0 | 112 | |
| Damotclese | 2:444eeedb41f0 | 113 | // In an effort to assist the random number generator we will read |
| Damotclese | 2:444eeedb41f0 | 114 | // vaues from some of the analog inputs which should be near zero |
| Damotclese | 2:444eeedb41f0 | 115 | // but perhaps not entirely |
| Damotclese | 2:444eeedb41f0 | 116 | static AnalogIn st_analog1(PF_3); |
| Damotclese | 2:444eeedb41f0 | 117 | static AnalogIn st_analog2(PF_4); |
| Damotclese | 2:444eeedb41f0 | 118 | static AnalogIn st_analog3(PF_5); |
| Damotclese | 1:316582aec4fb | 119 | |
| Damotclese | 1:316582aec4fb | 120 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 121 | // AnimationDrawSpriteAtThisLocation() |
| Damotclese | 1:316582aec4fb | 122 | // |
| Damotclese | 2:444eeedb41f0 | 123 | // This function will draw or erase the sprite at the X and Y |
| Damotclese | 2:444eeedb41f0 | 124 | // coordinate position passed to it, or it will erase the sprite |
| Damotclese | 2:444eeedb41f0 | 125 | // depending upon the argument passed to it. |
| Damotclese | 2:444eeedb41f0 | 126 | // |
| Damotclese | 2:444eeedb41f0 | 127 | // The colors that are supported are described in the sprite's |
| Damotclese | 2:444eeedb41f0 | 128 | // bit mapping. |
| Damotclese | 1:316582aec4fb | 129 | // |
| Damotclese | 4:5c70a30d6757 | 130 | // Note that we do not attempt to store the original pixel's color |
| Damotclese | 4:5c70a30d6757 | 131 | // value before writing it with a new value, so we can not restore |
| Damotclese | 4:5c70a30d6757 | 132 | // the pixel once the sprite moves off of it. This is a stark |
| Damotclese | 4:5c70a30d6757 | 133 | // divergence from real spite automation which restores the original, |
| Damotclese | 4:5c70a30d6757 | 134 | // but we are demo code, not a real project, so we don't even try. |
| Damotclese | 4:5c70a30d6757 | 135 | // |
| Damotclese | 1:316582aec4fb | 136 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 137 | static void AnimationDrawOrEraseSpriteAtThisLocation(uint16_t u16_thisX, uint16_t u16_thisY, bool b_drawSprite) |
| Damotclese | 1:316582aec4fb | 138 | { |
| Damotclese | 1:316582aec4fb | 139 | uint8_t u8_lineCount = 0; |
| Damotclese | 1:316582aec4fb | 140 | uint16_t u16_currentX = u16_thisX; |
| Damotclese | 1:316582aec4fb | 141 | uint16_t u16_currentY = u16_thisY; |
| Damotclese | 1:316582aec4fb | 142 | uint8_t u8_currentPixel = 0; |
| Damotclese | 1:316582aec4fb | 143 | uint32_t u32thisColor = LCD_COLOR_BLUE; |
| Damotclese | 1:316582aec4fb | 144 | |
| Damotclese | 1:316582aec4fb | 145 | // Record where we are placing the sprite this time |
| Damotclese | 1:316582aec4fb | 146 | u16_spriteCurrentX = u16_thisX; |
| Damotclese | 1:316582aec4fb | 147 | u16_spriteCurrentY = u16_thisY; |
| Damotclese | 1:316582aec4fb | 148 | |
| Damotclese | 1:316582aec4fb | 149 | // Place the sprite on the screen pixel by pixel |
| Damotclese | 1:316582aec4fb | 150 | for (u8_lineCount = 0; u8_lineCount < SPRITE_HEIGHT_IN_PIXELS; u8_lineCount++) |
| Damotclese | 1:316582aec4fb | 151 | { |
| Damotclese | 1:316582aec4fb | 152 | for (u8_currentPixel = 0; |
| Damotclese | 1:316582aec4fb | 153 | u8_currentPixel < strlen(pau8_mushroomMap[u8_lineCount]); |
| Damotclese | 1:316582aec4fb | 154 | u8_currentPixel++) |
| Damotclese | 1:316582aec4fb | 155 | { |
| Damotclese | 1:316582aec4fb | 156 | // Are we drawing the sprite rather than erasing it? |
| Damotclese | 1:316582aec4fb | 157 | if (true == b_drawSprite) |
| Damotclese | 1:316582aec4fb | 158 | { |
| Damotclese | 1:316582aec4fb | 159 | // Find out what the color of this pixel should be |
| Damotclese | 1:316582aec4fb | 160 | switch(pau8_mushroomMap[u8_lineCount][u8_currentPixel]) |
| Damotclese | 1:316582aec4fb | 161 | { |
| Damotclese | 1:316582aec4fb | 162 | case 'w': |
| Damotclese | 1:316582aec4fb | 163 | case 'W': |
| Damotclese | 1:316582aec4fb | 164 | { |
| Damotclese | 1:316582aec4fb | 165 | u32thisColor = LCD_COLOR_WHITE; |
| Damotclese | 1:316582aec4fb | 166 | break; |
| Damotclese | 1:316582aec4fb | 167 | } |
| Damotclese | 1:316582aec4fb | 168 | case 'b': |
| Damotclese | 1:316582aec4fb | 169 | case 'B': |
| Damotclese | 1:316582aec4fb | 170 | { |
| Damotclese | 1:316582aec4fb | 171 | u32thisColor = LCD_COLOR_BLUE; |
| Damotclese | 1:316582aec4fb | 172 | break; |
| Damotclese | 1:316582aec4fb | 173 | } |
| Damotclese | 1:316582aec4fb | 174 | case 'g': |
| Damotclese | 1:316582aec4fb | 175 | case 'G': |
| Damotclese | 1:316582aec4fb | 176 | { |
| Damotclese | 1:316582aec4fb | 177 | u32thisColor = LCD_COLOR_GREEN; |
| Damotclese | 1:316582aec4fb | 178 | break; |
| Damotclese | 1:316582aec4fb | 179 | } |
| Damotclese | 1:316582aec4fb | 180 | case 'r': |
| Damotclese | 1:316582aec4fb | 181 | case 'R': |
| Damotclese | 1:316582aec4fb | 182 | { |
| Damotclese | 1:316582aec4fb | 183 | u32thisColor = LCD_COLOR_RED; |
| Damotclese | 1:316582aec4fb | 184 | break; |
| Damotclese | 1:316582aec4fb | 185 | } |
| Damotclese | 1:316582aec4fb | 186 | case 'k': |
| Damotclese | 1:316582aec4fb | 187 | case 'K': |
| Damotclese | 1:316582aec4fb | 188 | { |
| Damotclese | 1:316582aec4fb | 189 | u32thisColor = LCD_COLOR_BLACK; |
| Damotclese | 1:316582aec4fb | 190 | break; |
| Damotclese | 1:316582aec4fb | 191 | } |
| Damotclese | 1:316582aec4fb | 192 | case 'y': |
| Damotclese | 1:316582aec4fb | 193 | case 'Y': |
| Damotclese | 1:316582aec4fb | 194 | { |
| Damotclese | 1:316582aec4fb | 195 | u32thisColor = LCD_COLOR_YELLOW; |
| Damotclese | 1:316582aec4fb | 196 | break; |
| Damotclese | 1:316582aec4fb | 197 | } |
| Damotclese | 1:316582aec4fb | 198 | } |
| Damotclese | 1:316582aec4fb | 199 | } |
| Damotclese | 1:316582aec4fb | 200 | else |
| Damotclese | 1:316582aec4fb | 201 | { |
| Damotclese | 1:316582aec4fb | 202 | // Since we are erasing the sprite, the color is white |
| Damotclese | 1:316582aec4fb | 203 | u32thisColor = LCD_COLOR_WHITE; |
| Damotclese | 1:316582aec4fb | 204 | } |
| Damotclese | 1:316582aec4fb | 205 | |
| Damotclese | 1:316582aec4fb | 206 | // Place the pixel on the screen with the correct color |
| Damotclese | 1:316582aec4fb | 207 | st_lcd.DrawPixel(u16_currentX, u16_currentY, u32thisColor); |
| Damotclese | 1:316582aec4fb | 208 | |
| Damotclese | 1:316582aec4fb | 209 | // Next pixel |
| Damotclese | 1:316582aec4fb | 210 | u16_currentX++; |
| Damotclese | 1:316582aec4fb | 211 | } |
| Damotclese | 1:316582aec4fb | 212 | |
| Damotclese | 1:316582aec4fb | 213 | // Start working on the next line |
| Damotclese | 1:316582aec4fb | 214 | u16_currentY++; |
| Damotclese | 1:316582aec4fb | 215 | |
| Damotclese | 1:316582aec4fb | 216 | u16_currentX = u16_thisX; |
| Damotclese | 1:316582aec4fb | 217 | } |
| Damotclese | 1:316582aec4fb | 218 | } |
| Damotclese | 1:316582aec4fb | 219 | |
| Damotclese | 1:316582aec4fb | 220 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 221 | // AnimationGetANewDirectionToTravel() |
| Damotclese | 1:316582aec4fb | 222 | // |
| Damotclese | 1:316582aec4fb | 223 | // We acquire a "random" direction to travel. Note that the mbed random |
| Damotclese | 1:316582aec4fb | 224 | // number generator is highly flawed, it produces the same numbers |
| Damotclese | 1:316582aec4fb | 225 | // despite how hard one seeds it. We could utilize an ununsed analog |
| Damotclese | 1:316582aec4fb | 226 | // input and use the noise that might be found there, but for purposes |
| Damotclese | 1:316582aec4fb | 227 | // of demonstrating animation, we'll just use what mben provided. |
| Damotclese | 1:316582aec4fb | 228 | // |
| Damotclese | 1:316582aec4fb | 229 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 230 | static uint8_t AnimationGetANewDirectionToTravel(void) |
| Damotclese | 1:316582aec4fb | 231 | { |
| Damotclese | 1:316582aec4fb | 232 | uint8_t u8_newDirection = 5; |
| Damotclese | 1:316582aec4fb | 233 | |
| Damotclese | 1:316582aec4fb | 234 | // Keep looking for a "random" number until one is valid |
| Damotclese | 1:316582aec4fb | 235 | while(5 == u8_newDirection || |
| Damotclese | 1:316582aec4fb | 236 | u8_newDirection < SPRITE_DIRECTION_LEFT_UP || |
| Damotclese | 1:316582aec4fb | 237 | u8_newDirection > SPRITE_DIRECTION_RIGHT_DOWN) |
| Damotclese | 1:316582aec4fb | 238 | { |
| Damotclese | 1:316582aec4fb | 239 | // Get a new direction to tavel |
| Damotclese | 1:316582aec4fb | 240 | u8_newDirection = (rand() % SPRITE_DIRECTION_RIGHT_DOWN); |
| Damotclese | 1:316582aec4fb | 241 | } |
| Damotclese | 1:316582aec4fb | 242 | |
| Damotclese | 1:316582aec4fb | 243 | // Return the new direction of travel |
| Damotclese | 1:316582aec4fb | 244 | return u8_newDirection; |
| Damotclese | 1:316582aec4fb | 245 | } |
| Damotclese | 1:316582aec4fb | 246 | |
| Damotclese | 1:316582aec4fb | 247 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 248 | // AnimationInit() |
| Damotclese | 1:316582aec4fb | 249 | // |
| Damotclese | 1:316582aec4fb | 250 | // Initializes any locally-held data and performs all other start-up |
| Damotclese | 1:316582aec4fb | 251 | // functionality required for the animated functionality, if any. |
| Damotclese | 1:316582aec4fb | 252 | // |
| Damotclese | 1:316582aec4fb | 253 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 254 | void AnimationInit(void) |
| Damotclese | 1:316582aec4fb | 255 | { |
| Damotclese | 1:316582aec4fb | 256 | // Initialize locally-held data |
| Damotclese | 1:316582aec4fb | 257 | u16_spriteCurrentX = 0; |
| Damotclese | 1:316582aec4fb | 258 | u16_spriteCurrentY = 0; |
| Damotclese | 1:316582aec4fb | 259 | b_animationThreadRunning = false; |
| Damotclese | 1:316582aec4fb | 260 | u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel(); |
| Damotclese | 1:316582aec4fb | 261 | u8_teleportCounter = 0; |
| Damotclese | 1:316582aec4fb | 262 | u16_teleportMessageRemovalCountDown = 0; |
| Damotclese | 1:316582aec4fb | 263 | } |
| Damotclese | 1:316582aec4fb | 264 | |
| Damotclese | 1:316582aec4fb | 265 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 266 | // AnimationMoveSprite() |
| Damotclese | 1:316582aec4fb | 267 | // |
| Damotclese | 2:444eeedb41f0 | 268 | // This function is the one that performs the actual move by 1 pixel |
| Damotclese | 2:444eeedb41f0 | 269 | // of the sprite. The sprite is erased from the screen and then the |
| Damotclese | 2:444eeedb41f0 | 270 | // new location is computed. If that places the sprite outside of the |
| Damotclese | 2:444eeedb41f0 | 271 | // boundaries, a new direction is selected and then the proposed |
| Damotclese | 2:444eeedb41f0 | 272 | // new location is selected. |
| Damotclese | 2:444eeedb41f0 | 273 | // |
| Damotclese | 2:444eeedb41f0 | 274 | // Once there is a new sprite location proposed, it gets re-drawn. |
| Damotclese | 1:316582aec4fb | 275 | // |
| Damotclese | 1:316582aec4fb | 276 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 277 | static void AnimationMoveSprite(void) |
| Damotclese | 1:316582aec4fb | 278 | { |
| Damotclese | 1:316582aec4fb | 279 | uint16_t u16_proposedX = u16_spriteCurrentX; |
| Damotclese | 1:316582aec4fb | 280 | uint16_t u16_proposedY = u16_spriteCurrentY; |
| Damotclese | 1:316582aec4fb | 281 | int8_t i8_proposedOffsetX = 0; |
| Damotclese | 1:316582aec4fb | 282 | int8_t i8_proposedOffsetY = 0; |
| Damotclese | 1:316582aec4fb | 283 | bool b_haveNewLocation = false; |
| Damotclese | 1:316582aec4fb | 284 | |
| Damotclese | 1:316582aec4fb | 285 | // Did we teleport and display a message indicating that we did? |
| Damotclese | 1:316582aec4fb | 286 | if (u16_teleportMessageRemovalCountDown > 0) |
| Damotclese | 1:316582aec4fb | 287 | { |
| Damotclese | 1:316582aec4fb | 288 | // Yes, so count down the timer / counter and see if it expired |
| Damotclese | 1:316582aec4fb | 289 | if (0 == --u16_teleportMessageRemovalCountDown) |
| Damotclese | 1:316582aec4fb | 290 | { |
| Damotclese | 1:316582aec4fb | 291 | // Clear the message line |
| Damotclese | 1:316582aec4fb | 292 | st_lcd.ClearStringLine(4); |
| Damotclese | 1:316582aec4fb | 293 | } |
| Damotclese | 1:316582aec4fb | 294 | } |
| Damotclese | 1:316582aec4fb | 295 | |
| Damotclese | 1:316582aec4fb | 296 | // Erase the entire sprite from where it currently exists |
| Damotclese | 1:316582aec4fb | 297 | AnimationDrawOrEraseSpriteAtThisLocation(u16_spriteCurrentX, u16_spriteCurrentY, false); |
| Damotclese | 1:316582aec4fb | 298 | |
| Damotclese | 1:316582aec4fb | 299 | // We loop until we have a new location to move the sprite to. |
| Damotclese | 1:316582aec4fb | 300 | // We look for a valid location more than once since we may |
| Damotclese | 1:316582aec4fb | 301 | // run in to a boundary and have to change our direction of travel |
| Damotclese | 1:316582aec4fb | 302 | while(false == b_haveNewLocation) |
| Damotclese | 1:316582aec4fb | 303 | { |
| Damotclese | 1:316582aec4fb | 304 | // Compute the new location of the sprite |
| Damotclese | 1:316582aec4fb | 305 | switch(u8_spriteCurrentDirection) |
| Damotclese | 1:316582aec4fb | 306 | { |
| Damotclese | 1:316582aec4fb | 307 | // Extract the proposed offsets for X and Y |
| Damotclese | 1:316582aec4fb | 308 | case SPRITE_DIRECTION_LEFT_UP: |
| Damotclese | 1:316582aec4fb | 309 | { |
| Damotclese | 1:316582aec4fb | 310 | i8_proposedOffsetX = i8_movementMatrix[0][0]; |
| Damotclese | 1:316582aec4fb | 311 | i8_proposedOffsetY = i8_movementMatrix[0][1]; |
| Damotclese | 1:316582aec4fb | 312 | break; |
| Damotclese | 1:316582aec4fb | 313 | } |
| Damotclese | 1:316582aec4fb | 314 | case SPRITE_DIRECTION_UP: |
| Damotclese | 1:316582aec4fb | 315 | { |
| Damotclese | 1:316582aec4fb | 316 | i8_proposedOffsetX = i8_movementMatrix[0][2]; |
| Damotclese | 1:316582aec4fb | 317 | i8_proposedOffsetY = i8_movementMatrix[0][3]; |
| Damotclese | 1:316582aec4fb | 318 | break; |
| Damotclese | 1:316582aec4fb | 319 | } |
| Damotclese | 1:316582aec4fb | 320 | case SPRITE_DIRECTION_RIGHT_UP: |
| Damotclese | 1:316582aec4fb | 321 | { |
| Damotclese | 1:316582aec4fb | 322 | i8_proposedOffsetX = i8_movementMatrix[0][4]; |
| Damotclese | 1:316582aec4fb | 323 | i8_proposedOffsetY = i8_movementMatrix[0][5]; |
| Damotclese | 1:316582aec4fb | 324 | break; |
| Damotclese | 1:316582aec4fb | 325 | } |
| Damotclese | 1:316582aec4fb | 326 | case SPRITE_DIRECTION_LEFT: |
| Damotclese | 1:316582aec4fb | 327 | { |
| Damotclese | 1:316582aec4fb | 328 | i8_proposedOffsetX = i8_movementMatrix[1][0]; |
| Damotclese | 1:316582aec4fb | 329 | i8_proposedOffsetY = i8_movementMatrix[1][1]; |
| Damotclese | 1:316582aec4fb | 330 | break; |
| Damotclese | 1:316582aec4fb | 331 | } |
| Damotclese | 1:316582aec4fb | 332 | case SPRITE_DIRECTION_RIGHT: |
| Damotclese | 1:316582aec4fb | 333 | { |
| Damotclese | 1:316582aec4fb | 334 | i8_proposedOffsetX = i8_movementMatrix[1][4]; |
| Damotclese | 1:316582aec4fb | 335 | i8_proposedOffsetY = i8_movementMatrix[1][5]; |
| Damotclese | 1:316582aec4fb | 336 | break; |
| Damotclese | 1:316582aec4fb | 337 | } |
| Damotclese | 1:316582aec4fb | 338 | default: |
| Damotclese | 1:316582aec4fb | 339 | case SPRITE_DIRECTION_NOT_VALID: |
| Damotclese | 1:316582aec4fb | 340 | { |
| Damotclese | 1:316582aec4fb | 341 | // We should never be able to get here |
| Damotclese | 1:316582aec4fb | 342 | return; |
| Damotclese | 1:316582aec4fb | 343 | } |
| Damotclese | 1:316582aec4fb | 344 | case SPRITE_DIRECTION_LEFT_DOWN: |
| Damotclese | 1:316582aec4fb | 345 | { |
| Damotclese | 1:316582aec4fb | 346 | i8_proposedOffsetX = i8_movementMatrix[2][0]; |
| Damotclese | 1:316582aec4fb | 347 | i8_proposedOffsetY = i8_movementMatrix[2][1]; |
| Damotclese | 1:316582aec4fb | 348 | break; |
| Damotclese | 1:316582aec4fb | 349 | } |
| Damotclese | 1:316582aec4fb | 350 | case SPRITE_DIRECTION_DOWN: |
| Damotclese | 1:316582aec4fb | 351 | { |
| Damotclese | 1:316582aec4fb | 352 | i8_proposedOffsetX = i8_movementMatrix[2][2]; |
| Damotclese | 1:316582aec4fb | 353 | i8_proposedOffsetY = i8_movementMatrix[2][3]; |
| Damotclese | 1:316582aec4fb | 354 | break; |
| Damotclese | 1:316582aec4fb | 355 | } |
| Damotclese | 1:316582aec4fb | 356 | case SPRITE_DIRECTION_RIGHT_DOWN: |
| Damotclese | 1:316582aec4fb | 357 | { |
| Damotclese | 1:316582aec4fb | 358 | i8_proposedOffsetX = i8_movementMatrix[2][4]; |
| Damotclese | 1:316582aec4fb | 359 | i8_proposedOffsetY = i8_movementMatrix[2][5]; |
| Damotclese | 1:316582aec4fb | 360 | break; |
| Damotclese | 1:316582aec4fb | 361 | } |
| Damotclese | 1:316582aec4fb | 362 | } |
| Damotclese | 1:316582aec4fb | 363 | |
| Damotclese | 1:316582aec4fb | 364 | // Apply the proposed offsets to the proposed new coordinates |
| Damotclese | 1:316582aec4fb | 365 | u16_proposedX += i8_proposedOffsetX; |
| Damotclese | 1:316582aec4fb | 366 | u16_proposedY += i8_proposedOffsetY; |
| Damotclese | 1:316582aec4fb | 367 | |
| Damotclese | 1:316582aec4fb | 368 | // Are the proposed coordinates within the bounds of where we |
| Damotclese | 1:316582aec4fb | 369 | // want the sprite to move within? |
| Damotclese | 1:316582aec4fb | 370 | if (u16_proposedX < SPRITE_MINIMUM_X || u16_proposedX > SPRITE_MAXIMUM_X || |
| Damotclese | 1:316582aec4fb | 371 | u16_proposedY < SPRITE_MINIMUM_Y || u16_proposedY > SPRITE_MAXIMUM_Y) |
| Damotclese | 1:316582aec4fb | 372 | { |
| Damotclese | 1:316582aec4fb | 373 | // We have encountered a boundary so we must choose |
| Damotclese | 1:316582aec4fb | 374 | // a new location and then try again |
| Damotclese | 1:316582aec4fb | 375 | u8_spriteCurrentDirection = AnimationGetANewDirectionToTravel(); |
| Damotclese | 1:316582aec4fb | 376 | |
| Damotclese | 1:316582aec4fb | 377 | // Increment the teleport counter and see if it's time to teleport |
| Damotclese | 1:316582aec4fb | 378 | if (++u8_teleportCounter == 10) |
| Damotclese | 1:316582aec4fb | 379 | { |
| Damotclese | 1:316582aec4fb | 380 | // It is time to teleport, pick a new "random" location |
| Damotclese | 1:316582aec4fb | 381 | u16_proposedX = (rand() % LCD_WIDTH); |
| Damotclese | 1:316582aec4fb | 382 | u16_proposedY = (rand() % LCD_HEIGHT); |
| Damotclese | 1:316582aec4fb | 383 | |
| Damotclese | 1:316582aec4fb | 384 | // Start counting for the next teleport |
| Damotclese | 1:316582aec4fb | 385 | u8_teleportCounter = 0; |
| Damotclese | 1:316582aec4fb | 386 | |
| Damotclese | 1:316582aec4fb | 387 | // Report that we teleported! |
| Damotclese | 1:316582aec4fb | 388 | st_lcd.DisplayStringAt(1, LINE(4), (uint8_t *)"Teleported!", CENTER_MODE); |
| Damotclese | 1:316582aec4fb | 389 | |
| Damotclese | 1:316582aec4fb | 390 | // After a while we will remove that message so this is a timer/counter |
| Damotclese | 1:316582aec4fb | 391 | u16_teleportMessageRemovalCountDown = 40; |
| Damotclese | 1:316582aec4fb | 392 | } |
| Damotclese | 1:316582aec4fb | 393 | else |
| Damotclese | 1:316582aec4fb | 394 | { |
| Damotclese | 1:316582aec4fb | 395 | // Start over from where we currently are |
| Damotclese | 1:316582aec4fb | 396 | u16_proposedX = u16_spriteCurrentX; |
| Damotclese | 1:316582aec4fb | 397 | u16_proposedY = u16_spriteCurrentY; |
| Damotclese | 1:316582aec4fb | 398 | } |
| Damotclese | 1:316582aec4fb | 399 | |
| Damotclese | 1:316582aec4fb | 400 | // Try for a new location |
| Damotclese | 1:316582aec4fb | 401 | continue; |
| Damotclese | 1:316582aec4fb | 402 | } |
| Damotclese | 1:316582aec4fb | 403 | |
| Damotclese | 1:316582aec4fb | 404 | // We have a new proposed location |
| Damotclese | 1:316582aec4fb | 405 | b_haveNewLocation = true; |
| Damotclese | 1:316582aec4fb | 406 | } |
| Damotclese | 1:316582aec4fb | 407 | |
| Damotclese | 1:316582aec4fb | 408 | // Place the sprite at the new location |
| Damotclese | 1:316582aec4fb | 409 | AnimationDrawOrEraseSpriteAtThisLocation(u16_proposedX, u16_proposedY, true); |
| Damotclese | 1:316582aec4fb | 410 | } |
| Damotclese | 1:316582aec4fb | 411 | |
| Damotclese | 1:316582aec4fb | 412 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 413 | // AnimationThread() |
| Damotclese | 1:316582aec4fb | 414 | // |
| Damotclese | 2:444eeedb41f0 | 415 | // This is the main thread for the animation functionality. The thread |
| Damotclese | 2:444eeedb41f0 | 416 | // usually runs forever however there is a mechanism for terminating |
| Damotclese | 2:444eeedb41f0 | 417 | // it provided in this module. |
| Damotclese | 2:444eeedb41f0 | 418 | // |
| Damotclese | 2:444eeedb41f0 | 419 | // The thread wakes up about 40 times a second so that the animation |
| Damotclese | 2:444eeedb41f0 | 420 | // can move fairly quickly and smoothly. |
| Damotclese | 1:316582aec4fb | 421 | // |
| Damotclese | 1:316582aec4fb | 422 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 423 | void AnimationThread(void) |
| Damotclese | 1:316582aec4fb | 424 | { |
| Damotclese | 1:316582aec4fb | 425 | // This thread will run until it gets terminated upon request |
| Damotclese | 1:316582aec4fb | 426 | while(true) |
| Damotclese | 1:316582aec4fb | 427 | { |
| Damotclese | 1:316582aec4fb | 428 | // Wake up 40 times a second |
| Damotclese | 1:316582aec4fb | 429 | wait(0.025); |
| Damotclese | 1:316582aec4fb | 430 | |
| Damotclese | 1:316582aec4fb | 431 | // Move ths sprite in the cirrent direction of travel |
| Damotclese | 1:316582aec4fb | 432 | AnimationMoveSprite(); |
| Damotclese | 1:316582aec4fb | 433 | } |
| Damotclese | 1:316582aec4fb | 434 | } |
| Damotclese | 1:316582aec4fb | 435 | |
| Damotclese | 1:316582aec4fb | 436 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 437 | // AnimationPerformAnimation() |
| Damotclese | 1:316582aec4fb | 438 | // |
| Damotclese | 2:444eeedb41f0 | 439 | // This function is called when it is time to start animating the |
| Damotclese | 2:444eeedb41f0 | 440 | // sprite. It checks to make sure that the animation thread is not |
| Damotclese | 2:444eeedb41f0 | 441 | // yet started before it starts the animation. |
| Damotclese | 1:316582aec4fb | 442 | // |
| Damotclese | 1:316582aec4fb | 443 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 444 | void AnimationPerformAnimation(uint32_t u32_randomSeeder) |
| Damotclese | 1:316582aec4fb | 445 | { |
| Damotclese | 1:316582aec4fb | 446 | // Are we currently not running the animation? |
| Damotclese | 1:316582aec4fb | 447 | if (false == b_animationThreadRunning) |
| Damotclese | 1:316582aec4fb | 448 | { |
| Damotclese | 1:316582aec4fb | 449 | // Place the sprite on to the screen |
| Damotclese | 1:316582aec4fb | 450 | AnimationDrawOrEraseSpriteAtThisLocation(LCD_WIDTH / 2, LCD_HEIGHT / 2, true); |
| Damotclese | 1:316582aec4fb | 451 | |
| Damotclese | 1:316582aec4fb | 452 | // Start the animation thread |
| Damotclese | 1:316582aec4fb | 453 | st_animationThread.start(AnimationThread); |
| Damotclese | 1:316582aec4fb | 454 | |
| Damotclese | 1:316582aec4fb | 455 | // Flag the fact that the thread is running |
| Damotclese | 1:316582aec4fb | 456 | b_animationThreadRunning = true; |
| Damotclese | 2:444eeedb41f0 | 457 | |
| Damotclese | 2:444eeedb41f0 | 458 | // In an effort to add more "randomness," read some of the |
| Damotclese | 2:444eeedb41f0 | 459 | // analog inputs and add their values, if any, to the seed |
| Damotclese | 2:444eeedb41f0 | 460 | u32_randomSeeder = (st_analog1 * 100) + (st_analog2 * 100) + (st_analog3 * 100); |
| Damotclese | 1:316582aec4fb | 461 | |
| Damotclese | 1:316582aec4fb | 462 | // In order to "seed" the random number generator, we acquire |
| Damotclese | 1:316582aec4fb | 463 | // and discard up to 2000 random numbers |
| Damotclese | 1:316582aec4fb | 464 | u32_randomSeeder %= 2000; |
| Damotclese | 1:316582aec4fb | 465 | |
| Damotclese | 1:316582aec4fb | 466 | // Acquire up to 2000 random numbers |
| Damotclese | 1:316582aec4fb | 467 | while (u32_randomSeeder-- > 0) |
| Damotclese | 1:316582aec4fb | 468 | { |
| Damotclese | 1:316582aec4fb | 469 | // Acquire the number and then discard it |
| Damotclese | 1:316582aec4fb | 470 | (void)AnimationGetANewDirectionToTravel(); |
| Damotclese | 1:316582aec4fb | 471 | } |
| Damotclese | 1:316582aec4fb | 472 | } |
| Damotclese | 1:316582aec4fb | 473 | } |
| Damotclese | 1:316582aec4fb | 474 | |
| Damotclese | 1:316582aec4fb | 475 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 476 | // AnimationStopAnimation() |
| Damotclese | 1:316582aec4fb | 477 | // |
| Damotclese | 2:444eeedb41f0 | 478 | // In the event the animation thread needs to be stopped, this function |
| Damotclese | 2:444eeedb41f0 | 479 | // may be called to terminate the animation thread. |
| Damotclese | 1:316582aec4fb | 480 | // |
| Damotclese | 1:316582aec4fb | 481 | // ---------------------------------------------------------------------- |
| Damotclese | 1:316582aec4fb | 482 | void AnimationStopAnimation(void) |
| Damotclese | 1:316582aec4fb | 483 | { |
| Damotclese | 1:316582aec4fb | 484 | // Is the animation thread running? |
| Damotclese | 1:316582aec4fb | 485 | if (true == b_animationThreadRunning) |
| Damotclese | 1:316582aec4fb | 486 | { |
| Damotclese | 1:316582aec4fb | 487 | // Stop the animation thread |
| Damotclese | 1:316582aec4fb | 488 | st_animationThread.terminate(); |
| Damotclese | 1:316582aec4fb | 489 | |
| Damotclese | 1:316582aec4fb | 490 | // Flag the fact that animation is no longer running |
| Damotclese | 1:316582aec4fb | 491 | b_animationThreadRunning = false; |
| Damotclese | 1:316582aec4fb | 492 | } |
| Damotclese | 1:316582aec4fb | 493 | } |
| Damotclese | 1:316582aec4fb | 494 | |
| Damotclese | 1:316582aec4fb | 495 | // End of file |
| Damotclese | 1:316582aec4fb | 496 |