Загрузка данных


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;

namespace Gungeon2
{
    public class GameForm : Form
    {
        // ================= CORE =================
        Timer timer;
        Random rnd = new Random();

        // ================= MAP =================
        int[,] map;
        int tileSize = 32;
        int mapW = 40;
        int mapH = 25;

        class Room
        {
            public Rectangle rect;
            public bool cleared;
        }

        List<Room> rooms = new List<Room>();
        Room currentRoom;

        // ================= PLAYER =================
        float px, py;
        float speed = 4f;
        int playerHP = 5;

        bool up, down, left, right;

        // ================= BULLETS =================
        class Bullet
        {
            public float x, y;
            public float dx, dy;
        }

        List<Bullet> bullets = new List<Bullet>();

        // ================= ENEMIES =================
        class Enemy
        {
            public float x, y;
            public int hp = 3;
        }

        List<Enemy> enemies = new List<Enemy>();

        bool roomLocked = false;

        // ================= INIT =================
        public GameForm()
        {
            Text = "Enter the Gungeon 2.0";
            Size = new Size(900, 700);
            DoubleBuffered = true;

            timer = new Timer();
            timer.Interval = 16;
            timer.Tick += UpdateGame;
            timer.Start();

            GenerateDungeon();
        }

        // ================= GENERATION =================
        void GenerateDungeon()
        {
            map = new int[mapW, mapH];
            rooms.Clear();

            for (int x = 0; x < mapW; x++)
                for (int y = 0; y < mapH; y++)
                    map[x, y] = 0;

            for (int i = 0; i < 6; i++)
            {
                int w = rnd.Next(6, 10);
                int h = rnd.Next(6, 10);
                int x = rnd.Next(1, mapW - w - 1);
                int y = rnd.Next(1, mapH - h - 1);

                Room r = new Room
                {
                    rect = new Rectangle(x, y, w, h)
                };

                rooms.Add(r);

                for (int ix = x; ix < x + w; ix++)
                    for (int iy = y; iy < y + h; iy++)
                        map[ix, iy] = 1;
            }

            for (int i = 1; i < rooms.Count; i++)
                DrawCorridor(Center(rooms[i - 1].rect), Center(rooms[i].rect));

            SpawnPlayer();
        }

        void DrawCorridor(Point a, Point b)
        {
            for (int x = Math.Min(a.X, b.X); x <= Math.Max(a.X, b.X); x++)
                for (int i = -1; i <= 1; i++)
                    map[x, a.Y + i] = 1;

            for (int y = Math.Min(a.Y, b.Y); y <= Math.Max(a.Y, b.Y); y++)
                for (int i = -1; i <= 1; i++)
                    map[b.X + i, y] = 1;
        }

        Point Center(Rectangle r)
        {
            return new Point(r.X + r.Width / 2, r.Y + r.Height / 2);
        }

        // ================= SPAWN =================
        void SpawnPlayer()
        {
            var start = rooms[0].rect;

            px = (start.X + start.Width / 2) * tileSize;
            py = (start.Y + start.Height / 2) * tileSize;

            EnterRoom(rooms[0]);
        }

        void EnterRoom(Room r)
        {
            currentRoom = r;
            bullets.Clear();

            if (!r.cleared)
                SpawnEnemies(r);
        }

        void SpawnEnemies(Room r)
        {
            enemies.Clear();
            roomLocked = true;

            int count = 3;

            for (int i = 0; i < count; i++)
            {
                enemies.Add(new Enemy
                {
                    x = (r.rect.X + rnd.Next(r.rect.Width)) * tileSize,
                    y = (r.rect.Y + rnd.Next(r.rect.Height)) * tileSize
                });
            }
        }

        // ================= UPDATE =================
        void UpdateGame(object sender, EventArgs e)
        {
            MovePlayer();
            MoveEnemies();
            MoveBullets();

            CheckCombat();
            CheckRoomTransition();

            Invalidate();
        }

        void MovePlayer()
        {
            if (up) TryMove(0, -speed);
            if (down) TryMove(0, speed);
            if (left) TryMove(-speed, 0);
            if (right) TryMove(speed, 0);
        }

        void MoveEnemies()
        {
            foreach (var e in enemies)
            {
                e.x += Math.Sign(px - e.x) * 1.2f;
                e.y += Math.Sign(py - e.y) * 1.2f;
            }
        }

