public void Render() { float ceilingHeight = 2f, floorHeight = 2f; double[] zBuffer = new double[Program.ScreenWidth]; for (int x = 0; x < Program.ScreenWidth; x += detailLevel) { double cameraX = 2 * x / (double)Program.ScreenWidth - 1; double rayPosX = Position.X, rayPosY = Position.Y; double rayDirX = dirX + planeX * cameraX, rayDirY = dirY + planeY * cameraX; int mapX = (int)rayPosX, mapY = (int)rayPosY; double sideDistX, sideDistY; double deltaDistX = Math.Sqrt(1 + (rayDirY * rayDirY) / (rayDirX * rayDirX)), deltaDistY = Math.Sqrt(1 + (rayDirX * rayDirX) / (rayDirY * rayDirY)); int stepX, stepY; byte side = 0; bool hit = false; if (rayDirX < 0) { stepX = -1; sideDistX = (rayPosX - mapX) * deltaDistX; } else { stepX = 1; sideDistX = (mapX + 1.0 - rayPosX) * deltaDistX; } if (rayDirY < 0) { stepY = -1; sideDistY = (rayPosY - mapY) * deltaDistY; } else { stepY = 1; sideDistY = (mapY + 1.0 - rayPosY) * deltaDistY; } while (!hit) { if (sideDistX < sideDistY) { sideDistX += deltaDistX; mapX += stepX; side = 0; } else { sideDistY += deltaDistY; mapY += stepY; side = 1; } if (WorldMap[mapX, mapY] != ' ') { hit = true; } } double wallDist = 0; if (side == 0) { wallDist = Math.Abs((mapX - rayPosX + (1 - stepX) / 2) / rayDirX); } else { wallDist = Math.Abs((mapY - rayPosY + (1 - stepY) / 2) / rayDirY); } zBuffer[x] = wallDist; int lineHeight = 1; if (wallDist != 0) { lineHeight = Math.Abs((int)((Program.ScreenHeight - 72) / wallDist)); } int drawStart = -(int)((float)lineHeight / ceilingHeight) + (Program.ScreenHeight - 72) / 2; if (drawStart < 0) { drawStart = 0; } int drawEnd = (int)((float)lineHeight / floorHeight) + (Program.ScreenHeight - 72) / 2; if (drawEnd >= (Program.ScreenHeight - 72)) { drawEnd = (Program.ScreenHeight - 72) - 1; } int textureIndex = 0; if (char.IsNumber(WorldMap[mapX, mapY])) { textureIndex = int.Parse(WorldMap[mapX, mapY].ToString()); } double wallX; if (side == 1) { wallX = rayPosX + ((mapY - rayPosY + (1 - stepY) / 2) / rayDirY) * rayDirX; } else { wallX = rayPosY + ((mapX - rayPosX + (1 - stepX) / 2) / rayDirX) * rayDirY; } wallX -= Math.Floor((wallX)); int texX = (int)(wallX * (double)(texWidth)); if (side == 0 && rayDirX > 0) { texX = texWidth - texX - 1; } if (side == 1 && rayDirY < 0) { texX = texWidth - texX - 1; } for (int y = drawStart; y < drawEnd; y += detailLevel) { int d = y * 256 - (Program.ScreenHeight - 72) * 128 + lineHeight * 128; int texY = ((d * texHeight) / lineHeight) / 256; if (texX < 0) { texX = 0; } if (texY < 0) { texY = 0; } UInt32 color = wallTextures[textureIndex].Pixels[wallTextures[textureIndex].Width - 1 - texX, texY]; if (side == 1) { color = (color >> 1) & 8355711; } for (int u = 0; u < detailLevel; u++) { for (int j = 0; j < detailLevel; j++) { ScreenBuffer.SetPixel(x + u, y + j, color); } } } } int h = (Program.ScreenHeight - 72), w = Program.ScreenWidth; List <int> sortedList = SortSprites(); for (int i = sortedList.Count - 1; i >= 0; i--) { if (!ActorList[sortedList[i]].Remove) { double spriteX = ActorList[sortedList[i]].Position.X - Position.X, spriteY = ActorList[sortedList[i]].Position.Y - Position.Y; double invDet = 1.0 / (planeX * dirY - dirX * planeY); double transformX = invDet * (dirY * spriteX - dirX * spriteY); double transformY = invDet * (-planeY * spriteX + planeX * spriteY); if (transformY > 0) { int screenOffset = (int)(ActorList[sortedList[i]].letsPrentendThisIsZ / transformY); int spriteScreenX = (int)((Program.ScreenWidth / 2) * (1 + transformX / transformY)); int spriteHeight = Math.Abs((int)((h / transformY))) / ActorList[sortedList[i]].Scale; int drawStartY = (-spriteHeight / 2 + h / 2) + screenOffset; if (drawStartY < 0) { drawStartY = 0; } int drawEndY = spriteHeight / 2 + h / 2 + screenOffset; if (drawEndY >= h) { drawEndY = h - 1; } int spriteWidth = Math.Abs((int)(h / (transformY))) / ActorList[sortedList[i]].Scale; int drawStartX = (-spriteWidth / 2 + spriteScreenX); if (drawStartX < 0) { drawStartX = 0; } int drawEndX = spriteWidth / 2 + spriteScreenX; if (drawEndX >= w) { drawEndX = w - 1; } for (int stripe = drawStartX; stripe < drawEndX; stripe++) { int texX = (int)(256 * (stripe - (-spriteWidth / 2 + spriteScreenX)) * texWidth / spriteWidth) / 256; if (transformY > 0 && stripe > 0 && stripe < w && transformY < zBuffer[stripe]) { for (int y = drawStartY; y < drawEndY; ++y) { int d = (y - screenOffset) * 256 - h * 128 + spriteHeight * 128; int texY = ((d * texHeight) / spriteHeight) / 256; uint color = ActorList[sortedList[i]].Sprite.Texture.Pixels[Math.Abs(texX), Math.Abs(texY)]; if (color != 4294967295) { for (int u = 0; u < detailLevel; u++) { for (int j = 0; j < detailLevel; j++) { ScreenBuffer.SetPixel(stripe + u, y + j, color); } } } } } } } } } }