diff --git a/constants.h b/constants.h index d45f546..7ccd1a4 100644 --- a/constants.h +++ b/constants.h @@ -11,4 +11,9 @@ */ #define SFG_PLAYER_MOVE_SPEED 5 +/** + How quickly elevators and squeezers move, in RCL_Unit per second. +*/ +#define SFG_MOVING_WALL_SPEED 1024 + #endif // guard diff --git a/levels.h b/levels.h index 58be1b5..6765934 100644 --- a/levels.h +++ b/levels.h @@ -51,6 +51,11 @@ typedef uint8_t SFG_MapArray[SFG_MAP_SIZE * SFG_MAP_SIZE]; bbbbbb: index into tile dictionary */ +#define SFG_TILE_PROPERTY_NORMAL 0x00 +#define SFG_TILE_PROPERTY_ELEVATOR 0x40 +#define SFG_TILE_PROPERTY_SQUEEZER 0x80 +#define SFG_TILE_PROPERTY_DOOR 0xc0 + typedef struct { SFG_MapArray mapArray; @@ -70,26 +75,20 @@ static inline SFG_TileDefinition SFG_getMapTile ( const SFG_Map *map, int16_t x, - int16_t y + int16_t y, + uint8_t *properties ) { if (x < 0 || x >= SFG_MAP_SIZE || y < 0 || y >= SFG_MAP_SIZE) + { + *properties = SFG_TILE_PROPERTY_NORMAL; return SFG_OUTSIDE_TILE; + } - return map->tileDictionary[map->mapArray[y * SFG_MAP_SIZE + x] & 0x3f]; -} + uint8_t tile = map->mapArray[y * SFG_MAP_SIZE + x]; -static inline uint8_t SFG_getMapTileProperties -( - const SFG_Map *map, - int16_t x, - int16_t y -) -{ - if (x < 0 || x >= SFG_MAP_SIZE || y < 0 || y >= SFG_MAP_SIZE) - return 0; - - return map->mapArray[y * SFG_MAP_SIZE + x] & 0xc0; + *properties = tile & 0xc0; + return map->tileDictionary[tile & 0x3f]; } static const SFG_Level SFG_level0 = @@ -100,7 +99,7 @@ static const SFG_Level SFG_level0 = .tileDictionary = { SFG_TD(0 ,31,0,0),SFG_TD(15,63,5,0),SFG_TD(28,63,1,0),SFG_TD(6 ,63,6,0), // 0 - SFG_TD(3 ,31,4,0),SFG_TD(4 ,63,4,0),SFG_TD(5 ,63,4,0),SFG_TD(1 ,10,1,0), // 4 + SFG_TD(10,28,4,0),SFG_TD(4 ,63,4,0),SFG_TD(5 ,63,4,0),SFG_TD(1 ,10,1,0), // 4 SFG_TD(0 ,31,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0), // 8 SFG_TD(0 ,31,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0), // 12 SFG_TD(0 ,31,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0),SFG_TD(0 ,63,0,0), // 16 @@ -119,6 +118,7 @@ static const SFG_Level SFG_level0 = .mapArray = { #define o 0 + #define AA (0x04 | SFG_TILE_PROPERTY_ELEVATOR) 1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,3 ,3 ,3 ,3 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,3 ,3 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , @@ -126,7 +126,7 @@ static const SFG_Level SFG_level0 = 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,3 ,3 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , - 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,3 ,3 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , + 1 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,AA,o ,o ,o ,o ,o ,AA,3 ,3 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , 1 ,o ,o ,o ,o ,o ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,2 ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , @@ -184,6 +184,7 @@ static const SFG_Level SFG_level0 = o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o ,o , #undef o + #undef A } } }; diff --git a/main.c b/main.c index 5871f9e..5e7d781 100755 --- a/main.c +++ b/main.c @@ -54,6 +54,11 @@ void SFG_init(); #include "raycastlib.h" +/** + Step in which walls get higher, in raycastlib units. +*/ +#define SFG_WALL_HEIGHT_STEP (RCL_UNITS_PER_SQUARE / 4) + RCL_Camera SFG_camera; RCL_RayConstraints SFG_rayConstraints; @@ -68,18 +73,9 @@ struct const SFG_Map *mapPointer; const SFG_Level *levelPointer; const uint8_t* textures[7]; + uint32_t timeStart; } SFG_currentLevel; -void SFG_setLevel(const SFG_Level *level) -{ - SFG_currentLevel.levelPointer = level; - SFG_currentLevel.mapPointer = &(level->map); - - for (uint8_t i = 0; i < 7; ++i) - SFG_currentLevel.textures[i] = - SFG_texturesWall[level->map.textureIndices[i]]; -} - void SFG_pixelFunc(RCL_PixelInfo *pixel) { uint8_t color; @@ -139,27 +135,59 @@ void SFG_pixelFunc(RCL_PixelInfo *pixel) RCL_Unit SFG_texturesAt(int16_t x, int16_t y) { - SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y); + uint8_t properties; + + SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y,&properties); return SFG_TILE_FLOOR_TEXTURE(tile) | (SFG_TILE_CEILING_TEXTURE(tile) << 3); // ^ store both textures (floor and ceiling) in one number } +RCL_Unit SFG_movingWallHeight +( + RCL_Unit low, + RCL_Unit high, + uint32_t time +) +{ + RCL_Unit height = high - low; + RCL_Unit halfHeight = height / 2; + + RCL_Unit sinArg = + (time * ((SFG_MOVING_WALL_SPEED * RCL_UNITS_PER_SQUARE) / 1000)) / height; + + return + low + halfHeight + (RCL_sinInt(sinArg) * halfHeight) / RCL_UNITS_PER_SQUARE; +} + RCL_Unit SFG_floorHeightAt(int16_t x, int16_t y) { - SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y); + uint8_t properties; - return SFG_TILE_FLOOR_HEIGHT(tile) * (RCL_UNITS_PER_SQUARE / 4); + SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y,&properties); + + return properties != SFG_TILE_PROPERTY_ELEVATOR ? + SFG_TILE_FLOOR_HEIGHT(tile) * SFG_WALL_HEIGHT_STEP : + SFG_movingWallHeight( + SFG_TILE_FLOOR_HEIGHT(tile) * SFG_WALL_HEIGHT_STEP, + SFG_TILE_CEILING_HEIGHT(tile) * SFG_WALL_HEIGHT_STEP, + SFG_getTimeMs() - SFG_currentLevel.timeStart); } +#define SFG_CEILING_MAX_HEIGHT (32 * RCL_UNITS_PER_SQUARE) + RCL_Unit SFG_ceilingHeightAt(int16_t x, int16_t y) { - SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y); + uint8_t properties; + SFG_TileDefinition tile = SFG_getMapTile(&(SFG_level0.map),x,y,&properties); + + if (properties == SFG_TILE_PROPERTY_ELEVATOR) + return SFG_CEILING_MAX_HEIGHT; uint8_t height = SFG_TILE_CEILING_HEIGHT(tile); return height != SFG_TILE_CEILING_MAX_HEIGHT ? - ((SFG_TILE_FLOOR_HEIGHT(tile) + height) * (RCL_UNITS_PER_SQUARE / 4)) : - (RCL_UNITS_PER_SQUARE * 32); + ((SFG_TILE_FLOOR_HEIGHT(tile) + height) * SFG_WALL_HEIGHT_STEP) : + SFG_CEILING_MAX_HEIGHT; } uint32_t SFG_frame; @@ -196,7 +224,34 @@ void SFG_init() #define SFG_PLAYER_MOVE_UNITS_PER_FRAME\ ((SFG_PLAYER_MOVE_SPEED * RCL_UNITS_PER_SQUARE) / SFG_FPS) -RCL_Vector2D playerDirection; +RCL_Vector2D SFG_playerDirection; + +void SFG_recompurePLayerDirection() +{ + SFG_camera.direction = RCL_wrap(SFG_camera.direction,RCL_UNITS_PER_SQUARE); + + SFG_playerDirection = RCL_angleToDirection(SFG_camera.direction); + + SFG_playerDirection.x = (SFG_playerDirection.x * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; + SFG_playerDirection.y = (SFG_playerDirection.y * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; + + SFG_backgroundScroll = + ((SFG_camera.direction * 8) * SFG_RESOLUTION_Y) / RCL_UNITS_PER_SQUARE; +} + +void SFG_setLevel(const SFG_Level *level) +{ + SFG_currentLevel.levelPointer = level; + SFG_currentLevel.mapPointer = &(level->map); + + for (uint8_t i = 0; i < 7; ++i) + SFG_currentLevel.textures[i] = + SFG_texturesWall[level->map.textureIndices[i]]; + + SFG_currentLevel.timeStart = SFG_getTimeMs(); + + SFG_recompurePLayerDirection(); +} /** Performs one game step (logic, physics), happening SFG_MS_PER_FRAME after @@ -218,27 +273,17 @@ void SFG_gameStep() } if (recomputeDirection) - { - SFG_camera.direction = RCL_wrap(SFG_camera.direction,RCL_UNITS_PER_SQUARE); - - playerDirection = RCL_angleToDirection(SFG_camera.direction); - - playerDirection.x = (playerDirection.x * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; - playerDirection.y = (playerDirection.y * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; - - SFG_backgroundScroll = - ((SFG_camera.direction * 8) * SFG_RESOLUTION_Y) / RCL_UNITS_PER_SQUARE; - } + SFG_recompurePLayerDirection(); if (SFG_keyPressed(SFG_KEY_UP)) { - SFG_camera.position.x += playerDirection.x; - SFG_camera.position.y += playerDirection.y; + SFG_camera.position.x += SFG_playerDirection.x; + SFG_camera.position.y += SFG_playerDirection.y; } else if (SFG_keyPressed(SFG_KEY_DOWN)) { - SFG_camera.position.x -= playerDirection.x; - SFG_camera.position.y -= playerDirection.y; + SFG_camera.position.x -= SFG_playerDirection.x; + SFG_camera.position.y -= SFG_playerDirection.y; } if (SFG_keyPressed(SFG_KEY_A))