From 61b55ebb0100c0dca0808d71881cd0db9ba88461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miloslav=20=C4=8C=C3=AD=C5=BE?= Date: Fri, 3 Jul 2020 21:51:29 +0200 Subject: [PATCH] Update --- TODO.txt | 2 + assets/levelZ.gif | Bin 0 -> 3236 bytes main.c | 16 ++--- raycastlib.h | 163 +++++++++++++++------------------------------- 4 files changed, 64 insertions(+), 117 deletions(-) create mode 100644 assets/levelZ.gif diff --git a/TODO.txt b/TODO.txt index e11ae22..320d473 100644 --- a/TODO.txt +++ b/TODO.txt @@ -1,5 +1,7 @@ general: +- automatic tests: a frontend that will play the game, check the state, rendered + frames etc. - weapon autoswitch: when a stronger weapon becomes available via picking up ammo, maybe it should automatically be switched to (could have disable setting) diff --git a/assets/levelZ.gif b/assets/levelZ.gif new file mode 100644 index 0000000000000000000000000000000000000000..18facb1a5660001de5983fbba0e6afd56cca15a6 GIT binary patch literal 3236 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 W5rUAzf=%}mCrE=l*n=n$5CA)f&+KFX literal 0 HcmV?d00001 diff --git a/main.c b/main.c index 3c8736e..b164de7 100755 --- a/main.c +++ b/main.c @@ -507,7 +507,7 @@ uint8_t SFG_weaponAmmo(uint8_t weapon) RCL_Unit SFG_taxicabDistance( RCL_Unit x0, RCL_Unit y0, RCL_Unit z0, RCL_Unit x1, RCL_Unit y1, RCL_Unit z1) { - return (RCL_absVal(x0 - x1) + RCL_absVal(y0 - y1) + RCL_absVal(z0 - z1)); + return (RCL_abs(x0 - x1) + RCL_abs(y0 - y1) + RCL_abs(z0 - z1)); } uint8_t SFG_isInActiveDistanceFromPlayer(RCL_Unit x, RCL_Unit y, RCL_Unit z) @@ -1045,7 +1045,7 @@ RCL_Unit SFG_movingWallHeight (time * ((SFG_MOVING_WALL_SPEED * RCL_UNITS_PER_SQUARE) / 1000)) / height; return - low + halfHeight + (RCL_sinInt(sinArg) * halfHeight) / RCL_UNITS_PER_SQUARE; + low + halfHeight + (RCL_sin(sinArg) * halfHeight) / RCL_UNITS_PER_SQUARE; } RCL_Unit SFG_floorHeightAt(int16_t x, int16_t y) @@ -1635,8 +1635,8 @@ uint8_t SFG_pushPlayerAway( RCL_Vector2D SFG_resolveCollisionWithElement( RCL_Vector2D position, RCL_Vector2D moveOffset, RCL_Vector2D elementPos) { - RCL_Unit dx = RCL_absVal(elementPos.x - position.x); - RCL_Unit dy = RCL_absVal(elementPos.y - position.y); + RCL_Unit dx = RCL_abs(elementPos.x - position.x); + RCL_Unit dy = RCL_abs(elementPos.y - position.y); if (dx > dy) { @@ -2134,7 +2134,7 @@ void SFG_monsterPerformAI(SFG_MonsterRecord *monster) SFG_floorCollisionHeightAt(newPos[0] / 4,newPos[1] / 4); collision = - RCL_absVal(currentHeight - newHeight) > RCL_CAMERA_COLL_STEP_HEIGHT; + RCL_abs(currentHeight - newHeight) > RCL_CAMERA_COLL_STEP_HEIGHT; } if (collision) @@ -3713,7 +3713,7 @@ void SFG_drawWinOverlay() for (uint16_t y = STRIP_START; y < STRIP_START + l; ++y) for (uint16_t x = 0; x < SFG_GAME_RESOLUTION_X; ++x) SFG_setGamePixel(x,y, - RCL_absVal(y - (SFG_GAME_RESOLUTION_Y / 2)) <= (INNER_STRIP_HEIGHT / 2) ? + RCL_abs(y - (SFG_GAME_RESOLUTION_Y / 2)) <= (INNER_STRIP_HEIGHT / 2) ? 0 : 172); char textLine[] = "level done"; @@ -3783,7 +3783,7 @@ void SFG_draw() if (SFG_game.state != SFG_GAME_STATE_LOSE) { - RCL_Unit bobSin = RCL_sinInt(SFG_player.headBobFrame); + RCL_Unit bobSin = RCL_sin(SFG_player.headBobFrame); headBobOffset = (bobSin * SFG_HEADBOB_OFFSET) / RCL_UNITS_PER_SQUARE; @@ -3930,7 +3930,7 @@ void SFG_draw() spriteSize = ( SFG_SPRITE_SIZE_PIXELS(2) * - RCL_sinInt( + RCL_sin( ((doubleFramesToLive - proj->doubleFramesToLive) * RCL_UNITS_PER_SQUARE / 4) / doubleFramesToLive) diff --git a/raycastlib.h b/raycastlib.h index bda7c59..37d34f1 100644 --- a/raycastlib.h +++ b/raycastlib.h @@ -26,7 +26,7 @@ author: Miloslav "drummyfish" Ciz license: CC0 1.0 - version: 0.904 + version: 0.906 */ #include @@ -364,13 +364,13 @@ Cos function. @return RCL_normalized output in RCL_Units (from -RCL_UNITS_PER_SQUARE to RCL_UNITS_PER_SQUARE) */ -RCL_Unit RCL_cosInt(RCL_Unit input); +RCL_Unit RCL_cos(RCL_Unit input); -RCL_Unit RCL_sinInt(RCL_Unit input); +RCL_Unit RCL_sin(RCL_Unit input); -RCL_Unit RCL_tanInt(RCL_Unit input); +RCL_Unit RCL_tan(RCL_Unit input); -RCL_Unit RCL_ctgInt(RCL_Unit input); +RCL_Unit RCL_ctg(RCL_Unit input); /// Normalizes given vector to have RCL_UNITS_PER_SQUARE length. RCL_Vector2D RCL_normalize(RCL_Vector2D v); @@ -378,7 +378,7 @@ RCL_Vector2D RCL_normalize(RCL_Vector2D v); /// Computes a cos of an angle between two vectors. RCL_Unit RCL_vectorsAngleCos(RCL_Vector2D v1, RCL_Vector2D v2); -uint16_t RCL_sqrtInt(RCL_Unit value); +uint16_t RCL_sqrt(RCL_Unit value); RCL_Unit RCL_dist(RCL_Vector2D p1, RCL_Vector2D p2); RCL_Unit RCL_len(RCL_Vector2D v); @@ -514,50 +514,8 @@ int16_t _RCL_cameraHeightScreen = 0; RCL_ArrayFunction _RCL_rollFunction = 0; // says door rolling RCL_Unit *_RCL_floorPixelDistances = 0; -#ifdef RCL_PROFILE - // function call counters for profiling - uint32_t profile_RCL_sqrtInt = 0; - uint32_t profile_RCL_clamp = 0; - uint32_t profile_RCL_cosInt = 0; - uint32_t profile_RCL_angleToDirection = 0; - uint32_t profile_RCL_dist = 0; - uint32_t profile_RCL_len = 0; - uint32_t profile_RCL_pointIsLeftOfRay = 0; - uint32_t profile_RCL_castRayMultiHit = 0; - uint32_t profile_RCL_castRay = 0; - uint32_t profile_RCL_absVal = 0; - uint32_t profile_RCL_normalize = 0; - uint32_t profile_RCL_vectorsAngleCos = 0; - uint32_t profile_RCL_perspectiveScaleVertical = 0; - uint32_t profile_RCL_wrap = 0; - uint32_t profile_RCL_divRoundDown = 0; - #define RCL_profileCall(c) profile_##c += 1 - - #define printProfile() {\ - printf("profile:\n");\ - printf(" RCL_sqrtInt: %d\n",profile_RCL_sqrtInt);\ - printf(" RCL_clamp: %d\n",profile_RCL_clamp);\ - printf(" RCL_cosInt: %d\n",profile_RCL_cosInt);\ - printf(" RCL_angleToDirection: %d\n",profile_RCL_angleToDirection);\ - printf(" RCL_dist: %d\n",profile_RCL_dist);\ - printf(" RCL_len: %d\n",profile_RCL_len);\ - printf(" RCL_pointIsLeftOfRay: %d\n",profile_RCL_pointIsLeftOfRay);\ - printf(" RCL_castRayMultiHit : %d\n",profile_RCL_castRayMultiHit);\ - printf(" RCL_castRay: %d\n",profile_RCL_castRay);\ - printf(" RCL_normalize: %d\n",profile_RCL_normalize);\ - printf(" RCL_vectorsAngleCos: %d\n",profile_RCL_vectorsAngleCos);\ - printf(" RCL_absVal: %d\n",profile_RCL_absVal);\ - printf(" RCL_perspectiveScaleVertical: %d\n",profile_RCL_perspectiveScaleVertical);\ - printf(" RCL_wrap: %d\n",profile_RCL_wrap);\ - printf(" RCL_divRoundDown: %d\n",profile_RCL_divRoundDown); } -#else - #define RCL_profileCall(c) -#endif - RCL_Unit RCL_clamp(RCL_Unit value, RCL_Unit valueMin, RCL_Unit valueMax) { - RCL_profileCall(RCL_clamp); - if (value >= valueMin) { if (value <= valueMax) @@ -569,17 +527,14 @@ RCL_Unit RCL_clamp(RCL_Unit value, RCL_Unit valueMin, RCL_Unit valueMax) return valueMin; } -static inline RCL_Unit RCL_absVal(RCL_Unit value) +static inline RCL_Unit RCL_abs(RCL_Unit value) { - RCL_profileCall(RCL_absVal); - return value * (((value >= 0) << 1) - 1); } /// Like mod, but behaves differently for negative values. static inline RCL_Unit RCL_wrap(RCL_Unit value, RCL_Unit mod) { - RCL_profileCall(RCL_wrap); RCL_Unit cmp = value < 0; return cmp * mod + (value % mod) - cmp; } @@ -587,8 +542,6 @@ static inline RCL_Unit RCL_wrap(RCL_Unit value, RCL_Unit mod) /// Performs division, rounding down, NOT towards zero. static inline RCL_Unit RCL_divRoundDown(RCL_Unit value, RCL_Unit divisor) { - RCL_profileCall(RCL_divRoundDown); - return value / divisor - ((value >= 0) ? 0 : 1); } @@ -628,10 +581,8 @@ const RCL_Unit cosLUT[128] = }; #endif -RCL_Unit RCL_cosInt(RCL_Unit input) +RCL_Unit RCL_cos(RCL_Unit input) { - RCL_profileCall(RCL_cosInt); - input = RCL_wrap(input,RCL_UNITS_PER_SQUARE); #if RCL_USE_COS_LUT == 1 @@ -658,37 +609,33 @@ RCL_Unit RCL_cosInt(RCL_Unit input) #undef trigHelper -RCL_Unit RCL_sinInt(RCL_Unit input) +RCL_Unit RCL_sin(RCL_Unit input) { - return RCL_cosInt(input - RCL_UNITS_PER_SQUARE / 4); + return RCL_cos(input - RCL_UNITS_PER_SQUARE / 4); } -RCL_Unit RCL_tanInt(RCL_Unit input) +RCL_Unit RCL_tan(RCL_Unit input) { - return (RCL_sinInt(input) * RCL_UNITS_PER_SQUARE) / RCL_cosInt(input); + return (RCL_sin(input) * RCL_UNITS_PER_SQUARE) / RCL_cos(input); } -RCL_Unit RCL_ctgInt(RCL_Unit input) +RCL_Unit RCL_ctg(RCL_Unit input) { - return (RCL_cosInt(input) * RCL_UNITS_PER_SQUARE) / RCL_sinInt(input); + return (RCL_cos(input) * RCL_UNITS_PER_SQUARE) / RCL_sin(input); } RCL_Vector2D RCL_angleToDirection(RCL_Unit angle) { - RCL_profileCall(RCL_angleToDirection); - RCL_Vector2D result; - result.x = RCL_cosInt(angle); - result.y = -1 * RCL_sinInt(angle); + result.x = RCL_cos(angle); + result.y = -1 * RCL_sin(angle); return result; } -uint16_t RCL_sqrtInt(RCL_Unit value) +uint16_t RCL_sqrt(RCL_Unit value) { - RCL_profileCall(RCL_sqrtInt); - #ifdef RCL_RAYCAST_TINY uint16_t result = 0; uint16_t a = value; @@ -719,16 +666,14 @@ uint16_t RCL_sqrtInt(RCL_Unit value) RCL_Unit RCL_dist(RCL_Vector2D p1, RCL_Vector2D p2) { - RCL_profileCall(RCL_dist); - RCL_Unit dx = p2.x - p1.x; RCL_Unit dy = p2.y - p1.y; #if RCL_USE_DIST_APPROX == 2 // octagonal approximation - dx = RCL_absVal(dx); - dy = RCL_absVal(dy); + dx = RCL_abs(dx); + dy = RCL_abs(dy); return dy > dx ? dx / 2 + dy : dy / 2 + dx; #elif RCL_USE_DIST_APPROX == 1 @@ -760,14 +705,12 @@ RCL_Unit RCL_dist(RCL_Vector2D p1, RCL_Vector2D p2) dx = dx * dx; dy = dy * dy; - return RCL_sqrtInt((RCL_Unit) (dx + dy)); + return RCL_sqrt((RCL_Unit) (dx + dy)); #endif } RCL_Unit RCL_len(RCL_Vector2D v) { - RCL_profileCall(RCL_len); - RCL_Vector2D zero; zero.x = 0; zero.y = 0; @@ -777,8 +720,6 @@ RCL_Unit RCL_len(RCL_Vector2D v) static inline int8_t RCL_pointIsLeftOfRay(RCL_Vector2D point, RCL_Ray ray) { - RCL_profileCall(RCL_pointIsLeftOfRay); - RCL_Unit dX = point.x - ray.start.x; RCL_Unit dY = point.y - ray.start.y; return (ray.direction.x * dY - ray.direction.y * dX) > 0; @@ -789,8 +730,6 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc, RCL_ArrayFunction typeFunc, RCL_HitResult *hitResults, uint16_t *hitResultsLen, RCL_RayConstraints constraints) { - RCL_profileCall(RCL_castRayMultiHit); - RCL_Vector2D currentPos = ray.start; RCL_Vector2D currentSquare; @@ -812,8 +751,8 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc, RCL_Unit dirVecLengthNorm = RCL_len(ray.direction) * RCL_UNITS_PER_SQUARE; - delta.x = RCL_absVal(dirVecLengthNorm / RCL_nonZero(ray.direction.x)); - delta.y = RCL_absVal(dirVecLengthNorm / RCL_nonZero(ray.direction.y)); + delta.x = RCL_abs(dirVecLengthNorm / RCL_nonZero(ray.direction.x)); + delta.y = RCL_abs(dirVecLengthNorm / RCL_nonZero(ray.direction.y)); // init DDA @@ -991,8 +930,6 @@ void RCL_castRayMultiHit(RCL_Ray ray, RCL_ArrayFunction arrayFunc, RCL_HitResult RCL_castRay(RCL_Ray ray, RCL_ArrayFunction arrayFunc) { - RCL_profileCall(RCL_castRay); - RCL_HitResult result; uint16_t RCL_len; RCL_RayConstraints c; @@ -1021,7 +958,7 @@ void RCL_castRaysMultiHit(RCL_Camera cam, RCL_ArrayFunction arrayFunc, /* We scale the side distances so that the middle one is RCL_UNITS_PER_SQUARE, which has to be this way. */ - RCL_Unit cos = RCL_nonZero(RCL_cosInt(RCL_HORIZONTAL_FOV_HALF)); + RCL_Unit cos = RCL_nonZero(RCL_cos(RCL_HORIZONTAL_FOV_HALF)); dir1.x = (dir1.x * RCL_UNITS_PER_SQUARE) / cos; dir1.y = (dir1.y * RCL_UNITS_PER_SQUARE) / cos; @@ -1139,7 +1076,7 @@ static inline int16_t _RCL_drawHorizontalColumn( {\ if (doDepth) /*constant condition - compiler should optimize it out*/\ {\ - depth = pixelInfo->depth + RCL_absVal(verticalOffset) *\ + depth = pixelInfo->depth + RCL_abs(verticalOffset) *\ RCL_VERTICAL_DEPTH_MULTIPLY;\ depthIncrement = depthIncrementMultiplier *\ _RCL_horizontalDepthStep;\ @@ -1207,15 +1144,15 @@ static inline int16_t _RCL_drawWall( { _RCL_UNUSED(height) - height = RCL_absVal(height); + height = RCL_abs(height); pixelInfo->isWall = 1; RCL_Unit limit = RCL_clamp(yTo,limit1,limit2); - RCL_Unit wallLength = RCL_nonZero(RCL_absVal(yTo - yFrom - 1)); + RCL_Unit wallLength = RCL_nonZero(RCL_abs(yTo - yFrom - 1)); - RCL_Unit wallPosition = RCL_absVal(yFrom - yCurrent) - increment; + RCL_Unit wallPosition = RCL_abs(yFrom - yCurrent) - increment; RCL_Unit heightScaled = height * RCL_TEXTURE_INTERPOLATION_SCALE; _RCL_UNUSED(heightScaled); @@ -1459,7 +1396,6 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount, RCL_Unit y = 0; RCL_Unit wallHeightScreen = 0; RCL_Unit wallStart = _RCL_middleRow; - RCL_Unit heightOffset = 0; RCL_Unit dist = 1; @@ -1524,18 +1460,32 @@ void _RCL_columnFunctionSimple(RCL_HitResult *hits, uint16_t hitCount, { dist = hit.distance; - int16_t wallHeightWorld = _RCL_floorFunction(hit.square.x,hit.square.y); + RCL_Unit wallHeightWorld = _RCL_floorFunction(hit.square.x,hit.square.y); - wallHeightScreen = RCL_perspectiveScaleVertical((wallHeightWorld * - _RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE,dist); + if (wallHeightWorld < 0) + { + /* We can't just do wallHeightWorld = max(0,wallHeightWorld) because + we would be processing an actual hit with height 0, which shouldn't + ever happen, so we assign some arbitrary height. */ - int16_t RCL_normalizedWallHeight = wallHeightWorld != 0 ? - ((RCL_UNITS_PER_SQUARE * wallHeightScreen) / wallHeightWorld) : 0; + wallHeightWorld = RCL_UNITS_PER_SQUARE; + } - heightOffset = RCL_perspectiveScaleVertical(_RCL_cameraHeightScreen,dist); + RCL_Unit worldPointTop = wallHeightWorld - _RCL_camera.height; + RCL_Unit worldPointBottom = -1 * _RCL_camera.height; - wallStart = _RCL_middleRow - wallHeightScreen + heightOffset + - RCL_normalizedWallHeight; + wallStart = _RCL_middleRow - + (RCL_perspectiveScaleVertical(worldPointTop,dist) + * _RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE; + + int16_t wallEnd = _RCL_middleRow - + (RCL_perspectiveScaleVertical(worldPointBottom,dist) + * _RCL_camera.resolution.y) / RCL_UNITS_PER_SQUARE; + + wallHeightScreen = wallEnd - wallStart; + + if (wallHeightScreen <= 0) // can happen because of rounding errors + wallHeightScreen = 1; } } else @@ -1599,7 +1549,7 @@ static inline void _RCL_precomputeFloorDistances(RCL_Camera camera, for (uint16_t i = startIndex; i < camera.resolution.y; ++i) dest[i] = RCL_perspectiveScaleVerticalInverse(camHeightScreenSize, - RCL_absVal(i - _RCL_middleRow)); + RCL_abs(i - _RCL_middleRow)); } void RCL_renderComplex(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc, @@ -1678,8 +1628,6 @@ void RCL_renderSimple(RCL_Camera cam, RCL_ArrayFunction floorHeightFunc, RCL_Vector2D RCL_normalize(RCL_Vector2D v) { - RCL_profileCall(RCL_normalize); - RCL_Vector2D result; RCL_Unit l = RCL_len(v); l = RCL_nonZero(l); @@ -1692,8 +1640,6 @@ RCL_Vector2D RCL_normalize(RCL_Vector2D v) RCL_Unit RCL_vectorsAngleCos(RCL_Vector2D v1, RCL_Vector2D v2) { - RCL_profileCall(RCL_vectorsAngleCos); - v1 = RCL_normalize(v1); v2 = RCL_normalize(v2); @@ -1712,10 +1658,10 @@ RCL_PixelInfo RCL_mapToScreen(RCL_Vector2D worldPosition, RCL_Unit height, RCL_Unit middleColumn = camera.resolution.x / 2; - // rotate the point + // rotate the point to camera space (y left/right, x forw/backw) - RCL_Unit cos = RCL_cosInt(camera.direction); - RCL_Unit sin = RCL_sinInt(camera.direction); + RCL_Unit cos = RCL_cos(camera.direction); + RCL_Unit sin = RCL_sin(camera.direction); RCL_Unit tmp = toPoint.x; @@ -1743,8 +1689,6 @@ RCL_Unit RCL_degreesToUnitsAngle(int16_t degrees) RCL_Unit RCL_perspectiveScaleVertical(RCL_Unit originalSize, RCL_Unit distance) { - RCL_profileCall(RCL_perspectiveScaleVertical); - return distance != 0 ? (originalSize * RCL_UNITS_PER_SQUARE) / ((RCL_VERTICAL_FOV_TAN * 2 * distance) / RCL_UNITS_PER_SQUARE) @@ -2036,3 +1980,4 @@ void RCL_initRayConstraints(RCL_RayConstraints *constraints) } #endif +