Created
April 10, 2018 02:19
-
-
Save TheV360/39d4b0baa9ee9c378334aed433c6beef to your computer and use it in GitHub Desktop.
A small Arduboy platformer I was working on a while ago, may return some day, but for now, have this spaghetti code.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Platformer | |
// By V360 (@TheV360gameDev) | |
//TODO: Pressing up shows how many keys you have and cuts off the map renderer to save CPU (except for dark mode) | |
// UI overhaul (more than the title screen!) | |
// Level titles | |
#include <Arduboy2.h> | |
#include <ArduboyTones.h> | |
Arduboy2 arduboy; | |
ArduboyTones sound(arduboy.audio.enabled); | |
#define ARDBITMAP_SBUF arduboy.getBuffer() | |
#include <ArdBitmap.h> | |
ArdBitmap<WIDTH, HEIGHT> ardbitmap; | |
#define LVLWIDTH 32 | |
#define LVLHEIGHT 16 | |
#define LVLNUMBER 3 | |
#define COLSTEP 4 | |
#define TILEBLOCK 1 | |
#define TILEEXIT 2 | |
#define TILEMINE 3 | |
#define TILEWATERS 4 | |
#define TILEWATER 5 | |
#define TILEKEY 6 | |
#define TILELOCKBLOCK 7 | |
#define TILELCONVEYOR 8 | |
#define TILERCONVEYOR 9 | |
#define TILEORB 10 | |
#define TILESPRING 11 | |
#define TILESWITCH 12 | |
#define TILESWITCHBLOCKOFF 13 | |
#define TILESWITCHBLOCKON 14 | |
#define TILEPLAYER 15 | |
byte state = 0; | |
const unsigned char titleTitle[] PROGMEM = { | |
0x7d,0x8f,0xbb,0x6b,0x6b,0xb5,0xda,0x91,0x9c,0x3a,0x66,0xb3,0x73,0x52,0x2f,0x92, | |
0x4b,0x8e,0x92,0x3d,0xe8,0xf6,0x2a,0x5d,0x0b,0x89,0x2a,0xd4,0x29,0x5e,0xd4,0xcb, | |
0x78,0xba,0x4e,0xe8,0xc5,0xeb,0x3a,0xa1,0x97,0x71,0x43,0x2f,0xe3,0xca,0x51,0xbc, | |
0xa8,0x97,0x71,0xcd,0x25,0x70,0x52,0xff,0xd8,0xf3,0x80,0x1d,0xa2,0x3d,0xc0,0x10, | |
0x00,0x81,0x70,0x1a,0x02,0x05,0xf1,0xc0,0x19,0x90,0x0c,0x84,0x23,0x70,0x93,0x21, | |
0x41,0x18,0xdb,0x1d,0x28,0x8c,0x52,0x2e,0x94,0x0b,0x65,0x05,0x0a,0xa3,0x94,0x11, | |
0x29,0x54,0xa1,0x48,0x02,0x85,0x51,0xca,0x52,0x0a,0x03,0x61,0x39,0xd5,0xb5,0x32, | |
0x0f,0x5c,0x28,0x4e,0x28,0x58,0xa1,0xa0,0x91,0x12,0x07,0x85,0x50,0x28,0x65,0x50, | |
0x2e,0x14,0x42,0xa1,0x94,0x41,0x21,0x14,0x4a,0x19,0x14,0x42,0xa1,0x94,0x41,0x71, | |
0x42,0x41,0x44,0x28,0x88,0x08,0x65,0x05,0x0a,0xa3,0x94,0x0b,0xe5,0x42,0xb9,0x50, | |
0x2e,0x94,0x0b,0xe5,0x42,0xb9,0x50,0x2e,0x94,0x0b,0xe5,0x42,0xb9,0x50,0x2e,0x94, | |
0x0b,0xe5,0x42,0xb9,0x50,0x2e,0x74,0x0d,0x0a,0x05,0x80,0x82,0x30,0x28,0x91,0x40, | |
0x89,0x83,0x72,0xa1,0x18,0x85,0x62,0x06,0x05,0x0a,0x40,0xa1,0x83,0x42,0x01,0xa0, | |
0x90,0x45,0xa1,0x01,0x0a,0x05 | |
}; | |
const unsigned char titlePlay[] PROGMEM = { | |
0x1f,0x9f,0xbf,0x8b,0xab,0xf7,0x3d,0x30,0x80,0x89,0x7b,0x20,0x5c,0xc0,0x3d,0x30, | |
0x80,0x03,0x77,0x22,0x69,0xe2,0x7c,0x90,0x56,0xe4,0x06,0x5c,0xd5,0x8b,0x27,0xcf, | |
0xc9,0xf8,0x33,0x41,0x26,0x9b,0xc5,0x64,0xb3,0xd8,0x0c,0x2e,0x94,0x4b,0x7e,0x47, | |
0x0f,0xe3,0xc8,0xbb,0xc3,0x72,0xb9,0x5c,0x2e,0xd7,0x8b,0xe5,0x72,0xb9,0x5c,0xae, | |
0x17,0xcb,0xe5,0x72,0xb9,0x5c,0x87,0x7d,0xce,0x69,0x16,0x8f | |
}; | |
const unsigned char titleEdit[] PROGMEM = { | |
0x1f,0x9f,0x97,0x2c,0x36,0xaf,0xd8,0xac,0x7c,0x72,0x0f,0x04,0x00,0x09,0xb8,0x07, | |
0x42,0x48,0x74,0x13,0x90,0x21,0x01,0x37,0x43,0x86,0x0c,0xe7,0x31,0x72,0xe1,0x0d, | |
0x17,0xcc,0xe0,0xea,0x11,0xfc,0x33,0x72,0x08,0xb6,0x47,0xe4,0x46,0x28,0x04,0x6a, | |
0x0f,0xcb,0xe5,0x72,0xb9,0x5c,0x87,0x9d,0xd3,0xb8,0xac,0x93,0xfb,0xb0,0x5c,0x2e, | |
0x97,0xcb,0xf5,0x62,0xb9,0x5c,0x2e,0x97,0xeb,0xc5,0x72,0xb9,0x5c,0x2e,0xd7,0xe1, | |
0xcc,0xe1,0x7a,0xe0,0x0c | |
}; | |
const unsigned char titleThanks[] PROGMEM = { | |
0x1f,0x9f,0x1f,0xde,0x0c,0x19,0x32,0xdc,0x03,0x43,0x07,0xee,0x81,0x01,0x1c,0xb8, | |
0x07,0x0e,0x52,0xdc,0x03,0x43,0x45,0xdc,0x01,0x04,0x00,0x21,0x38,0x37,0xb1,0x86, | |
0x0b,0xa0,0x02,0x05,0x54,0x60,0xa1,0x02,0x05,0x64,0x50,0xce,0x5c,0x28,0x17,0xca, | |
0x85,0x5f,0x8a,0xaa,0xca,0x01,0x00,0x0c,0x20,0x41,0x00,0x40,0x00,0x40,0x82,0x00, | |
0x08,0x00,0x08,0xc0,0x11,0x40,0xd8,0x40,0x81,0xcd,0x17,0x39,0xf6,0x98,0x5b,0x5e, | |
0x79,0xe7,0xc6,0x0b,0xfe,0x16,0x6b,0x9e,0xc6,0xe1,0x22 | |
}; | |
// 64 bytes | |
const unsigned char tiles[16][4] PROGMEM = { | |
{B0101,B0010,B0101,B0000}, // Nothing | |
{B1111,B1001,B1001,B1111}, // Block | |
{B1110,B1111,B1011,B1110}, // Exit door | |
{B1001,B0110,B0110,B1001}, // Mine | |
{B0100,B0010,B0100,B0010}, // Water surface | |
{B1010,B0000,B0101,B0000}, // Water | |
{B0000,B0110,B0110,B0000}, // Key | |
{B1111,B1011,B1101,B1111}, // Locked block | |
{B1111,B1011,B0101,B1111}, // Left conveyor | |
{B1111,B0101,B1011,B1111}, // Right conveyor | |
{B0110,B1111,B1101,B0110}, // Gravity Orb | |
{B1001,B1111,B1111,B1001}, // Spring | |
{B1100,B1000,B1000,B1100}, // Toggle switch | |
{B0101,B1000,B0001,B1010}, // Off switch block | |
{B0111,B1001,B1001,B1110}, // On switch block | |
{B1111,B1101,B1111,B1101} // Player | |
}; | |
const unsigned char arrow[4] PROGMEM = { | |
B0010,B0110,B0110,B0010 | |
}; | |
const unsigned char tileInfo[2] PROGMEM = { | |
B10000010, | |
B01000011 | |
}; | |
// 257 bytes per level, but this doesn't matter because it's in PROGMEM | |
const unsigned char levels[LVLNUMBER][257] PROGMEM = { | |
{ | |
B00000000, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x01,0x14,0x44,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x01,0x11,0x15,0x55,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0xF0,0x00,0x01,0x11,0x11,0x15,0x55,0x51,0x00,0x00,0x00,0x00,0x00,0x02,0x01, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 | |
}, | |
{ | |
B00000000, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x01,0x14,0x44,0x41,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x01,0x11,0x15,0x55,0x51,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0xF0,0x00,0x01,0x11,0x11,0x15,0x55,0x51,0x00,0x00,0x00,0x00,0x00,0x02,0x01, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11 | |
}, | |
{ | |
B00000000, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x00,0x11,0x11, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA0,0x00,0x00,0x00,0x00,0x01,0x11,0x51, | |
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x51, | |
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x51, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x30,0x06,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x18,0x88,0x99,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, | |
0x10,0x01,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x41, | |
0x10,0x10,0x00,0x00,0x11,0x11,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x05,0x51, | |
0x10,0x00,0x00,0x11,0x31,0x10,0x00,0x10,0x00,0x00,0xED,0x00,0x00,0x00,0x05,0x51, | |
0x11,0xF0,0x11,0x11,0x00,0x00,0x00,0xC0,0x0A,0x00,0xDE,0x00,0x20,0x00,0x05,0x51, | |
0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x77,0x11,0x11 | |
} | |
}; | |
// ugh, this reminds me of my early petit computer days with my awful programming | |
// but this is apparently how it's done? | |
const unsigned char title0[] PROGMEM = "Welcome"; | |
const unsigned char title1[] PROGMEM = "Locked door"; | |
const unsigned char title2[] PROGMEM = "test"; | |
const unsigned char* const levelTitles[] PROGMEM = { | |
title0,title1,title2 | |
}; | |
const unsigned char mode0[] PROGMEM = "Flip mode"; | |
const unsigned char mode1[] PROGMEM = "Dark mode"; | |
const unsigned char mode2[] PROGMEM = "L Wind mode"; | |
const unsigned char mode3[] PROGMEM = "R Wind mode"; | |
const unsigned char mode4[] PROGMEM = "Switch mode"; | |
const unsigned char mode5[] PROGMEM = "Water mode"; | |
const unsigned char mode6[] PROGMEM = "Volatile mode"; | |
const unsigned char mode7[] PROGMEM = "Void mode"; | |
const unsigned char* const modeTitles[] PROGMEM = { | |
mode0,mode1,mode2,mode3,mode4,mode5,mode6,mode7 | |
}; | |
char textBuffer[22]; | |
// 512 bytes for an unsquished level | |
unsigned char tileMap[32][16]; | |
// All the stuff needed for the platforming | |
float x = 0; | |
float y = 0; | |
float ax = 0; | |
float ay = 0; | |
bool gr = false; | |
bool dead = false; | |
unsigned char levelModes = 0; | |
/* | |
* Level modes: | |
* b0: *flip mode, flips gravity instead of jumping | |
* b1: *dark mode, can't see more than a 3 tile radius around you | |
* b2: *left conveyor mode, constantly moving left | |
* b3: *right conveyor mode, idk lol | |
* b4: *switch mode, when you jump, the switch tiles toggle | |
* b5: *water mode, water pulls you down when gravity is flipped | |
* b6: *volatile mode, don't fall too fast! | |
* b7: *void mode: don't render the normal solid block (challenging!) | |
*/ | |
int flip = 1; | |
unsigned char timer; | |
// Stuff for tiles that do things | |
unsigned char touchedTileL; | |
unsigned char touchedTileM; | |
unsigned char touchedTileR; | |
unsigned char prevX; | |
unsigned char prevY; | |
int keys; // for those people that will fill the level with coins... >:( i would put a limit but that would just mean more wasted space | |
// Menu variables! | |
unsigned char sel; | |
unsigned char currMap; | |
bool showDebug = false; | |
// Editor variables! | |
bool editor = false; | |
bool switched = false; | |
bool placedPlayer = false; | |
unsigned char cursorX; | |
unsigned char cursorY; | |
unsigned char cursorT; | |
void setup() { | |
// This stuff will run once! | |
//Start your Arduboys... | |
arduboy.begin(); | |
arduboy.setFrameRate(60); //60 fps | |
//Serial.begin(9600); | |
} | |
void loop() { | |
// I don't want to go on without waiting a frame first! | |
if (!(arduboy.nextFrame())) | |
return; | |
arduboy.pollButtons(); | |
arduboy.clear(); | |
// State zero is the title screen! | |
// State one is the level select! | |
// State two is the game, | |
// three is the pause screen, | |
// four is the level editor, | |
// five is the editor menu, | |
// six is the mode select menu, | |
// and seven is the credits! | |
switch (state) { | |
case 0: | |
ardbitmap.drawCompressed(1,0,titleTitle,WHITE,ALIGN_NONE,MIRROR_NONE); | |
if (arduboy.justPressed(LEFT_BUTTON) && sel > 0) { | |
sel--; | |
} | |
if (arduboy.justPressed(RIGHT_BUTTON) && sel < 2) { | |
sel++; | |
} | |
arduboy.fillRect(10 + (39 * sel),22,32,32,WHITE); | |
for (byte i = 0; i < 3; i++) { | |
arduboy.drawRect(8 + (39 * i),20,36,36); | |
} | |
ardbitmap.drawCompressed(10,22,titlePlay ,WHITE * (sel != 0),ALIGN_NONE,MIRROR_NONE); | |
ardbitmap.drawCompressed(49,22,titleEdit ,WHITE * (sel != 1),ALIGN_NONE,MIRROR_NONE); | |
ardbitmap.drawCompressed(88,22,titleThanks,WHITE * (sel != 2),ALIGN_NONE,MIRROR_NONE); // dangit | |
if (arduboy.justReleased(A_BUTTON)) { | |
if (sel == 0) { | |
state = 2; | |
editor = false; | |
loadMap(currMap); | |
} | |
if (sel == 1) { | |
state = 4; | |
editor = true; | |
fixMap(); | |
} | |
if (sel == 2) { | |
state = 7; | |
} | |
} | |
break; | |
case 2: | |
// First, logic... | |
if (arduboy.pressed(LEFT_BUTTON)) { | |
ax -= .4; | |
} | |
if (arduboy.pressed(RIGHT_BUTTON)) { | |
ax += .4; | |
} | |
if (arduboy.justPressed(A_BUTTON) && gr) { | |
if (bitRead(levelModes,0)) { | |
flip = -flip; | |
sound.tone(NOTE_C5,24); | |
} else { | |
if (bitRead(levelModes,6)) { | |
ay = -2 * flip; | |
} else { | |
ay = -3 * flip; | |
} | |
if (bitRead(levelModes,4)) | |
useSwitch(); | |
sound.tone(NOTE_F4,24); | |
} | |
} | |
if (arduboy.justReleased(B_BUTTON)) { | |
state = 3; | |
sound.tone(NOTE_F4,32,NOTE_F5,32); | |
} | |
ax *= .7; | |
ay = ((ay + (.2 * flip)) * .9); | |
gr = false; | |
for (byte col = 0; col < COLSTEP; col++) { // Collisions and special blocks | |
if (!isTileSolid(x,y)) { | |
prevX = floor(x / 4); | |
prevY = floor(y / 4); | |
x = modFloat(x + (ax / COLSTEP),128.0); | |
y = modFloat(y + (ay / COLSTEP), 64.0); | |
// Locked blocks (have to put this here) | |
if (keys > 0) { // this is a mess, why did i write this | |
if (pixelTile(x - 2,y) == TILELOCKBLOCK) { | |
keys -= 1; | |
tileMap[(byte)floor((x - 2) / 4)][(byte)floor(y / 4)] = TILELOCKBLOCK << 4; | |
sound.tone(NOTE_C6,16,NOTE_C5,16); | |
} | |
if (pixelTile(x + 2,y) == TILELOCKBLOCK) { | |
keys -= 1; | |
tileMap[(byte)floor((x + 2) / 4)][(byte)floor(y / 4)] = TILELOCKBLOCK << 4; | |
sound.tone(NOTE_C6,16,NOTE_C5,16); | |
} | |
if (pixelTile(x,y - 2) == TILELOCKBLOCK) { | |
keys -= 1; | |
tileMap[(byte)floor(x / 4)][(byte)floor((y - 2) / 4)] = TILELOCKBLOCK << 4; | |
sound.tone(NOTE_C6,16,NOTE_C5,16); | |
} | |
if (pixelTile(x,y + 2) == TILELOCKBLOCK) { | |
keys -= 1; | |
tileMap[(byte)floor(x / 4)][(byte)floor((y + 2) / 4)] = TILELOCKBLOCK << 4; | |
sound.tone(NOTE_C6,16,NOTE_C5,16); | |
} | |
} | |
// Spring | |
if ((pixelTile(x - 2,y) == TILESPRING || pixelTile(x + 2,y) == TILESPRING) && (prevX != floor(x / 4) || prevY != floor(y / 4))) { | |
if (abs(ay) > 1) { | |
ay = -ay * 2.5; | |
sound.tone(NOTE_C6,16,NOTE_C5,16); | |
} | |
} | |
// Too fast? | |
if ((abs(ay) > 1.62) && bitRead(levelModes,6)) { | |
dead = true; | |
} | |
// Collisions | |
// Ceiling | |
if (isTileSolid(x - 1,y - 2) || isTileSolid(x + 1,y - 2)) { | |
ay = 0; | |
y = ( ceil(y / 4) * 4) - 2; | |
gr = flip < 0; | |
} | |
// Floor | |
if (isTileSolid(x - 1,y + 2) || isTileSolid(x + 1,y + 2)) { | |
ay = 0; | |
y = (floor(y / 4) * 4) + 2; | |
gr = flip > 0; | |
} | |
// Walls | |
if (isTileSolid(x - 2,y - 1) || isTileSolid(x - 2,y + 1)) { | |
ax = 0; | |
x = ( ceil(x / 4) * 4) - 2; | |
} | |
if (isTileSolid(x + 2,y - 1) || isTileSolid(x + 2,y + 1)) { | |
ax = 0; | |
x = (floor(x / 4) * 4) + 2; | |
} | |
// Special blocks | |
touchedTileL = pixelTile(x - 2,y); | |
touchedTileM = pixelTile(x,y); | |
touchedTileR = pixelTile(x + 2,y); | |
// Water | |
if ((touchedTileL == TILEWATERS) || (touchedTileR == TILEWATERS)) { | |
ay += .05 * (float)((bitRead(levelModes,5) * 2) - 1); | |
gr = true; | |
} | |
if ((touchedTileL == TILEWATER) || (touchedTileR == TILEWATER)) { | |
ay += .07 * (float)((bitRead(levelModes,5) * 2) - 1); | |
gr = true; | |
} | |
// Mine | |
if ((touchedTileL == TILEMINE) || (touchedTileR == TILEMINE)) { | |
dead = true; | |
} | |
// Conveyors | |
if ((pixelTile(x,y + 2) == TILELCONVEYOR) || (pixelTile(x,y - 2) == TILELCONVEYOR)) { | |
ax -= .05; | |
} | |
if ((pixelTile(x,y + 2) == TILERCONVEYOR) || (pixelTile(x,y - 2) == TILERCONVEYOR)) { | |
ax += .05; | |
} | |
// Wind | |
if (bitRead(levelModes,2)) { | |
ax -= .05; | |
} | |
if (bitRead(levelModes,3)) { | |
ax += .05; | |
} | |
// Orb | |
if (touchedTileL == TILEORB) { | |
flip = -flip; | |
tileMap[(byte)floor((x - 2) / 4)][(byte)floor(y / 4)] = TILEORB << 4; | |
sound.tone(NOTE_F4,16,NOTE_C5,16,NOTE_F5,16); | |
} | |
if (touchedTileR == TILEORB) { | |
flip = -flip; | |
tileMap[(byte)floor((x + 2) / 4)][(byte)floor(y / 4)] = TILEORB << 4; | |
sound.tone(NOTE_F4,16,NOTE_C5,16,NOTE_F5,16); | |
} | |
// Key | |
if (touchedTileL == TILEKEY) { | |
keys += 1; | |
tileMap[(byte)floor((x - 2) / 4)][(byte)floor(y / 4)] = TILEKEY << 4; | |
sound.tone(NOTE_C5,16,NOTE_C6,16); | |
} | |
if (touchedTileR == TILEKEY) { | |
keys += 1; | |
tileMap[(byte)floor((x + 2) / 4)][(byte)floor(y / 4)] = TILEKEY << 4; | |
sound.tone(NOTE_C5,16,NOTE_C6,16); | |
} | |
// Switch | |
if (touchedTileM == TILESWITCH && (prevX != floor(x / 4) || prevY != floor(y / 4))) { | |
useSwitch(); | |
sound.tone(NOTE_C5,16,NOTE_E5,16); | |
} | |
// Dead | |
if (dead) { | |
dead = false; | |
if (editor) { | |
fixMap(); | |
loadMap(0); | |
} else { | |
loadMap(currMap); | |
} | |
sound.tone(NOTE_F5,16,NOTE_D4,16); | |
} | |
// Exit | |
if ((touchedTileL == TILEEXIT) || (touchedTileR == TILEEXIT)) { | |
if (editor) { | |
fixMap(); | |
state = 4; | |
} else { | |
currMap += 1; | |
loadMap(currMap); | |
} | |
sound.tone(NOTE_C3,32,NOTE_C4,32,NOTE_C5,32); | |
} | |
} | |
} | |
// Now draw! | |
if (bitRead(levelModes,1)) { | |
drawMap(floor(x / 4) + 29,floor(y / 4) + 13,7,7); | |
} else { | |
drawMap(0,0,32,16); | |
} | |
arduboy.drawBitmap(x - 2,y - 2,tiles[TILEPLAYER],4,4); | |
if (timer > 0) { | |
arduboy.setCursor(0,0); | |
arduboy.println(strcpy_P(textBuffer, (char*)pgm_read_word(&(levelTitles[currMap])))); | |
timer--; | |
} | |
break; | |
case 3: | |
sel = 0; | |
arduboy.setCursor(0,0); | |
arduboy.println(F("Paused")); | |
arduboy.print(F("Keys: ")); | |
arduboy.println(keys); | |
arduboy.println(F("A: Menu")); | |
arduboy.println(F("B: Back")); | |
if (arduboy.justReleased(A_BUTTON)) { | |
if (editor) { | |
fixMap(); | |
state = 4; | |
} else { | |
state = 0; | |
} | |
} | |
if (arduboy.justReleased(B_BUTTON)) { | |
state = 2; | |
} | |
break; | |
case 4: | |
if (arduboy.justPressed(UP_BUTTON)) { | |
cursorY--; | |
} | |
if (arduboy.justPressed(DOWN_BUTTON)) { | |
cursorY++; | |
} | |
if (arduboy.justPressed(LEFT_BUTTON)) { | |
cursorX--; | |
} | |
if (arduboy.justPressed(RIGHT_BUTTON)) { | |
cursorX++; | |
} | |
cursorX %= 32; | |
cursorY %= 16; | |
if (arduboy.pressed(A_BUTTON) && cursorT != TILEPLAYER) { | |
if (tileMap[cursorX][cursorY] == TILEPLAYER) { | |
placedPlayer = false; | |
} | |
tileMap[cursorX][cursorY] = cursorT; | |
} else if (arduboy.justReleased(A_BUTTON) && cursorT == TILEPLAYER) { | |
tileMap[cursorX][cursorY] = cursorT; | |
if (!placedPlayer) { | |
placedPlayer = true; | |
cursorT = 1; | |
} | |
} | |
if (arduboy.justReleased(B_BUTTON)) { | |
state = 5; | |
} | |
drawMap(0,0,32,16); | |
if (timer < 10) { | |
arduboy.drawBitmap(cursorX*4,cursorY*4,tiles[cursorT],4,4,INVERT); | |
} else { | |
arduboy.drawBitmap(cursorX*4,cursorY*4,tiles[cursorT],4,4,WHITE); | |
} | |
timer = (timer + 1) % 20; | |
break; | |
case 5: | |
arduboy.setCursor(0,0); | |
arduboy.println(F("Select tile")); | |
if (placedPlayer) | |
arduboy.println(F("Player placed!")); | |
arduboy.drawBitmap(cursorT*6,52,arrow,4,4); | |
for (byte i = 0; i < (16 - (byte)placedPlayer); i++) { | |
arduboy.drawBitmap(i*6,58,tiles[i],4,4); | |
} | |
if (arduboy.justPressed(LEFT_BUTTON)) { | |
cursorT--; | |
} | |
if (arduboy.justPressed(RIGHT_BUTTON)) { | |
cursorT++; | |
} | |
cursorT %= 16 - (byte)placedPlayer; | |
if (arduboy.justReleased(A_BUTTON) && placedPlayer) { | |
state = 2; | |
if (showDebug) | |
outputMap(); | |
loadMap(0); // dont need id | |
} | |
if (arduboy.justReleased(B_BUTTON)) { | |
state = 4; | |
} | |
if (arduboy.justReleased(UP_BUTTON)) { | |
state = 0; | |
} | |
if (arduboy.justReleased(DOWN_BUTTON)) { | |
/*for (byte j = 0; j < LVLHEIGHT; j++) { | |
for (byte i = 0; i < LVLWIDTH; i++) { | |
tileMap[i][j] = 0; | |
} | |
} | |
placedPlayer = false;*/ | |
sel = 0; | |
state = 6; | |
} | |
break; | |
case 6: | |
arduboy.setCursor(0,0); | |
arduboy.println(F("Select mode")); | |
arduboy.println(strcpy_P(textBuffer, (char*)pgm_read_word(&(modeTitles[sel])))); | |
arduboy.drawBitmap(sel * 6,52,arrow,4,4); | |
for (byte i = 0; i < 8; i++) { | |
arduboy.drawBitmap(i * 6,58,tiles[3 - (bitRead(levelModes,i) * 2)],4,4); | |
} | |
if (arduboy.justPressed(LEFT_BUTTON)) { | |
sel--; | |
} | |
if (arduboy.justPressed(RIGHT_BUTTON)) { | |
sel++; | |
} | |
sel %= 8; | |
if (arduboy.justReleased(A_BUTTON)) { | |
bitWrite(levelModes,sel,!bitRead(levelModes,sel)); | |
} | |
if (arduboy.justReleased(B_BUTTON)) { | |
sel = 0; | |
state = 5; | |
} | |
break; | |
case 7: | |
arduboy.setCursor(0,0); | |
arduboy.println(F("~thanks for playing~")); | |
arduboy.println(F("Thanks to Nathan,")); | |
arduboy.println(F("Arduboy forum,")); | |
arduboy.println(F("and you!")); | |
if (arduboy.justReleased(A_BUTTON)) { | |
state = 0; | |
} | |
break; | |
default: | |
arduboy.setCursor(0,0); | |
arduboy.println(F("whoops")); | |
arduboy.println(F("there's no state here!")); | |
break; | |
} | |
if (arduboy.pressed(UP_BUTTON) && arduboy.justPressed(DOWN_BUTTON)) { | |
showDebug = !showDebug; | |
} | |
if (showDebug) { | |
arduboy.setCursor(0,50 * ((byte)floor(y / 4) < 8)); | |
arduboy.print(arduboy.cpuLoad()); | |
} | |
arduboy.display(); // Actually make the stuff I drew visible | |
} | |
bool isTileSolid(byte x, byte y) { | |
return isSolid(pixelTile(x,y)); | |
} | |
byte pixelTile(byte x, byte y) { | |
return tileMap[(byte)floor(x / 4) % 32][(byte)floor(y / 4) % 16] & 15; | |
} | |
bool isSolid(byte tileID) { | |
return (bool)bitRead(pgm_read_byte(&(tileInfo[(byte)floor(tileID / 8)])),tileID % 8); | |
} | |
void loadMap(byte mapIndex) { | |
keys = 0; | |
ax = 0; | |
ay = 0; | |
flip = 1; | |
timer = 120 * (byte)!editor; | |
switched = false; | |
if (mapIndex >= LVLNUMBER) { | |
mapIndex = 0; | |
state = 7; | |
} | |
if (!editor) | |
levelModes = pgm_read_byte(&(levels[mapIndex][0])); | |
for (byte j = 0; j < LVLHEIGHT; j++) { | |
for (byte i = 0; i < LVLWIDTH; i++) { | |
if (!editor) { | |
if (i % 2 == 0) { | |
tileMap[i][j] = pgm_read_byte(&(levels[mapIndex][1 + (i / 2) + (j * 16)])) >> 4; | |
} else { | |
tileMap[i][j] = pgm_read_byte(&(levels[mapIndex][1 + (i / 2) + (j * 16)])) & 15; | |
} | |
} | |
if (tileMap[i][j] == TILEPLAYER) { | |
x = (i*4)+2; | |
y = (j*4)+2; | |
tileMap[i][j] = TILEPLAYER << 4; | |
placedPlayer = true; | |
} | |
} | |
} | |
} | |
void drawMap(byte x,byte y,byte w,byte h) { | |
for (byte j = y; j < y + h; j++) { | |
for (byte i = x; i < x + w; i++) { | |
if ((tileMap[i % 32][j % 16] & 15) > (bitRead(levelModes,7) * (state == 2))) { | |
arduboy.drawBitmap((i % 32)*4,(j % 16)*4,tiles[tileMap[i % 32][j % 16] & 15],4,4); | |
} | |
} | |
} | |
} | |
void fixMap() { | |
for (byte j = 0; j < LVLHEIGHT; j++) { | |
for (byte i = 0; i < LVLWIDTH; i++) { | |
if ((tileMap[i][j] >> 4) > 0) { | |
tileMap[i][j] = tileMap[i][j] >> 4; | |
} | |
if ((tileMap[i][j] == TILESWITCHBLOCKOFF || tileMap[i][j] == TILESWITCHBLOCKON) && switched) { | |
useSwitch(); | |
switched = false; | |
} | |
} | |
} | |
} | |
void outputMap() { | |
/* Serial.print("{\n"); | |
for (byte j = 0; j < LVLHEIGHT; j++) { | |
for (byte i = 0; i < LVLWIDTH; i+=2) { | |
Serial.print("0x"); | |
Serial.print(tileMap[i][j],HEX); | |
Serial.print(tileMap[i+1][j],HEX); | |
Serial.print(","); | |
} | |
Serial.print("\n"); | |
} | |
Serial.print("};");*/ | |
} | |
void useSwitch() { | |
for (byte j = 0; j < LVLHEIGHT; j++) { | |
for (byte i = 0; i < LVLWIDTH; i++) { | |
if (tileMap[i][j] == TILESWITCHBLOCKOFF) { | |
tileMap[i][j] = TILESWITCHBLOCKON; | |
} else if (tileMap[i][j] == TILESWITCHBLOCKON) { | |
tileMap[i][j] = TILESWITCHBLOCKOFF; | |
} | |
} | |
} | |
switched = !switched; | |
} | |
float modFloat(float n, float m) { | |
while (n < 0) { | |
n += m; | |
} | |
while (n >= m) { | |
n -= m; | |
} | |
return n; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment