diff --git a/main.c b/main.c index 7f48335..c9b3b23 100755 --- a/main.c +++ b/main.c @@ -141,6 +141,16 @@ void SFG_init(); #define SFG_HEADBOB_ENABLED (SFG_HEADBOB_SPEED > 0 && SFG_HEADBOB_OFFSET > 0) +#define SFG_CAMERA_SHEAR_STEP_PER_FRAME \ + ((SFG_GAME_RESOLUTION_Y * SFG_CAMERA_SHEAR_SPEED) / SFG_FPS) + +#if SFG_CAMERA_SHEAR_STEP_PER_FRAME == 0 + #define SFG_CAMERA_SHEAR_STEP_PER_FRAME 1 +#endif + +#define SFG_CAMERA_MAX_SHEAR_PIXELS \ + (SFG_CAMERA_MAX_SHEAR * SFG_GAME_RESOLUTION_Y / 1024) + #define SFG_FONT_SIZE_SMALL \ (SFG_GAME_RESOLUTION_X / (SFG_FONT_CHARACTER_SIZE * 50)) @@ -214,19 +224,28 @@ void SFG_recompurePLayerDirection() SFG_player.direction = RCL_angleToDirection(SFG_player.camera.direction); - SFG_player.direction.x = (SFG_player.direction.x * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; - SFG_player.direction.y = (SFG_player.direction.y * SFG_PLAYER_MOVE_UNITS_PER_FRAME) / RCL_UNITS_PER_SQUARE; + SFG_player.direction.x = + (SFG_player.direction.x * SFG_PLAYER_MOVE_UNITS_PER_FRAME) + / RCL_UNITS_PER_SQUARE; + + SFG_player.direction.y = + (SFG_player.direction.y * SFG_PLAYER_MOVE_UNITS_PER_FRAME) + / RCL_UNITS_PER_SQUARE; SFG_backgroundScroll = - ((SFG_player.camera.direction * 8) * SFG_GAME_RESOLUTION_Y) / RCL_UNITS_PER_SQUARE; + ((SFG_player.camera.direction * 8) * SFG_GAME_RESOLUTION_Y) + / RCL_UNITS_PER_SQUARE; } void SFG_initPlayer() { RCL_initCamera(&SFG_player.camera); - SFG_player.camera.resolution.x = SFG_GAME_RESOLUTION_X / SFG_RAYCASTING_SUBSAMPLE; + SFG_player.camera.resolution.x = + SFG_GAME_RESOLUTION_X / SFG_RAYCASTING_SUBSAMPLE; + SFG_player.camera.resolution.y = SFG_GAME_RESOLUTION_Y; + SFG_player.camera.height = RCL_UNITS_PER_SQUARE * 12; SFG_player.camera.position.x = RCL_UNITS_PER_SQUARE * 15; SFG_player.camera.position.y = RCL_UNITS_PER_SQUARE * 8; @@ -396,7 +415,7 @@ void SFG_pixelFunc(RCL_PixelInfo *pixel) { #if SFG_DITHERED_SHADOW uint8_t fogShadow = (pixel->depth * 4) / (RCL_UNITS_PER_SQUARE); - + uint8_t fogShadowPart = fogShadow & 0x07; fogShadow /= 8; @@ -749,8 +768,31 @@ void SFG_gameStep() int8_t strafe = 0; +#if SFG_HEADBOB_ENABLED + int8_t bobbing = 0; +#endif + + int8_t shearing = 0; + if (SFG_keyPressed(SFG_KEY_A)) { + if (SFG_keyPressed(SFG_KEY_UP)) + { + SFG_player.camera.shear = + RCL_min(SFG_CAMERA_MAX_SHEAR_PIXELS, + SFG_player.camera.shear + SFG_CAMERA_SHEAR_STEP_PER_FRAME); + + shearing = 1; + } + else if (SFG_keyPressed(SFG_KEY_DOWN)) + { + SFG_player.camera.shear = + RCL_max(-1 * SFG_CAMERA_MAX_SHEAR_PIXELS, + SFG_player.camera.shear - SFG_CAMERA_SHEAR_STEP_PER_FRAME); + + shearing = 1; + } + if (SFG_keyPressed(SFG_KEY_LEFT)) strafe = -1; else if (SFG_keyPressed(SFG_KEY_RIGHT)) @@ -771,6 +813,23 @@ void SFG_gameStep() if (recomputeDirection) SFG_recompurePLayerDirection(); + + if (SFG_keyPressed(SFG_KEY_UP)) + { + moveOffset.x += SFG_player.direction.x; + moveOffset.y += SFG_player.direction.y; +#if SFG_HEADBOB_ENABLED + bobbing = 1; +#endif + } + else if (SFG_keyPressed(SFG_KEY_DOWN)) + { + moveOffset.x -= SFG_player.direction.x; + moveOffset.y -= SFG_player.direction.y; +#if SFG_HEADBOB_ENABLED + bobbing = 1; +#endif + } } if (SFG_keyPressed(SFG_KEY_STRAFE_LEFT)) @@ -804,25 +863,14 @@ void SFG_gameStep() (SFG_player.verticalSpeed - SFG_GRAVITY_SPEED_INCREASE_PER_FRAME); #endif -#if SFG_HEADBOB_ENABLED - int8_t bobbing = 0; -#endif + if (!shearing && SFG_player.camera.shear != 0) + { + // gradually shear back to zero - if (SFG_keyPressed(SFG_KEY_UP)) - { - moveOffset.x += SFG_player.direction.x; - moveOffset.y += SFG_player.direction.y; -#if SFG_HEADBOB_ENABLED - bobbing = 1; -#endif - } - else if (SFG_keyPressed(SFG_KEY_DOWN)) - { - moveOffset.x -= SFG_player.direction.x; - moveOffset.y -= SFG_player.direction.y; -#if SFG_HEADBOB_ENABLED - bobbing = 1; -#endif + SFG_player.camera.shear = + (SFG_player.camera.shear > 0) ? + RCL_max(0,SFG_player.camera.shear - SFG_CAMERA_SHEAR_STEP_PER_FRAME) : + RCL_min(0,SFG_player.camera.shear + SFG_CAMERA_SHEAR_STEP_PER_FRAME); } #if SFG_HEADBOB_ENABLED diff --git a/raycastlib.h b/raycastlib.h index f57d8f6..e3239d1 100644 --- a/raycastlib.h +++ b/raycastlib.h @@ -26,7 +26,7 @@ author: Miloslav "drummyfish" Ciz license: CC0 1.0 - version: 0.87 + version: 0.88 */ #include @@ -280,6 +280,10 @@ typedef struct very often. */ typedef RCL_Unit (*RCL_ArrayFunction)(int16_t x, int16_t y); +/* + TODO: maybe array functions should be replaced by defines of funtion names + like with pixelFunc? Could be more efficient than function pointers. +*/ /** Function that renders a single pixel at the display. It is handed an info @@ -1034,7 +1038,7 @@ RCL_Unit RCL_adjustDistance(RCL_Unit distance, RCL_Camera *camera, } /// Helper for drawing floor or ceiling. Returns the last drawn pixel position. -static inline int16_t _RCL_drawVertical( +static inline int16_t _RCL_drawHorizontalColumn( RCL_Unit yCurrent, RCL_Unit yTo, RCL_Unit limit1, // TODO: int16_t? @@ -1058,13 +1062,19 @@ static inline int16_t _RCL_drawVertical( int16_t limit = RCL_clamp(yTo,limit1,limit2); + RCL_Unit depth = 0; /* TODO: this is for clamping depth to 0 so that we don't + have negative depths, but we should do it more + elegantly and efficiently */ + + _RCL_UNUSED(depth); + /* for performance reasons have different version of the critical loop to be able to branch early */ #define loop(doDepth,doCoords)\ {\ if (doDepth) /*constant condition - compiler should optimize it out*/\ {\ - pixelInfo->depth += RCL_absVal(verticalOffset) *\ + depth = pixelInfo->depth + RCL_absVal(verticalOffset) *\ RCL_VERTICAL_DEPTH_MULTIPLY;\ depthIncrement = depthIncrementMultiplier *\ _RCL_horizontalDepthStep;\ @@ -1080,7 +1090,10 @@ static inline int16_t _RCL_drawVertical( {\ pixelInfo->position.y = i;\ if (doDepth) /*constant condition - compiler should optimize it out*/\ - pixelInfo->depth += depthIncrement;\ + {\ + depth += depthIncrement;\ + pixelInfo->depth = RCL_max(0,depth); /*TODO: optimize */\ + }\ if (doCoords) /*constant condition - compiler should optimize it out*/\ {\ RCL_Unit d = _RCL_floorPixelDistances[i];\ @@ -1287,7 +1300,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t p.depth = 0; #endif - limit = _RCL_drawVertical(fPosY,fZ1Screen,cPosY + 1, + limit = _RCL_drawHorizontalColumn(fPosY,fZ1Screen,cPosY + 1, _RCL_camera.resolution.y,fZ1World,-1,RCL_COMPUTE_FLOOR_DEPTH, // ^ purposfully allow outside screen bounds RCL_COMPUTE_FLOOR_TEXCOORDS && p.height == RCL_FLOOR_TEXCOORDS_HEIGHT, @@ -1307,7 +1320,7 @@ void _RCL_columnFunctionComplex(RCL_HitResult *hits, uint16_t hitCount, uint16_t _RCL_horizontalDepthStep; #endif - limit = _RCL_drawVertical(cPosY,cZ1Screen, + limit = _RCL_drawHorizontalColumn(cPosY,cZ1Screen, -1,fPosY - 1,cZ1World,1,RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p); // ^ purposfully allow outside screen bounds here @@ -1472,7 +1485,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount, p.depth = 1; p.height = RCL_UNITS_PER_SQUARE; - y = _RCL_drawVertical(-1,wallStart,-1,_RCL_middleRow,_RCL_camera.height,1, + y = _RCL_drawHorizontalColumn(-1,wallStart,-1,_RCL_middleRow,_RCL_camera.height,1, RCL_COMPUTE_CEILING_DEPTH,0,1,&ray,&p); // draw wall @@ -1503,7 +1516,7 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount, p.depth = (_RCL_camera.resolution.y - y) * _RCL_horizontalDepthStep + 1; #endif - _RCL_drawVertical(y,_RCL_camResYLimit,-1,_RCL_camResYLimit, + _RCL_drawHorizontalColumn(y,_RCL_camResYLimit,-1,_RCL_camResYLimit, _RCL_camera.height,1,RCL_COMPUTE_FLOOR_DEPTH,RCL_COMPUTE_FLOOR_TEXCOORDS, -1,&ray,&p); } @@ -1627,8 +1640,6 @@ RCL_PixelInfo RCL_mapToScreen(RCL_Vector2D worldPosition, RCL_Unit height, { RCL_PixelInfo result; - RCL_Unit d = RCL_dist(worldPosition,camera.position); - RCL_Vector2D toPoint; toPoint.x = worldPosition.x - camera.position.x; diff --git a/settings.h b/settings.h index aae71fa..7ff929a 100644 --- a/settings.h +++ b/settings.h @@ -108,4 +108,14 @@ */ #define SFG_HEADBOB_OFFSET 200 +/** + Camera shearing (looking up/down) speed, in vertical resolutions per second. +*/ +#define SFG_CAMERA_SHEAR_SPEED 3 + +/** + Maximum camera shear (vertical angle). 1024 means 1.0 * vertical resolution. +*/ +#define SFG_CAMERA_MAX_SHEAR 1024 + #endif // guard