        void MoveBullets()
        {
            for (int i = bullets.Count - 1; i >= 0; i--)
            {
                bullets[i].x += bullets[i].dx;
                bullets[i].y += bullets[i].dy;

                if (bullets[i].x < 0 || bullets[i].y < 0)
                    bullets.RemoveAt(i);
            }
        }

        // ================= COMBAT =================
        void CheckCombat()
        {
            for (int i = enemies.Count - 1; i >= 0; i--)
            {
                foreach (var b in bullets)
                {
                    if (Distance(enemies[i].x, enemies[i].y, b.x, b.y) < 20)
                    {
                        enemies[i].hp--;
                        bullets.Remove(b);
                        break;
                    }
                }

                if (enemies[i].hp <= 0)
                    enemies.RemoveAt(i);
            }

            if (enemies.Count == 0)
            {
                roomLocked = false;
                currentRoom.cleared = true;
            }
        }

        float Distance(float x1, float y1, float x2, float y2)
        {
            return (float)Math.Sqrt((x1 - x2) * (x1 - x2) +
                                    (y1 - y2) * (y1 - y2));
        }

        // ================= ROOMS =================
        void CheckRoomTransition()
        {
            foreach (var r in rooms)
            {
                if (PlayerInRoom(r.rect))
                {
                    if (currentRoom != r)
                        EnterRoom(r);
                }
            }
        }

        bool PlayerInRoom(Rectangle r)
        {
            return r.Contains((int)(px / tileSize), (int)(py / tileSize));
        }

        // ================= MOVE =================
        void TryMove(float dx, float dy)
        {
            float nx = px + dx;
            float ny = py + dy;

            int tx = (int)(nx / tileSize);
            int ty = (int)(ny / tileSize);

            if (tx < 0 || ty < 0 || tx >= mapW || ty >= mapH)
                return;

            if (roomLocked)
                if (!currentRoom.rect.Contains(tx, ty))
                    return;

            if (map[tx, ty] == 1)
            {
                px = nx;
                py = ny;
            }
        }

        // ================= INPUT =================
        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.W) up = true;
            if (e.KeyCode == Keys.S) down = true;
            if (e.KeyCode == Keys.A) left = true;
            if (e.KeyCode == Keys.D) right = true;

            if (e.KeyCode == Keys.Space)
            {
                bullets.Add(new Bullet
                {
                    x = px,
                    y = py,
                    dx = 5,
                    dy = 0
                });
            }
        }

        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (e.KeyCode == Keys.W) up = false;
            if (e.KeyCode == Keys.S) down = false;
            if (e.KeyCode == Keys.A) left = false;
            if (e.KeyCode == Keys.D) right = false;
        }

        // ================= DRAW =================
        protected override void OnPaint(PaintEventArgs e)
        {
            Graphics g = e.Graphics;
            g.Clear(Color.Black);

            // MAP
            for (int x = 0; x < mapW; x++)
                for (int y = 0; y < mapH; y++)
                {
                    g.FillRectangle(
                        map[x, y] == 1 ? Brushes.Gray : Brushes.DarkSlateGray,
                        x * tileSize, y * tileSize,
                        tileSize, tileSize);
                }

            // ROOMS
            foreach (var r in rooms)
            {
                g.DrawRectangle(Pens.White,
                    r.rect.X * tileSize,
                    r.rect.Y * tileSize,
                    r.rect.Width * tileSize,
                    r.rect.Height * tileSize);
            }

            // ENEMIES
            foreach (var e2 in enemies)
                g.FillEllipse(Brushes.Red, e2.x, e2.y, 20, 20);

            // BULLETS
            foreach (var b in bullets)
                g.FillEllipse(Brushes.Yellow, b.x, b.y, 8, 8);

            // PLAYER
            g.FillEllipse(Brushes.Cyan, px, py, 25, 25);

            // UI
            g.DrawString($"Enemies: {enemies.Count}",
                new Font("Consolas", 10),
                Brushes.White, 10, 10);

            if (roomLocked)
                g.DrawString("ROOM LOCKED",
                    new Font("Consolas", 14),
                    Brushes.Red, 10, 40);
        }
    }
}