Files
snakePlus/source/main.cpp

201 lines
4.9 KiB
C++

#include <nds.h>
#include <vector>
#include <deque>
#include <array>
#include <consts.h>
#include <game_state.h>
#include <game_logic.h>
#include <game_render.h>
#include <game_audio.h>
#include <game_input.h>
#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<std::array<int, 3>> &snake = gameState.snake;
std::vector<std::array<int, 2>> &apples = gameState.apples;
std::vector<std::array<int, 2>> &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;
}