#include "game_render.h" #include #include #include #include "tilemap.h" namespace { const void *get_sprite_pointer(uint16_t spriteIndex) { return &tilemapTiles[spriteIndex * 16]; } void draw_snake_head(const GameState &state, const RenderAssets &assets, uint16_t &oamId) { const std::array dot = state.snake.front(); bool hflip = false; bool vflip = false; switch (state.snakeDirection) { case 0: dmaCopy(&tilemapTiles[64], assets.gfx_head, 64); break; case 1: dmaCopy(&tilemapTiles[48], assets.gfx_head, 64); break; case 2: dmaCopy(&tilemapTiles[64], assets.gfx_head, 64); vflip = true; break; case 3: dmaCopy(&tilemapTiles[48], assets.gfx_head, 64); hflip = true; break; default: break; } oamSet(&oamSub, oamId, dot[0] * 8, dot[1] * 8, 0, 0, SpriteSize_8x8, SpriteColorFormat_256Color, assets.gfx_head, -1, false, false, hflip, vflip, false); oamId++; } void draw_snake_tail(const GameState &state, const RenderAssets &assets, uint16_t &oamId) { const std::array dot = state.snake.back(); bool hflip = false; bool vflip = false; switch (state.snake.at(state.snake.size() - 2).at(2)) { case 0: dmaCopy(get_sprite_pointer(9 + ((state.snake.size() - 1) % 2)), assets.gfx_tail, 64); vflip = true; break; case 1: dmaCopy(get_sprite_pointer(7 + ((state.snake.size() - 1) % 2)), assets.gfx_tail, 64); hflip = true; break; case 2: dmaCopy(get_sprite_pointer(9 + ((state.snake.size() - 1) % 2)), assets.gfx_tail, 64); break; case 3: dmaCopy(get_sprite_pointer(7 + ((state.snake.size() - 1) % 2)), assets.gfx_tail, 64); break; default: break; } oamSet(&oamSub, oamId, dot[0] * 8, dot[1] * 8, 0, 0, SpriteSize_8x8, SpriteColorFormat_256Color, assets.gfx_tail, -1, false, false, hflip, vflip, false); oamId++; } void draw_snake(const GameState &state, const RenderAssets &assets, uint16_t &oamId) { draw_snake_head(state, assets, oamId); for (size_t i = 1; i < state.snake.size() - 1; i++) { oamSet(&oamSub, oamId, state.snake[i][0] * 8, state.snake[i][1] * 8, 0, 0, SpriteSize_8x8, SpriteColorFormat_256Color, (i % 2) ? assets.gfx_segment_small : assets.gfx_segment, -1, false, false, false, false, false); oamId++; } draw_snake_tail(state, assets, oamId); } void draw_apples(const GameState &state, const RenderAssets &assets, uint16_t &oamId) { for (const std::array &apple : state.apples) { oamSet(&oamSub, oamId, apple[0] * 8, apple[1] * 8, 0, 0, SpriteSize_8x8, SpriteColorFormat_256Color, assets.gfx_apple, -1, false, false, false, false, false); oamId++; } } void draw_apples_rotten(const GameState &state, const RenderAssets &assets, uint16_t &oamId) { for (const std::array &apple : state.bad_apples) { oamSet(&oamSub, oamId, apple[0] * 8, apple[1] * 8, 0, 0, SpriteSize_8x8, SpriteColorFormat_256Color, assets.gfx_apple_rotten, -1, false, false, false, false, false); oamId++; } } } // namespace void draw_game(const GameState &state, const RenderAssets &assets) { uint16_t oamId = 0; if (!state.gameOver) { draw_apples(state, assets, oamId); draw_apples_rotten(state, assets, oamId); draw_snake(state, assets, oamId); return; } iprintf("\x1b[11;12HGAME OVER!"); consoleSelect(assets.topScreen); iprintf("\x1b[10;13HGAME OVER!"); } void draw_stats(const GameState &state, bool internals, bool musicEnabled, uint8_t frame) { if (internals) { iprintf("\x1b[0;0HFrame = %i\nTick = %i\ndir = %i", frame, state.ticks, state.snakeDirection); iprintf("\x1b[3;0HLength: %i", state.snakelength); iprintf("\x1b[4;0Hx=%i\ny=%i", state.snake.front()[0], state.snake.front()[1]); } iprintf("\x1b[10;12HScore: %i", state.score); if (!state.paused) { return; } if (musicEnabled) { iprintf("\x1b[23;0HX = Disable Music"); } else { iprintf("\x1b[23;0HX = Enable Music "); } if (state.hardMode) { iprintf("\x1b[22;0HY = Restart in normal mode"); } else { iprintf("\x1b[22;0HY = Restart in Hard mode"); } } void blink_apples(const GameState &state, u16 *gfx_apple) { if (state.ticks % 4) { dmaCopy(get_sprite_pointer(5), gfx_apple, 64); } else { dmaCopy(get_sprite_pointer(6), gfx_apple, 64); } }