示例#1
0
 public static Color Divide(this Color c, float n)
 {
     return(new Color(
                (byte)(c.R / n),
                (byte)(c.G / n),
                (byte)(c.B / n)));
 }
示例#2
0
        private void LoadTextures()
        {
            Texture allWalls = new Texture(ContentPath + "walls.jpeg");
            int     Columns  = (int)allWalls.Width / TextureSize;
            int     Rows     = (int)allWalls.Height / TextureSize;

            // cookie undid his stupid! :D
            WallTextures = new Texture[Columns * Rows];
            for (int cellY = 0; cellY < Rows; cellY++)
            {
                for (int cellX = 0; cellX < Columns; cellX++)
                {
                    WallTextures[(Columns * cellY) + cellX] = new Texture((ushort)TextureSize, (ushort)TextureSize);
                    for (int texX = 0; texX < TextureSize; texX++)
                    {
                        for (int texY = 0; texY < TextureSize; texY++)
                        {
                            Color wallPixel = allWalls.GetPixel(cellX * TextureSize + texX,
                                                                cellY * TextureSize + texY);
                            // TODO: Workaround for chroma edge case, remove this line when fixed
                            wallPixel = new Color(wallPixel.A, wallPixel.B, wallPixel.G, wallPixel.R);
                            WallTextures[(Columns * cellY) + cellX].SetPixel(
                                texX, texY,
                                wallPixel
                                );
                        }
                    }
                    WallTextures[(Columns * cellY) + cellX].Flush();
                }
            }
        }
示例#3
0
 public static void Rectangle(
     this RenderContext context,
     ShapeMode mode,
     Vector2 position,
     Size size,
     Color color
     ) => context.Rectangle(mode, position, size.Width, size.Height, color);
示例#4
0
 public static void Circle(
     this RenderContext context,
     ShapeMode mode,
     Vector2 position,
     float radius,
     Color color
     ) => context.Circle(mode, position.X, position.Y, radius, color);
示例#5
0
 public Label(Vector2 position, string text, TrueTypeFont font = null, int fontSize = 12) : base(position, Vector2.One)
 {
     Text      = text;
     Color     = Color.White;
     Font      = font ?? new TrueTypeFont(UiContentLoader.Instance.DefaultFontPath, fontSize);
     Font.Size = fontSize;
 }
示例#6
0
 public static void Rectangle(
     this RenderContext context,
     ShapeMode mode,
     Vector2 position,
     float width,
     float height,
     Color color
     ) => context.Rectangle(mode, position.X, position.Y, width, height, color);
示例#7
0
 public static void Triangle(
     this RenderContext context,
     ShapeMode mode,
     Vector2 a,
     Vector2 b,
     Vector2 c,
     Color color
     ) => context.Triangle(mode, a.X, a.Y, b.X, b.Y, c.X, c.Y, color);
示例#8
0
 public static void Ellipse(
     this RenderContext context,
     ShapeMode mode,
     Vector2 position,
     Vector2 radii,
     float rotation,
     Color color
     ) => context.Ellipse(mode, position.X, position.Y, radii.X, radii.Y, rotation, color);
示例#9
0
 public static void DrawString(
     this RenderContext context,
     IFontProvider font,
     string text,
     float x,
     float y,
     Color color
     ) => context.DrawString(font, text, x, y, (_, _, p) => new(p) { Color = color });
示例#10
0
 public static void Arc(
     this RenderContext context,
     ShapeMode mode,
     Vector2 position,
     float radius,
     float startAngle,
     float endAngle,
     Color color
     ) => context.Arc(mode, position.X, position.Y, radius, startAngle, endAngle, color);
示例#11
0
        /// <summary>
        /// Draws a rectangle used for HUD elements.
        /// </summary>
        /// <param name="context">RenderContext to draw onto</param>
        /// <param name="rect">The rectangle to draw</param>
        /// <param name="lineWidth">How thicc the line should be</param>
        /// <param name="whiteOrCopyPen">0 = normal colors, 1 = white and right half isn't drawn, 2 = both halves are dark</param>
        private void DrawHudRectangle(RenderContext context, Rectangle rect, int lineWidth, int whiteOrCopyPen)
        {
            float oldThickness = Graphics.LineThickness;

            Graphics.LineThickness = 1;

            rect.X++;
            rect.Width--;

            // Top and left lines
            Color colorToDraw = whiteOrCopyPen == 1 ? Constants.RightRectangleColor : Constants.LeftRectangleColor;

            for (int i = 0; i < lineWidth; i++)
            {
                context.Line(new Vector2(rect.X, rect.Y + i),
                             new Vector2(rect.X + rect.Width - i - 1, rect.Y + i),
                             colorToDraw);

                context.Line(new Vector2(rect.X + i, rect.Y),
                             new Vector2(rect.X + i, rect.Y + rect.Height - i - 1),
                             colorToDraw);
            }

            if (whiteOrCopyPen != 1)
            {
                // Right and bottom lines
                Color newColorToDraw = whiteOrCopyPen < 2 ? Constants.RightRectangleColor : Constants.LeftRectangleColor;
                for (int i = 0; i < lineWidth; i++)
                {
                    context.Line(new Vector2(rect.X + rect.Width - i, rect.Y + i + 1),
                                 new Vector2(rect.X + rect.Width - i, rect.Y + rect.Height),
                                 newColorToDraw);

                    context.Line(new Vector2(rect.X + rect.Width, rect.Y + rect.Height - i - 1),
                                 new Vector2(rect.X + i, rect.Y + rect.Height - i),
                                 newColorToDraw);
                }
            }

            Graphics.LineThickness = oldThickness;
        }
