Загрузка данных
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);
}
}
}