Beispiel #1
0
        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);
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }