diff --git a/data/icons2.png b/data/icons2.png index e6d42ae..1fdf133 100644 Binary files a/data/icons2.png and b/data/icons2.png differ diff --git a/source/Globals.c b/source/Globals.c index fcf7a68..018fb41 100644 --- a/source/Globals.c +++ b/source/Globals.c @@ -1,6 +1,6 @@ #include "Globals.h" -char versionText[34] = "BETA BUILD 4"; +char versionText[34] = "BETA BUILD 5 (pre 1.0)"; char fpsstr[34]; u8 currentMenu = 0; @@ -118,6 +118,86 @@ bool moveMob(Entity* e, int xa, int ya){ return move(e, xa, ya); } +s16 lastTouchX = -1; +s16 lastTouchY = -1; +bool isDraggingMap = false; +bool isChangingSize = false; +void tickTouchMap(){ + if(shouldRenderMap){ + if(k_touch.px > 0 || k_touch.py > 0){ + // Plus/Minus zoom button + if(k_touch.py > 204 && k_touch.py < 232){ + if(k_touch.px > 284 && k_touch.px < 312){ + if(zoomLevel > 4) return; + if(!isChangingSize && !isDraggingMap){ + zoomLevel += 2; + mScrollX -= (50 * (zoomLevel/2)); + mScrollY -= (40 * (zoomLevel/2)); + isChangingSize = true; + sprintf(mapText,"x%d",zoomLevel); + } + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + return; + } else if(k_touch.px > 256 && k_touch.px < 284){ + if(zoomLevel < 4) return; + if(!isChangingSize && !isDraggingMap){ + mScrollX += (50 * (zoomLevel/2)); + mScrollY += (40 * (zoomLevel/2)); + zoomLevel -= 2; + isChangingSize = true; + sprintf(mapText,"x%d",zoomLevel); + } + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + return; + } + } else if(k_touch.py > 8 && k_touch.py < 40 && k_touch.px > 284 && k_touch.px < 312){ + // Exit Button + if(!isChangingSize && !isDraggingMap){ + shouldRenderMap = false; + return; + } + } + + if(!isDraggingMap){ + lastTouchX = k_touch.px; + lastTouchY = k_touch.py; + } + if(zoomLevel > 2){ + int dx = lastTouchX - k_touch.px; + if(dx > 1 || dx < -1){ + mScrollX -= dx; + if(mScrollX < 320-(128*zoomLevel)) mScrollX = 320-(128*zoomLevel); + else if(mScrollX > 0) mScrollX = 0; + } + lastTouchX = k_touch.px; + } + + int dy = lastTouchY - k_touch.py; + if(dy > 1 || dy < -1){ + mScrollY -= dy; + if(mScrollY < 240-(128*zoomLevel)) mScrollY = 240-(128*zoomLevel); + else if(mScrollY > 0) mScrollY = 0; + } + lastTouchY = k_touch.py; + isDraggingMap = true; + } else { + isDraggingMap = false; + isChangingSize = false; + } + } else { + // touch minimap to bring up zoomed map. + if(k_touch.py > 100 && k_touch.py < 228 && k_touch.px > 96 && k_touch.px < 228){ + shouldRenderMap = true; + } + } +} + void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){ if (e->hurtTime > 0) return; int xd = player.x - e->x; @@ -761,7 +841,11 @@ void tickEntity(Entity* e){ e->wizard.ya = ((rand()%3) - 1) * (rand()%2); } - if(e->wizard.xa != 0 || e->wizard.ya != 0) e->wizard.walkDist++; + if(e->wizard.xa != 0 || e->wizard.ya != 0){ + e->wizard.walkDist++; + awX = e->x; + awY = e->y; + } if(e->wizard.xa < 0) e->wizard.dir = 2; else if(e->wizard.xa > 0) e->wizard.dir = 3; @@ -1104,7 +1188,7 @@ void switchLevel(s8 change){ if(currentLevel > 4) currentLevel = 0; else if(currentLevel < 0) currentLevel = 4; if(currentLevel == 1) sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); else if(currentLevel > 1) sf2d_set_clear_color(RGBA8(0x66, 0x66, 0x66, 0xFF)); - else sf2d_set_clear_color(RGBA8(0x00, 0x1D, 0xC1, 0xFF)); + else sf2d_set_clear_color(RGBA8(0x00, 0x7F, 0x00, 0xFF)); } bool playerIntersectsEntity(Entity* e){ diff --git a/source/Globals.h b/source/Globals.h index a29a050..e2d83ab 100644 --- a/source/Globals.h +++ b/source/Globals.h @@ -54,11 +54,18 @@ bool screenShot; int loadedtp; +u8 MODEL_3DS; + extern char versionText[34]; Entity player; bool shouldRenderDebug; +bool shouldSpeedup; +bool shouldRenderMap; +u8 zoomLevel; +char mapText[32]; +s16 mScrollX, mScrollY; sf2d_texture *icons; sf2d_texture *font; @@ -76,6 +83,7 @@ extern char fpsstr[]; u8 initGame; Item noItem; int airWizardHealthDisplay; +s16 awX, awY; u32 tickCount; RecipeManager* currentRecipes; Entity* curChestEntity; @@ -90,6 +98,8 @@ s8 itemTileInteract(int tile, Item* item, int x, int y, int px, int py, int dir) void tickEntity(Entity* e); +void tickTouchMap(); + void trySpawn(int count, int level); int getTile(int x, int y); diff --git a/source/Input.c b/source/Input.c index 0b4387f..662cb69 100644 --- a/source/Input.c +++ b/source/Input.c @@ -6,6 +6,7 @@ void toggleKey(Key* key, bool held, bool down){ } void tickKeys(u32 held, u32 down){ + hidTouchRead(&k_touch); // Update touch position toggleKey(&k_up, held & k_up.input, down & k_up.input); toggleKey(&k_down, held & k_down.input, down & k_down.input); toggleKey(&k_left, held & k_left.input, down & k_left.input); @@ -16,5 +17,7 @@ void tickKeys(u32 held, u32 down){ toggleKey(&k_accept, held & k_accept.input, down & k_accept.input); toggleKey(&k_decline, held & k_decline.input, down & k_decline.input); toggleKey(&k_delete, held & k_delete.input, down & k_delete.input); + toggleKey(&k_menuNext, held & k_menuNext.input, down & k_menuNext.input); + toggleKey(&k_menuPrev, held & k_menuPrev.input, down & k_menuPrev.input); } diff --git a/source/Input.h b/source/Input.h index 3bd6270..761a315 100644 --- a/source/Input.h +++ b/source/Input.h @@ -16,6 +16,9 @@ Key k_pause; Key k_accept; Key k_decline; Key k_delete; +Key k_menuNext; +Key k_menuPrev; +touchPosition k_touch; -void tickKeys(u32 held,u32 down); +void tickKeys(u32 held, u32 down); bool clicked(Key key); diff --git a/source/Menu.c b/source/Menu.c index 9d9a313..38d1296 100644 --- a/source/Menu.c +++ b/source/Menu.c @@ -3,7 +3,7 @@ char options[][12] = {"Start Game", "How To Play","Settings", "About", "Exit"}; char pOptions[][24] = {"Return to game", "Save Progress", "Exit to title"}; char keybOptions[][24] = {"Exit and Save", "Exit and Don't save","Reset to default"}; -char setOptions[][24] = {"Rebind Buttons", "Texture packs", "Debug Text: ", "Return to title"}; +char setOptions[][24] = {"Rebind Buttons", "Texture packs", "Debug Text: ", "N3DS Speedup: ", "Return to title"}; // Rebind buttons menu (Settings) int keys[] = { @@ -14,7 +14,7 @@ int keys[] = { KEY_L,KEY_R,KEY_ZL,KEY_ZR, KEY_START,KEY_SELECT }; -int keyProp[10] = {[0 ... 9] = 0}; +int keyProp[12] = {[0 ... 11] = 0}; bool areYouSure = false; bool areYouSureSave = false; bool bindOpt = false; @@ -122,8 +122,8 @@ void addToFileName(char * c){ } /* Keypad */ -void doTouchButton(touchPosition touch){ - int xVal = touch.px, yVal = touch.py; +void doTouchButton(){ + int xVal = k_touch.px, yVal = k_touch.py; int strLength = strlen(fileNames[worldFileCount]); if(yVal >= 60 && yVal < 80){ // 0 to 9 if(xVal >= 4 && xVal < 4+16){ touchX = 4; if(strLength < 24)addToFileName("1");} @@ -233,7 +233,7 @@ void switchGameBut(bool left, int buttonID){ } void switchMenuBut(bool left, int buttonID){ int id; - for(id = 0; id < 10; ++id){ + for(id = 0; id < 12; ++id){ if(id > 3 && id < 7) continue; if(keyProp[id] & buttonID){ keyProp[id] ^= buttonID; // Toggle buttonID bit @@ -245,13 +245,13 @@ void switchMenuBut(bool left, int buttonID){ } else { int id2 = id+1; if (id2 == 4) id2 = 7; - if (id2 > 9) return; + if (id2 > 11) return; keyProp[id2] ^= buttonID; } return; } } - if(left) keyProp[9] ^= buttonID; + if(left) keyProp[11] ^= buttonID; else keyProp[0] ^= buttonID; } @@ -266,6 +266,8 @@ s8 checkPropButtons(){ if(keyProp[7] == 0) return 7; if(keyProp[8] == 0) return 8; if(keyProp[9] == 0) return 9; + if(keyProp[10] == 0) return 10; + if(keyProp[11] == 0) return 11; return -1; } @@ -315,9 +317,11 @@ void tickMenu(int menu){ k_accept.input = keyProp[7]; k_decline.input = keyProp[8]; k_delete.input = keyProp[9]; + k_menuNext.input = keyProp[10]; + k_menuPrev.input = keyProp[11]; FILE *fs=fopen("btnSave.bin","wb"); - fwrite(keyProp,sizeof(int),10,fs); + fwrite(keyProp,sizeof(int),12,fs); fclose(fs); currentSelection = 0; @@ -341,6 +345,8 @@ void tickMenu(int menu){ keyProp[7] = KEY_A; keyProp[8] = KEY_B; keyProp[9] = KEY_X; + keyProp[10] = KEY_R; + keyProp[11] = KEY_L; bindOpt = false; errorBut = -1; break; @@ -535,12 +541,10 @@ void tickMenu(int menu){ ++worldFileCount; } } - touchPosition touch; - hidTouchRead(&touch); - if((touch.px != 0 || touch.py != 0) && touchDelay == 0){ - if(!isTouching)doTouchButton(touch); + if((k_touch.px != 0 || k_touch.py != 0) && touchDelay == 0){ + if(!isTouching)doTouchButton(); } - else if(touch.px == 0 || touch.py == 0) isTouching = false; + else if(k_touch.px == 0 || k_touch.py == 0) isTouching = false; if(touchDelay > 0) --touchDelay; } break; @@ -575,8 +579,16 @@ void tickMenu(int menu){ break; case MENU_SETTINGS: - if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=3;} - if (k_down.clicked){ ++currentSelection; if(currentSelection > 3)currentSelection=0;} + if (k_up.clicked){ + --currentSelection; + if(currentSelection == 3 && !(MODEL_3DS & 6)) --currentSelection; + if(currentSelection < 0)currentSelection=4; + } + if (k_down.clicked){ + ++currentSelection; + if(currentSelection == 3 && !(MODEL_3DS & 6)) ++currentSelection; + if(currentSelection > 4)currentSelection=0; + } if(k_decline.clicked){ currentMenu = MENU_TITLE; currentSelection = 2; @@ -594,6 +606,8 @@ void tickMenu(int menu){ keyProp[7] = k_accept.input; keyProp[8] = k_decline.input; keyProp[9] = k_delete.input; + keyProp[10] = k_menuNext.input; + keyProp[11] = k_menuPrev.input; left = true; selBut = false; bindOpt = false; @@ -609,10 +623,17 @@ void tickMenu(int menu){ shouldRenderDebug = !shouldRenderDebug; // toggle option break; case 3: + if(MODEL_3DS & 6){ // detect if user is using a New 3DS + shouldSpeedup = !shouldSpeedup; // toggle option + osSetSpeedupEnable(shouldSpeedup); + } + break; + case 4: if(true){ - FILE * fset = fopen("settings.bin","wb"); - fwrite(&shouldRenderDebug,sizeof(bool),1,fset); - fclose(fset); + FILE * fset = fopen("settings.bin","wb"); + fwrite(&shouldRenderDebug,sizeof(bool),1,fset); + fwrite(&shouldSpeedup,sizeof(bool),1,fset); + fclose(fset); } currentMenu = MENU_TITLE; currentSelection = 2; @@ -633,6 +654,10 @@ void tickMenu(int menu){ enteringName = false; areYouSure = false; break; + case 1: + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + currentMenu = MENU_TUTORIAL; + break; case 2: currentSelection = 0; currentMenu = MENU_SETTINGS; @@ -647,6 +672,25 @@ void tickMenu(int menu){ } break; + case MENU_TUTORIAL: + if(k_decline.clicked){ + currentSelection = 1; + currentMenu = MENU_TITLE; + } + if(k_menuNext.clicked){ + if(pageNum < maxPageNum){ + ++pageNum; + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + } + } + if(k_menuPrev.clicked){ + if(pageNum > 0){ + --pageNum; + sprintf(pageText,"Page: %d/%d",pageNum+1,maxPageNum+1); + } + } + + break; } } @@ -673,6 +717,8 @@ char * getButtonFunctionMenu(int key){ if(keyProp[7] & key) return "Accept"; if(keyProp[8] & key) return "Decline"; if(keyProp[9] & key) return "Delete"; + if(keyProp[10] & key) return "Next"; + if(keyProp[11] & key) return "Previous"; return "Nothing"; } @@ -686,6 +732,14 @@ char guiText4[] = " SPACE BACKSPACE"; void renderMenu(int menu,int xscr,int yscr){ int i = 0; switch(menu){ + case MENU_TUTORIAL: + sf2d_start_frame(GFX_TOP, GFX_LEFT); + renderTutorialPage(true); + sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + renderTutorialPage(false); + sf2d_end_frame(); + break; case MENU_SETTINGS_TP: offsetX = 0;offsetY = (currentSelection * 40) - 48; sf2d_start_frame(GFX_TOP, GFX_LEFT); @@ -875,7 +929,7 @@ void renderMenu(int menu,int xscr,int yscr){ drawText("Press to return", 98, 190); renderButtonIcon(k_decline.input & -k_decline.input, 168, 188, 1); - if(errorBut >= 0 && errorBut < 9){ + if(errorBut >= 0 && errorBut < 12){ char errorText[30]; switch(errorBut){ case 0: sprintf(errorText, "Error: Missing 'Move up'"); break; @@ -888,6 +942,8 @@ void renderMenu(int menu,int xscr,int yscr){ case 7: sprintf(errorText, "Error: Missing 'Accept'"); break; case 8: sprintf(errorText, "Error: Missing 'Decline'"); break; case 9: sprintf(errorText, "Error: Missing 'Delete'"); break; + case 10: sprintf(errorText, "Error: Missing 'Next'"); break; + case 11: sprintf(errorText, "Error: Missing 'Previous'"); break; } drawTextColor(errorText,(400 - (strlen(errorText) * 12))/2,50,0xFF0000FF); } @@ -1080,16 +1136,25 @@ void renderMenu(int menu,int xscr,int yscr){ break; case MENU_SETTINGS: sf2d_start_frame(GFX_TOP, GFX_LEFT); - drawText("Settings",(400-(8*12))/2,40); - for(i = 3; i >= 0; --i){ + drawText("Settings",(400-(8*12))/2,30); + for(i = 4; i >= 0; --i){ char* msg = setOptions[i]; u32 color = 0x7F7F7FFF; if(i == currentSelection) color = 0xFFFFFFFF; if(i == 2){ - if(shouldRenderDebug) drawSizedTextColor("On",142, ((8 + i) * 32 - 170) >> 1,2.0, 0x00DF00FF); - else drawSizedTextColor("Off",142, ((8 + i) * 32 - 170) >> 1,2.0, 0xDF0000FF); + if(shouldRenderDebug) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0x00DF00FF); + else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xDF0000FF); + } else if(i == 3){ + + if(MODEL_3DS & 6){ // detect if user is using a New 3DS + if(shouldSpeedup) drawSizedTextColor("On",142, ((8 + i) * 32 - 190) >> 1,2.0, 0x00DF00FF); + else drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0xDF0000FF); + } else { + color = 0x3F3F3FFF; + drawSizedTextColor("Off",142, ((8 + i) * 32 - 190) >> 1,2.0, 0x3F3F3FFF); + } } - drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 32 - 170) >> 1,2.0, color); + drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 32 - 190) >> 1,2.0, color); } sf2d_end_frame(); sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); @@ -1104,6 +1169,9 @@ void renderMenu(int menu,int xscr,int yscr){ drawTextColor("Show FPS/Pos/Entities",(320 - (22 * 12))/2,24,0xFFFF7FFF); break; case 3: + drawTextColor("Use the N3DS 804mhz mode",(320 - (24 * 12))/2,24,0xFFFF7FFF); + break; + case 4: drawTextColor("Back to the titlescreen",(320 - (23 * 12))/2,24,0xFFFF7FFF); break; } @@ -1163,7 +1231,7 @@ void renderMenu(int menu,int xscr,int yscr){ render16 (startX+9,startY+18,16,112,0);//Player renderc (startX+9,startY+14,16,160,16,8,0);//Slash drawTextColor("Play minicraft",24,24,0xFFFF7FFF); - break; + break; case 1: // "How To Play" startX = 72;startY = 54; render16(startX,startY,96,208,0);//C-PAD @@ -1181,16 +1249,34 @@ void renderMenu(int menu,int xscr,int yscr){ render16(startX,startY,160,208,0);//C-PAD right drawTextColor("Learn the basics",64,24,0xFFFF7FFF); - break; + break; case 2: // "Settings" - break; + drawTextColor("Modify the game's feel",(320 - (22 * 12))/2,24,0xFFFF7FFF); + renderc(48,48,0,112,64,32,0); + break; case 3: // "About" - break; + drawTextColor("Who made this game?",(320 - (19 * 12))/2,24,0xFFFF7FFF); + + // Secret code ;) + drawSizedText("497420776173206e6f746368",(320 - (24 * 8))/2,80,1); + drawSizedText("506f727465642062792044617669646565736b",(320 - (38 * 8))/2,88,1); + drawSizedText("576879207265616420746869733f",(320 - (28 * 8))/2,96,1); + drawSizedText("596f75207761737465642074696d65",(320 - (30 * 8))/2,104,1); + drawSizedText("4861204861204861204861204861",(320 - (28 * 8))/2,112,1); + drawSizedText("5468652063616b652069732061206c6965",(320 - (34 * 8))/2,120,1); + drawSizedText("4044617669646565736b2074776974746572",(320 - (36 * 8))/2,128,1); + drawSizedText("3533363536333732363537343231",(320 - (28 * 8))/2,136,1); + drawSizedText("4c69617220746578742062656c6f77",(320 - (30 * 8))/2,144,1); + drawSizedText("(Totally not a secret code or anything)",4,160,1); + + break; + case 4: // "Exit" + drawTextColor("Exit to the homebrew menu",(320 - (25 * 12))/2,24,0xFFFF7FFF); + drawTextColor("(bye-bye)",(320 - (9 * 12))/2,100,0xFFFF7FFF); + break; } sf2d_end_frame(); break; - - } - + } diff --git a/source/Menu.h b/source/Menu.h index e86c898..61c20f9 100644 --- a/source/Menu.h +++ b/source/Menu.h @@ -1,12 +1,6 @@ #pragma once -#include <3ds.h> -#include -#include -#include -#include - -#include "Render.h" +#include "MenuTutorial.h" #include "texturepack.h" void renderMenu(int menu,int xscr,int yscr); diff --git a/source/MenuTutorial.c b/source/MenuTutorial.c new file mode 100644 index 0000000..dfb026d --- /dev/null +++ b/source/MenuTutorial.c @@ -0,0 +1,256 @@ +#include "MenuTutorial.h" + +u8 pageNum = 0; +u8 maxPageNum = 6; + +u32 biasedCirclePad(u32 in){ + if(in & KEY_CPAD_UP) return KEY_CPAD_UP; + else if(in & KEY_CPAD_DOWN) return KEY_CPAD_DOWN; + else if(in & KEY_CPAD_LEFT) return KEY_CPAD_LEFT; + else if(in & KEY_CPAD_RIGHT) return KEY_CPAD_RIGHT; + else return (in & -in); +} + +u32 biasedMenuXY(u32 in){ + if(in & KEY_X) return KEY_X; + else if(in & KEY_Y) return KEY_Y; + else return (in & -in); +} + +/** Oh my god, this was so damn tedious to make. */ +void renderTutorialPage(bool topScreen){ + if(topScreen){ + drawTextColor("How to Play",(400-11*12)/2,12,0xAFAF00FF); + switch(pageNum){ + case 0: // Moving the character + drawTextColor("Movement",(400-8*12)/2,40,0xBF7F00FF); + drawText("Press to move up",92,90); + renderButtonIcon(biasedCirclePad(k_up.input), 164, 88, 1); + drawText("Press to move down",80,120); + renderButtonIcon(biasedCirclePad(k_down.input), 152, 118, 1); + drawText("Press to move left",80,150); + renderButtonIcon(biasedCirclePad(k_left.input), 152, 148, 1); + drawText("Press to move right",74,180); + renderButtonIcon(biasedCirclePad(k_right.input), 146, 178, 1); + break; + case 1: // Attacking + drawTextColor("Attacking",(400-9*12)/2,40,0xBF7F00FF); + drawText("Press to Attack",98,80); + renderButtonIcon(k_attack.input & -k_attack.input, 168, 78, 1); + drawText("Attack with an item to use it",26,120); + drawText("Use the axe to cut down trees",26,140); + drawText("Use the sword to attack enemies",14,160); + drawText("Use the shovel to dig ground",32,180); + drawText("Use the pickaxe to mine rock/ore",8,200); + break; + case 2: // Inventory + drawTextColor("Inventory",(400-9*12)/2,40,0xBF7F00FF); + drawText("Press to open the menu",56,80); + renderButtonIcon(biasedMenuXY(k_menu.input), 126, 78, 1); + drawText("Press to scroll up",80,110); + renderButtonIcon(biasedCirclePad(k_up.input), 152, 108, 1); + drawText("Press to scroll down",68,140); + renderButtonIcon(biasedCirclePad(k_down.input), 140, 138, 1); + drawText("Press to select an item",50,170); + renderButtonIcon(k_accept.input & -k_accept.input, 120, 168, 1); + drawText("Press to close the menu",50,200); + renderButtonIcon(k_decline.input & -k_decline.input, 120, 198, 1); + break; + case 3: // Furniture + drawTextColor("Furniture",(400-9*12)/2,40,0xBF7F00FF); + drawText("Use furniture for item crafting",(400-31*12)/2,74); + drawText("Press to open the menu",56,100); + renderButtonIcon(biasedMenuXY(k_menu.input), 126, 98, 1); + drawText("while infront of the furniture",(400-30*12)/2,116); + drawText("Use the lantern item to light",(400-29*12)/2,144); + drawText("up underground areas",(400-20*12)/2,160); + drawText("Use the power glove item to",(400-27*12)/2,184); + drawText("pick up furniture",(400-17*12)/2,200); + break; + case 4: // Crafting + drawTextColor("Crafting",(400-8*12)/2,40,0xBF7F00FF); + drawText("Create new items and tools",(400-26*12)/2,74); + drawText("Go up to a furniture item and",(400-29*12)/2,104); + drawText("Press to open the menu",56,120); + renderButtonIcon(biasedMenuXY(k_menu.input), 126, 118, 1); + drawText("Gather up the required materials",(400-32*12)/2,150); + drawText("and then press to craft it",(400-28*12)/2,166); + renderButtonIcon(k_accept.input & -k_accept.input, 210, 164, 1); + break; + case 5: // Farming + drawTextColor("Farming",(400-7*12)/2,40,0xBF7F00FF); + drawText("Grow wheat to make bread",(400-24*12)/2,74); + drawText("Dig up grass to gather seeds",(400-28*12)/2,94); + drawText("Use the hoe to till ground",(400-26*12)/2,114); + drawText("Harvest wheat when it is yellow",(400-31*12)/2,134); + drawText("Use the oven to bake bread",(400-26*12)/2,154); + drawText("It takes 4 wheat to craft bread",(400-31*12)/2,174); + break; + case 6: // Mining + drawTextColor("Mining",(400-6*12)/2,40,0xBF7F00FF); + drawText("Use a pickaxe tool for mining",(400-29*12)/2,74); + drawText("Mine rocks for stone",(400-20*12)/2,94); + drawText("Mine iron ore for iron",(400-22*12)/2,114); + drawText("Mine gold ore for gold",(400-22*12)/2,134); + drawText("Mine gem ore to get gems",(400-24*12)/2,154); + drawText("It takes 4 ore and 1 coal to",(400-28*12)/2,190); + drawText("make an ingot inside a furnace",(400-30*12)/2,210); + break; + } + } else { + switch(pageNum){ + case 0: // Moving the character + render16(30,56,16,112,0);//Player up + renderButtonIcon(biasedCirclePad(k_up.input), 30,40, 2); + render16(60,56,0,112,0);//Player down + renderButtonIcon(biasedCirclePad(k_down.input), 60,40, 2); + render16(90,56,48,112,1);//Player left + renderButtonIcon(biasedCirclePad(k_left.input), 90,40, 2); + render16(120,56,48,112,0);//Player right + renderButtonIcon(biasedCirclePad(k_right.input), 120,40, 2); + break; + case 1: // Attacking + render16(60,56,0,112,0);//Player-down + renderButtonIcon(k_attack.input & -k_attack.input, 80, 56, 2); + renderc(60,68,16,160,16,8,2);//Slash + + render16b(12,20,16,80,0,0x69B569FF);// grass pit + render16b(12+16,20,32,80,0,0x69B569FF); + render16b(12,20+16,48,80,0,0x69B569FF); + render16b(12+16,20+16,64,80,0,0x69B569FF); + render16(12+8,20+4,0,16,0);//Tree + renderc(12+9,20+14,16,160,16,8,0);//Slash + render(12+9+4,20+14,192,144,0);//Axe + render16(12+9,20+18,16,112,0);//Player-up + + render16b(122,62,16,80,0,0xF7F77BFF);// sand pit + render16b(122+16,62,32,80,0,0xF7F77BFF); + render16b(122,62+16,48,80,0,0xF7F77BFF); + render16b(122+16,62+16,64,80,0,0xF7F77BFF); + render16b(130,70,0,96,0,0x383838FF);// hole + render16(116,70,48,112,0);//Player-right + renderb(136,76,16,152,0,0xAF9781FF);// Dirt item + renderc(128,70,40,160,8,16,0);//Slash + render(130,74,0,144,0);//Shovel + break; + case 2: // Inventory + renderFrame(4,4,17,11,0xAFFF); + renderItemStuffWithText(ITEM_APPLE,5,false,80,78); + renderItemStuffWithText(ITEM_SLIME,11,false,80,94); + renderItemStuffWithText(TOOL_SWORD,4,true,80,110); + renderItemStuffWithText(ITEM_IRONORE,3,false,80,126); + renderItemStuffWithText(ITEM_IRONINGOT,11,false,80,142); + sf2d_draw_rectangle(64, 110, 12, 12, 0xFF); + drawText(">", 64, 110); + renderButtonIcon(biasedCirclePad(k_up.input), 44, 92, 1); + renderButtonIcon(k_accept.input & -k_accept.input, 44, 108, 1); + renderButtonIcon(biasedCirclePad(k_down.input), 44, 125, 1); + break; + case 3: // Furniture + sf2d_draw_rectangle(64, 48, 192, 32, 0x69B569FF); + renderc(32,24,64,128,96,16,0);//Furniture entities + + renderFurniture(ITEM_WORKBENCH, 50,60); + render16(50,46,0,112,0);//Player-down + renderc(50,58,16,160,16,8,2);//Slash + render(54,58,56,152,0);//Power glove + + render16(92,56,0,128,0);//Player(Carrying) + render16(92,44,128,128,0);//Workbench + break; + case 4: // Crafting + renderFrame(11,3,19,6,0x1010FFFF); + renderFrame(11,7,19,12,0x1010FFFF); + renderFrame(1,3,10,12,0x1010FFFF); + renderItemStuffWithText(TOOL_AXE,0,true,28,64); + renderItemIcon(TOOL_AXE, 0, 94, 32); + drawText("0", 206, 66); + renderItemIcon(ITEM_WOOD, 0, 94, 64); + drawText("16/5", 206, 130); + break; + case 5: // Farming (Bottom screen) + renderc(24,16,144,0,112,16,0); // Wheat Stages + + render16(20,40,144,0,0); // Farm Tile + render16(36,40,240,0,0); // Wheat Tile + render16(52,40,240,0,0); // Wheat Tile + render16(20,54,16,112,0); // Player (Up) + renderc(20,50,16,160,16,8,0); // Slash (Up) + render(19,45,40,152,0); // Seeds + render(26,39,48,152,0); // Wheat1 + render(29,44,48,152,0); // Wheat2 + + renderc(72,40,144,0,32,16,0); // Farm Tile + Seeded Wheat Tile + render16(72,54,16,112,0); // Player (Up) + renderc(72,50,16,160,16,8,0); // Slash (Up) + render(76,48,40,152,0); // Seeds + + sf2d_draw_rectangle(216, 80, 32, 32, dirtColor[1]); // Dirt color for grass + render16b(108, 40, 0, 80, 0, 0x69B569FF); // Grass + render16(124, 40,144,0,0); // Farm Tile + render16(108,54,16,112,0); // Player (Up) + renderc(108,50,16,160,16,8,0); // Slash (Up) + render(112,48,72,144,0); // Gem Hoe + + sf2d_draw_rectangle(112, 156, 32, 32, dirtColor[1]); // Dirt color for grass + render16b(56, 78, 0, 80, 0, 0x69B569FF); // Grass + sf2d_draw_rectangle(80, 156, 32, 32, dirtColor[1]); // Dirt color + render16b(40, 78, 0, 0, 0, 0xA88F8FFF); // Dirt Dots + render(44, 82, 40,152,0); // Seeds + + render16(24,78,48,112,0); // Player (Right) + renderc(36,78,40,160,8,16,0); // Slash (Right) + render(38,82,32,144,0); // Gem Shovel + + render(82,78,48,152,0); // Wheat + render(90,78,48,152,0); // Wheat + render(82,86,48,152,0); // Wheat + render(90,86,48,152,0); // Wheat + drawText(">",203,164); + render16(108,76,96,128,0); // Oven + drawText(">",246,164); + render(132,82,72,152,0); // Bread + break; + case 6: //Mining + render16b(23,32,80,0,0,0xDFC8C8FF); // iron ore + render16b(23,52,80,0,0,0xE5E8B9FF); // gold ore + render16b(23,72,80,0,0,0xDF98DEFF); // gem ore + renderb(41,38,88,152,0,0xDFC8C8FF); // Iron ore item + renderb(41,58,88,152,0,0xE5E8B9FF); // Gold ore item + render(41,78,112,152,0); // Gem item + drawText(">",104,74); + drawText(">",104,114); + drawText(">",104,154); + render16(60,32,112,128,0); // Furnace + render16(60,52,112,128,0); // Furnace + render16(60,72,64,128,0); // Anvil + drawText(">",160,74); + drawText(">",160,114); + drawText(">",160,154); + renderb(88,36,96,152,0,0xDFC8C8FF); // Iron ingot item + renderb(88,56,96,152,0,0xE5E8B9FF); // Gold ingot item + renderb(88,76,152,144,0,0xE5E8B9FF); // Gem Pickaxe + drawText(">",200,74); + drawText(">",200,114); + render16(106,32,64,128,0); // Anvil + render16(106,52,64,128,0); // Anvil + drawText(">",244,74); + drawText(">",244,114); + render(130,36,136,144,0); // Iron Pickaxe + render(130,56,144,144,0); // Gold Pickaxe + break; + } + + drawText(pageText,(320-(strlen(pageText))*12)/2,12); + if(pageNum > 0){ + drawText("<",2,16); + renderButtonIcon(k_menuPrev.input & -k_menuPrev.input, 8, 2, 2); + } + if(pageNum < maxPageNum){ + drawText(">",306,16); + renderButtonIcon(k_menuNext.input & -k_menuNext.input, 136, 2, 2); + } + drawText("Press to exit",(320-(15*12))/2,218); + renderButtonIcon(k_decline.input & -k_decline.input, 140, 216, 1); + } +} diff --git a/source/MenuTutorial.h b/source/MenuTutorial.h new file mode 100644 index 0000000..84d5733 --- /dev/null +++ b/source/MenuTutorial.h @@ -0,0 +1,16 @@ +#pragma once + +#include <3ds.h> +#include +#include +#include +#include + +#include "Render.h" + +extern u8 pageNum; +extern u8 maxPageNum; + +char pageText[18]; + +void renderTutorialPage(bool topScreen); diff --git a/source/Render.c b/source/Render.c index 1e64b92..35952d3 100644 --- a/source/Render.c +++ b/source/Render.c @@ -93,20 +93,20 @@ void render16(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits) { scaleX, scaleY); } -void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float scaleX, - float scaleY) { +void render16c(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float scaleX,float scaleY) { xp -= offsetX; yp -= offsetY; + xp *= scaleX; + yp *= scaleY; if ((bits & 1) > 0) { + xp += 16 * scaleX; scaleX = -scaleX; - xp += 16; } if ((bits & 2) > 0) { + yp += 16 * scaleY; scaleY = -scaleY; - yp += 16; } - sf2d_draw_texture_part_scale(icons, xp * scaleX, yp * scaleY, xTile, yTile, - 16, 16, scaleX, scaleY); + sf2d_draw_texture_part_scale(icons, xp, yp, xTile, yTile,16, 16, scaleX, scaleY); } void render16b(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color) { @@ -548,7 +548,7 @@ void renderTile(int i, int x, int y) { render16s(x, y, rockTable[v] + 8192, 0, 0xCFCFFFFF); renderRockDotsWithColor(rockTable[v], x, y, 0x9494FFFF); break; - case TILE_DIRT: + case TILE_DIRT: // render dots. if (currentLevel > 1) render16b(x, y, 0, 0, 0, 0x383838FF); else @@ -637,10 +637,36 @@ void renderTile(int i, int x, int y) { } +void renderZoomedMap() { + int mx = mScrollX; + int my = mScrollY; + if(zoomLevel == 2) mx = 32; + sf2d_draw_texture_scale(minimap[currentLevel], mx, my, zoomLevel, zoomLevel); // zoomed map + if(currentLevel == 0){ + render16c( + (mx+((awX/16)*zoomLevel)-16)/2, + (my+((awY/16)*zoomLevel)-16)/2, + 160, 112, + ((player.p.walkDist >> 6) & 1) == 0 ? 0 : 1, + 2, 2 + ); // Airwizard on zoomed map + } + render16c( + (mx+((player.x/16)*zoomLevel)-16)/2, + (my+((player.y/16)*zoomLevel)-16)/2, + 0, 112, + ((player.p.walkDist >> 6) & 1) == 0 ? 0 : 1, + 2, 2 + ); // Player on zoomed map + drawText(mapText,224, 214); // "x2"/"x4"/"x6" + render16(142, 2, 72, 208, 0); // Exit button + renderc(126, 102, 40, 208, 32, 16, 0); // Plus/Minus zoom buttons + if(zoomLevel < 3) sf2d_draw_rectangle(258, 210, 26, 20, 0x4F4F4F7F); // gray out minus button + else if(zoomLevel > 5) sf2d_draw_rectangle(284, 210, 26, 20, 0x4F4F4F7F); // gray out minus button +} + char scoreT[32]; void renderGui() { - //renderFrame(0,0,11,3,0x201092FF); - //renderFrame(11,0,20,3,0x201092FF); int i; for (i = 0; i < 10; ++i) { if (i < player.p.health) @@ -657,6 +683,10 @@ void renderGui() { itoa(player.p.score, scoreT, 10); // integer to base10 string drawText("Score:",214,12); drawText(scoreT,(140-(strlen(scoreT)*12))/2 + 180,29); + if(currentLevel == 0){ + renderc(44 + (awX/32), 47 + (awY/32), 88, 216, 8, 8, 0); // Mini-AWizard head. + } + renderc(44 + (player.x/32), 47 + (player.y/32), 88, 208, 8, 8, 0); // Mini-Player head. } void renderPlayer() { @@ -748,7 +778,11 @@ void renderMenuBackground(int xScroll, int yScroll) { } void renderBackground(int xScroll, int yScroll) { - sf2d_draw_rectangle(0, 0, 400, 240, dirtColor[currentLevel]); // dirt color + if(currentLevel > 0) sf2d_draw_rectangle(0, 0, 400, 240, dirtColor[currentLevel]); // dirt color + else { + sf2d_draw_texture_part_scale(minimap[1], (-xScroll / 3) - 256, (-yScroll / 3) - 32, 0, 0, 128, 128, 12.5, 7.5); + sf2d_draw_rectangle(0, 0, 400, 240, 0xDFDFDFAF); + } int xo = xScroll >> 4; int yo = yScroll >> 4; int x, y; @@ -1037,6 +1071,15 @@ void renderItemWithText(Item* item, int x, int y) { y + 2, 0xD2D2D2FF, 0xFFFFFFFF); } +void renderItemStuffWithText(int itemID, int itemCL, bool onlyOne, int x, int y) { + renderItemIcon(itemID, itemCL, x >> 1, y >> 1); + if (onlyOne) + drawText(getItemName(itemID, itemCL), x + 18, y + 2); + else + drawTextColorSpecial(getItemName(itemID, itemCL), x + 18, + y + 2, 0xD2D2D2FF, 0xFFFFFFFF); +} + /* For bottom screen */ void renderItemWithTextCentered(Item* item, int width, int y) { char * tn = getItemName(item->id, item->countLevel); diff --git a/source/Render.h b/source/Render.h index 08ae9a3..1b91e04 100644 --- a/source/Render.h +++ b/source/Render.h @@ -39,6 +39,7 @@ void bakeLight(sf2d_texture* texture, int x, int y, int r); void renderLight(int x, int y, sf2d_texture* texture); void renderGui(); +void renderZoomedMap(); void renderPlayer(); void drawText(char * msg, u32 x, u32 y); @@ -56,6 +57,7 @@ void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1, int selected); void renderItemWithText(Item* item, int x, int y); +void renderItemStuffWithText(int itemID, int itemCL, bool onlyOne, int x, int y); void renderItemWithTextCentered(Item* item, int width, int y); void renderItemIcon(int itemID, int countLevel, int x, int y); void renderItemIcon2(int itemID, int countLevel, int x, int y, int z); diff --git a/source/main.c b/source/main.c index 97de4c9..e640b01 100644 --- a/source/main.c +++ b/source/main.c @@ -98,6 +98,9 @@ void initMiniMap(bool loadUpWorld) { case TILE_STAIRS_UP: sf2d_set_pixel(minimap[i], x, y, 0xFF9F9F9F); break; + case 255: + sf2d_set_pixel(minimap[i], x, y, 0xFF007F00); + break; default: sf2d_set_pixel(minimap[i], x, y, 0xFF111111); break; @@ -138,6 +141,11 @@ void setupGame(bool loadUpWorld) { } initMiniMap(loadUpWorld); + shouldRenderMap = false; + mScrollX = 0; + mScrollY = 0; + zoomLevel = 2; + sprintf(mapText,"x%d",zoomLevel); initGame = 0; } @@ -156,6 +164,8 @@ void tick() { --player.p.endTimer; return; } + + tickTouchMap(); int i; for (i = 0; i < 324; ++i) { @@ -194,6 +204,16 @@ void clearScreen(int* data, u8 fill, int size) { char debugText[34]; char bossHealthText[34]; int main() { + CFGU_GetSystemModel(&MODEL_3DS); + FILE * file; + shouldRenderDebug = true; + if ((file = fopen("settings.bin", "r"))) { + fread(&shouldRenderDebug,sizeof(bool),1,file); + fread(&shouldSpeedup,sizeof(bool),1,file); + osSetSpeedupEnable(shouldSpeedup); + fclose(file); + } + sf2d_init(); csndInit(); noItem = newItem(ITEM_NULL, 0); @@ -246,7 +266,8 @@ int main() { k_accept.input = KEY_A; k_decline.input = KEY_B; k_delete.input = KEY_X; - FILE * file; + k_menuNext.input = KEY_R; + k_menuPrev.input = KEY_L; /* If btnSave exists, then use that. */ if ((file = fopen("btnSave.bin", "rb"))) { @@ -260,6 +281,8 @@ int main() { fread(&k_accept.input, sizeof(int), 1, file); fread(&k_decline.input, sizeof(int), 1, file); fread(&k_delete.input, sizeof(int), 1, file); + fread(&k_menuNext.input, sizeof(int), 1, file); + fread(&k_menuPrev.input, sizeof(int), 1, file); fclose(file); } @@ -270,12 +293,6 @@ int main() { loadTexturePack(fnbuf); fclose(file); } - - shouldRenderDebug = true; - if ((file = fopen("settings.bin", "r"))) { - fread(&shouldRenderDebug,sizeof(bool),1,file); - fclose(file); - } tickCount = 0; initRecipes(); @@ -292,10 +309,6 @@ int main() { if (currentMenu == 0) { tick(); sf2d_start_frame(GFX_TOP, GFX_LEFT); - if (currentLevel == 0) { - sf2d_draw_texture_part_scale(minimap[1], (-xscr / 3) - 256, (-yscr / 3) - 32, 0, 0, 128, 128, 12.5, 7.5); - sf2d_draw_rectangle(0, 0, 400, 240, 0xDFDFDFAF); - } offsetX = xscr; offsetY = yscr; @@ -305,10 +318,11 @@ int main() { renderBackground(xscr, yscr); renderEntities(player.x, player.y, &eManager); renderPlayer(); - + resetStencilStuff(); offsetX = 0; offsetY = 0; + if(shouldRenderDebug){ sprintf(fpsstr, " FPS: %.0f, X:%d, Y:%d, E:%d", sf2d_get_fps(), player.x, player.y, eManager.lastSlot[currentLevel]); drawText(fpsstr, 2, 225); @@ -316,10 +330,14 @@ int main() { sf2d_end_frame(); - sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); - sf2d_draw_texture(bottombg, 0, 0); - renderGui(); - sf2d_end_frame(); + sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); + if(!shouldRenderMap){ + sf2d_draw_texture(bottombg, 0, 0); + renderGui(); + } else { + renderZoomedMap(); + } + sf2d_end_frame(); } else { tickMenu(currentMenu); renderMenu(currentMenu, xscr, yscr);