From 72c8bbe4f7217000e0b6c35405dc140c260e03ea Mon Sep 17 00:00:00 2001 From: nakst <> Date: Thu, 9 Sep 2021 14:26:19 +0100 Subject: [PATCH] create 2048 game; remove old game --- apps/2048.cpp | 384 ++++++++++++++ apps/2048.ini | 6 + apps/fly.cpp | 942 ----------------------------------- apps/fly.ini | 66 --- desktop/os.header | 8 +- desktop/prefix.h | 1 + desktop/styles.header | 1 + desktop/text.cpp | 9 + desktop/theme.cpp | 21 +- res/Fly Assets/R07_12.DAT | Bin 1261 -> 0 bytes res/Fly Assets/R07_13.DAT | Bin 775 -> 0 bytes res/Fly Assets/R07_14.DAT | Bin 1198 -> 0 bytes res/Fly Assets/R07_16.DAT | Bin 550 -> 0 bytes res/Fly Assets/R07_17.DAT | Bin 1432 -> 0 bytes res/Fly Assets/R07_18.DAT | Bin 1729 -> 0 bytes res/Fly Assets/R08_12.DAT | Bin 766 -> 0 bytes res/Fly Assets/R08_13.DAT | Bin 838 -> 0 bytes res/Fly Assets/R08_14.DAT | Bin 1009 -> 0 bytes res/Fly Assets/R08_16.DAT | Bin 1738 -> 0 bytes res/Fly Assets/R08_17.DAT | Bin 1324 -> 0 bytes res/Fly Assets/R08_18.DAT | Bin 883 -> 0 bytes res/Fly Assets/R09_10.DAT | Bin 1180 -> 0 bytes res/Fly Assets/R09_11.DAT | Bin 1261 -> 0 bytes res/Fly Assets/R09_12.DAT | Bin 1504 -> 0 bytes res/Fly Assets/R09_13.DAT | Bin 811 -> 0 bytes res/Fly Assets/R09_14.DAT | Bin 478 -> 0 bytes res/Fly Assets/R09_15.DAT | Bin 955 -> 0 bytes res/Fly Assets/R09_16.DAT | Bin 1153 -> 0 bytes res/Fly Assets/R09_17.DAT | Bin 1018 -> 0 bytes res/Fly Assets/R09_18.DAT | Bin 1432 -> 0 bytes res/Fly Assets/R10_09.DAT | Bin 2026 -> 0 bytes res/Fly Assets/R10_10.DAT | Bin 1666 -> 0 bytes res/Fly Assets/R10_11.DAT | Bin 973 -> 0 bytes res/Fly Assets/R10_12.DAT | Bin 2035 -> 0 bytes res/Fly Assets/R10_13.DAT | Bin 649 -> 0 bytes res/Fly Assets/R10_14.DAT | Bin 568 -> 0 bytes res/Fly Assets/R10_15.DAT | Bin 1423 -> 0 bytes res/Fly Assets/R10_16.DAT | Bin 775 -> 0 bytes res/Fly Assets/R11_09.DAT | Bin 1594 -> 0 bytes res/Fly Assets/R11_10.DAT | Bin 2260 -> 0 bytes res/Fly Assets/R11_11.DAT | Bin 946 -> 0 bytes res/Fly Assets/R11_13.DAT | Bin 577 -> 0 bytes res/Fly Assets/R11_14.DAT | Bin 559 -> 0 bytes res/Fly Assets/R11_15.DAT | Bin 550 -> 0 bytes res/Fly Assets/R12_09.DAT | Bin 28 -> 0 bytes res/Fly Assets/R12_10.DAT | Bin 1108 -> 0 bytes res/Fly Assets/R12_11.DAT | Bin 595 -> 0 bytes res/Fly Assets/bgm1.mid | Bin 22884 -> 0 bytes res/Fly Assets/bgm2.mid | Bin 26455 -> 0 bytes res/Fly Assets/bgm3.mid | Bin 30205 -> 0 bytes res/Fly Assets/block.png | Bin 173 -> 0 bytes res/Fly Assets/block2.png | Bin 368 -> 0 bytes res/Fly Assets/check1.png | Bin 257 -> 0 bytes res/Fly Assets/check2.png | Bin 264 -> 0 bytes res/Fly Assets/controls.png | Bin 1184 -> 0 bytes res/Fly Assets/dash_msg.png | Bin 759 -> 0 bytes res/Fly Assets/end1.png | Bin 1152 -> 0 bytes res/Fly Assets/end2.png | Bin 1278 -> 0 bytes res/Fly Assets/end3.png | Bin 629 -> 0 bytes res/Fly Assets/key.png | Bin 278 -> 0 bytes res/Fly Assets/key_msg.png | Bin 740 -> 0 bytes res/Fly Assets/lock.png | Bin 268 -> 0 bytes res/Fly Assets/moveblock.png | Bin 375 -> 0 bytes res/Fly Assets/numbers.png | Bin 656 -> 0 bytes res/Fly Assets/player.png | Bin 427 -> 0 bytes res/Fly Assets/powerup.png | Bin 256 -> 0 bytes res/Fly Assets/star.png | Bin 283 -> 0 bytes res/Fly Assets/white.png | Bin 149 -> 0 bytes res/Theme Source.dat | Bin 52669 -> 52779 bytes res/Themes/Theme.dat | Bin 53944 -> 54064 bytes shared/math.cpp | 19 + shared/strings.cpp | 10 + util/api_table.ini | 2 + 73 files changed, 440 insertions(+), 1029 deletions(-) create mode 100644 apps/2048.cpp create mode 100644 apps/2048.ini delete mode 100644 apps/fly.cpp delete mode 100644 apps/fly.ini delete mode 100644 res/Fly Assets/R07_12.DAT delete mode 100644 res/Fly Assets/R07_13.DAT delete mode 100644 res/Fly Assets/R07_14.DAT delete mode 100644 res/Fly Assets/R07_16.DAT delete mode 100644 res/Fly Assets/R07_17.DAT delete mode 100644 res/Fly Assets/R07_18.DAT delete mode 100644 res/Fly Assets/R08_12.DAT delete mode 100644 res/Fly Assets/R08_13.DAT delete mode 100644 res/Fly Assets/R08_14.DAT delete mode 100644 res/Fly Assets/R08_16.DAT delete mode 100644 res/Fly Assets/R08_17.DAT delete mode 100644 res/Fly Assets/R08_18.DAT delete mode 100644 res/Fly Assets/R09_10.DAT delete mode 100644 res/Fly Assets/R09_11.DAT delete mode 100644 res/Fly Assets/R09_12.DAT delete mode 100644 res/Fly Assets/R09_13.DAT delete mode 100644 res/Fly Assets/R09_14.DAT delete mode 100644 res/Fly Assets/R09_15.DAT delete mode 100644 res/Fly Assets/R09_16.DAT delete mode 100644 res/Fly Assets/R09_17.DAT delete mode 100644 res/Fly Assets/R09_18.DAT delete mode 100644 res/Fly Assets/R10_09.DAT delete mode 100644 res/Fly Assets/R10_10.DAT delete mode 100644 res/Fly Assets/R10_11.DAT delete mode 100644 res/Fly Assets/R10_12.DAT delete mode 100644 res/Fly Assets/R10_13.DAT delete mode 100644 res/Fly Assets/R10_14.DAT delete mode 100644 res/Fly Assets/R10_15.DAT delete mode 100644 res/Fly Assets/R10_16.DAT delete mode 100644 res/Fly Assets/R11_09.DAT delete mode 100644 res/Fly Assets/R11_10.DAT delete mode 100644 res/Fly Assets/R11_11.DAT delete mode 100644 res/Fly Assets/R11_13.DAT delete mode 100644 res/Fly Assets/R11_14.DAT delete mode 100644 res/Fly Assets/R11_15.DAT delete mode 100644 res/Fly Assets/R12_09.DAT delete mode 100644 res/Fly Assets/R12_10.DAT delete mode 100644 res/Fly Assets/R12_11.DAT delete mode 100644 res/Fly Assets/bgm1.mid delete mode 100644 res/Fly Assets/bgm2.mid delete mode 100644 res/Fly Assets/bgm3.mid delete mode 100644 res/Fly Assets/block.png delete mode 100644 res/Fly Assets/block2.png delete mode 100644 res/Fly Assets/check1.png delete mode 100644 res/Fly Assets/check2.png delete mode 100644 res/Fly Assets/controls.png delete mode 100644 res/Fly Assets/dash_msg.png delete mode 100644 res/Fly Assets/end1.png delete mode 100644 res/Fly Assets/end2.png delete mode 100644 res/Fly Assets/end3.png delete mode 100644 res/Fly Assets/key.png delete mode 100644 res/Fly Assets/key_msg.png delete mode 100644 res/Fly Assets/lock.png delete mode 100644 res/Fly Assets/moveblock.png delete mode 100644 res/Fly Assets/numbers.png delete mode 100644 res/Fly Assets/player.png delete mode 100644 res/Fly Assets/powerup.png delete mode 100644 res/Fly Assets/star.png delete mode 100644 res/Fly Assets/white.png diff --git a/apps/2048.cpp b/apps/2048.cpp new file mode 100644 index 0000000..dab8133 --- /dev/null +++ b/apps/2048.cpp @@ -0,0 +1,384 @@ +#include +#include + +// TODO Application icon. + +#define TILE_COUNT (4) +#define TILE_SIZE ((int32_t) (75 * scale)) +#define TILE_GAP ((int32_t) (10 * scale)) +#define CELL_FILL (0xFFEEEEEE) +#define TILE_TEXT_COLOR (0xFFFFFF) +#define TILE_TEXT_GLOW (0x000000) +#define MAIN_AREA_SIZE() (TILE_SIZE * TILE_COUNT + TILE_GAP * (TILE_COUNT + 1)) +#define MAIN_AREA_FILL (0xFFFFFFFF) +#define MAIN_AREA_BORDER (0xFFCCCCCC) +#define ANIMATION_TIME (100) + +#define TILE_BOUNDS(x, y) ES_RECT_4PD(mainArea.l + TILE_GAP * (x + 1) + TILE_SIZE * x, mainArea.t + TILE_GAP * (y + 1) + TILE_SIZE * y, TILE_SIZE, TILE_SIZE) + +#define SETTINGS_FILE "|Settings:/Default.ini" + +struct AnimatingTile { + float sourceOpacity, targetOpacity; + uint8_t sourceX, targetX; + uint8_t sourceY, targetY; + uint8_t sourceNumber; +}; + +const uint32_t tileColors[] = { + 0x000000, 0x7CB5E2, 0x4495D4, 0x2F6895, + 0xF5BD70, 0xF2A032, 0xE48709, 0xE37051, + 0xDE5833, 0xBD4A2B, 0x5454DA, 0x3B3C99, + 0xFFD700, +}; + +const uint32_t tileTextSizes[] = { + 0, 18, 18, 18, 18, 18, 18, 18, + 18, 18, 16, 16, 16, 16, 14, 14, + 14, 12, 12, 12, 10, 10, 10, 10, + 8, 8, 8, 6, 6, 6, 6, 6, +}; + +AnimatingTile animatingTiles[TILE_COUNT * TILE_COUNT + 1]; +size_t animatingTileCount; +float animationTimeMs; + +uint8_t grid[TILE_COUNT][TILE_COUNT]; +uintptr_t currentTileCount; +int32_t score, highScore; + +EsInstance *instance; +EsElement *gameArea; +EsTextDisplay *scoreDisplay, *highScoreDisplay; + +void SaveConfiguration() { + EsBuffer buffer = {}; + buffer.canGrow = true; + EsBufferFormat(&buffer, "high_score=%d\n", highScore); + EsFileWriteAll(EsLiteral(SETTINGS_FILE), buffer.out, buffer.position); + EsHeapFree(buffer.out); +} + +bool MoveTiles(intptr_t dx, intptr_t dy, bool speculative) { + uint8_t undo[TILE_COUNT][TILE_COUNT]; + EsMemoryCopy(undo, grid, sizeof(undo)); + + bool validMove = false; + + for (uintptr_t p = 0; p < TILE_COUNT; p++) { + bool doneMerge = false; + + for (uintptr_t q = 0; q < TILE_COUNT; q++) { + // The tile being moved. + intptr_t x = dx ? q : p; + intptr_t y = dx ? p : q; + if (dx > 0) x = TILE_COUNT - 1 - x; + if (dy > 0) y = TILE_COUNT - 1 - y; + + // Ignore empty spaces. + if (!grid[x][y]) continue; + + // Setup the animation. + if (!speculative) { + AnimatingTile *animation = &animatingTiles[animatingTileCount]; + animation->sourceOpacity = 1; + animation->targetOpacity = 1; + animation->sourceX = x; + animation->sourceY = y; + animation->sourceNumber = grid[x][y]; + } + + while (true) { + // The position to move the tile to. + intptr_t nx = x + dx; + intptr_t ny = y + dy; + + // If the next position is outside the grid, stop. + if (nx < 0 || nx >= TILE_COUNT) break; + if (ny < 0 || ny >= TILE_COUNT) break; + + if (grid[nx][ny]) { + // If tiles are different, we can't merge; stop. + if (grid[nx][ny] != grid[x][y]) break; + + // If there's already been a merge this band, stop. + if (doneMerge) break; + + // Merge the tiles. + grid[nx][ny]++; + grid[x][y] = 0; + doneMerge = true; + + // Add the score. + if (!speculative) score += 1 << grid[nx][ny]; + } else { + // Slide the tile. + grid[nx][ny] = grid[x][y]; + grid[x][y] = 0; + } + + // Update the position. + x = nx; + y = ny; + validMove = true; + } + + // Set the animation target. + if (!speculative) { + AnimatingTile *animation = &animatingTiles[animatingTileCount]; + animation->targetX = x; + animation->targetY = y; + animatingTileCount++; + } + } + } + + if (speculative) { + EsMemoryCopy(grid, undo, sizeof(undo)); + } + + return validMove; +} + +void SpawnTile() { + if (currentTileCount == TILE_COUNT * TILE_COUNT) { + // The grid is full. + return; + } + + while (true) { + uintptr_t x = EsRandomU64() % TILE_COUNT; + uintptr_t y = EsRandomU64() % TILE_COUNT; + + if (!grid[x][y]) { + grid[x][y] = EsRandomU8() < 25 ? 2 : 1; + + // Setup the animation. + AnimatingTile *animation = &animatingTiles[animatingTileCount]; + animation->sourceOpacity = 0; + animation->targetOpacity = 1; + animation->sourceX = x; + animation->targetX = x; + animation->sourceY = y; + animation->targetY = y; + animation->sourceNumber = grid[x][y]; + animatingTileCount++; + + break; + } + } + + if (!MoveTiles(-1, 0, true) && !MoveTiles(1, 0, true) && !MoveTiles(0, -1, true) && !MoveTiles(0, 1, true)) { + // No moves are possible. + if (highScore < score) { + EsDialogShowAlert(instance->window, INTERFACE_STRING(Game2048GameOver), INTERFACE_STRING(Game2048NewHighScore), + ES_ICON_DIALOG_INFORMATION, ES_DIALOG_ALERT_OK_BUTTON); + } else { + EsDialogShowAlert(instance->window, INTERFACE_STRING(Game2048GameOver), INTERFACE_STRING(Game2048GameOverExplanation), + ES_ICON_DIALOG_INFORMATION, ES_DIALOG_ALERT_OK_BUTTON); + } + } +} + +void Update(intptr_t dx, intptr_t dy) { + animatingTileCount = 0; + animationTimeMs = 0; + + if (dx || dy) { + if (!MoveTiles(dx, dy, false)) { + return; + } + } + + SpawnTile(); + EsElementStartAnimating(gameArea); + + if (score > highScore) { + highScore = score; + } + + char buffer[64]; + size_t bytes = EsStringFormat(buffer, sizeof(buffer), "%d", score); + EsTextDisplaySetContents(scoreDisplay, buffer, bytes); + bytes = EsStringFormat(buffer, sizeof(buffer), interfaceString_Game2048HighScore, highScore); + EsTextDisplaySetContents(highScoreDisplay, buffer, bytes); +} + +void DrawTileText(EsPainter *painter, EsElement *element, EsRectangle bounds, float opacity, uint8_t number) { + char buffer[64]; + size_t bytes = EsStringFormat(buffer, sizeof(buffer), "%d", 1 << (uint32_t) number); + uint32_t alpha = ((uint32_t) (255 * opacity) << 24); + EsTextStyle style = { .font = { .family = ES_FONT_SANS, .weight = ES_FONT_SEMIBOLD }, .size = (uint16_t) tileTextSizes[number] }; + + if (number >= 12) { + style.color = TILE_TEXT_GLOW | alpha; + style.blur = 3; + EsDrawTextSimple(painter, element, bounds, buffer, bytes, style, ES_TEXT_H_CENTER | ES_TEXT_V_CENTER); + } + + style.color = TILE_TEXT_COLOR | alpha; + style.blur = 0; + EsDrawTextSimple(painter, element, bounds, buffer, bytes, style, ES_TEXT_H_CENTER | ES_TEXT_V_CENTER); +} + +void DrawTile(EsPainter *painter, EsElement *element, uint8_t sourceNumber, uint8_t targetNumber, + EsRectangle bounds, float opacity, const uint32_t *cornerRadii, float progress) { + size_t tileColorCount = sizeof(tileColors) / sizeof(tileColors[0]); + uint32_t sourceColor = sourceNumber >= tileColorCount ? tileColors[tileColorCount - 1] : tileColors[sourceNumber]; + uint32_t targetColor = targetNumber >= tileColorCount ? tileColors[tileColorCount - 1] : tileColors[targetNumber]; + uint32_t fill = EsColorInterpolate(sourceColor, targetColor, progress) | ((uint32_t) (255 * opacity) << 24); + float scale = EsElementGetScaleFactor(element); + + EsDrawRoundedRectangle(painter, bounds, fill, EsColorBlend(fill, 0x20000000, true), ES_RECT_4(0, 0, 0, 3 * scale), cornerRadii); + + if (sourceNumber == targetNumber) { + progress = 1.0f; + } + + DrawTileText(painter, element, bounds, progress, targetNumber); + + if (sourceNumber != targetNumber && targetNumber) { + DrawTileText(painter, element, bounds, 1.0f - progress, sourceNumber); + } +} + +int GameAreaMessage(EsElement *element, EsMessage *message) { + if (message->type == ES_MSG_PAINT) { + EsPainter *painter = message->painter; + float scale = EsElementGetScaleFactor(element); + + const uint32_t cornerRadii[4] = { (uint32_t) (3 * scale), (uint32_t) (3 * scale), (uint32_t) (3 * scale), (uint32_t) (3 * scale) }; + + EsRectangle bounds = EsPainterBoundsInset(painter); + EsRectangle mainArea = EsRectangleFit(bounds, ES_RECT_1S(MAIN_AREA_SIZE()), false); + EsDrawRoundedRectangle(painter, mainArea, MAIN_AREA_FILL, MAIN_AREA_BORDER, ES_RECT_1(scale * 1), cornerRadii); + + float progress = animationTimeMs / ANIMATION_TIME; + bool animationComplete = progress == 1.0; + + progress -= 1.0; + progress = 1 + progress * progress * progress; + + for (uintptr_t j = 0; j < TILE_COUNT; j++) { + for (uintptr_t i = 0; i < TILE_COUNT; i++) { + if (grid[i][j] && animationComplete) { + DrawTile(painter, element, grid[i][j], grid[i][j], TILE_BOUNDS(i, j), 1.0f, cornerRadii, 1.0f); + } else { + EsDrawRoundedRectangle(painter, TILE_BOUNDS(i, j), CELL_FILL, 0, ES_RECT_1(0), cornerRadii); + } + } + } + + if (!animationComplete) { + for (uintptr_t i = 0; i < animatingTileCount; i++) { + AnimatingTile *tile = &animatingTiles[i]; + EsRectangle bounds = EsRectangleLinearInterpolate(TILE_BOUNDS(tile->sourceX, tile->sourceY), TILE_BOUNDS(tile->targetX, tile->targetY), progress); + float opacity = (tile->targetOpacity - tile->sourceOpacity) * progress + tile->sourceOpacity; + DrawTile(painter, element, tile->sourceNumber, grid[tile->targetX][tile->targetY], bounds, opacity, cornerRadii, progress); + } + } + } else if (message->type == ES_MSG_ANIMATE) { + animationTimeMs += message->animate.deltaMs; + + if (animationTimeMs > ANIMATION_TIME) { + animationTimeMs = ANIMATION_TIME; + message->animate.complete = true; + } else { + message->animate.complete = false; + } + + EsElementRepaint(element); + } else if (message->type == ES_MSG_KEY_TYPED) { + if (message->keyboard.scancode == ES_SCANCODE_LEFT_ARROW) { + Update(-1, 0); + } else if (message->keyboard.scancode == ES_SCANCODE_RIGHT_ARROW) { + Update(1, 0); + } else if (message->keyboard.scancode == ES_SCANCODE_UP_ARROW) { + Update(0, -1); + } else if (message->keyboard.scancode == ES_SCANCODE_DOWN_ARROW) { + Update(0, 1); + } else { + return 0; + } + } else if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) { + float scale = EsElementGetScaleFactor(element); + message->measure.width = message->measure.height = MAIN_AREA_SIZE(); + } else { + return 0; + } + + return ES_HANDLED; +} + +int InfoPanelMessage(EsElement *element, EsMessage *message) { + if (message->type == ES_MSG_GET_WIDTH || message->type == ES_MSG_GET_HEIGHT) { + float scale = EsElementGetScaleFactor(element); + message->measure.width = MAIN_AREA_SIZE() / 2; + message->measure.height = MAIN_AREA_SIZE(); + } else { + return 0; + } + + return ES_HANDLED; +} + +void NewGameCommand(EsInstance *, EsElement *, EsCommand *) { + SaveConfiguration(); + EsMemoryZero(grid, sizeof(grid)); + score = 0; + Update(0, 0); + EsElementFocus(gameArea); +} + +void ProcessApplicationMessage(EsMessage *message) { + if (message->type == ES_MSG_INSTANCE_CREATE) { + // Create the instance. + instance = EsInstanceCreate(message, EsLiteral("2048")); + EsWindowSetIcon(instance->window, ES_ICON_APPLICATIONS_OTHER); + + // Main horizontal stack. + EsPanel *panel = EsPanelCreate(instance->window, ES_CELL_FILL | ES_PANEL_HORIZONTAL, ES_STYLE_PANEL_WINDOW_BACKGROUND); + EsSpacerCreate(panel, ES_CELL_FILL); + gameArea = EsCustomElementCreate(panel, ES_ELEMENT_FOCUSABLE); + gameArea->messageUser = GameAreaMessage; + EsSpacerCreate(panel, ES_FLAGS_DEFAULT, nullptr, 30, 0); + EsPanel *info = EsPanelCreate(panel); + EsSpacerCreate(panel, ES_CELL_FILL); + + // Info panel. + info->messageUser = InfoPanelMessage; + EsTextDisplayCreate(info, ES_CELL_H_FILL, ES_STYLE_TEXT_LABEL_SECONDARY, INTERFACE_STRING(Game2048Score)); + scoreDisplay = EsTextDisplayCreate(info, ES_CELL_H_FILL, ES_STYLE_TEXT_HEADING0); + EsSpacerCreate(info, ES_FLAGS_DEFAULT, nullptr, 0, 10); + highScoreDisplay = EsTextDisplayCreate(info, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT, ES_STYLE_TEXT_LABEL_SECONDARY); + EsSpacerCreate(info, ES_CELL_FILL); + EsTextDisplayCreate(info, ES_CELL_H_FILL | ES_TEXT_DISPLAY_RICH_TEXT, ES_STYLE_TEXT_PARAGRAPH_SECONDARY, INTERFACE_STRING(Game2048Instructions)); + EsSpacerCreate(info, ES_FLAGS_DEFAULT, nullptr, 0, 10); + EsButton *newGame = EsButtonCreate(info, ES_CELL_H_LEFT | ES_BUTTON_NOT_FOCUSABLE, nullptr, INTERFACE_STRING(Game2048NewGame)); + newGame->accessKey = 'N'; + EsButtonOnCommand(newGame, NewGameCommand); + + // Start the game! + EsElementFocus(gameArea); + Update(0, 0); + animationTimeMs = ANIMATION_TIME; + } else if (message->type == ES_MSG_APPLICATION_EXIT) { + SaveConfiguration(); + } +} + +void _start() { + _init(); + + EsINIState state = { (char *) EsFileReadAll(EsLiteral(SETTINGS_FILE), &state.bytes) }; + + while (EsINIParse(&state)) { + if (0 == EsStringCompareRaw(state.key, state.keyBytes, EsLiteral("high_score"))) { + highScore = EsIntegerParse(state.value, state.valueBytes); + } + } + + while (true) { + ProcessApplicationMessage(EsMessageReceive()); + } +} diff --git a/apps/2048.ini b/apps/2048.ini new file mode 100644 index 0000000..16151bd --- /dev/null +++ b/apps/2048.ini @@ -0,0 +1,6 @@ +[general] +name=2048 +icon=icon_applications_other + +[build] +source=apps/2048.cpp diff --git a/apps/fly.cpp b/apps/fly.cpp deleted file mode 100644 index da29786..0000000 --- a/apps/fly.cpp +++ /dev/null @@ -1,942 +0,0 @@ -// TODO Icon. -// TODO Music. -// TODO Draw() with rotation. -// TODO Saving with new file IO. - -#include - -EsInstance *instance; -uint32_t backgroundColor; -int musicIndex; -bool keysPressedSpace, keysPressedEscape, keysPressedX; -uint32_t previousControllerButtons[ES_GAME_CONTROLLER_MAX_COUNT]; -uint32_t *targetBits; -size_t targetWidth, targetHeight, targetStride; -double updateTimeAccumulator; -float gameScale; -uint32_t gameOffsetX, gameOffsetY, gameWidth, gameHeight; - -#define GAME_SIZE (380) -#define BRAND "fly" - -struct Texture { - uint32_t width, height; - uint32_t *bits; -}; - -void Transform(float *destination, float *left, float *right) { - float d[6]; - d[0] = left[0] * right[0] + left[1] * right[3]; - d[1] = left[0] * right[1] + left[1] * right[4]; - d[2] = left[0] * right[2] + left[1] * right[5] + left[2]; - d[3] = left[3] * right[0] + left[4] * right[3]; - d[4] = left[3] * right[1] + left[4] * right[4]; - d[5] = left[3] * right[2] + left[4] * right[5] + left[5]; - destination[0] = d[0]; - destination[1] = d[1]; - destination[2] = d[2]; - destination[3] = d[3]; - destination[4] = d[4]; - destination[5] = d[5]; -} - -ES_FUNCTION_OPTIMISE_O3 -void Draw(Texture *texture, - float x, float y, float w = -1, float h = -1, - float sx = 0, float sy = 0, float sw = -1, float sh = -1, - float _a = 1, float _r = 1, float _g = 1, float _b = 1, - float rot = 0) { - (void) rot; - - if (sw == -1 && sh == -1) sw = texture->width, sh = texture->height; - if (w == -1 && h == -1) w = sw, h = sh; - if (_a <= 0) return; - - if (x + w < 0 || y + h < 0 || x > GAME_SIZE || y > GAME_SIZE) return; - - x *= gameScale, y *= gameScale, w *= gameScale, h *= gameScale; - - float m[6] = {}; - float m1[6] = { sw / w, 0, 0, 0, sh / h, 0 }; - float m2[6] = { 1, 0, -x * (sw / w), 0, 1, -y * (sh / h) }; - - Transform(m, m2, m1); - - intptr_t yStart = y - 1, yEnd = y + h + 1, xStart = x - 1, xEnd = x + w + 1; - // if (rot) yStart -= h * 0.45f, yEnd += h * 0.45f, xStart -= w * 0.45f, xEnd += w * 0.45f; - if (yStart < 0) yStart = 0; - if (yStart > gameHeight) yStart = gameHeight; - if (yEnd < 0) yEnd = 0; - if (yEnd > gameHeight) yEnd = gameHeight; - if (xStart < 0) xStart = 0; - if (xStart > gameWidth) xStart = gameWidth; - if (xEnd < 0) xEnd = 0; - if (xEnd > gameWidth) xEnd = gameWidth; - m[2] += m[0] * xStart, m[5] += m[3] * xStart; - - uint32_t *scanlineStart = targetBits + (gameOffsetY + yStart) * targetStride / 4 + (gameOffsetX + xStart); - - uint32_t r = _r * 255, g = _g * 255, b = _b * 255, a = _a * 255; - - for (intptr_t y = yStart; y < yEnd; y++, scanlineStart += targetStride / 4) { - uint32_t *output = scanlineStart; - - float tx = m[1] * y + m[2]; - float ty = m[4] * y + m[5]; - - for (intptr_t x = xStart; x < xEnd; x++, output++, tx += m[0], ty += m[3]) { - if (tx + sx < 0 || ty + sy < 0) continue; - uintptr_t txi = tx + sx, tyi = ty + sy; - if (txi < sx || tyi < sy || txi >= sx + sw || tyi >= sy + sh) continue; - uint32_t modified = texture->bits[tyi * texture->width + txi]; - if (!(modified & 0xFF000000)) continue; - uint32_t original = *output; - uint32_t alpha1 = (((modified & 0xFF000000) >> 24) * a) >> 8; - uint32_t alpha2 = (255 - alpha1) << 8; - uint32_t r2 = alpha2 * ((original & 0x00FF0000) >> 16); - uint32_t g2 = alpha2 * ((original & 0x0000FF00) >> 8); - uint32_t b2 = alpha2 * ((original & 0x000000FF) >> 0); - uint32_t r1 = r * alpha1 * ((modified & 0x00FF0000) >> 16); - uint32_t g1 = g * alpha1 * ((modified & 0x0000FF00) >> 8); - uint32_t b1 = b * alpha1 * ((modified & 0x000000FF) >> 0); - *output = 0xFF000000 - | (0x00FF0000 & ((r1 + r2) << 0)) - | (0x0000FF00 & ((g1 + g2) >> 8)) - | (0x000000FF & ((b1 + b2) >> 16)); - } - } -} - -void CreateTexture(Texture *texture, const char *cName) { - size_t dataBytes; - const void *data = EsEmbeddedFileGet(cName, -1, &dataBytes); - texture->bits = (uint32_t *) EsImageLoad(data, dataBytes, &texture->width, &texture->height, 4); - EsAssert(texture->bits); -} - -void ExitGame() { - EsInstanceDestroy(instance); -} - -/////////////////////////////////////////////////////////// - -#define TAG_ALL (-1) -#define TAG_SOLID (-2) -#define TAG_KILL (-3) -#define TAG_WORLD (-4) - -#define TILE_SIZE (16) - -struct Entity { - uint8_t tag; - uint8_t layer; - bool solid, kill, hide; - char symbol; - int8_t frameCount, stepsPerFrame; - Texture *texture; - float texOffX, texOffY, w, h; - int uid; - - void (*create)(Entity *); - void (*destroy)(Entity *); - void (*stepAlways)(Entity *); // Called even if level editing. - void (*step)(Entity *); - void (*draw)(Entity *); - void (*drawAfter)(Entity *); - - float x, y, px, py; - int stepIndex; - bool isUsed, isDestroyed; - - union { - struct { - float cx, cy; - float th, dth; - float dths; - int respawn, respawnGrow, dash; - } player; - - struct { - int random; - } block; - - struct { - float vel; - } moveBlock; - - struct { - float th, cx, cy; - } spin; - - struct { - float vx, vy, th, dth; - int life; - uint32_t col; - } star; - }; - - void Destroy() { - if (isDestroyed) return; - isDestroyed = true; - if (destroy) destroy(this); - } -}; - -Texture textureDashMessage, textureKeyMessage, textureKey, textureControlsMessage, textureWhite; - -Entity typePlayer, typeBlock, typeCheck, typeMoveH, typeStar, typeMoveV, typePowerup, typeShowMessage, typeKey, typeLock, typeSpin, typeEnd; - -// All the entities that can be loaded from the rooms. -Entity *entityTypes[] = { - &typeBlock, &typeCheck, &typeMoveH, &typeMoveV, &typePowerup, &typeKey, &typeLock, &typeSpin, &typeEnd, - nullptr, -}; - -int levelTick; -bool justLoaded = true; - -#define MAX_ENTITIES (1000) - -struct SaveState { - float checkX, checkY; - int roomX, roomY; - bool hasDash, hasKey; - int deathCount; - uint32_t check; -}; - -struct GameState : SaveState { - Entity entities[MAX_ENTITIES]; - int world; - Entity *player; -}; - -GameState state; - -Entity *AddEntity(Entity *templateEntity, float x, float y, int uid = 0) { - for (int i = 0; i < MAX_ENTITIES; i++) { - if (!state.entities[i].isUsed) { - EsMemoryCopy(state.entities + i, templateEntity, sizeof(Entity)); - state.entities[i].isUsed = true; - if (!state.entities[i].frameCount) state.entities[i].frameCount = 1; - if (!state.entities[i].stepsPerFrame) state.entities[i].stepsPerFrame = 1; - state.entities[i].x = state.entities[i].px = x; - state.entities[i].y = state.entities[i].py = y; - if (!state.entities[i].w) state.entities[i].w = state.entities[i].texture->width - 1; - if (!state.entities[i].h) state.entities[i].h = state.entities[i].texture->height / state.entities[i].frameCount - 1; - state.entities[i].uid = uid; - if (state.entities[i].create) state.entities[i].create(state.entities + i); - return state.entities + i; - } - } - - static Entity fake = {}; - return &fake; -} - -Entity *FindEntity(float x, float y, float w, float h, int tag, Entity *exclude) { - for (int i = 0; i < MAX_ENTITIES; i++) { - if (state.entities[i].isUsed && !state.entities[i].isDestroyed - && (state.entities[i].tag == tag - || tag == TAG_ALL - || (tag == TAG_SOLID && state.entities[i].solid) - || (tag == TAG_KILL && state.entities[i].kill) - ) - && state.entities + i != exclude) { - if (x <= state.entities[i].x + state.entities[i].w && state.entities[i].x <= x + w - && y <= state.entities[i].y + state.entities[i].h && state.entities[i].y <= y + h) { - return state.entities + i; - } - } - } - - return nullptr; -} - -char roomName[16]; - -void UpdateRoomName() { - roomName[0] = 'R'; - roomName[1] = (state.roomX / 10) + '0'; - roomName[2] = (state.roomX % 10) + '0'; - roomName[3] = '_'; - roomName[4] = (state.roomY / 10) + '0'; - roomName[5] = (state.roomY % 10) + '0'; - roomName[6] = '.'; - roomName[7] = 'D'; - roomName[8] = 'A'; - roomName[9] = 'T'; - roomName[10] = 0; -} - -#define ROOM_ID ((state.roomX - 7) + (state.roomY - 9) * 6) - -void LoadRoom() { - state.world = 0; - - UpdateRoomName(); - - roomName[6] = '_'; - const uint8_t *buffer = (const uint8_t *) EsEmbeddedFileGet(roomName, -1); - - for (int i = 0; i < MAX_ENTITIES; i++) { - if (!state.entities[i].isUsed || state.entities[i].isDestroyed) continue; - - if (state.entities[i].tag != typePlayer.tag) { - state.entities[i].Destroy(); - } else { - state.entities[i].px = state.entities[i].x; - state.entities[i].py = state.entities[i].y; - } - } - - int p = 0; - int iir = 0; - - while (true) { - uint8_t tag = buffer[p++]; - if (!tag) break; - float x = *(float *) (buffer + p); p += 4; - float y = *(float *) (buffer + p); p += 4; - - if (tag == (uint8_t) TAG_WORLD) { - state.world = x; - } - - for (int i = 0; entityTypes[i]; i++) { - if (entityTypes[i]->tag == tag) { - AddEntity(entityTypes[i], x, y, (state.roomX << 24) | (state.roomY << 16) | iir); - iir++; - } - } - } - - musicIndex = state.world; -} - -void CalculateCheck() { - state.check = 0; - - uint8_t *buffer = (uint8_t *) &state; - uint32_t check = 0x1D471D47; - - for (uintptr_t i = 0; i < sizeof(SaveState); i++) { - check ^= ((uint32_t) buffer[i] + 10) * (i + 100); - } - - state.check = check; -} - -float FadeInOut(float t) { - if (t < 0.3f) return t / 0.3f; - else if (t < 0.7f) return 1; - else return 1 - (t - 0.7f) / 0.3f; -} - -void InitialiseGame() { - state.roomX = 10; - state.roomY = 10; - - CreateTexture(&textureWhite, "white_png"); - CreateTexture(&textureKey, "key_png"); - CreateTexture(&textureDashMessage, "dash_msg_png"); - CreateTexture(&textureKeyMessage, "key_msg_png"); - CreateTexture(&textureControlsMessage, "controls_png"); - - int tag = 1; - - { - static Texture texture; - CreateTexture(&texture, "player_png"); - typePlayer.tag = tag++; - typePlayer.texture = &texture; - typePlayer.frameCount = 6; - typePlayer.stepsPerFrame = 5; - typePlayer.layer = 1; - - typePlayer.step = [] (Entity *entity) { - if (entity->player.respawn) { - if (entity->stepIndex > entity->player.respawn) { - entity->player.respawn = 0; - entity->hide = false; - entity->player.cx = state.checkX; - entity->player.cy = state.checkY; - entity->player.respawnGrow = entity->stepIndex + 20; - entity->player.dash = 0; - } else { - return; - } - } - - if (!entity->player.respawnGrow && !entity->player.dash) { - if (keysPressedSpace) { - entity->player.cx += (entity->x - entity->player.cx) * 2; - entity->player.cy += (entity->y - entity->player.cy) * 2; - entity->player.th += 3.15f; - entity->player.dth = -entity->player.dth; - entity->player.dths = 5; - } else if (keysPressedX && state.hasDash) { - entity->player.dash = 10; - } - } - - float rd = 40; - - if (entity->player.respawnGrow) { - if (entity->stepIndex > entity->player.respawnGrow) { - entity->player.respawnGrow = 0; - } else { - rd *= 1 - (entity->player.respawnGrow - entity->stepIndex) / 20.0f; - } - } - - entity->x = rd * EsCRTcosf(entity->player.th) + entity->player.cx; - entity->y = rd * EsCRTsinf(entity->player.th) + entity->player.cy + 5 * EsCRTsinf(4.71f + entity->stepIndex * 0.1f); - - if (entity->player.dash) { - float pt = entity->player.th - entity->player.dth; - float px = rd * EsCRTcosf(pt) + entity->player.cx; - float py = rd * EsCRTsinf(pt) + entity->player.cy + 5 * EsCRTsinf(4.71f + (entity->stepIndex - 1) * 0.1f); - float dx = entity->x - px; - float dy = entity->y - py; - entity->player.cx += dx * 3.2f; - entity->player.cy += dy * 3.2f; - entity->player.dash--; - AddEntity(&typeStar, entity->x + 8, entity->y + 8)->star.col = 0xFF; - } else { - entity->player.th += entity->player.dth; - } - - if (entity->player.respawnGrow) { - entity->px = entity->x; - entity->py = entity->y; - } - - if (entity->player.dths) { - entity->player.th += entity->player.dth; - entity->player.dths--; - entity->stepIndex = 5 * 3; - } - - if (FindEntity(entity->x + 5, entity->y + 5, entity->w - 10, entity->h - 10, TAG_KILL, 0)) { - for (int i = 0; i < 20; i++) { - AddEntity(&typeStar, entity->x + 8, entity->y + 8)->star.col = 0xFF0000; - } - - entity->hide = true; - entity->player.respawn = entity->stepIndex + 20; - state.deathCount++; - } - - if (entity->x > GAME_SIZE - 8) { - entity->x -= GAME_SIZE; - entity->player.cx -= GAME_SIZE; - state.checkX -= GAME_SIZE; - state.roomX++; - LoadRoom(); - } else if (entity->x < -8) { - entity->x += GAME_SIZE; - entity->player.cx += GAME_SIZE; - state.checkX += GAME_SIZE; - state.roomX--; - LoadRoom(); - } - - if (entity->y > GAME_SIZE - 8) { - entity->y -= GAME_SIZE; - entity->player.cy -= GAME_SIZE; - state.checkY -= GAME_SIZE; - state.roomY++; - LoadRoom(); - } else if (entity->y < -8) { - entity->y += GAME_SIZE; - entity->player.cy += GAME_SIZE; - state.checkY += GAME_SIZE; - state.roomY--; - LoadRoom(); - } - }; - - typePlayer.create = [] (Entity *entity) { - state.player = entity; - entity->player.cx = entity->x; - entity->player.cy = entity->y; - entity->player.dth = 0.06f; - }; - } - - { - static Texture texture; - CreateTexture(&texture, "block_png"); - - static Texture block2; - CreateTexture(&block2, "block2_png"); - - typeBlock.tag = tag++; - typeBlock.texture = &texture; - typeBlock.kill = true; - typeBlock.hide = true; - typeBlock.layer = 2; - - typeBlock.create = [] (Entity *entity) { - uint8_t r = EsRandomU8(); - - if (r < 20) { - entity->block.random = 1; - } else if (r < 50) { - entity->block.random = 2; - } else { - entity->block.random = 0; - } - }; - - typeBlock.stepAlways = [] (Entity *entity) { - if (FindEntity(entity->x + 1, entity->y + 1, entity->w - 2, entity->h - 2, entity->tag, entity)) { - entity->Destroy(); - } - }; - - typeBlock.drawAfter = [] (Entity *entity) { - if (!FindEntity(entity->x - 16, entity->y, 1, 1, entity->tag, entity)) { - Draw(&block2, entity->x - 16, entity->y, 16, 16, 0, entity->block.random * 16, 16, 16, 1); - } - - if (!FindEntity(entity->x + 16, entity->y, 1, 1, entity->tag, entity)) { - Draw(&block2, entity->x + 16, entity->y, 16, 16, 32, entity->block.random * 16, 16, 16, 1); - } - - if (!FindEntity(entity->x, entity->y - 16, 1, 1, entity->tag, entity)) { - Draw(&block2, entity->x, entity->y - 16, 16, 16, 16, entity->block.random * 16, 16, 16, 1); - } - - if (!FindEntity(entity->x, entity->y + 16, 1, 1, entity->tag, entity)) { - Draw(&block2, entity->x, entity->y + 16, 16, 16, 48, entity->block.random * 16, 16, 16, 1); - } - }; - } - - { - static Texture check1, check2; - CreateTexture(&check1, "check1_png"); - CreateTexture(&check2, "check2_png"); - typeCheck.tag = tag++; - typeCheck.texture = &check1; - - typeCheck.step = [] (Entity *entity) { - if (state.checkX == entity->x && state.checkY == entity->y) { - entity->texture = &check2; - } else { - entity->texture = &check1; - } - - if (FindEntity(entity->x - 4, entity->y - 4, entity->w + 8, entity->h + 8, typePlayer.tag, 0)) { - if (state.checkX != entity->x || state.checkY != entity->y) { - for (int i = 0; i < 10; i++) AddEntity(&typeStar, entity->x + 8, entity->y + 8)->star.col = 0xFFFFFF; - } - - state.checkX = entity->x; - state.checkY = entity->y; - - CalculateCheck(); - EsFileWriteAll("|Settings:/Save.dat", -1, &state, sizeof(SaveState)); - } - }; - } - - { - static Texture texture; - CreateTexture(&texture, "moveblock_png"); - typeMoveH.tag = tag++; - typeMoveH.texture = &texture; - typeMoveH.kill = true; - typeMoveH.w = 16; - typeMoveH.h = 16; - typeMoveH.texOffX = -4; - typeMoveH.texOffY = -4; - - typeMoveH.create = [] (Entity *entity) { - entity->moveBlock.vel = -4; - }; - - typeMoveH.step = [] (Entity *entity) { - entity->x += entity->moveBlock.vel; - - if (FindEntity(entity->x, entity->y, entity->w, entity->h, typeBlock.tag, 0)) { - entity->moveBlock.vel = -entity->moveBlock.vel; - } - }; - } - - { - // Removed entity. - tag++; - } - - { - static Texture texture; - CreateTexture(&texture, "star_png"); - typeStar.texture = &texture; - typeStar.tag = tag++; - typeStar.hide = true; // Draw manually. - typeStar.layer = 2; - - typeStar.create = [] (Entity *entity) { - float th = EsRandomU8() / 255.0 * 6.24; - float sp = EsRandomU8() / 255.0 * 0.5 + 0.5; - entity->star.vx = sp * EsCRTcosf(th); - entity->star.vy = sp * EsCRTsinf(th); - entity->star.life = EsRandomU8(); - entity->star.dth = (EsRandomU8() / 255.0f - 0.5f) * 0.2f; - }; - - typeStar.step = [] (Entity *entity) { - entity->x += entity->star.vx; - entity->y += entity->star.vy; - entity->star.th += entity->star.dth; - - if (entity->star.life < entity->stepIndex) { - entity->Destroy(); - } - }; - - typeStar.drawAfter = [] (Entity *entity) { - Draw(entity->texture, entity->x - 4, entity->y - 4, -1, -1, 0, 0, -1, -1, - 1.0 - (float) entity->stepIndex / entity->star.life, - ((entity->star.col >> 16) & 0xFF) / 255.0f, - ((entity->star.col >> 8) & 0xFF) / 255.0f, - ((entity->star.col >> 0) & 0xFF) / 255.0f, - entity->star.th); - }; - } - - { - static Texture texture; - CreateTexture(&texture, "moveblock_png"); - typeMoveV.tag = tag++; - typeMoveV.texture = &texture; - typeMoveV.kill = true; - typeMoveV.w = 16; - typeMoveV.h = 16; - typeMoveV.texOffX = -4; - typeMoveV.texOffY = -4; - - typeMoveV.create = [] (Entity *entity) { - entity->moveBlock.vel = -4; - }; - - typeMoveV.step = [] (Entity *entity) { - entity->y += entity->moveBlock.vel; - - if (FindEntity(entity->x, entity->y, entity->w, entity->h, typeBlock.tag, 0)) { - entity->moveBlock.vel = -entity->moveBlock.vel; - } - }; - } - - { - static Texture texture; - CreateTexture(&texture, "powerup_png"); - typePowerup.tag = tag++; - typePowerup.texture = &texture; - - typePowerup.step = [] (Entity *entity) { - if (state.hasDash) { - entity->Destroy(); - return; - } - - if (FindEntity(entity->x, entity->y, entity->w, entity->h, typePlayer.tag, 0)) { - state.hasDash = true; - AddEntity(&typeShowMessage, 0, 0)->texture = &textureDashMessage; - entity->Destroy(); - } - }; - } - - { - typeShowMessage.texture = &textureKeyMessage; - typeShowMessage.tag = tag++; - typeShowMessage.hide = true; - - typeShowMessage.draw = [] (Entity *entity) { - Draw(entity->texture, entity->x, entity->y, -1, -1, 0, 0, -1, -1, FadeInOut(entity->stepIndex / 180.0)); - if (entity->stepIndex > 180) entity->Destroy(); - }; - } - - { - typeKey.tag = tag++; - typeKey.texture = &textureKey; - - typeKey.step = [] (Entity *entity) { - if (state.hasKey) { - entity->Destroy(); - } else if (FindEntity(entity->x, entity->y, entity->w, entity->h, typePlayer.tag, 0)) { - state.hasKey = true; - AddEntity(&typeShowMessage, 0, 0)->texture = &textureKeyMessage; - entity->Destroy(); - for (int i = 0; i < 10; i++) AddEntity(&typeStar, entity->x + 8, entity->y + 8)->star.col = 0xFFFFFF; - } - }; - } - - { - static Texture texture; - CreateTexture(&texture, "lock_png"); - typeLock.tag = tag++; - typeLock.texture = &texture; - typeLock.kill = true; - - typeLock.step = [] (Entity *entity) { - if (state.hasKey) { - for (int i = 0; i < 1; i++) AddEntity(&typeStar, entity->x + 8, entity->y + 8)->star.col = 0x000000; - entity->Destroy(); - } - }; - } - - { - static Texture texture; - CreateTexture(&texture, "moveblock_png"); - typeSpin.tag = tag++; - typeSpin.texture = &texture; - typeSpin.kill = true; - typeSpin.w = 16; - typeSpin.h = 16; - typeSpin.texOffX = -4; - typeSpin.texOffY = -4; - - typeSpin.create = [] (Entity *entity) { - entity->spin.cx = entity->x; - entity->spin.cy = entity->y; - }; - - typeSpin.step = [] (Entity *entity) { - entity->x = 60 * EsCRTcosf(entity->spin.th) + entity->spin.cx; - entity->y = 60 * EsCRTsinf(entity->spin.th) + entity->spin.cy; - entity->spin.th += 0.04f; - }; - } - - { - static Texture msg1, msg2, msg3, num; - CreateTexture(&msg1, "end1_png"); - CreateTexture(&msg2, "end2_png"); - CreateTexture(&msg3, "end3_png"); - CreateTexture(&num, "numbers_png"); - - typeEnd.tag = tag++; - typeEnd.texture = &textureKey; - typeEnd.hide = true; - - typeEnd.create = [] (Entity *) { - state.player->Destroy(); - }; - - typeEnd.draw = [] (Entity *entity) { - float t = entity->stepIndex / 180.0f; - - if (t < 1) { - Draw(&msg1, 40, 150, -1, -1, 0, 0, -1, -1, FadeInOut(t)); - } else if (t < 2) { - Draw(&msg2, 40, 150, -1, -1, 0, 0, -1, -1, FadeInOut(t - 1)); - } else if (t < 3) { - Draw(&msg3, 40, 150, -1, -1, 0, 0, -1, -1, FadeInOut(t - 2)); - - int p = state.deathCount; - char digits[10]; - int dc = 0; - - if (p == 0) { - digits[dc++] = 0; - } else { - while (p) { - digits[dc++] = p % 10; - p /= 10; - } - } - - int w = dc * 16; - - for (int i = dc - 1; i >= 0; i--) { - Draw(&num, 40 + 150 - w / 2 + (dc - 1 - i) * 16, - 150 + 33, 16, 30, 16 * digits[i], 0, 16, 30, FadeInOut(t - 2)); - } - } else { - ExitGame(); - } - }; - } - - state.checkX = GAME_SIZE / 2; - state.checkY = GAME_SIZE / 2 - 20; - - size_t loadedStateBytes; - SaveState *loadedState = (SaveState *) EsFileReadAll("|Settings:/Save.dat", -1, &loadedStateBytes); - bool noSave = true; - - if (loadedStateBytes == sizeof(SaveState)) { - EsMemoryCopy(&state, loadedState, loadedStateBytes); - - uint32_t oldCheck = state.check; - CalculateCheck(); - EsAssert(oldCheck == state.check); - - noSave = false; - } - - LoadRoom(); - - AddEntity(&typePlayer, state.checkX, state.checkY); - - if (noSave) { - AddEntity(&typeShowMessage, 0, GAME_SIZE - 65)->texture = &textureControlsMessage; - } -} - -void UpdateGame() { - if (keysPressedEscape) { - ExitGame(); - } - - for (int i = 0; i < MAX_ENTITIES; i++) { - if (state.entities[i].isUsed) { - state.entities[i].stepIndex++; - - state.entities[i].px += (state.entities[i].x - state.entities[i].px) * 0.5f; - state.entities[i].py += (state.entities[i].y - state.entities[i].py) * 0.5f; - } - } - - for (int i = 0; i < MAX_ENTITIES; i++) if (state.entities[i].isUsed && state.entities[i].stepAlways) state.entities[i].stepAlways(state.entities + i); - - for (int i = 0; i < MAX_ENTITIES; i++) if (state.entities[i].isUsed && state.entities[i].step) { - state.entities[i].step(state.entities + i); - } - - for (int i = 0; i < MAX_ENTITIES; i++) { - if (state.entities[i].isUsed && state.entities[i].isDestroyed) state.entities[i].isUsed = false; - } - - levelTick++; - - state.world %= 3; - - if (state.world == 0) { - backgroundColor = 0xbef1b1; - } else if (state.world == 1) { - backgroundColor = 0xcee5f1; - } else if (state.world == 2) { - backgroundColor = 0xf3bdf6; - } -} - -void RenderGame() { - for (int layer = -1; layer <= 3; layer++) { - for (int i = 0; i < MAX_ENTITIES; i++) { - Entity *entity = state.entities + i; - if (!entity->isUsed) continue; - if (entity->layer != layer) continue; - if (!entity->texture) continue; - if (entity->hide) continue; - - int frame = entity->stepsPerFrame >= 0 ? ((entity->stepIndex / entity->stepsPerFrame) % entity->frameCount) : (-entity->stepsPerFrame - 1); - Draw(entity->texture, (int) (entity->px + entity->texOffX + 0.5f), - (int) (entity->py + entity->texOffY + 0.5f), - entity->texture->width, entity->texture->height / entity->frameCount, - 0, entity->texture->height / entity->frameCount * frame, - entity->texture->width, entity->texture->height / entity->frameCount); - } - } - - for (int i = 0; i < MAX_ENTITIES; i++) if (state.entities[i].isUsed && state.entities[i].draw ) state.entities[i].draw (state.entities + i); - for (int i = 0; i < MAX_ENTITIES; i++) if (state.entities[i].isUsed && state.entities[i].drawAfter ) state.entities[i].drawAfter (state.entities + i); - - if (state.hasKey) { - Draw(&textureKey, GAME_SIZE - 20, 4); - } -} - -/////////////////////////////////////////////////////////// - -int ProcessCanvasMessage(EsElement *element, EsMessage *message) { - if (message->type == ES_MSG_ANIMATE) { - message->animate.complete = false; - updateTimeAccumulator += message->animate.deltaMs / 1000.0; - - while (updateTimeAccumulator > 1 / 60.0) { - { - EsGameControllerState state[ES_GAME_CONTROLLER_MAX_COUNT]; - size_t count = EsGameControllerStatePoll(state); - - for (uintptr_t i = 0; i < count; i++) { - if (state[i].buttons & (1 << 0) && (~previousControllerButtons[i] & (1 << 0))) { - keysPressedSpace = true; - } else if (state[i].buttons & (1 << 1) && (~previousControllerButtons[i] & (1 << 1))) { - keysPressedX = true; - } - - previousControllerButtons[i] = state[i].buttons; - } - } - - UpdateGame(); - updateTimeAccumulator -= 1 / 60.0; - keysPressedSpace = keysPressedEscape = keysPressedX = false; - } - - EsElementRepaint(element); - } else if (message->type == ES_MSG_KEY_DOWN && !message->keyboard.repeat) { - if (message->keyboard.scancode == ES_SCANCODE_SPACE || message->keyboard.scancode == ES_SCANCODE_Z) { - keysPressedSpace = true; - } else if (message->keyboard.scancode == ES_SCANCODE_ESCAPE) { - keysPressedEscape = true; - } else if (message->keyboard.scancode == ES_SCANCODE_X) { - keysPressedX = true; - } - } else if (message->type == ES_MSG_PAINT) { - EsPainter *painter = message->painter; - EsPaintTargetStartDirectAccess(painter->target, &targetBits, nullptr, nullptr, &targetStride); - targetBits = (uint32_t *) ((uint8_t *) targetBits + targetStride * painter->offsetY + 4 * painter->offsetX); - targetWidth = painter->width, targetHeight = painter->height; - - gameScale = (float) painter->width / GAME_SIZE; - if (gameScale * GAME_SIZE > painter->height) gameScale = (float) painter->height / GAME_SIZE; - if (gameScale > 1) gameScale = EsCRTfloorf(gameScale); - gameWidth = GAME_SIZE * gameScale, gameHeight = GAME_SIZE * gameScale; - gameOffsetX = painter->width / 2 - gameWidth / 2; - gameOffsetY = painter->height / 2 - gameHeight / 2; - - // TODO Clear margins. - - Draw(&textureWhite, 0, 0, GAME_SIZE, GAME_SIZE, 0, 0, 1, 1, 1, - ((backgroundColor >> 16) & 0xFF) / 255.0f, - ((backgroundColor >> 8) & 0xFF) / 255.0f, - ((backgroundColor >> 0) & 0xFF) / 255.0f); - - RenderGame(); - - EsPaintTargetEndDirectAccess(painter->target); - } - - return 0; -} - -void _start() { - _init(); - - while (true) { - EsMessage *message = EsMessageReceive(); - - if (message->type == ES_MSG_INSTANCE_CREATE) { - instance = EsInstanceCreate(message, BRAND); - EsWindow *window = instance->window; - EsPanel *container = EsPanelCreate(window, ES_CELL_FILL, ES_STYLE_PANEL_WINDOW_DIVIDER); - EsElement *canvas = EsCustomElementCreate(container, ES_CELL_FILL | ES_ELEMENT_FOCUSABLE, {}); - canvas->messageUser = ProcessCanvasMessage; - EsElementStartAnimating(canvas); - EsElementFocus(canvas); - InitialiseGame(); - } - } -} diff --git a/apps/fly.ini b/apps/fly.ini deleted file mode 100644 index 65ad1f3..0000000 --- a/apps/fly.ini +++ /dev/null @@ -1,66 +0,0 @@ -[general] -name=Fly - -[build] -source=apps/fly.cpp - -[embed] -bgm1_mid=res/Fly Assets/bgm1.mid -bgm2_mid=res/Fly Assets/bgm2.mid -bgm3_mid=res/Fly Assets/bgm3.mid -block2_png=res/Fly Assets/block2.png -block_png=res/Fly Assets/block.png -check1_png=res/Fly Assets/check1.png -check2_png=res/Fly Assets/check2.png -controls_png=res/Fly Assets/controls.png -dash_msg_png=res/Fly Assets/dash_msg.png -end1_png=res/Fly Assets/end1.png -end2_png=res/Fly Assets/end2.png -end3_png=res/Fly Assets/end3.png -key_msg_png=res/Fly Assets/key_msg.png -key_png=res/Fly Assets/key.png -lock_png=res/Fly Assets/lock.png -moveblock_png=res/Fly Assets/moveblock.png -numbers_png=res/Fly Assets/numbers.png -player_png=res/Fly Assets/player.png -powerup_png=res/Fly Assets/powerup.png -R07_12_DAT=res/Fly Assets/R07_12.DAT -R07_13_DAT=res/Fly Assets/R07_13.DAT -R07_14_DAT=res/Fly Assets/R07_14.DAT -R07_16_DAT=res/Fly Assets/R07_16.DAT -R07_17_DAT=res/Fly Assets/R07_17.DAT -R07_18_DAT=res/Fly Assets/R07_18.DAT -R08_12_DAT=res/Fly Assets/R08_12.DAT -R08_13_DAT=res/Fly Assets/R08_13.DAT -R08_14_DAT=res/Fly Assets/R08_14.DAT -R08_16_DAT=res/Fly Assets/R08_16.DAT -R08_17_DAT=res/Fly Assets/R08_17.DAT -R08_18_DAT=res/Fly Assets/R08_18.DAT -R09_10_DAT=res/Fly Assets/R09_10.DAT -R09_11_DAT=res/Fly Assets/R09_11.DAT -R09_12_DAT=res/Fly Assets/R09_12.DAT -R09_13_DAT=res/Fly Assets/R09_13.DAT -R09_14_DAT=res/Fly Assets/R09_14.DAT -R09_15_DAT=res/Fly Assets/R09_15.DAT -R09_16_DAT=res/Fly Assets/R09_16.DAT -R09_17_DAT=res/Fly Assets/R09_17.DAT -R09_18_DAT=res/Fly Assets/R09_18.DAT -R10_09_DAT=res/Fly Assets/R10_09.DAT -R10_10_DAT=res/Fly Assets/R10_10.DAT -R10_11_DAT=res/Fly Assets/R10_11.DAT -R10_12_DAT=res/Fly Assets/R10_12.DAT -R10_13_DAT=res/Fly Assets/R10_13.DAT -R10_14_DAT=res/Fly Assets/R10_14.DAT -R10_15_DAT=res/Fly Assets/R10_15.DAT -R10_16_DAT=res/Fly Assets/R10_16.DAT -R11_09_DAT=res/Fly Assets/R11_09.DAT -R11_10_DAT=res/Fly Assets/R11_10.DAT -R11_11_DAT=res/Fly Assets/R11_11.DAT -R11_13_DAT=res/Fly Assets/R11_13.DAT -R11_14_DAT=res/Fly Assets/R11_14.DAT -R11_15_DAT=res/Fly Assets/R11_15.DAT -R12_09_DAT=res/Fly Assets/R12_09.DAT -R12_10_DAT=res/Fly Assets/R12_10.DAT -R12_11_DAT=res/Fly Assets/R12_11.DAT -star_png=res/Fly Assets/star.png -white_png=res/Fly Assets/white.png diff --git a/desktop/os.header b/desktop/os.header index 3b8ea8f..9df07b9 100644 --- a/desktop/os.header +++ b/desktop/os.header @@ -419,8 +419,6 @@ define ES_PERMISSION_POSIX_SUBSYSTEM (1 << 8) define ES_PERMISSION_ALL ((_EsLongConstant) (-1)) define ES_PERMISSION_INHERIT ((_EsLongConstant) (1) << 63) -define ES_PANEL_BAND_SIZE_DEFAULT (-1) - // Element flags - bits 0-31 for custom use; bits 32-63 common to all elements. define ES_ELEMENT_FOCUSABLE ((_EsLongConstant) (1) << 32) @@ -455,6 +453,8 @@ define ES_CELL_V_SHRINK ((_EsLongConstant) (1) << 61) define ES_CELL_V_TOP ((_EsLongConstant) (1) << 62) define ES_CELL_V_BOTTOM ((_EsLongConstant) (1) << 63) +define ES_PANEL_BAND_SIZE_DEFAULT (-1) + define ES_PANEL_STACK (0) // Default. define ES_PANEL_SWITCHER (1 << 0) define ES_PANEL_Z_STACK (1 << 1) @@ -471,6 +471,7 @@ define ES_PANEL_HORIZONTAL (1 << 8) define ES_PANEL_REVERSE (1 << 9) // Reverse layout is not supported with ES_PANEL_TABLE yet. // For ES_PANEL_TABLE. +// TODO Implement these! define ES_PANEL_H_LEFT (1 << 16) define ES_PANEL_H_RIGHT (1 << 17) define ES_PANEL_H_CENTER (1 << 18) @@ -542,6 +543,7 @@ define ES_FONT_SERIF (0xFFFE) define ES_FONT_MONOSPACED (0xFFFD) define ES_FONT_REGULAR (4) +define ES_FONT_SEMIBOLD (6) define ES_FONT_BOLD (7) define ES_TEXT_FIGURE_DEFAULT (0) @@ -2047,6 +2049,7 @@ function uint32_t EsColorBlend(uint32_t under, uint32_t over, bool fullAlpha); function uint32_t EsColorConvertToRGB(float h, float s, float v); // 0 <= hue < 6; 0 <= saturation <= 1; 0 <= value <= 1. function bool EsColorConvertToHSV(uint32_t color, float *h, float *s, float *v); function uint32_t EsColorParse(STRING string); +function uint32_t EsColorInterpolate(uint32_t from, uint32_t to, float progress); function void EsDrawBitmap(EsPainter *painter, EsRectangle region, uint32_t *bits, uintptr_t stride, uint16_t mode); // OR mode with alpha. function void EsDrawBitmapScaled(EsPainter *painter, EsRectangle destinationRegion, EsRectangle sourceRegion, uint32_t *bits, uintptr_t stride, uint16_t alpha); // Set alpha to 0xFFFF if source is opaque. @@ -2060,6 +2063,7 @@ function void EsDrawRoundedRectangle(EsPainter *painter, EsRectangle bounds, EsD function bool EsDrawStandardIcon(EsPainter *painter, uint32_t id, int size, EsRectangle region, EsDeviceColor color); function void EsDrawPaintTarget(EsPainter *painter, EsPaintTarget *source, EsRectangle destinationRegion, EsRectangle sourceRegion, uint8_t alpha); function void EsDrawText(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, EsRectangle *clip = ES_NULL, EsTextSelection *selectionProperties = ES_NULL); +function void EsDrawTextSimple(EsPainter *painter, EsElement *element, EsRectangle bounds, const char *string, ptrdiff_t stringBytes, EsTextStyle style, uint32_t flags = ES_FLAGS_DEFAULT); function void EsDrawTextLayers(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, EsTextSelection *selectionProperties = ES_NULL); function void EsDrawVectorFile(EsPainter *painter, EsRectangle bounds, const void *data, size_t dataBytes); diff --git a/desktop/prefix.h b/desktop/prefix.h index f728d6c..3b0df81 100644 --- a/desktop/prefix.h +++ b/desktop/prefix.h @@ -84,6 +84,7 @@ ES_EXTERN_C __attribute__((noreturn)) void _EsCRTlongjmp(EsCRTjmp_buf *env, int #define ES_RECT_1(x) ((EsRectangle) { (int32_t) (x), (int32_t) (x), (int32_t) (x), (int32_t) (x) }) #define ES_RECT_1I(x) ((EsRectangle) { (int32_t) (x), (int32_t) -(x), (int32_t) (x), (int32_t) -(x) }) +#define ES_RECT_1S(x) ((EsRectangle) { 0, (int32_t) (x), 0, (int32_t) (x) }) #define ES_RECT_2(x, y) ((EsRectangle) { (int32_t) (x), (int32_t) (x), (int32_t) (y), (int32_t) (y) }) #define ES_RECT_2I(x, y) ((EsRectangle) { (int32_t) (x), (int32_t) -(x), (int32_t) (y), (int32_t) -(y) }) #define ES_RECT_2S(x, y) ((EsRectangle) { 0, (int32_t) (x), 0, (int32_t) (y) }) diff --git a/desktop/styles.header b/desktop/styles.header index ace1382..4b4823d 100644 --- a/desktop/styles.header +++ b/desktop/styles.header @@ -104,6 +104,7 @@ define ES_STYLE_TEXT_LABEL (ES_STYLE_CAST(1391)) define ES_STYLE_TEXT_LABEL_INVERTED (ES_STYLE_CAST(1393)) define ES_STYLE_TEXT_LABEL_SECONDARY (ES_STYLE_CAST(1395)) define ES_STYLE_TEXT_PARAGRAPH (ES_STYLE_CAST(1397)) +define ES_STYLE_TEXT_PARAGRAPH_SECONDARY (ES_STYLE_CAST(1635)) define ES_STYLE_TEXT_TOOLBAR (ES_STYLE_CAST(1553)) define ES_STYLE_TEXTBOX_BORDERED_MULTILINE (ES_STYLE_CAST(1399)) define ES_STYLE_TEXTBOX_BORDERED_SINGLE (ES_STYLE_CAST(1401)) diff --git a/desktop/text.cpp b/desktop/text.cpp index 9b2ee65..ce3ad60 100644 --- a/desktop/text.cpp +++ b/desktop/text.cpp @@ -2566,6 +2566,15 @@ void EsDrawText(EsPainter *painter, EsTextPlan *plan, EsRectangle bounds, EsRect painter->clip = oldClip; } +void EsDrawTextSimple(EsPainter *painter, EsElement *element, EsRectangle bounds, const char *string, ptrdiff_t stringBytes, EsTextStyle style, uint32_t flags) { + EsTextPlanProperties properties = {}; + properties.flags = ES_TEXT_PLAN_SINGLE_USE | flags; + EsTextRun textRuns[2] = {}; + textRuns[0].style = style; + textRuns[1].offset = stringBytes == -1 ? EsCStringLength(string) : stringBytes; + EsDrawText(painter, EsTextPlanCreate(element, &properties, bounds, string, textRuns, 1), bounds); +} + #elif defined(TEXT_ELEMENTS) // --------------------------------- Markup parsing. diff --git a/desktop/theme.cpp b/desktop/theme.cpp index b8dce35..09908df 100644 --- a/desktop/theme.cpp +++ b/desktop/theme.cpp @@ -1465,25 +1465,8 @@ ThemeVariant ThemeAnimatingPropertyInterpolate(ThemeAnimatingProperty *property, float to = *(float *) (layerData + dataOffset); return (ThemeVariant) { .f32 = (float) LinearInterpolate(property->from.f32, to, position) }; } else if (property->type == THEME_OVERRIDE_COLOR) { - uint32_t from = property->from.u32; uint32_t to = *(uint32_t *) (layerData + dataOffset); - - float fa = ((from >> 24) & 0xFF) / 255.0f; - float fb = ((from >> 16) & 0xFF) / 255.0f; - float fg = ((from >> 8) & 0xFF) / 255.0f; - float fr = ((from >> 0) & 0xFF) / 255.0f; - float ta = ((to >> 24) & 0xFF) / 255.0f; - float tb = ((to >> 16) & 0xFF) / 255.0f; - float tg = ((to >> 8) & 0xFF) / 255.0f; - float tr = ((to >> 0) & 0xFF) / 255.0f; - - if (fa && !ta) { tr = fr, tg = fg, tb = fb; } - if (ta && !fa) { fr = tr, fg = tg, fb = tb; } - - return (ThemeVariant) { .u32 = (uint32_t) (LinearInterpolate(fr, tr, position) * 255.0f) << 0 - | (uint32_t) (LinearInterpolate(fg, tg, position) * 255.0f) << 8 - | (uint32_t) (LinearInterpolate(fb, tb, position) * 255.0f) << 16 - | (uint32_t) ((fa + (ta - fa) * position) * 255.0f) << 24 }; + return (ThemeVariant) { .u32 = EsColorInterpolate(property->from.u32, to, position) }; } else { EsAssert(false); return {}; @@ -2188,7 +2171,7 @@ bool UIStyle::IsRegionCompletelyOpaque(EsRectangle region, int width, int height void EsDrawRoundedRectangle(EsPainter *painter, EsRectangle bounds, EsDeviceColor mainColor, EsDeviceColor borderColor, EsRectangle borderSize, const uint32_t *cornerRadii) { ThemeLayer layer = {}; - uint8_t info[sizeof(ThemeLayerBox) + sizeof(ThemePaintSolid) * 2]; + uint8_t info[sizeof(ThemeLayerBox) + sizeof(ThemePaintSolid) * 2] = {}; ThemeLayerBox *infoBox = (ThemeLayerBox *) info; infoBox->borders = { (int8_t) borderSize.l, (int8_t) borderSize.r, (int8_t) borderSize.t, (int8_t) borderSize.b }; diff --git a/res/Fly Assets/R07_12.DAT b/res/Fly Assets/R07_12.DAT deleted file mode 100644 index f432ca9f521a0daca1b64941234aec3e5ad68c40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1261 zcmYk5y^+E&5QTMA;1X1VOVB|BF2NX3 zeJG`$O1Yg5FSr}7K>f736=krLp?pR1o^VDXyaN|2Sb=gjtO*-RSlO&# ztyqg;PG~4CVeuSo$C^-p*-!!IC`?Nk2C9W6*bHIdgbH61#=WF)9l@S3vx1D2+b3u; zit4mV$#6fue-_RogE5%R^lL4y`erBr~q(mxDl!q-K zPy&Su_JocCJPc|@D!MzMD+84luo(11JyKawIFDYW?hGJn=crtn@J9HV5C*+k)OVEb zFgMjepkwi;XwGb?1~Rf(sufErl@?320?lTH}Oj z5mtun6XDgc8NxuOk!cClFaubN6=j$+K$-3qmg=-*u}gJ879fi^Q&w1E&crU1)u0yP wQEynx85zwXBWrh9vN92LvT%~r>|0ee|Y}#e{FjH0cG8`AOHXW diff --git a/res/Fly Assets/R07_13.DAT b/res/Fly Assets/R07_13.DAT deleted file mode 100644 index 4a92c5df65b5f41ba913664786c18bc38eaf43f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 775 zcmYk%v5~?+5Jb^|BLIb<5EO!rO+Xs%&blxNM7>5#faGE9#@%RuvN}K=pbj`X$IY9kR-+n=F@tB0_n;*vV>AXs9m*XE zI}0x-;iNMLV>Bj%@vU6=i-__SL0PZQ3GGa>@fPC(<3dYl!!=RqRD)z8;pW*;a&rPE zj)3lYB-%BTdt%@S=xG0hj!1esObP5$8J`m!N7|4Cgi*iWouI?#2xH@tmQ8UM*aQ)x2kk4 diff --git a/res/Fly Assets/R07_14.DAT b/res/Fly Assets/R07_14.DAT deleted file mode 100644 index a239e8598a0ed6a81303b3301e5258f58321fe51..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1198 zcmX|=yK#g-5JX2(0)#*ags|cgAOu1ngf%fS&s_7&Gi6e;6b6CF(7e|58dSaN?)g1zzM8Y z0PVx{g)qus7!4D!q@@kX6#9&=nhf+&xF+I_t>fCdZ>0}-jv zP#cozowZ?0<)VsAKc{E3A=4FJXy^m`rRt2Oa{4G!0Xk!81kg~{gbHj1!o}eepw9)g z`L%ORkV1LGLiwMSpy{W9a%C7%2s2%PRjmk6WE}~24&>RaKugf2JT{F0bTU?PcyqWK z7J#sTurkkt$r+6xqdr)ptCV4l9fid@94J#N4?r&*pnL%K1YH3%lxm<)S5&^G^0>W4 z{Cx9ec$Jc{7>Z#u42Cwpb`C2g6>WGWXapH4H9?C3Qn0iSAnQy}6(Fl5>|6nChN`<# jDOOg)VvtocGdVm0bPk{;3Sz3`89!U<5{BgP^bgBQOFZP*PG-Qc_Y~ARcMdGk8Qw zuV7gzMuIw_Bh}fo2`X$7T1FTFM$4oIk4juAdbG^%v-_SA_&g#e8^JTp>d|Z{X0uTb yaeW}E0w+6|%b;b9;=tk_0mtheE>zE%pdO3>qe6^;|Fpo_-y+^Go^Ql_*Yg9)##X8T diff --git a/res/Fly Assets/R07_17.DAT b/res/Fly Assets/R07_17.DAT deleted file mode 100644 index 513b28d9cf5ccd43efdde92cd554659b0e86172f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1432 zcmYk4v2lY?5Jb;X1C*c==)m8i0ZO0*mGDD_gbE225;|lYxeOKJ!1osRj{-Dr_V(`f z5a)<~h^W^SKM~!Kup~ST--gxjG%SYMa0hA*T!(W+VX{k;VKnrHVz>ZXZr{j5jLxMn zyj+q8^MV3YLjjgl8ibYlb(A6!A``Y4)t&{|X!p{ap#snB(!ht?ffjyWk;RNn^5jB-y{fH^_uY}ezhqNpT=1N9QvMVD4o1KYI= zkMaN;W-h%sYKt*CPjRUQYkBq+nMdZDAP+Fp1t>G1E}(T??CFP(h~FQc6X}kDz+{gS z(q2(0Ndcr#YUW~(@^pD%j}qJtpzNN6&ZUb%$}0zk6#sBU<|!;?vdn36?*~TV?C|Jm1DHZ`OMfYYv5G=OS!h=OSMcl&Xu9`w5Wy+KzHbGRb z6jTUu#fiOG1}*##tStPV_wo%11RmZW-#0s(?1r$8Aq;6Jgg%APrRL|&v+3cD{nUJa z`Z#@l|0|j`HET@Gi|70C;MNtwos><>tZyH_#FO8zWAkUcpRRtomztLskK?r`$FaF| z=Rtb*?oDhiKf0S;0m7!kz7=po+7KQCr7vZ&Wx84E?w8Ptpb zW$JYS%FLAtb&fI&lr@ zwgOAL2ySZ#xLWm5#jfv{TLwsIQY^MQ6DQr4aU^fMEzkn61x)k739I`_PaMTJx7DpA> z;n&KTlJ_iJuy_itS5~_Xg)pxvJ9Gf=D*)U^1r5Zipvh9ar8=#Q!mgFiDFC}F$U<3r zMoNyGGj|5sHCSfOjiCt02#N#OQZxEHpj61Za0^$c)`&%T5LiZ*wtGvNV3smK@2x)l Jv-)j){{xhj2-*Mu diff --git a/res/Fly Assets/R08_12.DAT b/res/Fly Assets/R08_12.DAT deleted file mode 100644 index 89b732d5e2cafbce81578331181b131d577be072..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 766 zcmYk)v2}w$5QO2CDxd_FKnch+KnavU2^T6PRCu96LPDM*mq8&8yffxU4tVFGcP1gbMu|ScLdnoAduNqa zmG<1n&3ZvY$xWs0KRS{Y41&fOK>-u+S?ZZd&fzPGXI9Tbvi6sV@3)?x{9K)%U#pgN A>i_@% diff --git a/res/Fly Assets/R08_13.DAT b/res/Fly Assets/R08_13.DAT deleted file mode 100644 index ebb7c06c4603fbeb1335d31384bf75e7e128c054..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 838 zcmX|;v2nvd3n9ePQ%r3Gu#c$ z@Bo(FS+jt~EUwVd?$VYp)Q{JtBV8n#j-v-jic6YKa&w~TB!{f&Bnysa8I-U_cd{DP zg{%hwjR3B8ieWO0h9?Ii4^DKcX8Cq~1f0NO!?B)Ux3Bd*_nrS|QR+A?zx)D}EGdZu z?MxzQ1`^3Q0!r%Q!9(8kvK{tO0(??pX8~O*?I~~dE#l{!Upie$0VOhd0wo;KfJ&eQm2ja#LWLKqjC+n;28B5A{t-jK4xUg&E{$)5;PBrpd>s=W=>(S4)T6Lg(sWw*kWRbqz%?j>M9jpN0@GNr5rRww0QsD_rHF}4H+^0_q+pb{P_ zfINT#@kogT{SLWBnR6b79~ca%R+^z3c0*tuGAEWR8ONUpMLB@XfR6X{1jp&#oKvh+ cE2l>}m}B|oGx8+#%vqPOh~FQczpNKM|D^<)YybcN diff --git a/res/Fly Assets/R08_16.DAT b/res/Fly Assets/R08_16.DAT deleted file mode 100644 index 7532e449b74098a0d10793f00d64d82f401a58c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1738 zcmYk6v6UJ@5JX3J32X=(!e($INMJ+Q5C~yROw2RK#Ke@jlBF;<5E<(Kq32=n?!T() z>Rt}`D5afBsppSU%DI&5`LmQQ;DXY_`Uc1d`#apQj!>=%4Vdf+pm1ayr%;8Sl`!CV z4KQ=0)dM_?jDR&xbytrS3q6kj3x5S{sR-YpOelosgrSsFj#Fe>WOm>lP_Y>AD1a6# zI@T?%Ye3B@?_qo+19%u=#{rj8crb+`Tml-(7El51=>V3%t{sJOd&o2ttdUV+s%DQ+ zGdu;b%ojBf%^3C{se(QF2Ad<}2~&?#hB%VrhE z1qvNU*~y?Bz%Agxt`guqWCWB|D_qaO8ad161$$q2N-6BPy&YKco;7${;IHjfKw<=^>@%}89oA3 zfM;{QnRO@;vF8z1=Xl@_@O2RSJ3O%XJPR#>&$G&wa7kDbYQhp=Glwk{&MKdAOehzW z9^gHD0*X^)v|1`P0m}^k+yREkjH%H)&UiNGVN*g}^qeZ8R1V{K;mAUsYdnR(_(~XS z0@eh^XA~aU9x^H=z~9v^z#hT^<7Th~6fMT>VZ75!#>bfgES%rrMg~h*0-PcvVD{W=)i~603}cYC0t0Tknlo6LPFulWl)F%?;mLn>peaGo1LB8 zyF;6Z%NX$(Hw)Z>DV3X{0oPQnh6!k?2<{0xo8_ThIV3CRHLMDtwE&eOAGOb^sJ&)a z#D}>8`%AwSgXD`tV72ptxA%K=j2Q6{6 zLg0)CXohMih5*`-Ib0lO$LSYGcCYLxdc~E+L2Q5M1dr@*;!`d|)s)0fq z(o?!(sE4(SA1%s{)&hbqo?@tm+3+&x{DS^kje zsVHSwftkDcGJZt-eDl(kC4D=AnZZzsAe8`0f)qeXP0*H`fzoma26ChTOBc$pL0*qH z(p*r0w@2GakG6w(@=iM}-}`et4Lmvoa{At7uBix0!V+j`E&)rRA?yLvj;Ark{2y*s U?uN(snS07V+iv{LS-$lC0eLdMw*UYD diff --git a/res/Fly Assets/R08_18.DAT b/res/Fly Assets/R08_18.DAT deleted file mode 100644 index d2fa08dd14c93440ab3a19f2a58476be8a72f713..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 883 zcmYk4yK#e15JlH=1C&4sbl?XxKnW^ACA?4}p~4qBROpa#;MVId?y> z=n^r^5zBmusAEI`A8Fo!m?Ao0Pq+bHMyqQEn+MQmB)Gf%na~rlLJ>w?n00<-PcC-N z9l)Gjin=t-D+II)N`f8?bHdfdCoCA|$N<_E?!r`eDdKfbqsi0=h*pYeKL=_BQ6Vah zmIQURgpOAp63Ub{n9UG$t!bK#J^{z97@!!!P{$*RNO)$Ay11dBOvg8U*swxTHQWqW z!(dnp#n2l%1Am*&*U;oWmkKsRGgLz{gn>Eg$|wGV-^p2{`)mnye2Mt_Ayrg?h(iB60s*d?+LGj&CnUz=(Krf^h~pWRD%~I3I%usc*2ERx};KFD5c^-A*In~ zSPi5$rwTBpQoL00DHZLS6LbrjmBKt=21cNK!enJORKo)x)dNF9^Q=}DoAt$L-kfU6 zZl!^~56y?;QdprlATywz{&S>*q39TZjsa*ys-3X10%bCcURn%;p$En^cZLAwR0LDP z$-e;Q0BSK?j;(z6!ns5rS3F-UKCKR02|FDUJg{d`e}ZIF$oB3RX!7 zfRhif6;cM)UQe*6;_jUkV|3Nn8iFa6#h@BnT&EBxHGl{45U>QF^O3M6v;>ry1MdR2 z0IX0`(sENQD_$?wLyC9E7zad-;dy#}rao2Eu>f1Zp2fC&APNUsp_jWe&vbo>`1$6o z8Z6JeC7}EdU!Qj;<#?B}GV>7JfFiK93*J$H2Fyxrz$CD>q*4SQSZl&9;hqoz$6G4I zJ1HhK@TC}f)_f*B&fs&{#sTiWNpYMO2D%$=32Q=0SOkvG32ft@H?7sQ`ydn zi`kE#6!v2vK8SaL=K+o})*NifnM;B#iaq=g?DfK@=R80`VH*L=Sp5GiXE>f*58q{V NTJQsC^;gmV*B|jV#AyHk diff --git a/res/Fly Assets/R09_12.DAT b/res/Fly Assets/R09_12.DAT deleted file mode 100644 index 90b51fa40eac206ed93ff96e9b82810df1988505..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1504 zcmYMzU2Kz87zgkJERSY9d1N-vM=WRiXR*dQi`k7$SQ%fM#^2v3u-uOB4T`jqBe=K;t{-!Ml3i(!!l# zJnrYL7qKvQY>I*EO3IOLOk4W$;AYtS>p=f~RELkxRe^eM_u8Jb0L`y?AL%2E`ej=X zIof2Yc-t;ieiH>fXskx_cYjz~ed-hZ`~4Y9t)F@5K3WKhe7*=p!9>vGS3kw_yF6HP zM-rEp%>}joUXGT=m7sB52?QT3292(pg50C&pn@aiXwAL>THQMv@#qyxEeBph<=V-h zF(=E=Q27?0G!en2W*&9J_~S@l$XeRlRf~d|^`Oh4D%AXJLB(a0P_dv4)O~3S`uEP~ zdG5WAT?O3YR&ON^bxi<0x>$j)ik5;3Pt3*jTMIxt*R97uEl1|nZ$e*k1L1(qs4!lvual0*J?g#Xdr>UNn9{il0fN?JpAd_3Iwn44;R0=3fFFP zR#iXHv3~~WmnjyT|F$SJrU}L*G1?f9krBidNkvNGD2LN z2m&js3}2B|a7t>cy?l3z+`oqR#JS<>?b zT~mn!S|^XBL<}z(U5X1r90>_>c6ceP2o%1;Qy7IG9nRvfp~}+26_iKR*pWlm;zt<) zM;zpNcE~8?QFjqvky0cTafPRl?(S9v?Q#l18%7v&rBmL+5qAl)iHCCT!mgZ$~a_x}#bPJ{pe diff --git a/res/Fly Assets/R09_13.DAT b/res/Fly Assets/R09_13.DAT deleted file mode 100644 index 6a73a66f8dbfc91b95a5cb665de6f5d08efd8aa2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 811 zcmYk4v2lY?5JcCw0ZO0*O89~XC_yEtgdY+rRQN-M3LP?zTn2?W@VynsIAG>!Z+GuB z&`E8U#<`Q80c{F+1#AGy34MAhqdG||N(s2-NC5GM2e26^sVJdd4v!Q-PbIDZ_n=&J z#gb4Gd^4UQ6<>&Q#02CL}-0%P!Py+T;444~= jdlCvT#tJtBZZ_n|o)V)I#0bSHK>Cn=zIlG*NAdFq!Ki)2 diff --git a/res/Fly Assets/R09_14.DAT b/res/Fly Assets/R09_14.DAT deleted file mode 100644 index 92773b3041a5b2eb4b5aaff3295817d20887e73f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 478 zcmYk%u@Qnm6olbb8=wSAu!K_@pae^>gbN7?2`?lhBxH;%!$J(a|LHO^!^}5t_uaus z>N{z>9;K!tcNHsO0ty%_Y@o5QW#c0ZO0*ci=-bKnW^=5-ubpB)pK2P@%?=%TOT>{JtmcjhNBQH}7X} zb>a|lzl45=h&F6c6UrXydCM5cbR~w(DhU-}vNOQ*A|=#v_~Ao8BZ|N+uR-f6WhDH@ z0$vGjk(pAlg@U#2gN1?>0CNmX?us*>Lk7!rXF^KLa17h>MG)*$1v4!&-jIv|t6>$v zlHf2_O{GIa30Wn<7Rz5biz7OWK3$40v#51KVdq;y1#VIdT+2OM58y7vK*n=WJb6qD zu*K<~T+b25oZJ91hHJK}z-KYgEx-zE^nKQWsj$W)Cp*mKKBu=vGF+5zjCT)itP0BT z5%K%Ovni{kolmp~e`Vdk>lm=gpiBrH1|q{pph_{61Qch0WjOG6*nN~S>m9BrMVaD( zI^7CuID^#{XLP`7EwWxYuw~sq%RqRw_KI6A>wq(J0(F07l$ptk;GHl5Se^rP#hE6> Zb-tICx>p>=a-Fa23@}~(bgSQf{sCYRurmMv diff --git a/res/Fly Assets/R09_17.DAT b/res/Fly Assets/R09_17.DAT deleted file mode 100644 index 432130c942ea1c6473690474dbb510c3a47db2a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1018 zcmYk5v2nsc5JlIb0hOQ<=)i|)fD%-KO1O|vA>oCDgbp>1T!sp9;C)|w3^ST}{Qq}v z_YhsgbdIQ}L&T8qICp%DxB%N2`AJv}gr!`8F|BGvfPz&F)tP!qYj&876si=)`p-}m zV?+bi1X-H_MO8qI-E&l+*#as`eFs$)D?n2wSMFIkY;g&DdBQ8RI=mTzs>bkE2H)Y) zPz)2m5ih7#X2TUInQ2xQ!_6RT%0o3X;XBsR%Hnx$hKH^DyP}z~8p8vtVKW4sv9t~_ zSSf~!VKQiD!n2iX(1KW6hZo>ss{u@?b+}alTL=~d?~fG9cNm{Ar=o`3&kMfj+?)Yq zt?!@=gQ;O8^i=hR!B7kr1BdqK!~PQ#uCCf*RQ0KOmM&qj!d|kPf!(DPhnwId;^&*E bd;T35Y?GD1VCozOW|nd^6v1!GpL+fP(QTip diff --git a/res/Fly Assets/R09_18.DAT b/res/Fly Assets/R09_18.DAT deleted file mode 100644 index 2f180b06226c67246da158f6b453b3e1c9cf5f46..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1432 zcmYk5u~EZ75JeXVNL7MLPzRi?23&$dLYHtM0f9rp3mrNn6hxGvLI~LR#lNvx45`Qy z1{5`YOSoa4th9s=lw##%phZ1A?Pm32!f*?nL-#9j-~y0Z@c^2qB`AJ&{3D^_sQ@c8 zm_Q|z%e_)C(_#hi1i@#U4^BF{*%G0_M?ylmzv@Bo9~j z=Dn8rA>!woZ?`poM_$0wxp`1MyukR6`i*;on0G^`gbzG(qz;E5$%u9+VsFaL%5}WdtaC z6hIzQySYP_CgOZLXl9fvPry3wzOnx90#@z^N?{%WO$9XFArI`Zr@m}XxXr)0#f!dw D!QtX# diff --git a/res/Fly Assets/R10_09.DAT b/res/Fly Assets/R10_09.DAT deleted file mode 100644 index 1c2a80a816343bf7685eadaec645fc8abeac113c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2026 zcmYk5y^$J07(_?91PFl;2w}CCz=l8wgfJ%NnwV>1VxGArOJNX*41MoGkB%y+SKa;n z%q;t(wLic4{%oy(@_oY!>~m{hfk)sT*np|3256xe21faf@RIO3a0xKWp}mwVVc-%t ze}1%fFXa?v0k&jlxX-1m1zOjFBN?Ct4k;Iy{-laohABTMJo>1xVJA$(OEMj}mEz7= z1J=y)>{tS`Hmt20n!!@(rM%8w;E1Wf>4a5)p)B;-OF00o`gjQ_4dq$j0Z{}p+x)f+ zZ)Hu{$37^>C?}wo(xVJ;)v2rt7O*5dphcMiqv0{i0br;-2sdz7h8(dSa0 zr3jo$I0UdZGJD`u)`UX2uzZI*BhFEJf%^c4dCCIMOCY?_aEk(Tlt!)A~s9;Sf zJSHt}^@*}Xp=w9L8en)WrKjN&prM&#tW#hrunI*u$65lEYi$7*^IZ2Rj{pzXFwmJ! zl^0IfD#D}O+pvnu1iW5gSccb9yk3VAM!5zI-%^fs!D6}%sS=nzz$!8VmJR9SEI^Bf oqiU=%!aZvUG}Pi0Du4=WjEulgfm!a%tS46o?163m%m2yGKjH&pd;kCd diff --git a/res/Fly Assets/R10_10.DAT b/res/Fly Assets/R10_10.DAT deleted file mode 100644 index 6e7064779549d6cf063f11ff940cda83c7404e40..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1666 zcmYk6y>S9D5QW!v=!6m|ff9shfD$O-N>J#KkWit+3kh!=xeQ8h0S>(16HnutVdmrQ z+aIkC-Xh8=Vt;y#xFtj+ToYPN=m`ZNB=}6|D6Kv{9}e|Y4svss7{93k@SS|WctDBcoZrI2AgJ0$oE#CbvnQ^VYBiu z=n80BrUGaTDU|}$Nf=8opoGn%JE5rncvQJeGajyBGw3*&bwEJp0v4aW8FXKSu2#5Z zwYXX72E727S9^eFB>+5{hb#eg1oRTnOTZX{#c(mGGUsabxt5Zk!2mUlgkE3AS~kN2 zVBr(yrO2~oR>9K~0?^EWMpY=s=!OO`Y5^Eka5fafR-Xl1f;_+{KgLK{4MRzB!U&~u z$HVXfvINCIK`HxeDtK54D?0-VS7k<(`CwpXDHp?HSQ9i@vqBx2uLc$+r5o6x6w(DK z>VE$Zs*Ezt@-UBpf&y9yXewYH!D6@=&W7%79IWgOJHuvASYd~wMQ&bDredJ7LZnag zyur@JktGGQ0JC7tUN=0PYj_MSN(!Jlm<23qg3|LH$-ly^^OK?T=_TU(i_b3sJ%79? B{EPqq diff --git a/res/Fly Assets/R10_11.DAT b/res/Fly Assets/R10_11.DAT deleted file mode 100644 index 2a03887c7967b00b94856145db4c95d666588dff..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 973 zcmYk(v2nsc5QX72Zonl_f=W0<11fR7l7;av3hff%kvXV_?SkV{iBE zAwD90zWF;u+|Lp7xzI*F6dqNXz*@K%SFpGORO!NJ#86202#hO-K;`6VUlHEL(#}*C z7C>cHrJ83SspnZoLN};rDm_I-TS3phw$*atPEB&^S;aP&4DI0QIbeHr7=^fT%m`i0Ax*k~vaND`;sN z-5@7V2hR6EpcNp;{YX9JL{xNL4YXn#2 z8ehhdtMV-dqZyNt#>KcAv%#;U93HsP-=U?8D?pXiU`iEo1d;`|3oI45hAuLA KZxQjwn_mAxw2?;u diff --git a/res/Fly Assets/R10_12.DAT b/res/Fly Assets/R10_12.DAT deleted file mode 100644 index f1cbc9d089e8bb40d663774b471fd0b7d36ff560..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2035 zcmYk6y;UPY5QH1u1)vZVfKZ@%X5! z{+ZFhA)>!W95086=OtpD66S=6gb%|qy(s;C&j`Mpc^HO)hU)YA3WE_;{ghj2hHj|v zVr2zrs0`3h7+Mg{2v|e2$OyEUGo`2;Yr#?#pmP}%UZ%ZIBxpoSP6|!mUlHwkisXZ z@|McL8VL>H{U`%0vJ$$jJF|GJ8bPLJ-LUkK3>v{2+7L?{0;Q;mhOz)v0m=YZ4{ZQL zD_rIG%db2^TFt9=hpS3q%GD4!Iip#usxY8TOuNz(RyuRxohqO*A1H)ppd~yEvQWyZ z^1G|f01a=3T4U>+&9`tumDfM$iZhwSY$O2pWNV_sNaZm&hzs9;;EMnmAKvo` zM_XTJuRrdKSzXPh)o~Xd!YMoh-)5U5xI8>*SSe|4dVV_Be gok`*pAeOIr9H%*AAFwgi9Xo#tug$T(c^%^V0PQz$QUCw| diff --git a/res/Fly Assets/R10_14.DAT b/res/Fly Assets/R10_14.DAT deleted file mode 100644 index d848c5aae257933efa1d49e0843614c1c6ca9731..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 568 zcmYk3u@S;B5Ck97042BtN|5EoJ|rY0bVwP3h%!_N0l#Ox2hT9GKJ7iP@nq)J%<8m* z10@oHCHRs_xH|GU+K{((0If#yh@=A+i5%*J$VT$YBwNU8c|tkr>5v?bt<%2q1>mUE zkqBbao&K8bj;L2Zg5(WYq*#6;=HHVhhkQulEBnPxi zdV;Qlqw4^3Ua$bnab$KjwE&Lz1Zq74)B?0Ka>S~c7(`*&1+WB{pc2kv11fii7w`JVDuVEyr_ zV9m^u@XV+X9+@;;3$%LR2%G_|yA5j}8(sqM1*1I57GQb9C>!M;1vg-i1y~L|W6{tm z!die9phbB0xl{G$e{0Q%H{e%UDo23|uwnf!un*+|Bec!}XQ4O(un%A#z}Epf4FTU2 z*rWKS?d8*23KlFBGk~2ryR#kzH!@qG$GQYs;HYw|&Ok4)oUpJ)SpqFU_|<)CCD-6j zGL%?UsjPvcz|LoYeN@=leK>`{@>(2FXjQc^ls>bwVWzKGOIa#}2h@h6ykII@miJN0 z8IJ;tn=j~Qs*egId?sK|xe8S(SdIW33OEb!-GSNA5$rr?jc_T3IfWZiHK3H0>0S6z z|J9#-OW`uL4y{to0B<^~3LL?Ot8n4d61eaQ4n?tQ4^X8-XERI}m@X^@W>`a|2i5?Y p8FnbjJo|*sk*Ts_4;+Crz#3-Qa10G_Wv;6ojAc1}K3NC;_1cC_yE-gbNiqbaQ2doe_w7?O-dW5z50EZ_j3v+fs0gGS;c+?5F zy=JVmWU$;qIX8s?XS%@e^(E+7Kno13P`WEXmSLTQ7g;NNNM_FVF42!iRIuJ@>u)(h28Wa4wYz1yLv| zB&uWqiheAmrENf|4s)u|0Ava+wkyOEmAnS7ql7M+ku&lrP;pkmES3PA4)f?3>LDy? zpbOi92>|Vcon6#`T)gFeoc9xuuZcJXlLqxcN+#(d#J0w_xD9DHuux#~>h?fIvcG zP&6nQID<^@PBXSaz&1wh3Y?yfE78o~266};g)Xk#Fu+ij$_6+Ol_i6!L27^<(u4hQ z76J*G0hT}oM~!B_1FD~ zSAm-c&=&?7uqBI_u&5&C#2FcXc$0Y7d!-v zh`%?SSbg>y3XaQCKfe!VJ#;l93qIeaX0^WTDB&fS$)tJA@sKhu#@ zxx>L9%dN?W6AQt=_;OonxBm3~$#hy4e}4>q<=P$T|57+R(-he{5d4j5U0U5kCBJ9q z6REsCs-<^r2}isp&o<@a%J-75y?-XVriOigW#N&uHy49HU3(zQbA!I0uiTgVG_wo zvh}k0#}m84yNA=}pDbMq4?a0&{?(OF!;$qL%wL$^8Ajiam_N2=QwXy|!8cb%!q1D( z%x@ffZ;!q@bl11{-wHE34+j7E#f~sLzF_|E
    *F+0P3MMyKJ7*^vKTHlLV!pD^C*Csd?>8 zz=#DY1dOPada+(SmzXL9aS)hFio-(%;CLbtLNFni z5~K`VzMX+6uA#ehmiyj=AfFl!P4KjBIfoq_1 zVZ-@VXNZ6~DS%o@DwP5Uz`1%u1@lS)Si&U`*bvuC4*&{FPzp3;3V;+9K$MaMrJxe< zPX?#pmx&ZV5;Sb%I|OtDT>w0UZU(+e#Q7b<%s4zO0qRmcf(=pP2tY%f9Tr0$ZU{(H zN&$C9sZOyou7yKUB6KrwdS?*0Axea{0H>gWJ~c3oh6KKDtP1D~IszUC@dgwCR|V81 znxQZb;PPn5vtw1J0PNGsz_YhARJa5v2@qA9k}@G^WGLV%GDH9r!lmn0Bbk^ SW)WHfq^O{?vv>Jd@A(MsI+Pgz diff --git a/res/Fly Assets/R11_11.DAT b/res/Fly Assets/R11_11.DAT deleted file mode 100644 index 3b457cdd5c2566bf946efc063737beab5c6b23b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 946 zcmYk4yK#gt6h)uy1}I@mpad;6KnYs{B`DmG(4j(y8#=^}Tn2?W@H=;XH82BnIPWJR z-XfMcqD-$mA_5rF96+@J3Z|W*V)iu6AakTSFyTHx%xUO60QD>HYr@3_xDXo8Fk*^x zfNpxSI#aHpjM$mZGMbmsjeulTF-z;AN~UI2M3#T1(FoqF`Xm&fUXy^5$=XFrP!&cH z4k?+2&nsbL7Utd13?GKa88m|RbkKB+`Y3r~#Pn~}2eYTy_=eluY^P9EC`}Vc6*^$eg=PHOR0+K{>;woHT-FI1G^u6&ehjpv-6}hQ)9*tcGgX z610q#pcUS22+43d0_E_p$^d*8odtW>S@1tUAwNP72`FFL;3MH?C;)vF0(xk1Xq;an Le!jVXHHpU`gx`a- diff --git a/res/Fly Assets/R11_13.DAT b/res/Fly Assets/R11_13.DAT deleted file mode 100644 index 0dac4eda114cbf13020288466f31acecec82f2cb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 577 zcmX}ou@Qnm5QX8D3MhdRC;_DbN}vQvxR8+0kkHW3&@r+M3o&s2hwqqS=9}HOdpFla z%wxnfHW6K-15086Q=$jGTR;`U!sqhG;7S;+@pNW4X19ROS`xYjQ@RFw1db5cBa}qT z#Remca&{)6Oyno*nK?EajMs$+^3dInaPuQPj62}Y70PgVRe-`|gp#;2wI)_TrdEnu zi(9iR6`NZMvsrt9T0jfgyc4D(P*J8NG!8TlbSRja0+Y{Di}4!X##6-m#sB3^_5A?y C)>Fp- diff --git a/res/Fly Assets/R11_14.DAT b/res/Fly Assets/R11_14.DAT deleted file mode 100644 index 0175aeb2d9641ca4224bb33a77814a655f663682..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 559 zcmYk3u@Qnm5JgvF0|E=M1WP!@0w{qJDB(gvLciYZvr6p9Q diff --git a/res/Fly Assets/R11_15.DAT b/res/Fly Assets/R11_15.DAT deleted file mode 100644 index 39b17bcb4dfb6117e9f5aa227990dda011c25615..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 550 zcmYk2Q4PZ|5JSBoD1<^Ngft~E2!k*P2PIIVeGNu{>|?gOi&`ntlkM{*y#b%M&K)R~ z=ODxmYyy1~Y=IdoL0FX0l$AjkmCADb0fa6Ev}W@OR9205f_qvjnzACxnQ_g)7h}dC zYi4{6jT=X-ic{Q#HKN3{R| diff --git a/res/Fly Assets/R12_09.DAT b/res/Fly Assets/R12_09.DAT deleted file mode 100644 index 0f1962cf55eaff26970166e602afcbb60ff2806f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28 acmd;OU~q6|U{G*oWMDXP2!#JIzyJVAYXt=W diff --git a/res/Fly Assets/R12_10.DAT b/res/Fly Assets/R12_10.DAT deleted file mode 100644 index 1b0749df83eff666d6c62f74c4446092def3a033..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1108 zcmYk4v5~?+5Cr#$fDjY{AsiwBLLdY}IP*=Jm}knw#8kcYVJMI{etM3*f+|qg?9ATY zibF)XL_9Bt4llzT@c{fum=ccZX;x(3XX1htrJj{bPw%XfJBPpuU^Cznsd4&KICc7jofK>7V+fogK5;MLlu#0`2{(ZF zcPjUUnx!R`zGqEnr6h1u$3sd7jpM=e>@x$EQSpR9&tYyT^sxshLpi@wH6h|{j`Ubj zKefQjCyy9?TAH^kImLP_%1y9x)4SlAcek=iX(&rVO*8AYr_JxzL?4?e8CdTC?~wTL zjP-gO#0R*9;uM291z7nO_;lcv6MFb2#qjtn*@M|7#u(;)3n@Ng5%>t=R!CVPWnhdY z4|N=~8y3ONR#C=;?nBA1pb0$BNzgD)0>6tbml;`F1@41l&n}N41RL>^sVz$_fzECI OiunEE``7;?`uzv_lc>Z1 diff --git a/res/Fly Assets/R12_11.DAT b/res/Fly Assets/R12_11.DAT deleted file mode 100644 index 3a67d3108afac643d84292e48f8f05df635222a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 595 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 XRIqAylh#%=RQghrs?13Rqc6 diff --git a/res/Fly Assets/bgm2.mid b/res/Fly Assets/bgm2.mid deleted file mode 100644 index 0b640ed94de2fb88699ba167cc89cc698926f1aa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26455 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 ZK`>J>m>a5Sr2UeiL0~Kn5FbR({{edHzDNK7 diff --git a/res/Fly Assets/block.png b/res/Fly Assets/block.png deleted file mode 100644 index 320e3bf2d82f30fcc88fa703b88dc3f290c24993..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 173 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#2^TY$v`XW$ch7)AvY8S|xv6<2KrRD=b5UwyNotBhd1gt5g1e`0K#E=} zJ5XHN)5S5w;&gIKLc)*p4vGtoH2n9Oa?393zzW92Yz_>{OK(atTs3BqeEFod8)S~B LtDnm{r-UW|P|Pp1 diff --git a/res/Fly Assets/block2.png b/res/Fly Assets/block2.png deleted file mode 100644 index ef87ee2011ac50195edaf231ac07e6d9933021cd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 368 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#2^TYuruL5~x3>U=WHUn|N}Tg^b5rw5fLsO!=c3falGGH1^30M91$R&1fE2w{ zcA)q(PZ!6Kid%1IUF17tz~TDx(f|LS?%tj^ZHwkxuA+0Nlg@0A+0eDsb5mqgw$bJ^ zyFG?aDnHJDdOWn@bXPM2ivj~9hXVtXKm(AuKuvp@W2o2)2E!*6Yc!_Dt0sPvTJ+Yx z%;^`O#$NU%es*hFR69M{H?Ut|e8X76P<_Dtq`b73lInX&w;-{XE z)7O>#2^TY$HUExz#wEak-ar*A$gM1AJ9L~|3{{MekWuO;vapD`b?Tod|OjB6QC;6*0c$VB>(IR@~ zk+4W?Vc%0O&6OgP|1h1IcBnc35f=-C&HYbt8?&CD;?B9n&yZ}oWc$nWTq+wUM;ufw woUxeoq`cd`w^x~dirs6w(YT}H-l21r@*;gFVdQ&MBb@09)=>yZ`_I diff --git a/res/Fly Assets/check2.png b/res/Fly Assets/check2.png deleted file mode 100644 index 2485fb5a7441430a9cdef4e878c4c4ccdfd6fc93..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 264 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 SZEJV{0000 diff --git a/res/Fly Assets/end2.png b/res/Fly Assets/end2.png deleted file mode 100644 index 3d31c1a89ab785644db4409f0957194b533e95c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1278 zcmVx1Q0AXZhj$!0000TX;fHrLvL+uWo~o;00000Lvm$d zbY)~9cWHEJAV*0}P-HG;2LJ#BbV)=(RCwC$o!JiKAPhxwtN#BldtPRws?(+{#uzw9 z>RUsCH*6r}x&QzG00000000000000W4*UD#`Oq;G@Z8u)UQyxy?*2RK*|N(HkYO4g z7!?4lf;R5kuPnK-^3jhdM000Cmzw{X31bg0UTgCG* zrOMeDMo18%iOFo!zjJJ^#0zcGV}N*Lw(48uHZgcfc|S`TBHA(>~EXx z6(?j^N>EOHbJ(7Klm?Gca_qgo4SrT7Eqz*pN7nujuqKyzvkf!js3?c)X3xW|9ITEk z|0oITlrD_rXuS3B-G)xgvY5kKV^p)n9pAq6N9ey=cB{#dl5mo->g@-62i_6-Z^_zz z-S4RE|C9_%mGcL)UyQzz-Jii~j1Egym{kz$>=YXz!&*OBtgw?=3zsrV*q&#Wztm26 z0@gUC_fFbopY&%TqTT6hbc>t`SY3|UIwDzTn|Ie}f(&Z21|6>do}grofy^A*pxgNu6QJtlsRR1hYj2+NDzSgho%hYBVLTiZ zU>h4$&Hu=r{4!1C7?-&(CF>`OZu(!#*Gq81-=nc@+`pEpq~zN7mzfn{|0AI_SpInGJ_hCPFpO|<{8Lm5v!59`PS{1lzoV zY>*6UZO21?R2ThiHQU-VP(Y;ytl($y4!r7g;F@4qE60_$610{%p7JAmo=i=^8nF@< zx#ZuoI;FzEtHAzSWjj4vGd#-`k5xjCrG1-ZhZ%yEoZAa4Wg{ltztz99MzAa+rz+*= zdBm*}%caHH6fD1$(aQexI3#G8^Yyy=J~*L4ax7hCTlovjo)ti={3rz%C<#f0|8GMR zjX?wClHF02w5^lu|Fz9<8J_lPjx{LP3JkyJ^@vDkw`>Lo>Fqxid`Q)2R9@+`>t1i< z15gr9C?igIx6N)!zfY%ckZI-7Rd4C%ZU0kN2g$IYH0xTaq=C&LVEH(V;qcQk?;~KG47H$B*g`t6YrjJzTl=u;`@H7mj2<`f+Ce@06&*QTJM~za=zfpb%LuSt$pioZ o000000000000000005AcKO_%MdsziHWB>pF07*qoM6N<$f(IT@TL1t6 diff --git a/res/Fly Assets/end3.png b/res/Fly Assets/end3.png deleted file mode 100644 index 4b98e611f055aa93e6a2a3998dc372deeefe77a5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 629 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!9XZ&5WOl+#S0Ke%;1OBOz`!jG!i)^F=12eq z*-JcqUD=;-u?Xm~KAxc@2o#dd42dXl&d<$F%_{+N85o?4QWHy3QxwWGOEMJPJ$(aG z^itV@HoW$9aSW-r_4f9`yu%7S3>PYI{r|tI{AT7Yu`bT$5A&`By9o1GsO8?f2R4O) zp<>#fUkAR~$?bB8K5}@nh|Rg(rr}I;U{BTAoeqBj5=-?z{dgE*cIV}PtAEkI zcVt=%2#ZIl)`f?j_?{xv`*-!X{agQ@_}J}vJ6!Zyv&-X_J1hCM=l{-{c>L^jDehzM zf5dN7UGtB1bM>LW=huE&vCTMN>K|LOcZHAZw4{r38C1Ab)_7iRV&9~Ym^<@HS&b}* z${N?nUOacE&G}Sh>hpBr?-@(3|9*Z!@_Br%_uWtNt0zC_7YYk5HT}Hsr?7giPe%2n z*IJr8=g!@>BS0UY6gBpt;miA8WlN(~UNGk7|`e50tEp}-Md6fwaL8j62j1xXz6p%>JKiHdO zb|A2+dTq>m{sUT}7t>xp7TvXbRaJ{?n%m6HCCTr6;_Dt3vd@*bVDyl++|H(?D8gCb z5n0T@z%2~Ij105pNB{-dOFVsD*`IK+aGOY-J2!J3P)Ig2B%;JQKQ}iuuLQ_tU~n!< zO)N=GQ7F$W$xv|j^bJVSOJ!$ZVDj*EaSW-r_4dxiyrl{P3<1ku{{R2!&1t(FvwLAI zj1T85$-Fcp`T%3P-m5~eIoJpX@t@z@YtQ#fRP21;c(789t1mXO>ED(2=HDKl{h$10 z$I*?Q>rXb7OxKRcyOsZ9--|hG-+jEV_5Y>Bvn!APbTD?GQ+}Dk<8ib2fy-T^t!?i; z)$Xp7WI9p85EfCg?%kCy8XMDY6>a_7{pppf*S5R$R(9Op^Vew1+?2TgvD@wUeRqZb zR#=HGa(?4-wBp!0@j2V4g)iQAxA;QJnaOK3+VIr+xuIpw|Q&XpQK5i#oy1p zyY^ApJF4d5#=9|gY+L(d&-}RI<~ciR%l}h{RLsQn*Qe<|eX;vN!bQOszc%LlKVLTY zUETD>dxSo?zU_Pb=ceJelXj`m!s%Aw?>%RHE#+Umw=JR7_0wg(q&+MCN5`$PVJno| zv9oZ&p0|20B`*9Ah}xTcvC>M^Px$-AkMnU1N%oh#?5!P3W*8_e`lPb8qHe|2?BKF+t6l|Uic%#er@=ltB<)VvZPmw~~#C^fMp zHASI3vm`^o-P1Q9MK6^dC|=;{;uvCaIyogF;m3Ig#)QO#goG1apVYlSZ%LI_WP32l zg>8pU;-Td~|CTYgeZS4SL8{|A!;G|?oJG6}Vh>ClE_`MRGYe!(;5L}VG%-ovCwiNp zvVdnF>!#R-JZr`94FX+^i#{OIEjE!O5G)<}7+smec9Odci=d#Wzp$Pyn C=~VRq diff --git a/res/Fly Assets/moveblock.png b/res/Fly Assets/moveblock.png deleted file mode 100644 index b5bdae0a43d37c0734e0e8964d742abe534684f2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-1$&97 zuPgf#E@mDB(M7HK>_8#e%#er@=ltB<)VvZPmw~~#C^fMpHASI3vm`^o-P1Q9MK2Yk z@U5qdV~EG`t)bpxEebr@75Dz1nt8Ngec7cZi!x>FlfEr8t-cw=#1Io3{93iK zT;elFP-EP;qY@?VGiLsOxc{R2PW?w)U0$)~SbUv$|D~ll`>(~XJ`_!rn)G~y&V>HG z6AT#?=B6*WtRvO)PDC@1jqAa2{m>1;HGZPYBDXj*9H`o(=i)x;_x8|~-~H;#!?coe z4=lfas#EPjw&4xc!t30T8TAb7sxRJ+II<<|`jxQVi?x&{ZQ`&ETfOdBbJ+i5dqNz9 zB6qIddR3>3OW;%Fw^0015c1^@s6s}B_@00009a7bBm000XU z000XU0RWnu7ytkO2XskIMF->x1Q0F(yEI4+w^)6_(~Q z(*!UMC242d8jVJy(P%UpjYgvoIQgE=>$jVEX2;FgSNT303xnK8;$UL#Q~1Y35SS1V zg2Gdf7ZD;01rW(W)P6bt`^^M6_>Ce0JV|E3_$?u(EFKt)(IP(Y{1)x}^L=+X38M(N zgbIVJAdG}(`L4X(Q!vL&g`#1+heO=t?-xTHJpO#tiNjV8K4dFXd`MV47T<9vz!j3i z1md$d9o3sgEap=v&qKU(TO~nXJei2Z?paKwJ@3AV$dDX3C$ERtrl&WnJPNb)*sK!Z zsw;oCM`FN^TJRPzSazEgMS>T_0bdlLS`;i4xn)5yILFK>fcI#Iq6KU|V;nCO9}0x5 z7N6G-oE&9D#8r9sqSe>&Vey^q7%8Y0Gs#Bc+*w?Eo|YW(%sXDkN5vOep?Fvz5c7wi z4-hRryr~CdQert_JF`!GOONe&66NA#B;JZv5?__yT!6n-TL@lNz?tfRhr~z2Z51NY ztKwEatL9rozAsim-dOn>fkiq_2C;ZmS;fZ}R|QXks7$hmr<7OihH+4|I?X%^JNm3# zU18j1D|YJHeIJGV(cAk(-iV%kBbfryBK9j|L6TiXrHtBk$L^gB4<$|EM@H4o{7(%< q8QdF?B>Z!{W>Mx)Vad>B8iySFZ~wNm8(0000x0}2upcD-c-0000TX;fHrLvL+uWo~o;00000Lvm$d zbY)~9cWHEJAV*0}P-HG;2LJ#8AxT6*R9M69SX&Z;Fbv#fyau1#g5z@wKRHPJkUF*W zkyvF=vop+KnuaE9mR8{FK>(P>1=n?!?Vhp2b)Cbl#B&~)#w83su4!C?eK!^b0svg1 zs1iL@Qd_#}fT1*yPTo>WeVzgU0Mi;2f+JUlVohpu(-nlO)ASk(5RKo^N-6i-0)fL} zpt2}wzN0rAY-59wWCvww>BeGOG&B>vBOQMZDcB@!5NT*Y*3RCBVQ1HojeM<|>2Ms| zjqm%k4ZX|zXaITl3PiJo(JB;?J8V^)rM1NoqvTQT;P@3Scv%lb<9l8`P=D%aoJ?y9 zY`qmKt8Uf<)rrka8pqjB?=MTcifuKb4T=VmnyqKIUOoP|(&6EnX!|?xusx#VjvKaC VT})oRYg_;T002ovPDHLkV1nj?s4M^g diff --git a/res/Fly Assets/powerup.png b/res/Fly Assets/powerup.png deleted file mode 100644 index 93400eac714eefc81c8bf4ceac26c2294e585e82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 256 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`oCO|{#S9GG!XV7ZFl&wkP>{XE z)7O>#2^X_~Hrp)2{oz0%+02lL66gHf+|;}hAeVu`xhOTUBsE2$JhLQ2!QIn0AVn{g z9VlMr>Eak-aXLBX+JqwxoC%KN9a%HJ%g@}uMzK?HK4Z@bJ%{T(+zQgCTGmAdJU0&O zIX%_q$S={^js?sUa@9o*CQAP@@b)xgxC<0+v$?wG!#^&4uMi`{0FD_Ggjvs&bWJi+ tT>jYS)DxBDo;?lc6=G&~O}zAmhao@TqISlub%#Mt^K|udS?83{1OSdZR1E+C diff --git a/res/Fly Assets/star.png b/res/Fly Assets/star.png deleted file mode 100644 index dfe9b56c54d60075b6bf3cc290b7b84075e09eb9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 283 zcmeAS@N?(olHy`uVBq!ia0vp^oFL4>1|%O$WD@{VY)RhkE)4%caKYZ?lR?r29+AZi z4BWyX%*Zfnjs#GUy~NYkmHi19vna3Tm#>Ep0)=EVLn2C?^K)}k^GbkR1_tM%)Wnk1 z6ovB4k_-iRPv3wPy;OFfc)h2KV~E7%slA3=hYbW+%&R6^PtTM6ko<+^CI7EptEqX9 zj!l@LcC^vq4*QjqV97T}ZltVgo_m`$Y{HvDwv*94g%(0mlR~ckj=NEKy1KNyyTnuT ztCEp^XUCaqQ4-19dbeKNIK^mU%DJCA&2LVsVQBa+x9V5XxxXIQ-yauX`uB)gk10z~ T>+cc`kQ+T+{an^LB{Ts5TI^+N diff --git a/res/Fly Assets/white.png b/res/Fly Assets/white.png deleted file mode 100644 index 5e65d7a2ddbdf847f3dc656ecfdedbee0c5051e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 149 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 24) & 0xFF) / 255.0f; + float fb = ((from >> 16) & 0xFF) / 255.0f; + float fg = ((from >> 8) & 0xFF) / 255.0f; + float fr = ((from >> 0) & 0xFF) / 255.0f; + float ta = ((to >> 24) & 0xFF) / 255.0f; + float tb = ((to >> 16) & 0xFF) / 255.0f; + float tg = ((to >> 8) & 0xFF) / 255.0f; + float tr = ((to >> 0) & 0xFF) / 255.0f; + + if (fa && !ta) { tr = fr, tg = fg, tb = fb; } + if (ta && !fa) { fr = tr, fg = tg, fb = tb; } + + return (uint32_t) (LinearInterpolate(fr, tr, progress) * 255.0f) << 0 + | (uint32_t) (LinearInterpolate(fg, tg, progress) * 255.0f) << 8 + | (uint32_t) (LinearInterpolate(fb, tb, progress) * 255.0f) << 16 + | (uint32_t) (LinearInterpolate(fa, ta, progress) * 255.0f) << 24; +} + float RubberBand(float original, float target) { float sign = SignFloat(original - target); float distance = AbsoluteFloat(original - target); diff --git a/shared/strings.cpp b/shared/strings.cpp index 4c9bb2a..c3a1d45 100644 --- a/shared/strings.cpp +++ b/shared/strings.cpp @@ -264,6 +264,16 @@ DEFINE_INTERFACE_STRING(FileManagerListContextActions, "Actions"); DEFINE_INTERFACE_STRING(FileManagerCopyTask, "Copying" ELLIPSIS); DEFINE_INTERFACE_STRING(FileManagerMoveTask, "Moving" ELLIPSIS); +// 2048. + +DEFINE_INTERFACE_STRING(Game2048Score, "Score:"); +DEFINE_INTERFACE_STRING(Game2048Instructions, "Use the \aw6]arrow-keys\a] to slide the tiles. When matching tiles touch, they \aw6]merge\a] into one. Try to create the number \aw6]2048\a]!"); +DEFINE_INTERFACE_STRING(Game2048GameOver, "Game over"); +DEFINE_INTERFACE_STRING(Game2048GameOverExplanation, "There are no valid moves left."); +DEFINE_INTERFACE_STRING(Game2048NewGame, "New game"); +DEFINE_INTERFACE_STRING(Game2048HighScore, "High score: \aw6]%d\a]"); +DEFINE_INTERFACE_STRING(Game2048NewHighScore, "You reached a new high score!"); + // TODO System Monitor. #pragma GCC diagnostic pop diff --git a/util/api_table.ini b/util/api_table.ini index 5d03d9d..d867a8a 100644 --- a/util/api_table.ini +++ b/util/api_table.ini @@ -440,3 +440,5 @@ EsTextboxSetFont=438 EsTextboxSetTextSize=439 EsRectangleLinearInterpolate=440 EsDrawRoundedRectangle=441 +EsDrawTextSimple=442 +EsColorInterpolate=443