示例#12
0
 public static void Rectangle(
     this RenderContext context,
     ShapeMode mode,
     RectangleF rectangle,
     Color color
     ) => context.Rectangle(mode, rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height, color);
示例#13
0
 public static void Line(
     this RenderContext context,
     Vector2 start,
     Vector2 end,
     Color color
     ) => context.Line(start.X, start.Y, end.X, end.Y, color);
示例#14
0
 public static void Clear(
     this RenderContext context,
     Color color
     ) => context.Clear(color.R, color.G, color.B, color.A);
示例#15
0
        protected override void Draw(RenderContext context)
        {
            context.Clear(Color.Gray);

            int leftRayX = 0, leftRayY = 0, rightRayX = 0, rightRayY = 0;

            List <Object> spritesDrawn = new List <Object>();

            for (int x = 0; x <= ScreenWidth; x += ScreenWidthDivision)
            {
                // Calculate the direction needed for the ray, and the cam space
                double cameraX = 2 * x / (double)ScreenWidth - 1;
                double rayDirX = DirX + PlaneX * cameraX;
                double rayDirY = DirY + PlaneY * cameraX;

                // Where is the ray located in the map?
                int mapX = (int)PlayerPos.X;
                int mapY = (int)PlayerPos.Y;

                // These variables tell us how far until the next X side of the matrix
                // Or the next Y side, relative to the current position
                double sideDistX;
                double sideDistY;

                // Same principle as the sideDistX/Y except its from the *last* X or Y side
                // Also prevent deviding by 0 (does C# even care about this? Should look that up)
                double deltaDistX = (rayDirY == 0) ? 0 : ((rayDirX == 0) ? 1 : Abs(1 / rayDirX));
                double deltaDistY = (rayDirX == 0) ? 0 : ((rayDirY == 0) ? 1 : Abs(1 / rayDirY));
                double perpWallDist;

                // Either -1 or 1 depending on what direction we need to step in next
                int stepX;
                int stepY;

                int hit  = 0; // Did we hit a wall?
                int side = 0; // Which side we hit the wall on (North/South or East/West)

                // Actually calculate side and directions
                if (rayDirX < 0)
                {
                    stepX     = -1;
                    sideDistX = (PlayerPos.X - mapX) * deltaDistX;
                }
                else
                {
                    stepX     = 1;
                    sideDistX = (mapX + 1.0 - PlayerPos.X) * deltaDistX;
                }
                if (rayDirY < 0)
                {
                    stepY     = -1;
                    sideDistY = (PlayerPos.Y - mapY) * deltaDistY;
                }
                else
                {
                    stepY     = 1;
                    sideDistY = (mapY + 1.0 - PlayerPos.Y) * deltaDistY;
                }

                // Finally, Actually, do the raycasting using the DDA algorithm
                while (hit == 0)
                {
                    // Jump to the next map square/X direction/Y direction
                    if (sideDistX < sideDistY)
                    {
                        sideDistX += deltaDistX;
                        mapX      += stepX;
                        side       = 0;
                    }
                    else
                    {
                        sideDistY += deltaDistY;
                        mapY      += stepY;
                        side       = 1;
                    }

                    if (Abs(mapX) > 255 || Abs(mapY) > 255)
                    {
                        break;
                    }
                    if (mapX >= WorldMap.GetLength(0) || mapY >= WorldMap.GetLength(1))
                    {
                        continue;
                    }
                    if (mapX < 0 || mapY < 0)
                    {
                        continue;
                    }

                    // Check if ray has hit a wall
                    if (WorldMap[mapX, mapY] > 0)
                    {
                        hit = 1;
                    }
                    if (RenderSprites)
                    {
                        // Check if a sprite is in view
                        if (SpriteMap[mapX, mapY] != null)
                        {
                            if (!spritesDrawn.Contains(SpriteMap[mapX, mapY]))
                            {
                                // Calculate sprite distance from the player so we can render it properly
                                Object sprite = SpriteMap[mapX, mapY];
                                double spriteDist;
                                // Calculate distance projected on camera direction (Euclidean distance will give fisheye effect!)
                                if (side == 0)
                                {
                                    spriteDist = (mapX - PlayerPos.X + (1 - stepX) / 2) / rayDirX;
                                }
                                else
                                {
                                    spriteDist = (mapY - PlayerPos.Y + (1 - stepY) / 2) / rayDirY;
                                }
                                int usableDist = (int)(spriteDist * 1000);
                                sprite.ZIndex = usableDist;
                                spritesDrawn.Add(sprite);
                                context.Batch(() => sprite.Draw(
                                                  context,
                                                  PlayerPos,
                                                  new Vector2((float)DirX, (float)DirY),
                                                  new Vector2((float)PlaneX, (float)PlaneY),
                                                  new Vector2(ScreenWidth, ScreenHeight)
                                                  ), (int)sprite.ZIndex);
                            }
                        }
                    }
                }

                if (hit == 0)
                {
                    continue;
                }

                if (x == 0)
                {
                    leftRayX = mapX;
                    leftRayY = mapY;
                }
                else if (x == ScreenWidth)
                {
                    rightRayX = mapX;
                    rightRayY = mapY;
                }

                // Calculate distance projected on camera direction (Euclidean distance will give fisheye effect!)
                if (side == 0)
                {
                    perpWallDist = (mapX - PlayerPos.X + (1 - stepX) / 2) / rayDirX;
                }
                else
                {
                    perpWallDist = (mapY - PlayerPos.Y + (1 - stepY) / 2) / rayDirY;
                }

                // Calculate height of the strip that we draw to the screen
                int lineHeight = (int)(ScreenHeight / perpWallDist);

                // Calculate lowest and highest pixel to fill in current stripe
                int drawStart = -lineHeight / 2 + ScreenHeight / 2;
                if (drawStart < 0)
                {
                    drawStart = 0;
                }
                int drawEnd = lineHeight / 2 + ScreenHeight / 2;
                if (drawEnd >= ScreenHeight)
                {
                    drawEnd = ScreenHeight - 1;
                }

                // Calculate texture rendering
                int texNum = WorldMap[mapX, mapY] - 1; // Subtract 1 so we are 0 indexed

                // Calculate where the wall was hit
                double wallX;
                if (side == 0)
                {
                    wallX = PlayerPos.Y + perpWallDist * rayDirY;
                }
                else
                {
                    wallX = PlayerPos.X + perpWallDist * rayDirX;
                }
                wallX -= Floor(wallX);

                // Calculate the X coordinate of the txture
                int texX = (int)(wallX * TextureSize);
                if (side == 0 && rayDirX > 0)
                {
                    texX = TextureSize - texX - 1;
                }
                if (side == 1 && rayDirY < 0)
                {
                    texX = TextureSize - texX - 1;
                }

                Color color;

                if (!FlatRender)
                {
                    // Draw textures using strips instead of pixels
                    int       texY            = Min(drawStart, -(lineHeight - ScreenHeight) / 2);
                    Texture   stripTex        = WallTextures[texNum];
                    Rectangle SourceRectangle = new Rectangle(texX, 0, ScreenWidthDivision, TextureSize);
                    Vector2   Position        = new Vector2(x, texY);
                    Vector2   Scale           = new Vector2(1, (float)lineHeight / TextureSize);
                    Color     StripColor      = side == 1 ? Color.Gray : Color.White;
                    int       usableDist      = (int)(perpWallDist * 1000);
                    context.Batch(() =>
                    {
                        if (!stripTex.ColorMask.Equals(StripColor))
                        {
                            stripTex.ColorMask = StripColor;
                        }
                        context.DrawTexture(stripTex, Position, Scale, Vector2.Zero, 0, SourceRectangle);
                    }, usableDist);
                }
                else
                {
                    // Debugging wall colors for flat renderer
                    color = (WorldMap[mapX, mapY]) switch
                    {
                        1 => Color.Red,
                        2 => Color.Green,
                        3 => Color.Blue,
                        4 => Color.Beige,
                        5 => Color.Aquamarine,
                        6 => Color.HotPink,
                        7 => Color.Purple,
                        8 => Color.Brown,
                        _ => Color.Yellow,
                    };

                    // Darken the color to create perspective
                    if (side == 1)
                    {
                        color.R /= 2;
                        color.G /= 2;
                        color.B /= 2;
                    }
                    int usableDist = (int)(perpWallDist * 1000);

                    // Actually draw the pixels of the stripe as a vertical line
                    DrawColorStrip(context, x, drawStart, drawEnd, usableDist, color);
                }
            }

            if (RenderSprites)
            {
                foreach (Enemy enemy in EnemyList)
                {
                    // Calculate distance projected on camera direction (Euclidean distance will give fisheye effect!)
                    float dX = PlayerPos.X - enemy.PosX;
                    float dY = PlayerPos.Y - enemy.PosY;
                    // Calculate sprite distance from the player so we can render it properly
                    double spriteDist;
                    spriteDist = Sqrt(dX * dX + dY * dY);
                    int usableDist = (int)(spriteDist * 1000);
                    enemy.ZIndex = usableDist;
                    context.Batch(() => enemy.Draw(
                                      context,
                                      PlayerPos,
                                      new Vector2((float)DirX, (float)DirY),
                                      new Vector2((float)PlaneX, (float)PlaneY),
                                      new Vector2(ScreenWidth, ScreenHeight)
                                      ), (int)enemy.ZIndex);
                }
            }

            context.DrawBatch(DrawOrder.FrontToBack);

            if (MiniMap)
            {
                // Move these to meta variables later, im tired
                Vector2 MinimapSize     = new Vector2(300, 300);
                Vector2 MinimapPosition = new Vector2(ScreenWidth - MinimapSize.X, 0);
                // Render minimap
                for (int x = 0; x < MapWidth; x++)
                {
                    for (int y = 0; y < MapHeight; y++)
                    {
                        // Debugging wall colors for flat renderer
                        var color = (WorldMap[y, x]) switch
                        {
                            1 => Color.Red,
                            2 => Color.Green,
                            3 => Color.Blue,
                            4 => Color.Beige,
                            5 => Color.Aquamarine,
                            6 => Color.HotPink,
                            7 => Color.Purple,
                            8 => Color.Brown,
                            _ => Color.Yellow,
                        };
                        Vector2 tileSize = new Vector2(MinimapSize.X / MapWidth, MinimapSize.Y / MapHeight);
                        Vector2 tilePos  = new Vector2(tileSize.X * x, tileSize.Y * y);
                        context.Rectangle(ShapeMode.Fill, MinimapPosition + tilePos, tileSize.X, tileSize.Y, color);
                    }
                }

                Vector2 tileRefSize   = new Vector2(MinimapSize.X / MapWidth, MinimapSize.Y / MapHeight);
                Vector2 playerDotSize = tileRefSize / 2;
                Vector2 playerDotPos  = new Vector2(tileRefSize.X * PlayerPos.Y, tileRefSize.Y * PlayerPos.X);
                playerDotPos -= playerDotSize / 2;
                context.Rectangle(ShapeMode.Fill, MinimapPosition + playerDotPos, playerDotSize.X, playerDotSize.Y, Color.Red);

                context.Line(MinimapPosition + playerDotPos + (playerDotSize / 2),
                             MinimapPosition + new Vector2(tileRefSize.X * leftRayY, tileRefSize.Y * leftRayX),
                             Color.Red
                             );
                context.Line(MinimapPosition + playerDotPos + (playerDotSize / 2),
                             MinimapPosition + new Vector2(tileRefSize.X * rightRayY, tileRefSize.Y * rightRayX),
                             Color.Red
                             );

                foreach (Enemy enemy in EnemyList)
                {
                    Vector2 enemyDotSize = tileRefSize / 2;
                    Vector2 enemyDotPos  = new Vector2(tileRefSize.X * enemy.PosY, tileRefSize.Y * enemy.PosX);
                    enemyDotPos -= enemyDotSize / 2;
                    context.Rectangle(ShapeMode.Fill, MinimapPosition + enemyDotPos, enemyDotSize.X, enemyDotSize.Y, Color.LimeGreen);
                }
            }

            DebugText = $"{PerformanceCounter.FPS} FPS\n" + DebugText;
            context.DrawString(DebugFont, DebugText, Vector2.Zero, (c, i, p, g) => new GlyphTransformData()
            {
                Color = Color.White
            });
        }
示例#16
0
 private void DrawColorStrip(RenderContext context, int screenX, int drawStart, int drawEnd, int z, Color color)
 {
     if (drawEnd - drawStart <= 0)
     {
         return;
     }
     context.Batch(() => context.Line(new Vector2(screenX, drawStart), new Vector2(screenX, drawEnd), color), z);
 }
示例#17
0
 public static void Pixel(
     this RenderContext context,
     Vector2 position,
     Color color
     ) => context.Pixel(position.X, position.Y, color);