#include #include #include #include #include #include #include #include #include #include #include #include "tilemap.h" using namespace std; volatile uint8_t frame = 0; volatile bool internals = false; GameState gameState; volatile uint16_t &ticks = gameState.ticks; volatile uint16_t &snakelength = gameState.snakelength; /*** * 0 = up * 1 = right * 2 = down * 3 = left ***/ volatile uint16_t &snakeDirection = gameState.snakeDirection; volatile uint16_t &score = gameState.score; bool &gameOver = gameState.gameOver; bool &paused = gameState.paused; bool &hardMode = gameState.hardMode; std::deque> &snake = gameState.snake; std::vector> &apples = gameState.apples; std::vector> &bad_apples = gameState.bad_apples; // 31x23 PrintConsole topScreen; PrintConsole bottomScreen; int sound; AudioContext audioContext; RenderAssets renderAssets; const void * get_sprite_pointer(uint16 spriteIndex) { return &tilemapTiles[spriteIndex*16]; } void setup() { // Set up screens videoSetMode(MODE_0_2D); videoSetModeSub(MODE_0_2D); vramSetBankC(VRAM_C_SUB_BG); vramSetBankD(VRAM_D_SUB_SPRITE); consoleInit(&topScreen, 3,BgType_Text4bpp, BgSize_T_256x256, X_MAX, 0, true, true); consoleInit(&bottomScreen, 3,BgType_Text4bpp, BgSize_T_256x256, X_MAX, 0, false, true); oamInit(&oamSub, SpriteMapping_1D_32, false); renderAssets.topScreen = &topScreen; renderAssets.bottomScreen = &bottomScreen; renderAssets.gfx_segment = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); renderAssets.gfx_segment_small = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); renderAssets.gfx_head = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); renderAssets.gfx_apple = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); renderAssets.gfx_apple_rotten = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); renderAssets.gfx_tail = oamAllocateGfx(&oamSub, SpriteSize_8x8, SpriteColorFormat_256Color); dmaCopy(get_sprite_pointer(1), renderAssets.gfx_segment, 64); dmaCopy(get_sprite_pointer(2), renderAssets.gfx_segment_small, 64); dmaCopy(get_sprite_pointer(3), renderAssets.gfx_head, 64); dmaCopy(get_sprite_pointer(5), renderAssets.gfx_apple, 64); dmaCopy(get_sprite_pointer(11), renderAssets.gfx_apple_rotten, 64); consoleSelect(&topScreen); dmaCopy(tilemapPal,SPRITE_PALETTE_SUB,tilemapPalLen); audio_setup(audioContext); } void handle_vblank() { frame++; consoleSelect(&topScreen); draw_stats(gameState, internals, audio_is_music_enabled(audioContext), frame); oamUpdate(&oamSub); //flashy_colors(); } void do_tick() { if (!paused) { ticks++; if (!gameOver){ const bool wasGameOver = gameOver; /*if (hardMode) { timerStop(0); timerStart(0, ClockDivider_1024, TIMER_FREQ_1024(ticks+5), do_tick); }*/ update_snake(gameState); audio_play_plop(audioContext); check_collision_self(gameState); if (check_collision_apples(gameState)) { audio_play_pickup(audioContext); } if (check_collision_apples_rotten(gameState)) { audio_play_boom(audioContext); } spawn_apples(gameState); spawn_apples_rotten(gameState); if (!wasGameOver && gameOver) { audio_stop_music(); audio_play_fail(audioContext); } blink_apples(gameState, renderAssets.gfx_apple); //consoleSelect(&bottomScreen); draw_game(gameState, renderAssets); } } } void init_game() { if (hardMode) { timerStart(0, ClockDivider_1024, TIMER_FREQ_1024(9), do_tick); setBackdropColorSub(RGB15(10,5,5)); score = 0; snakelength = START_LENGTH_HARD; snake = { {2,1,1}, {1,1,1} }; apples.clear(); bad_apples.clear(); snakeDirection = 1; ticks = 0; gameOver=false; consoleSelect(&topScreen); consoleClear(); consoleSelect(&bottomScreen); consoleClear(); oamClear(&oamSub,0,0); audio_start_music(audioContext); } else { timerStart(0, ClockDivider_1024, TIMER_FREQ_1024(5), do_tick); setBackdropColorSub(RGB15(5,5,5)); score = 0; snakelength = START_LENGTH; snake = { {4,1,1}, {3,1,1}, {2,1,1}, {1,1,1} }; snakeDirection = 1; ticks = 0; gameOver=false; consoleSelect(&topScreen); consoleClear(); consoleSelect(&bottomScreen); consoleClear(); oamClear(&oamSub,0,0); audio_start_music(audioContext); } } int main(void) { // Set up VBlank handler irqSet(IRQ_VBLANK, handle_vblank); setup(); init_game(); // Start timer for game ticks InputContext inputContext; inputContext.state = &gameState; inputContext.renderAssets = &renderAssets; inputContext.audio = &audioContext; inputContext.internals = &internals; inputContext.topScreen = &topScreen; inputContext.init_game = init_game; while(1) { if (!handle_input_frame(inputContext)) { break; } } return 0; }