Загрузка данных
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Runtime.CompilerServices;
namespace ArkanoidGame
{
public partial class Form1 : Form
{
int ballX = 300;
int ballY = 300;
int dx = 8;
int dy = -8;
int paddleX = 400;
int paddleY = 600;
int paddleWidth = 120;
int paddleHeight = 15;
int score = 0;
int lives = 3;
int ballSize = 20;
bool gameStarted = false;
bool paused = false;
int currentLevel;
int reachedLevel = 1;
List<Rectangle> bricks = new List<Rectangle>();
public Form1(int level)
{
InitializeComponent();
currentLevel = level;
timer1.Interval = 16; // 16 мс для ~60 FPS
timer1.Tick += timer1_Tick;
this.DoubleBuffered = true;
currentLevel = level;
CreateLevel(level);
// Уберем лишний вызов Start(), так как таймер уже включен в InitializeComponent()
timer1.Start();
btnResume.Visible = false;
btnRestart.Visible = false;
btnMenu.Visible = false;
this.MouseMove += Form1_MouseMove;
// --- ИСПРАВЛЕНИЕ ---
// Не начинаем игру сразу. Ставим мяч на платформу и ставим игру на паузу.
gameStarted = false;
ResetBall();
// -------------------
if (gameStarted && bricks.Count == 0)
{
timer1.Stop();
gameStarted = false;
MessageBox.Show("You Win!");
}
gameStarted = false;
ResetBall();
}
private void Form1_Load(object sender, EventArgs e)
{
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
// мяч
g.FillEllipse(Brushes.White, ballX, ballY, ballSize, ballSize);
// платформа
g.FillRectangle(Brushes.Blue, paddleX, paddleY, paddleWidth, paddleHeight);
// UI
g.DrawString("Score: " + score, Font, Brushes.White, 10, 10);
g.DrawString("Lives: " + lives, Font, Brushes.White, 10, 30);
foreach (var b in bricks)
{
g.FillRectangle(Brushes.OrangeRed, b);
g.DrawRectangle(Pens.Black, b);
}
if (paused)
{
e.Graphics.FillRectangle(
new SolidBrush(Color.FromArgb(150, Color.Black)),
ClientRectangle
);
e.Graphics.DrawString(
"PAUSED",
new Font("Arial", 40),
Brushes.White,
300,
200
);
}
try
{
string imagePath = @"C:\Users\PC\Pictures\P.jpg";
this.BackgroundImage = Image.FromFile(imagePath);
this.BackgroundImageLayout = ImageLayout.Stretch;
}
catch (Exception ex)
{
}
this.StartPosition = FormStartPosition.CenterScreen;
this.ClientSize = new Size(850, 700);
this.Text = "Форма с изображением из файла";
}
private void timer1_Tick(object sender, EventArgs e)
{
if (!gameStarted || paused)
return;
ballX += dx;
ballY += dy;
// Отскок от боковых стен и потолка
if (ballX < 0 || ballX + ballSize > ClientSize.Width)
dx *= -1;
if (ballY < 0)
dy *= -1;
Rectangle ballRect = new Rectangle(ballX, ballY, ballSize, ballSize);
// Отскок от платформы с эффектом угла
Rectangle paddleRect = new Rectangle(paddleX, paddleY, paddleWidth, paddleHeight);
if (ballRect.IntersectsWith(paddleRect))
{
dy *= -1;
// Угол отскока зависит от точки удара по платформе
double relativeIntersectX = (paddleX + (paddleWidth / 2)) - ballX;
double normalizedIntersect = relativeIntersectX / (paddleWidth / 2);
double bounceAngle = normalizedIntersect * (5 * Math.PI / 12); // ~75 градусов в сумме
dx = (int)(-8 * Math.Sin(bounceAngle));
dy = (int)(-8 * Math.Cos(bounceAngle));
// Убедимся, что мяч не застрял в платформе
while (ballRect.IntersectsWith(paddleRect))
{
ballY -= dy / 2;
ballRect.Y = ballY;
}
}
// Проверка столкновений с кирпичами
for (int i = bricks.Count - 1; i >= 0; i--)
{
if (bricks[i].IntersectsWith(ballRect))
{
bricks.RemoveAt(i);
score += 10;
// Простая логика отскока: если мяч движется горизонтально к кирпичу - меняем dx,
// если вертикально - меняем dy.
bool movingLeft = dx < 0;
bool movingRight = dx > 0;
bool brickLeft = bricks[i].Right <= ballRect.Left && bricks[i].Right > ballRect.Left - Math.Abs(dx);
bool brickRight = bricks[i].Left >= ballRect.Right && bricks[i].Left < ballRect.Right + Math.Abs(dx);
if ((movingLeft && brickLeft) || (movingRight && brickRight))
dx *= -1;
bool movingUp = dy < 0;
bool brickTop = bricks[i].Bottom <= ballRect.Top && bricks[i].Bottom > ballRect.Top - Math.Abs(dy);
if ((movingUp && brickTop) || (!movingUp && bricks[i].Top >= ballRect.Bottom))
dy *= -1;
IncreaseSpeed();
break; // Удаляем только один кирпич за тик для стабильности физики
}
}
// Проверка проигрыша (мяч ушел за нижнюю границу)
if (ballY > ClientSize.Height + ballSize)
{
lives--;
if (lives <= 0)
{
timer1.Stop();
MessageBox.Show("Game Over! \nYour score: " + score);
SaveScore();
this.Close();
}
else
{
ResetBall();
}
}
Invalidate();
}
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
if (keyData == Keys.Escape)
{
paused = !paused;
timer1.Enabled = !paused;
btnResume.Visible = true;
btnRestart.Visible = true;
btnMenu.Visible = true;
btnResume.Enabled = true;
btnRestart.Enabled = true;
btnMenu.Enabled = true;
btnResume.BringToFront();
btnRestart.BringToFront();
btnMenu.BringToFront();
}
return base.ProcessCmdKey(ref msg, keyData);
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
paddleX = e.X - paddleWidth / 2;
}
private void CreateLevel(int level)
{
bricks.Clear();
switch (level)
{
case 1:
SimpleLevel();
break;
case 2:
PyramidLevel();
break;
case 3:
WallsLevel();
break;
case 4:
CheckerLevel();
break;
case 5:
HardLevel();
break;
case 6:
CrossLevel();
break;
case 7:
RandomLevel();
break;
}
}
void SimpleLevel()
{
for (int i = 0; i < 4; i++)
for (int j = 0; j < 8; j++)
bricks.Add(new Rectangle(100 + j * 80, 50 + i * 30, 70, 20));
}
void PyramidLevel()
{
for (int i = 0; i < 5; i++)
for (int j = 0; j <= i; j++)
bricks.Add(new Rectangle(300 + j * 80 - i * 40, 50 + i * 30, 70, 20));
}
void IncreaseSpeed()
{
dx += Math.Sign(dx);
dy += Math.Sign(dy);
dx = Math.Max(Math.Min(dx, 12), -12);
dy = Math.Max(Math.Min(dy, 12), -12);
}
void WallsLevel()
{
for (int i = 0; i < 6; i++)
{
bricks.Add(new Rectangle(100, 50 + i * 30, 70, 20));
bricks.Add(new Rectangle(700, 50 + i * 30, 70, 20));
}
}
void CheckerLevel()
{
for (int i = 0; i < 6; i++)
for (int j = 0; j < 10; j++)
if ((i + j) % 2 == 0)
bricks.Add(new Rectangle(100 + j * 70, 50 + i * 30, 65, 20));
}
void HardLevel()
{
for (int i = 0; i < 7; i++)
for (int j = 0; j < 10; j++)
bricks.Add(new Rectangle(80 + j * 75, 40 + i * 25, 70, 20));
}
void CrossLevel()
{
for (int i = 0; i < 7; i++)
{
bricks.Add(new Rectangle(400, 50 + i * 30, 70, 20));
bricks.Add(new Rectangle(200 + i * 70, 200, 70, 20));
}
}
void RandomLevel()
{
Random rnd = new Random();
for (int i = 0; i < 30; i++)
{
int x = rnd.Next(50, 700);
int y = rnd.Next(50, 300);
bricks.Add(new Rectangle(x, y, 70, 20));
}
}
void SaveScore()
{
string line = UserSession.Username + ";" + reachedLevel;
File.AppendAllText("scores.txt", line + Environment.NewLine);
}
private void btnResume_Click(object sender, EventArgs e)
{
paused = false;
btnResume.Visible = false;
btnRestart.Visible = false;
btnMenu.Visible = false;
timer1.Start();
}
void ResetBall()
{
ballX = paddleX + paddleWidth / 2 - ballSize / 2; // По центру платформы
ballY = paddleY - ballSize; // Чуть выше платформы
// Небольшая пауза перед запуском, чтобы игрок успел подготовиться
paused = true;
// Используем Task.Delay для асинхронной паузы, чтобы не блокировать UI поток
Task.Delay(1500).ContinueWith(t => { paused = false; });
}
private void btnRestart_Click(object sender, EventArgs e)
{
lives = 3;
score = 0;
CreateLevel(currentLevel);
ballX = 300;
ballY = 300;
dx = 5;
dy = -5;
paused = false;
btnResume.Visible = false;
btnRestart.Visible = false;
btnMenu.Visible = false;
timer1.Start();
}
private void btnMenu_Click(object sender, EventArgs e)
{
MainMenuForm menu = new MainMenuForm();
menu.Show();
this.Close();
}
}
}