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


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

namespace GungeonLike
{
    public partial class Form1 : Form
    {
        // ================= MAP =================
        int[,] map;
        int tileSize = 32;
        int mapW = 40;
        int mapH = 25;

        // ================= ROOMS =================
        enum RoomType { Start, Fight, Boss }

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

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

        // ================= PLAYER =================
        float px, py;
        float speed = 4f;
        bool up, down, left, right;

        // ================= ENEMIES =================
        List<PointF> enemies = new List<PointF>();

        // ================= GAME =================
        Timer timer;
        Random rnd = new Random();
        bool roomLocked = false;

        enum GameState { Menu, Playing }
        GameState state = GameState.Menu;

        // ================= INIT =================
        public Form1()
        {
            InitializeComponent();
            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;

            // rooms
            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);

                RoomType type = RoomType.Fight;
                if (i == 0) type = RoomType.Start;
                if (i == 5) type = RoomType.Boss;

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

                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++)
                    if (InMap(x, a.Y + 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++)
                    if (InMap(b.X + i, y))
                        map[b.X + i, y] = 1;
        }

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

        bool InMap(int x, int y)
        {
            return x >= 0 && y >= 0 && x < mapW && y < mapH;
        }

        // ================= 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;

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

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

            int count = (r.type == RoomType.Boss) ? 6 : 3;

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

        // ================= UPDATE =================
        void UpdateGame(object sender, EventArgs e)
        {
            if (state != GameState.Playing)
            {
                Invalidate();
                return;
            }

            MovePlayer();

            MoveEnemies();

            CheckRoomClear();

            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()
        {
            for (int i = 0; i < enemies.Count; i++)
            {
                var e = enemies[i];

                e.X += Math.Sign(px - e.X) * 1.2f;
                e.Y += Math.Sign(py - e.Y) * 1.2f;

                enemies[i] = e;
            }
        }

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

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

        bool PlayerInRoom(Rectangle r)
        {
            int tx = (int)(px / tileSize);
            int ty = (int)(py / tileSize);

            return r.Contains(tx, ty);
        }

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

            if (CanMove(nx, ny))
            {
                px = nx;
                py = ny;
            }
        }

        bool CanMove(float x, float y)
        {
            if (map == null) return false;

            int tx = (int)(x / tileSize);
            int ty = (int)(y / tileSize);

            if (!InMap(tx, ty)) return false;

            if (roomLocked && currentRoom != null)
            {
                if (!currentRoom.rect.Contains(tx, ty))
                    return false;
            }

            return map[tx, ty] == 1;
        }

        // ================= 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.Enter)
                state = GameState.Playing;

            if (e.KeyCode == Keys.R)
                GenerateDungeon();
        }

        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);

            if (state == GameState.Menu)
            {
                g.DrawString("GUNGEON CORE",
                    new Font("Arial", 28, FontStyle.Bold),
                    Brushes.White, 120, 100);

                g.DrawString("ENTER - Start",
                    new Font("Consolas", 14),
                    Brushes.Gray, 150, 200);

                return;
            }

            if (map != null)
            {
                for (int x = 0; x < mapW; x++)
                {
                    for (int y = 0; y < mapH; y++)
                    {
                        Brush b = map[x, y] == 0
                            ? Brushes.DarkSlateGray
                            : Brushes.Gray;

                        g.FillRectangle(b,
                            x * tileSize,
                            y * tileSize,
                            tileSize,
                            tileSize);
                    }
                }
            }

            // rooms outline
            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);
            }

            // 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);
        }
    }
}