diff --git a/data/icons2.png b/data/icons2.png index 34f7d40..37a97d6 100644 Binary files a/data/icons2.png and b/data/icons2.png differ diff --git a/source/Entity.c b/source/Entity.c index 815ca7b..604e4b1 100644 --- a/source/Entity.c +++ b/source/Entity.c @@ -228,6 +228,60 @@ Entity newSparkEntity(Entity* parent, float xa, float ya){ return e; } +Entity newDragonEntity(int x, int y, int level) { + Entity e; + e.type = ENTITY_DRAGON; + e.level = level; + e.x = x; + e.y = y; + e.hurtTime = 0; + e.xKnockback = 0; + e.yKnockback = 0; + e.dragon.dir = 0; + e.dragon.health = 2000; + e.dragon.attackDelay = 0; + e.dragon.attackTime = 0; + e.dragon.attackType = 0; + e.dragon.animTimer = 0; + e.dragon.xa = 0; + e.dragon.ya = 0; + e.xr = 8; + e.yr = 8; + e.canPass = false; + return e; +} + +Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya) { + Entity e; + e.type = ENTITY_DRAGONPROJECTILE; + e.level = parent->level; + e.dragonFire.age = 0; + e.dragonFire.type = type; + e.dragonFire.parent = parent; + e.dragonFire.xa = xa; + e.dragonFire.ya = ya; + e.dragonFire.xx = x; + e.dragonFire.yy = y; + e.x = (int) x; + e.y = (int) y; + e.xr = 3; + e.yr = 3; + e.canPass = true; + return e; +} + +Entity newMagicPillarEntity(int x, int y, int level){ + Entity e; + e.type = ENTITY_MAGIC_PILLAR; + e.level = level; + e.x = x; + e.y = y; + e.xr = 3; + e.yr = 3; + e.canPass = false; + return e; +} + Entity newTextParticleEntity(char * str, u32 color, int x, int y, int level){ Entity e; e.type = ENTITY_TEXTPARTICLE; diff --git a/source/Entity.h b/source/Entity.h index 4a14d66..57df29d 100644 --- a/source/Entity.h +++ b/source/Entity.h @@ -19,6 +19,10 @@ #define ENTITY_KNIGHT 13 #define ENTITY_GLOWWORM 14 +#define ENTITY_DRAGON 15 +#define ENTITY_DRAGONPROJECTILE 16 +#define ENTITY_MAGIC_PILLAR 17 + typedef struct Entity Entity; typedef struct { @@ -109,6 +113,15 @@ typedef struct { s8 spriteAdjust; } AirWizard; +typedef struct { + Entity* parent; + s16 age; + float xa; + float ya; + float xx; + float yy; +} Spark; + typedef struct { Entity* parent; s16 age; @@ -117,14 +130,28 @@ typedef struct { s8 ya; } Arrow; +typedef struct { + s8 xa; + s8 ya; + s16 health; + s8 randWalkTime; + s8 walkDist; + s8 dir; + int attackDelay; + int attackTime; + int attackType; + int animTimer; +} Dragon; + typedef struct { Entity* parent; + u8 type; s16 age; float xa; float ya; float xx; float yy; -} Spark; +} DragonFire; typedef struct { s8 xa; @@ -171,6 +198,8 @@ struct Entity { Spark spark; Arrow arrow; Glowworm glowworm; + Dragon dragon; + DragonFire dragonFire; TextParticleEntity textParticle; SmashParticleEntity smashParticle; }; @@ -178,7 +207,6 @@ struct Entity { typedef struct { Entity entities[6][1000]; - Entity wizardSparks[120]; s16 lastSlot[6]; Inventory invs[301];//1 for the player, 300 for chests. s16 nextInv; @@ -199,6 +227,9 @@ Entity newKnightEntity(int lvl, int x, int y, int level); Entity newSlimeEntity(int lvl, int x, int y, int level); Entity newAirWizardEntity(int x, int y, int level); Entity newSparkEntity(Entity* parent, float xa, float ya); +Entity newDragonEntity(int x, int y, int level); +Entity newDragonFireEntity(Entity* parent, u8 type, int x, int y, float xa, float ya); +Entity newMagicPillarEntity(int x, int y, int level); Entity newTextParticleEntity(char * str, u32 color, int xa, int ya, int level); Entity newSmashParticleEntity(int xa, int ya, int level); Entity newArrowEntity(Entity* parent, int itemID, s8 xa, s8 ya, int level); diff --git a/source/Globals.c b/source/Globals.c index f53beb8..e52d4a7 100644 --- a/source/Globals.c +++ b/source/Globals.c @@ -1,6 +1,6 @@ #include "Globals.h" -char versionText[34] = "Version 1.2"; +char versionText[34] = "Version 1.2.1"; char fpsstr[34]; u8 currentMenu = 0; @@ -199,7 +199,7 @@ void tickTouchMap(){ } void tickTouchQuickSelect() { - if (currentMenu == 0) { + if (currentMenu == 0 && !shouldRenderMap) { int i = 0; Inventory * inv = player.p.inv; @@ -299,6 +299,17 @@ void hurtEntity(Entity* e, int damage, int dir, u32 hurtColor){ return; } break; + case ENTITY_DRAGON: + e->dragon.health -= damage; + if(e->dragon.health < 1){ + addItemsToWorld(newItem(ITEM_DRAGON_EGG,1),e->x+8, e->y+8, 1); + addItemsToWorld(newItem(ITEM_DRAGON_SCALE,1),e->x+8, e->y+8, (rand()%11) + 10); + removeEntityFromList(e,e->level,&eManager); + playSound(snd_bossdeath); + player.p.score += 1000; + return; + } + break; } switch(dir){ @@ -368,9 +379,14 @@ bool ItemVsEntity(Item* item, Entity* e, int dir){ case ENTITY_KNIGHT: case ENTITY_SLIME: case ENTITY_AIRWIZARD: + case ENTITY_DRAGON: if(playerUseEnergy(4-item->countLevel)) hurtEntity(e,(item->countLevel + 1) * 2 + (rand()%4),dir,0xFF0000FF); else hurtEntity(e,1+rand()%3,dir,0xFF0000FF); return true; + + case ENTITY_MAGIC_PILLAR: + removeEntityFromList(e, e->level, &eManager); + return true; } break; case TOOL_SWORD: switch(e->type){ @@ -380,9 +396,14 @@ bool ItemVsEntity(Item* item, Entity* e, int dir){ case ENTITY_KNIGHT: case ENTITY_SLIME: case ENTITY_AIRWIZARD: + case ENTITY_DRAGON: if(playerUseEnergy(4-item->countLevel)) hurtEntity(e,(item->countLevel+1)*3+(rand()%(2+item->countLevel*item->countLevel*2)),dir,0xFF0000FF); else hurtEntity(e,1+rand()%3,dir,0xFF0000FF); return true; + + case ENTITY_MAGIC_PILLAR: + removeEntityFromList(e, e->level, &eManager); + return true; } break; case ITEM_NULL: switch(e->type){ @@ -392,8 +413,13 @@ bool ItemVsEntity(Item* item, Entity* e, int dir){ case ENTITY_KNIGHT: case ENTITY_SLIME: case ENTITY_AIRWIZARD: + case ENTITY_DRAGON: hurtEntity(e,1+rand()%3,dir,0xFF0000FF); return true; + + case ENTITY_MAGIC_PILLAR: + removeEntityFromList(e, e->level, &eManager); + return true; } break; } return false; @@ -504,6 +530,12 @@ void EntityVsEntity(Entity* e1, Entity* e2){ break; case ENTITY_SPARK: if(e2 != e1->spark.parent) hurtEntity(e2, 1, -1, 0xFFAF00FF); + break; + case ENTITY_DRAGON: + if(e2->type == ENTITY_PLAYER) hurtEntity(e2, 3, e1->dragon.dir, 0xFFAF00FF); + break; + case ENTITY_DRAGONPROJECTILE: + if(e2 != e1->dragonFire.parent) hurtEntity(e2, 1, -1, 0xFFAF00FF); break; case ENTITY_ARROW: switch(e1->arrow.itemID) { @@ -550,8 +582,10 @@ bool EntityBlocksEntity(Entity* e1, Entity* e2){ case ENTITY_KNIGHT: case ENTITY_SLIME: case ENTITY_AIRWIZARD: + case ENTITY_DRAGON: case ENTITY_PLAYER: case ENTITY_PASSIVE: + case ENTITY_MAGIC_PILLAR: return true; break; } @@ -576,6 +610,7 @@ bool tileIsSolid(int tile, Entity * e){ case TILE_GOLD_WALL: case TILE_GEM_WALL: case TILE_DUNGEON_WALL: + case TILE_MAGIC_BARRIER: return true; case TILE_LAVA: case 255: @@ -616,6 +651,7 @@ u32 getTileColor(int tile){ case TILE_GEM_WALL: return SWAP_UINT32(gemColor); case TILE_DUNGEON_WALL: return SWAP_UINT32(dungeonColor[0]); case TILE_DUNGEON_FLOOR: return SWAP_UINT32(dungeonColor[1]); + case TILE_MAGIC_BARRIER: return SWAP_UINT32(dungeonColor[0]); default: return 0x111111FF; } @@ -966,6 +1002,18 @@ void tickTile(int x, int y){ case TILE_CLOUD: if((rand()%24000)==0) setTile(TILE_CLOUDCACTUS,x,y); break; + case TILE_MAGIC_BARRIER: + data = 0; + int i = 0; + for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) { + Entity * e = &eManager.entities[currentLevel][i]; + + if(e->type == ENTITY_MAGIC_PILLAR) { + ++data; + } + } + if(data==0) setTile(TILE_DUNGEON_FLOOR,x,y); + break; } } @@ -1028,6 +1076,7 @@ void tickEntity(Entity* e){ switch(e->type){ case ENTITY_ITEM: tickEntityItem(e); return; case ENTITY_FURNITURE: return; + case ENTITY_MAGIC_PILLAR: return; case ENTITY_ZOMBIE: case ENTITY_SKELETON: case ENTITY_KNIGHT: @@ -1062,6 +1111,17 @@ void tickEntity(Entity* e){ int aitemID = ITEM_ARROW_WOOD; if(e->hostile.lvl >= 2) aitemID = ITEM_ARROW_STONE; + //turn to player when attacking + int xd = player.x - e->x; + int yd = player.y - e->y; + if(xd*xd > yd*yd) { + if (xd < 0) e->hostile.dir = 2; + if (xd > 0) e->hostile.dir = 3; + } else { + if (yd < 0) e->hostile.dir = 1; + if (yd > 0) e->hostile.dir = 0; + } + switch(e->hostile.dir) { case 0: addEntityToList(newArrowEntity(e, aitemID, 0, 2, e->level), &eManager); @@ -1212,10 +1272,141 @@ void tickEntity(Entity* e){ EntityVsEntity(e, &player); removeEntityFromList(e,e->level,&eManager); } + return; + case ENTITY_DRAGON: + if (e->hurtTime > 0) e->hurtTime--; + + e->dragon.animTimer++; + if(e->dragon.animTimer>=20) { + e->dragon.animTimer = 0; + } + + //choose random attack + if (e->dragon.attackDelay > 0) { + e->dragon.attackDelay--; + if (e->dragon.attackDelay <= 0) { + e->wizard.attackType = rand()%2; + e->wizard.attackTime = 121; + } + return; + } + + if (e->dragon.attackTime > 0) { + e->dragon.attackTime--; + + //turn to player when attacking + int xd = player.x - e->x; + int yd = player.y - e->y; + if(xd*xd > yd*yd) { + if (xd < 0) e->dragon.dir = 2; + if (xd > 0) e->dragon.dir = 3; + } else { + if (yd < 0) e->dragon.dir = 1; + if (yd > 0) e->dragon.dir = 0; + } + + switch(e->dragon.attackType) { + case 0: //Firebreathing + if(e->dragon.attackTime%2 == 0) { + float dfdir = 0; + + if(e->dragon.dir==0) dfdir = 1 * 3.141592 / 2; + else if(e->dragon.dir==1) dfdir = 3 * 3.141592 / 2; + else if(e->dragon.dir==2) dfdir = 2 * 3.141592 / 2; + else if(e->dragon.dir==3) dfdir = 0 * 3.141592 / 2; + + dfdir += 0.03141592 * ((rand()%33) - 16); + + addEntityToList(newDragonFireEntity(e, e->dragon.attackType, e->x + cos(dfdir)*14, e->y + sin(dfdir)*14, cos(dfdir), sin(dfdir)), &eManager); + } + break; + case 1: //Firering + if(e->dragon.attackTime%20 == 0) { + int ai = 0; + for(ai = 0; ai < 16; ai++) { + float ddir = (3.141592 * 2 / 16.0) * ai; + float ddist = (140 - e->dragon.attackTime) / 2; + + addEntityToList(newDragonFireEntity(e, e->dragon.attackType, (e->x) + cos(ddir)*ddist, (e->y) + sin(ddir)*ddist, 0, 0), &eManager); + } + } + break; + } + + return; + } + + //TODO - movement copied from airwizard, adjust to better fit dragon + if (e->dragon.randWalkTime == 0) { + int xd = player.x - e->x; + int yd = player.y - e->y; + int dist = xd * xd + yd * yd; + if (dist > 64 * 64) { + e->dragon.xa = 0; + e->dragon.ya = 0; + if (xd < 0) e->dragon.xa = -1; + if (xd > 0) e->dragon.xa = +1; + if (yd < 0) e->dragon.ya = -1; + if (yd > 0) e->dragon.ya = +1; + } else if (dist < 16 * 16) { + e->dragon.xa = 0; + e->dragon.ya = 0; + if (xd < 0) e->dragon.xa = +1; + if (xd > 0) e->dragon.xa = -1; + if (yd < 0) e->dragon.ya = +1; + if (yd > 0) e->dragon.ya = -1; + } + } + + int dSpeed = (tickCount % 4) == 0 ? 0 : 1; + if (!moveMob(e, e->dragon.xa * dSpeed, e->dragon.ya * dSpeed) || (rand()%120) == 0) { + e->dragon.randWalkTime = 30; + e->dragon.xa = ((rand()%3) - 1) * (rand()%2); + e->dragon.ya = ((rand()%3) - 1) * (rand()%2); + } + + if(e->dragon.xa != 0 || e->dragon.ya != 0){ + e->dragon.walkDist++; + } + + if(e->dragon.xa < 0) e->dragon.dir = 2; + else if(e->dragon.xa > 0) e->dragon.dir = 3; + if(e->dragon.ya < 0) e->dragon.dir = 1; + else if(e->dragon.ya > 0) e->dragon.dir = 0; + + //if (e->dragon.randWalkTime > 0) { + // e->dragon.randWalkTime--; + // if (e->dragon.randWalkTime == 0) { + int xd = player.x - e->x; + int yd = player.y - e->y; + if (rand()%12 == 0 && xd * xd + yd * yd < 50 * 50) { + if (e->dragon.attackDelay == 0 && e->dragon.attackTime == 0) e->dragon.attackDelay = 40; + } + // } + //} + + return; + case ENTITY_DRAGONPROJECTILE: + e->dragonFire.age++; + if (e->dragonFire.age >= 30) { + removeEntityFromList(e,e->level,&eManager); + return; + } + e->dragonFire.xx += e->dragonFire.xa; + e->dragonFire.yy += e->dragonFire.ya; + e->x = (int) e->dragonFire.xx; + e->y = (int) e->dragonFire.yy; + + if(intersects(player, e->x + e->dragonFire.xa - e->xr, e->y + e->dragonFire.ya - e->yr, e->x + e->dragonFire.xa + e->xr, e->y + e->dragonFire.ya + e->yr)){ + EntityVsEntity(e, &player); + removeEntityFromList(e,e->level,&eManager); + } return; case ENTITY_ARROW: e->arrow.age++; if (e->arrow.age >= 260 || !move(e, e->arrow.xa, e->arrow.ya)) { + //only drop arrows shot by player + if(e->arrow.parent->type == ENTITY_PLAYER) addItemsToWorld(newItem(e->arrow.itemID,1),e->x+4, e->y+4, 1); removeEntityFromList(e,e->level,&eManager); return; } @@ -1355,7 +1546,7 @@ void setTile(int id, int x, int y){ if(x < 0 || y < 0 || x > 128 || y > 128) return; map[currentLevel][x+y*128] = id; data[currentLevel][x+y*128] = 0; //reset data(set again if needed, hopefully this breaks nothing) - sf2d_set_pixel(minimap[currentLevel], x, y, getTileColor(id)); + sf2d_set_pixel(minimap[currentLevel], x, y, getMinimapColor(currentLevel,x,y)); } int getData(int x, int y){ if(x < 0 || y < 0 || x > 128 || y > 128) return -1; @@ -1676,6 +1867,9 @@ void switchLevel(s8 change){ else sf2d_set_clear_color(0xFF007F00); //sf2d_set_clear_color(RGBA8(0x00, 0x7F, 0x00, 0xFF)); updateMusic(currentLevel, daytime); + + //for level 0 background + updateLevel1Map(); } bool playerIntersectsEntity(Entity* e){ @@ -1918,6 +2112,20 @@ void tickPlayer(){ if(isSwimming()) ++player.p.swimTimer; if(player.p.attackTimer > 0) --player.p.attackTimer; + + //TODO - maybe move to own function + //Update Minimap + int xp; + int yp; + for(xp = (player.x>>4)-5; xp<(player.x>>4)+5; ++xp) { + for(yp = (player.y>>4)-5; yp<(player.y>>4)+5; ++yp) { + if(xp>=0 && xp<128 && yp>=0 && yp<128) { + if(!getMinimapVisible(currentLevel,xp,yp)) { + setMinimapVisible(currentLevel,xp,yp,true); + } + } + } + } } bool isSwimming(){ @@ -1931,13 +2139,25 @@ void playerSetActiveItem(Item * item) { } void enterDungeon() { - currentLevel = 5; - createDungeonMap(128, 128, map[5], data[5]); - initMinimapLevel(5, false); - newSeed(); //reset Entities (&eManager)->lastSlot[5] = 0; (&eManager)->entities[5][0] = nullEntity; + + //create map + currentLevel = 5; + createDungeonMap(128, 128, map[5], data[5]); + + //reset minimap clear state + int xd,yd; + for(xd = 0; xd < 128; ++xd) { + for(yd = 0; yd < 128; ++yd) { + setMinimapVisible(5, xd, yd, false); + } + } + initMinimapLevel(5, false); + newSeed(); + + //spawn new entities trySpawn(500, 5); player.x = ((128/2) << 4) + 8; @@ -1959,6 +2179,24 @@ void leaveDungeon() { updateMusic(currentLevel, daytime); } +void setMinimapVisible(int level, int x, int y, bool visible) { + if(visible) { + minimapData[x + y * 128] = minimapData[x + y * 128] | (1 << level); + } else { + minimapData[x + y * 128] = minimapData[x + y * 128] & (0xFF - (1 << level)); + } + sf2d_set_pixel(minimap[level], x, y, getMinimapColor(level, x, y)); +} + +bool getMinimapVisible(int level, int x, int y) { + return (minimapData[x + y * 128] & (1 << level)) > 0; +} + +u32 getMinimapColor(int level, int x, int y) { + if(getMinimapVisible(level, x, y) || (currentLevel==0 && level==1)) return getTileColor(map[level][x + y * 128]); + else return getTileColor(map[level][x + y * 128]) & 0xFFFFFF00; +} + void initMinimapLevel(int level, bool loadUpWorld) { int x; int y; @@ -2010,11 +2248,23 @@ void initMinimapLevel(int level, bool loadUpWorld) { } /* Minimaps */ - sf2d_set_pixel(minimap[level], x, y, getTileColor(map[level][x + y * 128])); + sf2d_set_pixel(minimap[level], x, y, getMinimapColor(level, x, y)); } } } +void updateLevel1Map() { + int x; + int y; + + for (x = 0; x < 128; ++x) { + for (y = 0; y < 128; ++y) { + sf2d_set_pixel(minimap[1], x, y, getMinimapColor(1, x, y)); + } + } +} + + void reloadColors() { dirtColor[0] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 0)); dirtColor[1] = SWAP_UINT32(sf2d_get_pixel(icons, 16, 1)); diff --git a/source/Globals.h b/source/Globals.h index fd23ba2..b5a9be6 100644 --- a/source/Globals.h +++ b/source/Globals.h @@ -59,6 +59,7 @@ #define TILE_DUNGEON_WALL 27 #define TILE_DUNGEON_FLOOR 28 #define TILE_DUNGEON_ENTRANCE 29 +#define TILE_MAGIC_BARRIER 30 #define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | (((x) & 0x0000FF00) << 8) | ((x) << 24)) @@ -84,6 +85,7 @@ sf2d_texture *bottombg; sf2d_texture * minimap[6]; u8 map[6][128*128]; u8 data[6][128*128]; +u8 minimapData[128*128]; u32 dirtColor[5]; u32 grassColor; @@ -101,6 +103,7 @@ char currentFileName[256]; extern u8 currentMenu; extern char fpsstr[]; u8 initGame; +u8 initBGMap; Item noItem; int airWizardHealthDisplay; s16 awX, awY; @@ -150,6 +153,10 @@ void playerSetActiveItem(Item * item); void enterDungeon(); void leaveDungeon(); +void setMinimapVisible(int level, int x, int y, bool visible); +bool getMinimapVisible(int level, int x, int y); +u32 getMinimapColor(int level, int x, int y); void initMinimapLevel(int level, bool loadUpWorld); +void updateLevel1Map(); void reloadColors(); \ No newline at end of file diff --git a/source/Item.c b/source/Item.c index 89e0591..fdfbb1b 100644 --- a/source/Item.c +++ b/source/Item.c @@ -181,6 +181,8 @@ char* getItemName(int itemID, int countLevel){ case ITEM_BONE: sprintf(currentName,"%d Bone", countLevel); return currentName; case ITEM_DUNGEON_KEY: sprintf(currentName,"%d Dungeon Key", countLevel); return currentName; case ITEM_WIZARD_SUMMON: sprintf(currentName,"%d Wizard Summon", countLevel); return currentName; + case ITEM_DRAGON_EGG: sprintf(currentName,"%d Dragon Egg", countLevel); return currentName; + case ITEM_DRAGON_SCALE: sprintf(currentName,"%d Dragon Scale", countLevel); return currentName; case TOOL_BUCKET: switch(countLevel){ case 1: return "Water Bucket"; @@ -285,6 +287,8 @@ char* getBasicItemName(int itemID, int countLevel){ case ITEM_BONE: return "Bone"; case ITEM_DUNGEON_KEY: return "Dungeon Key"; case ITEM_WIZARD_SUMMON: return "Wizard Summon"; + case ITEM_DRAGON_EGG: return "%d Dragon Egg"; + case ITEM_DRAGON_SCALE: return "%d Dragon Scale"; case TOOL_BUCKET: switch(countLevel){ case 1: return "Water Bucket"; diff --git a/source/Item.h b/source/Item.h index 74314e9..490dbc7 100644 --- a/source/Item.h +++ b/source/Item.h @@ -66,6 +66,9 @@ #define ITEM_BONE 68 #define ITEM_DUNGEON_KEY 69 #define ITEM_WIZARD_SUMMON 70 +//TODO - implement icon +#define ITEM_DRAGON_EGG 71 +#define ITEM_DRAGON_SCALE 72 #define TOOL_BUCKET 101 #define TOOL_BOW 102 diff --git a/source/MapGen.c b/source/MapGen.c index 12ffacb..559a834 100644 --- a/source/MapGen.c +++ b/source/MapGen.c @@ -357,12 +357,12 @@ void createUndergroundMap(int w, int h,int depthLevel, u8 * map, u8 * data) { } -void createDungeonRoom(int w, int h, u8 * map, u8 * data) { +void createDungeonRoom(int w, int h, bool dragon, u8 * map, u8 * data) { int tries; for(tries=0; tries<100; ++tries) { - int x = 5+(rand()%(w-10)); - int y = 5+(rand()%(h-10)); + int x = 5+(rand()%(w-10 -10)); + int y = 5+(rand()%(h-10 -10)); int xr; int yr; int wr = 10+(rand()%11); @@ -371,13 +371,21 @@ void createDungeonRoom(int w, int h, u8 * map, u8 * data) { int yp; int i; + //create Dragonroom + if(dragon) { + wr = 20; + hr = 20; + x = 5 + (rand()%2)*(w-5*2-wr); + y = 5 + (rand()%2)*(h-5*2-hr); + } + if(x+wr > w-5) wr = (w-5) - x; if(y+hr > h-5) hr = (h-5) - y; //check instersection bool allowed = true; - for(xr = x; xr < x+wr; ++xr) { - for(yr = y; yr < y+hr; ++yr) { + for(xr = x-1; xr < x+wr+1; ++xr) { + for(yr = y-1; yr < y+hr+1; ++yr) { i = xr + yr * w; //255 for paths so rooms can overlap paths @@ -400,15 +408,13 @@ void createDungeonRoom(int w, int h, u8 * map, u8 * data) { } //Create path back to existing stuff - xp = x; - yp = y; + xp = x + wr/2; + yp = y + hr/2; i = xp + yp * w; bool checkForFloor = false; bool xFirst = (rand()%2)==0; while((checkForFloor && (map[i]!=TILE_DUNGEON_FLOOR && map[i]!=255)) || (!checkForFloor && (map[i]==TILE_DUNGEON_FLOOR || map[i]==255))) { if(checkForFloor) { - //TODO check for dungeon entrance: if(map[i]==TILE_DUNGEON_ENTRANCE) break; - //make connection map[i] = 255; } @@ -434,6 +440,23 @@ void createDungeonRoom(int w, int h, u8 * map, u8 * data) { if(!checkForFloor && (map[i]!=TILE_DUNGEON_FLOOR && map[i]!=255)) checkForFloor = true; } + //dekorate dragon room + if(dragon) { + for(xr = x; xr < x+wr; ++xr) { + for(yr = y; yr < y+hr; ++yr) { + i = xr + yr * w; + + if((xr==x+1 || xr==x+wr-2 || yr==y+1 || yr==y+hr-2) && (xr!=x && xr!=x+wr-1 && yr!=y && yr!=y+hr-1)) { + map[i] = TILE_MAGIC_BARRIER; + } + } + } + + //add Dragon Entity + addEntityToList(newDragonEntity((x+wr/2) << 4, (y+hr/2) << 4, 5), &eManager); + break; + } + //dekorate room bool lava = (rand()%4)==0; bool pillars = (rand()%4)==0; @@ -446,6 +469,23 @@ void createDungeonRoom(int w, int h, u8 * map, u8 * data) { } else if(pillars && xr > x && xr < x+wr-1 && yr > y && yr < y+hr-1 && xr%2 == 0 && yr%2 == 0) { map[i] = TILE_DUNGEON_WALL; } else { + //add magic pillars for dragon barrier + if(xr==x+wr/2 && yr==y+hr/2) { + int pcount = 0; + int i = 0; + for (i = 0; i < eManager.lastSlot[5]; ++i) { + Entity * e = &eManager.entities[5][i]; + + if(e->type == ENTITY_MAGIC_PILLAR) { + ++pcount; + } + } + if(pcount<8) { + addEntityToList(newMagicPillarEntity((xr << 4) + 8, (yr << 4) + 8, 5), &eManager); + } + continue; + } + if(rand()%50==0) map[i] = TILE_IRONORE + (rand()%3); } } @@ -471,8 +511,11 @@ void createDungeonMap(int w, int h, u8 * map, u8 * data) { } } + //create dragon chamber(only call once and before other rooms) + createDungeonRoom(w, h, true, map, data); + for(i = 0; i < 40; ++i) { - createDungeonRoom(w, h, map, data); + createDungeonRoom(w, h, false, map, data); } //replace paths with actual dungeon floor diff --git a/source/Menu.c b/source/Menu.c index 9f4a0e2..874f1c0 100644 --- a/source/Menu.c +++ b/source/Menu.c @@ -271,6 +271,28 @@ s8 checkPropButtons(){ return -1; } +bool menuHasMapLoaded = false; +float mxscr = 400; +float myscr = 400; +float menuxa = 0; +float menuya = 0; +void initMenus() { + readFiles(); + + if(worldFileCount>0) { + memset(¤tFileName, 0, 255); // reset currentFileName + sprintf(currentFileName,"%s.wld",fileNames[currentSelection]); + + initBGMap = 1; + } else { + initBGMap = 2; + } + + menuHasMapLoaded = true; + menuxa = (rand()%3 - 1) * 0.25; + menuya = (rand()%3 - 1) * 0.25; +} + Item median; void tickMenu(int menu){ switch(menu){ @@ -663,6 +685,27 @@ void tickMenu(int menu){ } break; case MENU_TITLE: + //Map BG + if(menuHasMapLoaded) { + mxscr += menuxa; + myscr += menuya; + + if (mxscr < 16) { + mxscr = 16; + menuxa = -menuxa; + } else if (mxscr > 1832) { + mxscr = 1832; + menuxa = -menuxa; + } + if (myscr < 16) { + myscr = 16; + menuya = -menuya; + } else if (myscr > 1792) { + myscr = 1792; + menuya = -menuya; + } + } + if (k_up.clicked){ --currentSelection; if(currentSelection < 0)currentSelection=4;} if (k_down.clicked){ ++currentSelection; if(currentSelection > 4)currentSelection=0;} @@ -1140,7 +1183,7 @@ void renderMenu(int menu,int xscr,int yscr){ sf2d_end_frame(); break; - case MENU_CONTAINER: + case MENU_CONTAINER: 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); @@ -1148,18 +1191,18 @@ void renderMenu(int menu,int xscr,int yscr){ } offsetX = xscr;offsetY = yscr; renderMenuBackground(xscr,yscr); - if (curChestEntity->entityFurniture.r == 1){ offsetX = 48;offsetY = 0;} + if (curChestEntity->entityFurniture.r == 1){ offsetX = 48; offsetY = 0;} else {offsetX = 0;offsetY = 0;} - renderFrame(1,1,14,14,0xFFFF1010); + renderFrame(1,1,15,14,0xFFFF1010); drawTextColor("Chest",24+1,14+1,0xFF000000); drawTextColor("Chest",24,14,0xFF6FE2E2); - renderItemList(curChestEntity->entityFurniture.inv,1,1,14,14, + renderItemList(curChestEntity->entityFurniture.inv,1,1,15,14, curChestEntity->entityFurniture.r == 0 ? curInvSel : -curChestEntity->entityFurniture.oSel - 1); - renderFrame(15,1,28,14,0xFFFF1010); - drawTextColor("Inventory",248+1,14+1,0xFF000000); - drawTextColor("Inventory",248,14,0xFF6FE2E2); - renderItemList(player.p.inv,15,1,28,14, + renderFrame(16,1,30,14,0xFFFF1010); + drawTextColor("Inventory",264+1,14+1,0xFF000000); + drawTextColor("Inventory",264,14,0xFF6FE2E2); + renderItemList(player.p.inv,16,1,30,14, curChestEntity->entityFurniture.r == 1 ? curInvSel : -curChestEntity->entityFurniture.oSel - 1); offsetX = 0;offsetY = 0; sf2d_end_frame(); @@ -1296,6 +1339,14 @@ void renderMenu(int menu,int xscr,int yscr){ /* Top Screen */ sf2d_start_frame(GFX_TOP, GFX_LEFT); sf2d_draw_rectangle(0, 0, 400, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + //map BG + if(menuHasMapLoaded) { + offsetX = (int) mxscr; offsetY = (int) myscr; + renderBackground((int) mxscr, (int) myscr); + offsetX = 0; offsetY = 0; + + sf2d_draw_rectangle(0, 0, 400, 240, 0xAA0C0C0C); //You might think "real" black would be better, but it actually looks better that way + } renderTitle(76,16); @@ -1303,6 +1354,7 @@ void renderMenu(int menu,int xscr,int yscr){ char* msg = options[i]; u32 color = 0xFF7F7F7F; if(i == currentSelection) color = 0xFFFFFFFF; + drawSizedTextColor(msg,((200 - (strlen(msg) * 8))/2) + 1, (((8 + i) * 20 - 50) >> 1) + 1,2.0, 0xFF000000); drawSizedTextColor(msg,(200 - (strlen(msg) * 8))/2, ((8 + i) * 20 - 50) >> 1,2.0, color); } @@ -1312,34 +1364,18 @@ void renderMenu(int menu,int xscr,int yscr){ /* Bottom Screen */ sf2d_start_frame(GFX_BOTTOM, GFX_LEFT); sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + //map BG + if(menuHasMapLoaded) { + offsetX = (int) mxscr + 20; offsetY = (int) myscr + 120; + renderBackground((int) mxscr + 20, (int) myscr + 120); + offsetX = 0; offsetY = 0; + + sf2d_draw_rectangle(0, 0, 320, 240, 0xAA0C0C0C); //You might think "real" black would be better, but it actually looks better that way + } int startX = 0, startY = 0;// relative coordinates ftw switch(currentSelection){ case 0: // "Start Game" - startX = 20;startY = 50; - render16(startX,startY+12,0,128,0);//Player(Carrying) - render16(startX,startY,128,128,0);//Workbench - startX = 120;startY = 20; - menuRenderTilePit(startX,startY,176,16,waterColor[0]);// water pit - renderc (startX+8,startY+12,48,160,16,8,0);//Waves - renderc (startX+8,startY+8,0,112,16,8,0);//Player (Top-Half) - startX = 110;startY = 76; - render16 (startX,startY,48,112,0);//Player - renderc (startX+12,startY,40,160,8,16,0);//Slash - render (startX+14,startY+4,152,144,0);//Pickaxe - render16b(startX+18,startY,80,0,0,0xFFAEC6DC);//Iron ore - startX = 40;startY = 90; - render16b (startX,startY,128,112,0,0xFFADFFAD);//Slime - render16 (startX+18,startY,48,112,1);//Player (Mirrored) - renderc (startX+14,startY,32,160,8,16,0);//Slash - render (startX+12,startY+4,104,144,1);//Sword - startX = 64;startY = 40; - menuRenderTilePit(startX,startY,112,16,grassColor);// grass pit - render16 (startX+8,startY+4,0,16,0);//Tree - render (startX+1,startY+14,80,152,0);// Apple - 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,0xFF7FFFFF); break; case 1: // "How To Play" startX = 72;startY = 54; @@ -1356,7 +1392,6 @@ void renderMenu(int menu,int xscr,int yscr){ startX = 89;startY = 54; render16(startX+16,startY,48,112,0);//Player render16(startX,startY,160,208,0);//C-PAD right - drawTextColor("Learn the basics",64,24,0xFF7FFFFF); break; case 2: // "Settings" diff --git a/source/Menu.h b/source/Menu.h index 8899882..348fd59 100644 --- a/source/Menu.h +++ b/source/Menu.h @@ -3,6 +3,8 @@ #include "MenuTutorial.h" #include "texturepack.h" +void initMenus(); + void renderMenu(int menu,int xscr,int yscr); void tickMenu(int menu); diff --git a/source/Render.c b/source/Render.c index e51d0e3..dabb407 100644 --- a/source/Render.c +++ b/source/Render.c @@ -142,6 +142,22 @@ void render16s(s32 xp, s32 yp, u32 tile, u8 bits, u32 color) { 16, 16, scaleX, scaleY, color); } +void render32(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits) { + xp -= offsetX; + yp -= offsetY; + int scaleX = 2, scaleY = 2; + if ((bits & 1) > 0) { + scaleX = -2; + xp += 32; + } + if ((bits & 2) > 0) { + scaleY = -2; + yp += 32; + } + sf2d_draw_texture_part_scale(icons, xp << 1, yp << 1, xTile, yTile, 32, 32, + scaleX, scaleY); +} + void renderTitle(int x, int y) { sf2d_draw_texture_part_scale(icons, (x - 26) << 1, y << 1, 0, 240, 104, 16, 2.0, 2.0); // MINICRAFT @@ -392,11 +408,17 @@ bool tur = false; bool tdl = false; bool tdr = false; -void renderDotsWithColor(int x, int y, u8 bits1, u8 bits2, u8 bits3, u8 bits4, u32 color) { - if(tu && tl) renderb(x, y, 0, 0, bits1, color); - if(tu && tr) renderb(x + 8, y, 8, 0, bits2, color); - if(td && tl) renderb(x, y + 8, 0, 8, bits3, color); - if(td && tr) renderb(x + 8, y + 8, 8, 8, bits4, color); +void renderDots(int x, int y, u8 bits1, u8 bits2, u8 bits3, u8 bits4, u32 xTile, u32 yTile) { + //another speedhack for o3DS + if(tu && tl && tr && td) { + render16(x, y, xTile, yTile, bits1); + return; + } + + if(tu && tl) render(x, y, xTile, yTile, bits1); + if(tu && tr) render(x + 8, y, xTile+8, yTile, bits2); + if(td && tl) render(x, y + 8, xTile, yTile+8, bits3); + if(td && tr) render(x + 8, y + 8, xTile+8, yTile+8, bits4); } void resetSurrTiles() { @@ -450,167 +472,194 @@ void renderTile(int i, int d, int x, int y) { checkSurrTiles4(x >> 4, y >> 4, TILE_FLOWER); checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_TREE); - renderConnectedTile4(x, y, 112, 16, grassColor); + renderConnectedTile4(x, y, 256, 0); break; case TILE_TREE: renderTile(TILE_GRASS, 0, x, y); checkSurrTiles8(x >> 4, y >> 4, TILE_TREE); - render(x, y, 0+((tu && tl && tul) ? 16 : 0), 16, 0); - render(x+8, y, 8+((tu && tr && tur) ? 16 : 0), 16, 0); - render(x, y+8, 0+((td && tl && tdl) ? 16 : 0), 24, 0); - render(x+8, y+8, 8+((td && tr && tdr) ? 16 : 0), 24, 0); + render(x, y, 256+((tu && tl && tul) ? 16 : 0), 48, 0); + render(x+8, y, 264+((tu && tr && tur) ? 16 : 0), 48, 0); + render(x, y+8, 256+((td && tl && tdl) ? 16 : 0), 56, 0); + render(x+8, y+8, 264+((td && tr && tdr) ? 16 : 0), 56, 0); break; case TILE_ROCK: checkSurrTiles8(x >> 4, y >> 4, TILE_ROCK); - renderConnectedTile8(x, y, 32, 16, rockColor[0]); + renderConnectedTile8(x, y, 336, 64); break; case TILE_HARDROCK: checkSurrTiles8(x >> 4, y >> 4, TILE_HARDROCK); - renderConnectedTile8(x, y, 32, 16, rockColor[2]); + renderConnectedTile8(x, y, 416, 64); break; case TILE_DIRT: // render dots. if (currentLevel > 1) - render16b(x, y, 0, 0, 0, 0xFF383838); + render16(x, y, 320, 80, 0); else - render16b(x, y, 0, 0, 0, 0xFF8F8FA8); + render16(x, y, 336, 80, 0); break; case TILE_SAND: checkSurrTiles4(x >> 4, y >> 4, TILE_SAND); checkSurrTiles4(x >> 4, y >> 4, TILE_CACTUS); checkSurrTiles4(x >> 4, y >> 4, TILE_SAPLING_CACTUS); - renderConnectedTile4(x, y, 112, 16, sandColor); + renderConnectedTile4(x, y, 320, 0); if (d > 0) { - render16b(x, y, 128, 0, 0, sandColor); + render16(x, y, 336, 48, 0); } break; case TILE_WATER: checkSurrTiles4(x >> 4, y >> 4, TILE_WATER); checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); - renderConnectedTile4(x, y, 176, 16, waterColor[0]); + renderConnectedTile4(x, y, 384, 0); srand((tickCount + (x / 2 - y) * 4311) / 10); - renderDotsWithColor(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, waterColor[1]); + renderDots(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, 288, 64); break; case TILE_LAVA: checkSurrTiles4(x >> 4, y >> 4, TILE_LAVA); checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); - renderConnectedTile4(x, y, 176, 16, lavaColor[0]); + renderConnectedTile4(x, y, 448, 0); srand((tickCount + (x / 2 - y) * 4311) / 10); - renderDotsWithColor(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, lavaColor[1]); + renderDots(x, y, rand() & 3, rand() & 3, rand() & 3, rand() & 3, 304, 64); break; case TILE_HOLE: checkSurrTiles4(x >> 4, y >> 4, TILE_HOLE); checkSurrTiles4(x >> 4, y >> 4, TILE_WATER); checkSurrTiles4(x >> 4, y >> 4, TILE_LAVA); - renderConnectedTile4(x, y, 176, 16, 0xFF383838); + renderConnectedTile4(x, y, 256, 16); break; case TILE_CACTUS: renderTile(TILE_SAND, 0, x, y); - render16(x, y, 48, 0, 0); + render16(x, y, 304, 48, 0); break; case TILE_FLOWER: renderTile(TILE_GRASS, 0, x, y); - render16(x, y, 64, 0, getData(x >> 4, y >> 4)); + render16(x, y, 320, 48, getData(x >> 4, y >> 4)); break; case TILE_STAIRS_DOWN: if (currentLevel == 0) renderTile(TILE_CLOUD, 0, x, y); - render16(x, y, 96, 0, 0); + render16(x, y, 256, 64, 0); break; case TILE_STAIRS_UP: - render16(x, y, 112, 0, 0); + render16(x, y, 272, 64, 0); break; case TILE_IRONORE: - render16b(x, y, 80, 0, 0, ironColor); + render16(x, y, 464, 48, 0); break; case TILE_GOLDORE: - render16b(x, y, 80, 0, 0, goldColor); + render16(x, y, 480, 48, 0); break; case TILE_GEMORE: - render16b(x, y, 80, 0, 0, gemColor); + render16(x, y, 496, 48, 0); break; case TILE_CLOUD: checkSurrTiles4(x >> 4, y >> 4, TILE_CLOUD); checkSurrTiles4(x >> 4, y >> 4, TILE_STAIRS_DOWN); checkSurrTiles4(x >> 4, y >> 4, TILE_CLOUDCACTUS); - renderConnectedTile4(x, y, 64, 32, 0xFFFFFFFF); + renderConnectedTile4(x, y, 320, 16); break; case TILE_CLOUDCACTUS: renderTile(TILE_CLOUD, 0, x, y); - render16(x, y, 80, 0, 0); + render16(x, y, 496, 64, 0); break; case TILE_SAPLING_TREE: renderTile(TILE_GRASS, 0, x, y); - render16(x, y, 32, 0, 0); + render16(x, y, 288, 48, 0); break; case TILE_SAPLING_CACTUS: renderTile(TILE_SAND, 0, x, y); - render16(x, y, 32, 0, 0); + render16(x, y, 288, 48, 0); break; case TILE_FARM: - render16(x, y, 144, 0, 0); + render16(x, y, 352, 48, 0); break; case TILE_WHEAT: age = getData(x >> 4, y >> 4) / 20; if (age > 5) age = 5; - render16(x, y, 160 + (age << 4), 0, 0); + render16(x, y, 368 + (age << 4), 48, 0); break; case TILE_WOOD_WALL: checkSurrTiles4(x >> 4, y >> 4, TILE_WOOD_WALL); - renderConnectedTile4(x, y, 0, 32, woodColor); + renderConnectedTile4(x, y, 384, 16); break; case TILE_STONE_WALL: checkSurrTiles4(x >> 4, y >> 4, TILE_STONE_WALL); - renderConnectedTile4(x, y, 128, 32, rockColor[0]); + renderConnectedTile4(x, y, 256, 80); break; case TILE_IRON_WALL: checkSurrTiles4(x >> 4, y >> 4, TILE_IRON_WALL); - renderConnectedTile4(x, y, 128, 32, ironColor); + renderConnectedTile4(x, y, 448, 16); break; case TILE_GOLD_WALL: checkSurrTiles4(x >> 4, y >> 4, TILE_GOLD_WALL); - renderConnectedTile4(x, y, 128, 32, goldColor); + renderConnectedTile4(x, y, 256, 32); break; case TILE_GEM_WALL: checkSurrTiles4(x >> 4, y >> 4, TILE_GEM_WALL); - renderConnectedTile4(x, y, 128, 32, gemColor); + renderConnectedTile4(x, y, 320, 32); break; case TILE_DUNGEON_WALL: checkSurrTiles8(x >> 4, y >> 4, TILE_DUNGEON_WALL); - renderConnectedTile8(x, y, 128, 32, dungeonColor[0]); + renderConnectedTile8(x, y, 384, 32); break; case TILE_DUNGEON_FLOOR: - render16b(x, y, 208, 32, 0, dungeonColor[1]); + render16(x, y, 464, 32, 0); break; case TILE_DUNGEON_ENTRANCE: - render16b(x, y, 224 + (currentLevel==5 ? 16 : 0), 32, 0, dungeonColor[0]); + render16(x, y, 480 + (currentLevel==5 ? 16 : 0), 32, 0); + break; + case TILE_MAGIC_BARRIER: + renderTile(TILE_DUNGEON_FLOOR, 0, x, y); + render16(x, y, 320, 64, 0); + + //draw remaining pillar count + if((player.x - (x+8))*(player.x - (x+8)) + (player.y - (y+8))*(player.y - (y+8)) <= 24*24) { + x -= offsetX; + y -= offsetY; + + int data = 0; + int i = 0; + for (i = 0; i < eManager.lastSlot[currentLevel]; ++i) { + Entity * e = &eManager.entities[currentLevel][i]; + + if(e->type == ENTITY_MAGIC_PILLAR) { + ++data; + } + } + + char currentCount[3]; + sprintf(currentCount,"%d", data); + + drawSizedTextColor(currentCount, x+4 + 1, y+4 + 1, 2, dungeonColor[1]); + drawSizedTextColor(currentCount, x+4, y+4, 2, dungeonColor[0]); + } + break; } resetSurrTiles(); } -void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile, u32 color) { +void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile) { //render complete tile in one piece to reduce strain(added for o3DS) if (tl && tr && tu && td) { - render16b(x, y, xTile+48, yTile, 0, color); + render16(x, y, xTile+48, yTile, 0); return; } @@ -619,16 +668,16 @@ void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile, u32 color) { int u = (tu ? 32 : 0); int d = (td ? 32 : 0); - renderb(x, y, xTile +l+u, yTile, 0, color); - renderb(x+8, y, xTile+8+r+u, yTile, 0, color); - renderb(x, y+8, xTile +l+d, yTile+8, 0, color); - renderb(x+8, y+8, xTile+8+r+d, yTile+8, 0, color); + render(x, y, xTile +l+u, yTile, 0); + render(x+8, y, xTile+8+r+u, yTile, 0); + render(x, y+8, xTile +l+d, yTile+8, 0); + render(x+8, y+8, xTile+8+r+d, yTile+8, 0); } -void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile, u32 color) { +void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile) { //render complete tile in one piece to reduce strain(added for o3DS) if (tl && tr && tu && td && tul && tur && tdl && tdr) { - render16b(x, y, xTile+64, yTile, 0, color); + render16(x, y, xTile+64, yTile, 0); return; } @@ -637,13 +686,15 @@ void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile, u32 color) { int u = (tu ? 32 : 0); int d = (td ? 32 : 0); - renderb(x, y, xTile +l+u+((tl && tu && tul) ? 16 : 0), yTile, 0, color); - renderb(x+8, y, xTile+8+r+u+((tr && tu && tur) ? 16 : 0), yTile, 0, color); - renderb(x, y+8, xTile +l+d+((tl && td && tdl) ? 16 : 0), yTile+8, 0, color); - renderb(x+8, y+8, xTile+8+r+d+((tr && td && tdr) ? 16 : 0), yTile+8, 0, color); + render(x, y, xTile +l+u+((tl && tu && tul) ? 16 : 0), yTile, 0); + render(x+8, y, xTile+8+r+u+((tr && tu && tur) ? 16 : 0), yTile, 0); + render(x, y+8, xTile +l+d+((tl && td && tdl) ? 16 : 0), yTile+8, 0); + render(x+8, y+8, xTile+8+r+d+((tr && td && tdr) ? 16 : 0), yTile+8, 0); } void renderZoomedMap() { + sf2d_draw_rectangle(0, 0, 320, 240, 0xFF0C0C0C); //You might think "real" black would be better, but it actually looks better that way + int mx = mScrollX; int my = mScrollY; if(zoomLevel == 2) mx = 32; @@ -1081,6 +1132,33 @@ void renderEntity(Entity* e, int x, int y) { return; renderr(x, y, 200, 152, 0, e->spark.age * 0.0349); break; + case ENTITY_DRAGON: + //TODO - render dragon(maybe with flying animation) + switch (e->dragon.dir) { + case 0: // down + render32(x - 16, y - 16, 0+(e->dragon.animTimer<10 ? 0 : 64), 256, 2); + break; + case 1: // up + render32(x - 16, y - 16, 0+(e->dragon.animTimer<10 ? 0 : 64), 256, 0); + break; + case 2: // left + render32(x - 16, y - 16, 0+(e->dragon.animTimer<10 ? 0 : 64), 288, 1); + break; + case 3: // right + render32(x - 16, y - 16, 0+(e->dragon.animTimer<10 ? 0 : 64), 288, 0); + break; + } + break; + case ENTITY_DRAGONPROJECTILE: + if(e->dragonFire.type==0) { + renderr(x, y, 0, 320, 0, e->dragonFire.age * 0.349); + } else { + render(x, y, 8, 320 + (e->dragonFire.age/10)*8, 0); + } + break; + case ENTITY_MAGIC_PILLAR: + render16(x - 8, y - 8, 16, 320, 0); + break; case ENTITY_ARROW: if (e->arrow.age >= 200) if (e->arrow.age / 6 % 2 == 0) diff --git a/source/Render.h b/source/Render.h index 85641cd..89f2ef7 100644 --- a/source/Render.h +++ b/source/Render.h @@ -16,21 +16,19 @@ int offsetX, offsetY; void render(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); void renderb(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color); void renderr(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, float rotate); -void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, - u8 bits); -void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, - u8 bits, u32 color); +void renderc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, u8 bits); +void renderbc(s32 xp, s32 yp, u32 xTile, u32 yTile, int sizeX, int sizeY, u8 bits, u32 color); void render16(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); -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); void render16b(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits, u32 color); void render16s(s32 xp, s32 yp, u32 tile, u8 bits, u32 color); +void render32(s32 xp, s32 yp, u32 xTile, u32 yTile, u8 bits); void renderTitle(int x, int y); void renderFrame(int x1, int y1, int x2, int y2, u32 bgColor); void renderTile(int i, int d, int x, int y); -void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile, u32 color); -void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile, u32 color); +void renderConnectedTile4(int x, int y, u32 xTile, u32 yTile); +void renderConnectedTile8(int x, int y, u32 xTile, u32 yTile); void renderBackground(int xScroll, int yScroll); void renderMenuBackground(int xScroll, int yScroll); //Renders the darkness void renderDayNight(); @@ -57,10 +55,8 @@ void renderFurniture(int itemID, int x, int y); void renderEntity(Entity* e, int x, int y); void renderEntities(int x, int y, EntityManager* em); -void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, - int selected); -void renderItemList(Inventory * inv, int xo, int yo, int x1, int y1, - int selected); +void renderRecipes(RecipeManager * r, int xo, int yo, int x1, int y1, int selected); +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); diff --git a/source/SaveLoad.c b/source/SaveLoad.c index 3cca5ca..da49522 100644 --- a/source/SaveLoad.c +++ b/source/SaveLoad.c @@ -14,6 +14,7 @@ s16 calculateImportantEntites(EntityManager * eManager, int level){ case ENTITY_FURNITURE: case ENTITY_PASSIVE: case ENTITY_GLOWWORM: + case ENTITY_DRAGON: count++; break; } @@ -32,6 +33,7 @@ bool entityIsImportant(Entity * e){ case ENTITY_FURNITURE: case ENTITY_PASSIVE: case ENTITY_GLOWWORM: + case ENTITY_DRAGON: return true; default: return false; @@ -101,6 +103,9 @@ void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player case ENTITY_PASSIVE: fwrite(&eManager->entities[i][j].passive.health, sizeof(s16), 1, file); fwrite(&eManager->entities[i][j].passive.mtype, sizeof(u8), 1, file); + break; + case ENTITY_DRAGON: + fwrite(&eManager->entities[i][j].dragon.health, sizeof(s16), 1, file); break; } } @@ -112,6 +117,8 @@ void saveCurrentWorld(char * filename, EntityManager * eManager, Entity * player fwrite(mapData, sizeof(u8), 128*128*5, file); // Map Tile Data (Damage done to trees/rocks, age of wheat & saplings, etc). 80KB fwrite(&daytime, sizeof(u16), 1, file); + + fwrite(minimapData, sizeof(u8), 128*128, file); // Minimap, visibility data 16KB fclose(file); } @@ -311,6 +318,23 @@ int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * m eManager->entities[i][j].glowworm.randWalkTime = 0; eManager->entities[i][j].glowworm.waitTime = 0; break; + case ENTITY_DRAGON: + fread(&eManager->entities[i][j].dragon.health, sizeof(s16), 1, file); + eManager->entities[i][j].level = i; + eManager->entities[i][j].hurtTime = 0; + eManager->entities[i][j].xKnockback = 0; + eManager->entities[i][j].yKnockback = 0; + eManager->entities[i][j].dragon.dir = 0; + eManager->entities[i][j].dragon.attackDelay = 0; + eManager->entities[i][j].dragon.attackTime = 0; + eManager->entities[i][j].dragon.attackType = 0; + eManager->entities[i][j].dragon.animTimer = 0; + eManager->entities[i][j].dragon.xa = 0; + eManager->entities[i][j].dragon.ya = 0; + eManager->entities[i][j].xr = 8; + eManager->entities[i][j].yr = 8; + eManager->entities[i][j].canPass = true; + break; } } } @@ -322,6 +346,8 @@ int loadWorld(char * filename, EntityManager * eManager, Entity * player, u8 * m daytime = 6001; fread(&daytime, sizeof(u16), 1, file); + fread(minimapData, sizeof(u8), 128*128, file); + fclose(file); return 0; } diff --git a/source/main.c b/source/main.c index 7bc8b52..eb1432e 100644 --- a/source/main.c +++ b/source/main.c @@ -13,6 +13,13 @@ #include "Menu.h" #include "texturepack.h" +void initMiniMapData() { + int i; + for(i = 0; i < 128 * 128; ++i) { + minimapData[i] = 0; + } +} + void initMiniMap(bool loadUpWorld) { int i; for (i = 0; i < 5; ++i) { @@ -36,6 +43,8 @@ void setupGame(bool loadUpWorld) { memset(&eManager, 0, sizeof(eManager)); sf2d_set_clear_color(0xFF6C6D82); //sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); + initMiniMapData(); + if (!loadUpWorld) { initNewMap(); initPlayer(); @@ -62,6 +71,25 @@ void setupGame(bool loadUpWorld) { initGame = 0; } +void setupBGMap(bool loadUpWorld) { + // Reset entity manager. + memset(&eManager, 0, sizeof(eManager)); + sf2d_set_clear_color(0xFF6C6D82); //sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); + + if(!loadUpWorld) { + newSeed(); + createAndValidateTopMap(128, 128, map[1], data[1]); + } else { + loadWorld(currentFileName, &eManager, &player, (u8*) map, (u8*) data); + } + + // Reset entity manager. + memset(&eManager, 0, sizeof(eManager)); + sf2d_set_clear_color(0xFF6C6D82); //sf2d_set_clear_color(RGBA8(0x82, 0x6D, 0x6C, 0xFF)); + + initBGMap = 0; +} + int xscr = 0, yscr = 0; void tick() { if (player.p.isDead) { @@ -147,6 +175,7 @@ int main() { csndInit(); noItem = newItem(ITEM_NULL, 0); + initMenus(); currentMenu = MENU_TITLE; currentSelection = 0; quitGame = false; @@ -163,8 +192,7 @@ int main() { int i; for (i = 0; i < 6; ++i) { - minimap[i] = sf2d_create_texture(128, 128, TEXFMT_RGBA8, - SF2D_PLACE_RAM); + minimap[i] = sf2d_create_texture(128, 128, TEXFMT_RGBA8, SF2D_PLACE_RAM); sf2d_texture_tile32(minimap[i]); } @@ -223,6 +251,7 @@ int main() { if (quitGame) break; if (initGame > 0) setupGame(initGame == 1 ? true : false); + if (initBGMap > 0) setupBGMap(initBGMap == 1 ? true : false); if (currentMenu == 0) { tick();