diff --git a/assets/item_teleport.png b/assets/item_teleport.png new file mode 100644 index 0000000..4b0614c Binary files /dev/null and b/assets/item_teleport.png differ diff --git a/images.h b/images.h index 69eb382..bef029c 100644 --- a/images.h +++ b/images.h @@ -511,7 +511,7 @@ SFG_PROGRAM_MEMORY uint8_t SFG_itemSprites[][SFG_TEXTURE_STORE_SIZE] = 16,0,0,0,0,0,17,22,36,0,0,0,0,1,167,209,0,0,0,0,0,0,0,1,17,0,0,0,0,0,17,16,0,0, 0,0,0,0,0,0,0 }, - { // 6, finish teleport + { // 6, finish 175,0,151,3,6,4,143,5,134,55,63,127,2,71,61,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,17,16,0,0,1,17,0,0,1,17,17,16,0,0,0,1,69,17,0,0,20,81,16,0,28,193,17,17, 0,0,0,20,119,81,16,1,71,117,17,0,21,92,28,193,0,1,17,51,51,51,17,19,51,51,49,17, @@ -534,7 +534,31 @@ SFG_PROGRAM_MEMORY uint8_t SFG_itemSprites[][SFG_TEXTURE_STORE_SIZE] = 119,81,16,1,71,117,17,0,20,124,21,81,0,0,0,1,69,17,0,0,20,81,16,0,23,81,19,49,0, 0,0,0,17,16,0,0,1,17,0,0,1,17,17,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }, - { // 7, access card + { // 7, teleport +175,0,151,6,3,143,5,134,4,53,55,63,127,45,71,2,0,0,0,0,17,16,0,0,1,17,0,0,0,0,0, +0,0,0,0,1,56,17,0,0,19,129,16,0,1,17,17,16,0,0,0,1,102,129,0,0,22,104,16,0,31, +241,17,17,0,0,0,1,102,129,0,0,22,104,16,0,24,143,31,241,0,1,17,17,68,68,17,17, +20,68,65,17,19,56,248,129,0,20,51,51,51,51,51,51,51,51,51,51,143,51,246,97,0,19, +68,68,34,34,34,37,85,34,34,37,17,99,134,97,0,19,68,187,178,238,165,87,82,34,137, +204,145,68,72,129,0,19,190,37,82,39,82,34,114,85,124,119,159,68,68,65,0,19,68, +39,114,85,85,87,199,204,205,215,223,152,132,65,0,19,190,39,114,85,34,89,121,220, +205,217,223,116,79,241,0,19,69,172,206,165,34,34,85,119,204,119,212,125,70,132, +0,19,68,172,202,170,190,34,85,34,217,153,148,121,70,132,0,19,74,172,203,170,226, +34,85,34,221,153,152,121,70,132,0,19,74,170,187,170,226,34,85,37,124,119,152, +121,134,132,0,19,171,235,226,85,34,37,87,119,199,217,152,121,214,132,0,19,75, +187,178,87,34,85,119,119,199,153,157,121,214,132,0,19,68,187,187,186,34,34,85, +37,119,119,157,121,214,132,0,19,69,187,187,234,178,34,114,34,156,201,152,121, +134,132,0,19,68,90,170,170,174,34,114,34,156,201,152,121,134,132,0,19,170,74, +190,229,114,37,85,119,124,204,152,121,70,132,0,19,90,87,34,37,82,89,121,156,204, +221,157,116,68,241,0,19,68,71,34,37,85,85,119,204,205,215,159,118,51,49,0,19, +165,39,34,34,114,37,114,85,87,85,159,147,54,49,0,19,170,187,178,235,162,34,85, +34,204,153,159,99,134,97,0,19,68,68,34,34,34,34,34,34,37,85,129,131,134,97,0,20, +51,51,51,51,51,51,51,51,51,51,212,99,246,97,0,1,17,17,68,68,17,17,20,68,65,17, +24,54,246,129,0,0,0,1,102,129,0,0,22,104,16,0,19,111,24,129,0,0,0,1,102,129,0,0, +22,104,16,0,22,129,20,65,0,0,0,1,56,17,0,0,19,129,16,0,1,17,17,16,0,0,0,0,17,16, +0,0,1,17,0,0,0,0,0,0 + }, + { // 8, access card 175,0,21,45,44,23,46,2,19,34,69,22,68,60,131,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,17,17,17,17,17,17,0,0,0,0,0,0,0,0,1, 68,17,24,102,101,86,97,0,0,0,0,0,0,0,0,1,68,17,24,102,85,86,101,16,0,0,0,0,0,0, diff --git a/levels.h b/levels.h index 3a822a5..da829ec 100644 --- a/levels.h +++ b/levels.h @@ -94,15 +94,16 @@ typedef struct #define SFG_LEVEL_ELEMENT_PLASMA 0x05 #define SFG_LEVEL_ELEMENT_TREE 0x06 #define SFG_LEVEL_ELEMENT_FINISH 0x07 -#define SFG_LEVEL_ELEMENT_CARD0 0x08 ///< Access card, unlocks doors with lock. -#define SFG_LEVEL_ELEMENT_CARD1 0x09 -#define SFG_LEVEL_ELEMENT_CARD2 0x0a -#define SFG_LEVEL_ELEMENT_LOCK0 0x0b /**< Special level element that must be +#define SFG_LEVEL_ELEMENT_TELEPORT 0x08 +#define SFG_LEVEL_ELEMENT_CARD0 0x09 ///< Access card, unlocks doors with lock. +#define SFG_LEVEL_ELEMENT_CARD1 0x0a +#define SFG_LEVEL_ELEMENT_CARD2 0x0b +#define SFG_LEVEL_ELEMENT_LOCK0 0x0c /**< Special level element that must be placed on a tile with door. This door is then unlocked by taking the corresponding access card. */ -#define SFG_LEVEL_ELEMENT_LOCK1 0x0c -#define SFG_LEVEL_ELEMENT_LOCK2 0x0d +#define SFG_LEVEL_ELEMENT_LOCK1 0x0d +#define SFG_LEVEL_ELEMENT_LOCK2 0x0e /* Monsters have lower 4 bits zero and are only distinguished by the 4 upper @@ -295,8 +296,8 @@ SFG_PROGRAM_MEMORY SFG_Level SFG_level0 = {SFG_LEVEL_ELEMENT_CARD2, {13, 21}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_LOCK1, {3, 21}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_FINISH, {8, 44}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, - {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, - {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, + {SFG_LEVEL_ELEMENT_TELEPORT, {11, 12}}, {SFG_LEVEL_ELEMENT_TELEPORT, {17, 20}}, + {SFG_LEVEL_ELEMENT_TELEPORT, {20, 40}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, {SFG_LEVEL_ELEMENT_NONE, {0, 0}}, diff --git a/main.c b/main.c index 0840557..810a0a1 100755 --- a/main.c +++ b/main.c @@ -251,6 +251,7 @@ struct for mouse control. */ uint8_t cards; /**< Lowest bits say which access cards have been taken. */ + uint8_t justTeleported; } SFG_player; uint8_t SFG_explosionSoundPlayed; /**< Prevents playing too many explosion @@ -306,6 +307,8 @@ struct uint8_t projectileRecordCount; uint8_t backgroundImage; + + uint8_t teleportCount; } SFG_currentLevel; #if SFG_DITHERED_SHADOW @@ -980,6 +983,8 @@ void SFG_initPlayer() SFG_player.cards = 0; + SFG_player.justTeleported = 0; + for (uint8_t i = 0; i < SFG_AMMO_TOTAL; ++i) SFG_player.ammo[i] = 0; } @@ -1033,6 +1038,8 @@ void SFG_setAndInitLevel(const SFG_Level *level) SFG_currentLevel.projectileRecordCount = 0; + SFG_currentLevel.teleportCount = 0; + for (uint8_t j = 0; j < SFG_MAP_SIZE; ++j) { for (uint8_t i = 0; i < SFG_MAP_SIZE; ++i) @@ -1101,6 +1108,9 @@ void SFG_setAndInitLevel(const SFG_Level *level) SFG_LOG("adding item"); SFG_currentLevel.itemRecords[SFG_currentLevel.itemRecordCount] = i; SFG_currentLevel.itemRecordCount++; + + if (e->type == SFG_LEVEL_ELEMENT_TELEPORT) + SFG_currentLevel.teleportCount++; } else { @@ -1818,10 +1828,32 @@ static inline uint8_t SFG_elementCollides( <= SFG_ELEMENT_COLLISION_DISTANCE; } -uint8_t SFG_getLevelElementSpriteIndex(uint8_t elementType) +SFG_getLevelElementSprite( + uint8_t elementType, uint8_t *spriteIndex, uint8_t *spriteSize) { - return ((elementType < SFG_LEVEL_ELEMENT_CARD0) - ? elementType : SFG_LEVEL_ELEMENT_CARD0) - 1; + *spriteSize = 0; + *spriteIndex = elementType - 1; + + switch (elementType) + { + case SFG_LEVEL_ELEMENT_TREE: + *spriteSize = 2; + break; + + case SFG_LEVEL_ELEMENT_TELEPORT: + case SFG_LEVEL_ELEMENT_FINISH: + *spriteSize = 3; + break; + + case SFG_LEVEL_ELEMENT_CARD0: + case SFG_LEVEL_ELEMENT_CARD1: + case SFG_LEVEL_ELEMENT_CARD2: + *spriteIndex = SFG_LEVEL_ELEMENT_CARD0 - 1; + break; + + default: + break; + } } /** @@ -2202,6 +2234,8 @@ void SFG_gameStep() } } + uint8_t collidesWithTeleport = 0; + // items: for (int16_t i = 0; i < SFG_currentLevel.itemRecordCount; ++i) // ^ has to be int16_t (signed) @@ -2255,6 +2289,11 @@ void SFG_gameStep() SFG_player.cards |= 1 << (e->type - SFG_LEVEL_ELEMENT_CARD0); break; + case SFG_LEVEL_ELEMENT_TELEPORT: + collidesWithTeleport = 1; + eliminate = 0; + break; + default: eliminate = 0; break; @@ -2269,14 +2308,63 @@ void SFG_gameStep() SFG_playSoundSafe(3,255); #endif } - else // collide + else { - moveOffset = SFG_resolveCollisionWithElement( - SFG_player.camera.position,moveOffset,ePos); + if (e->type != SFG_LEVEL_ELEMENT_TELEPORT) + { + // collide + moveOffset = SFG_resolveCollisionWithElement( + SFG_player.camera.position,moveOffset,ePos); + } + else if ((SFG_currentLevel.teleportCount > 1) && + !SFG_player.justTeleported) + { + // teleport to random destination teleport + + uint8_t teleportNumber = + SFG_random() % (SFG_currentLevel.teleportCount - 1) + 1; + + for (uint16_t j = 0; j < SFG_currentLevel.itemRecordCount; ++j) + { + SFG_LevelElement e2 = + SFG_currentLevel.levelPointer->elements + [SFG_currentLevel.itemRecords[j] & + ~SFG_ITEM_RECORD_ACTIVE_MASK]; + + if ((e2.type == SFG_LEVEL_ELEMENT_TELEPORT) && (j != i)) + teleportNumber--; + + if (teleportNumber == 0) + { + SFG_player.camera.position.x = + SFG_ELEMENT_COORD_TO_RCL_UNITS(e2.coords[0]); + + SFG_player.camera.position.y = + SFG_ELEMENT_COORD_TO_RCL_UNITS(e2.coords[1]); + + SFG_player.camera.height = + SFG_floorHeightAt(e2.coords[0],e2.coords[1]) + + RCL_CAMERA_COLL_HEIGHT_BELOW; + + SFG_currentLevel.itemRecords[j] |= SFG_ITEM_RECORD_ACTIVE_MASK; + /* ^ we have to make the new teleport immediately active so + that it will immediately collide */ + + SFG_player.justTeleported = 1; + + SFG_playSoundSafe(4,255); + + break; + } + } + } } } - } - } + } + } // item collision check + + if (!collidesWithTeleport) + SFG_player.justTeleported = 0; #if SFG_PREVIEW_MODE SFG_player.camera.position.x += @@ -2987,26 +3075,24 @@ void SFG_draw() worldPosition.y = SFG_ELEMENT_COORD_TO_RCL_UNITS(e.coords[1]); - uint8_t size = 0; + uint8_t spriteIndex; + uint8_t spriteSize; - if (e.type == SFG_LEVEL_ELEMENT_TREE) - size = 2; - else if (e.type == SFG_LEVEL_ELEMENT_FINISH) - size = 3; + SFG_getLevelElementSprite(e.type,&spriteIndex,&spriteSize); RCL_PixelInfo p = RCL_mapToScreen( worldPosition, SFG_floorHeightAt(e.coords[0],e.coords[1]) - + SFG_SPRITE_SIZE_TO_HEIGH_ABOVE_GROUND(size), + + SFG_SPRITE_SIZE_TO_HEIGH_ABOVE_GROUND(spriteSize), SFG_player.camera); if (p.depth > 0) { SFG_drawScaledSprite( - SFG_itemSprites[SFG_getLevelElementSpriteIndex(e.type)], + SFG_itemSprites[spriteIndex], p.position.x * SFG_RAYCASTING_SUBSAMPLE,p.position.y, - RCL_perspectiveScale(SFG_SPRITE_SIZE(size),p.depth), + RCL_perspectiveScale(SFG_SPRITE_SIZE(spriteSize),p.depth), p.depth / (RCL_UNITS_PER_SQUARE * 2),p.depth - 1000); } }