void Slice::Draw(Ray ray, Vector pos, Vector dir, const Level& level, const ResourceCache& res) { const int wall_height = std::abs(int(mSurface->h / ray.GetDistance())); int wall_start = (mSurface->h / 2) - (wall_height / 2); int wall_end = (mSurface->h / 2) + (wall_height / 2); if (wall_start < 0) { wall_start = 0; } if (wall_end >= mSurface->h) { wall_end = mSurface->h - 1; } // Get the texture that matches the cell type. const auto cell_id = level.mGrid[ray.GetMapIntersectionX()][ray.GetMapIntersectionY()] - 1; //const auto cell_id = level.mGrid[ray.GetMapIntersectionX()][ray.GetMapIntersectionY()] - 1; const auto wall_tex = res.GetWall(cell_id); // Where exactly the wall was hit. double wall_x = ray.GetIntersection().GetY(); wall_x -= std::floor(wall_x); // X-coordinate on the texture. int tex_x = wall_x * wall_tex->w; if (( ray.VerticalSideHit() && dir.GetY() < 0) || (!ray.VerticalSideHit() && dir.GetX() > 0)) { tex_x = wall_tex->w - tex_x - 1; } for (int y = wall_start; y < wall_end; y++) { const int tex_y = (y * 2 - mSurface->h + wall_height) * (wall_tex->h / 2) / wall_height; const auto tex_offset = (wall_tex->pitch * tex_y) + (tex_x * 4); const auto tex_ptr = static_cast<Uint8*>(wall_tex->pixels) + tex_offset; SDL_Color color = { tex_ptr[0], tex_ptr[1], tex_ptr[2] }; if (ray.VerticalSideHit()) { // Give X and Y-sides different brightness. color.r /= 2; color.g /= 2; color.b /= 2; } const auto scr_offset = (mSurface->pitch * y) + (mXCoordinate * 4); const auto scr_ptr = static_cast<Uint8*>(mSurface->pixels) + scr_offset; memcpy(scr_ptr, &color, sizeof(color)); } // Get the texture for the ceiling and floor. // const auto ceiling_tex = res.GetCeiling(0); const auto floor_tex = res.GetWall(2); // Position of the floor at the bottom of the wall. double floor_x_wall; double floor_y_wall; if (!ray.VerticalSideHit() && (dir.GetX() > 0)) { floor_x_wall = ray.GetMapIntersectionX(); floor_y_wall = ray.GetMapIntersectionY() + wall_x; } else if (!ray.VerticalSideHit() && (dir.GetX() < 0)) { floor_x_wall = ray.GetMapIntersectionX() + 1.; floor_y_wall = ray.GetMapIntersectionY() + wall_x; } else if (ray.VerticalSideHit() && (dir.GetY() > 0)) { floor_x_wall = ray.GetMapIntersectionX() + wall_x; floor_y_wall = ray.GetMapIntersectionY(); } else { floor_x_wall = ray.GetMapIntersectionX() + wall_x; floor_y_wall = ray.GetMapIntersectionY() + 1.; } const double dist_wall = ray.GetDistance(); const double dist_player = .0; // Draw the floor from below the wall to the bottom of the screen. for (int y = wall_end; y < mSurface->h; y++) { const double cur_dist = mSurface->h / (2. * y - mSurface->h); const double weight = (cur_dist - dist_player) / (dist_wall - dist_player); double cur_floor_x = weight * floor_x_wall + (1.0 - weight) * pos.GetX(); double cur_floor_y = weight * floor_y_wall + (1.0 - weight) * pos.GetY(); if (cur_floor_x < 0.) { cur_floor_x = 0.; } if (cur_floor_y < 0.) { cur_floor_y = 0.; } const int floor_tex_x = int(cur_floor_x * floor_tex->w / 4) % floor_tex->w; const int floor_tex_y = int(cur_floor_y * floor_tex->h / 4) % floor_tex->h; // const auto ceiling_tex_offset = (ceiling_tex->pitch * floor_tex_y) + (floor_tex_x * 4); // const auto ceiling_tex_ptr = static_cast<Uint8*>(ceiling_tex->pixels) + ceiling_tex_offset; const auto floor_tex_offset = (floor_tex->pitch * floor_tex_y) + (floor_tex_x * 4); const auto floor_tex_ptr = static_cast<Uint8*>(floor_tex->pixels) + floor_tex_offset; // const SDL_Color ceiling_color = { ceiling_tex_ptr[0], ceiling_tex_ptr[1], ceiling_tex_ptr[2] }; SDL_Color floor_color = { floor_tex_ptr[0], floor_tex_ptr[1], floor_tex_ptr[2] }; // Make the floor darker. floor_color.r /= 2; floor_color.g /= 2; floor_color.b /= 2; // const auto ceiling_offset = (mSurface->pitch * (mSurface->h - y - 1)) + (mXCoordinate * 4); // const auto ceiling_ptr = static_cast<Uint8*>(mSurface->pixels) + ceiling_offset; // memcpy(ceiling_ptr, &ceiling_color, sizeof(ceiling_color)); const auto floor_offset = (mSurface->pitch * y) + (mXCoordinate * 4); const auto floor_ptr = static_cast<Uint8*>(mSurface->pixels) + floor_offset; memcpy(floor_ptr, &floor_color, sizeof(floor_color)); } }