OurGamesForCourse
206 строк · 7.3 Кб
1using System.Text;
2using System.Windows;
3using System.Windows.Controls;
4using System.Windows.Data;
5using System.Windows.Documents;
6using System.Windows.Input;
7using System.Windows.Media;
8using System.Windows.Media.Imaging;
9using System.Windows.Navigation;
10using System.Windows.Shapes;
11
12namespace PauchiaUkladka;
13
14/// <summary>
15/// Interaction logic for MainWindow.xaml
16/// </summary>
17public partial class MainWindow : Window
18{
19private readonly ImageSource[] tileImages = new ImageSource[]
20{
21new BitmapImage(new Uri("Assets/TileEmpty.png", UriKind.Relative)),
22new BitmapImage(new Uri("Assets/TileCyan.png", UriKind.Relative)),
23new BitmapImage(new Uri("Assets/TileBlue.png", UriKind.Relative)),
24new BitmapImage(new Uri("Assets/TileOrange.png", UriKind.Relative)),
25new BitmapImage(new Uri("Assets/TileYellow.png", UriKind.Relative)),
26new BitmapImage(new Uri("Assets/TileGreen.png", UriKind.Relative)),
27new BitmapImage(new Uri("Assets/TilePurple.png", UriKind.Relative)),
28new BitmapImage(new Uri("Assets/TileRed.png", UriKind.Relative))
29};
30
31private readonly ImageSource[] blockImages = new ImageSource[]
32{
33new BitmapImage(new Uri("Assets/Block-Empty.png", UriKind.Relative)),
34new BitmapImage(new Uri("Assets/Block-I.png", UriKind.Relative)),
35new BitmapImage(new Uri("Assets/Block-J.png", UriKind.Relative)),
36new BitmapImage(new Uri("Assets/Block-L.png", UriKind.Relative)),
37new BitmapImage(new Uri("Assets/Block-O.png", UriKind.Relative)),
38new BitmapImage(new Uri("Assets/Block-S.png", UriKind.Relative)),
39new BitmapImage(new Uri("Assets/Block-T.png", UriKind.Relative)),
40new BitmapImage(new Uri("Assets/Block-Z.png", UriKind.Relative))
41};
42
43private readonly Image[,] imageControls;
44
45private readonly int maxDelay = 1000;
46private readonly int minDelay = 100;
47private readonly int delayDecrease = 25;
48
49private GameState gameState = new GameState();
50
51public MainWindow()
52{
53InitializeComponent();
54imageControls = SetupGameCanvas(gameState.GameGrid);
55}
56
57private Image[,] SetupGameCanvas(GameGrid grid) //Двумерный массив для отрисовки поля
58{
59Image[,] imageControls = new Image[grid.Rows, grid.Colums]; //Создаём поле
60int cellSize = 25; //Размер каждого блока (размер поля 250 на 500). Если разделить на 25 — 10 на 20.
61
62for (int r = 0; r < grid.Rows; r++) //Перебираем строки
63{
64for (int c = 0; c < grid.Colums; c++) //Перебираем колонки (вместе со строками — перебираем каждый блок)
65{
66Image imageControl = new Image //Создаём новую картинку с заданными размерами
67{
68Width = cellSize, //Размеры указываем по 25 пикселей в ширину
69Height = cellSize //и высоту
70};
71
72Canvas.SetTop(imageControl, (r - 2) * cellSize + 10); //Отрисовываем поле начиная сверзху и скрываем 2 строки в самом верху
73Canvas.SetLeft(imageControl, c * cellSize); //Отрисовываем поле начиная слева (обычно, указывается 2 направления отрисовки в 2D и три в 3D) и по размерам — равно количеству колонок
74GameCanvas.Children.Add(imageControl); //Отрисовка по заданным параметрам...
75imageControls[r, c] = imageControl; //... размером r на c (то есть числом наших строк и столбцов)
76}
77}
78
79return imageControls; //Возврат отрисованного изображения
80}
81
82private void DrawGrid(GameGrid grid)
83{
84for (int r = 0; r < grid.Rows; r++)
85{
86for (int c = 0; c < grid.Colums; c++)
87{
88int id = grid[r, c];
89imageControls[r, c].Opacity = 1;
90imageControls[r, c].Source = tileImages[id];
91}
92}
93}
94
95private void DrawBlock(Block block)
96{
97foreach (Position p in block.TilePositions())
98{
99imageControls[p.Row, p.Column].Opacity = 1;
100imageControls[p.Row, p.Column].Source = tileImages[block.Id];
101}
102}
103
104private void DrawNextBlock(BlockQueue blockQueue)
105{
106Block next = blockQueue.NextBlock;
107NextImage.Source = blockImages[next.Id];
108}
109
110private void DrawHeldBlock(Block heldBlock)
111{
112if (heldBlock == null)
113{
114HoldImage.Source = blockImages[0];
115}
116else
117{
118HoldImage.Source = blockImages[heldBlock.Id];
119}
120}
121
122private void Draw(GameState gameState)
123{
124DrawGrid(gameState.GameGrid);
125DrawGhostBlock(gameState.CurrentBlock);
126DrawBlock(gameState.CurrentBlock);
127DrawNextBlock(gameState.BlockQueue);
128DrawHeldBlock(gameState.HeldBlock);
129ScoreText.Text = $"Очки: {gameState.Score}";
130}
131
132private void DrawGhostBlock(Block block)
133{
134int dropDistance = gameState.BlockDropDistance();
135
136foreach (Position p in block.TilePositions())
137{
138imageControls[p.Row + dropDistance, p.Column].Opacity = 0.25;
139imageControls[p.Row + dropDistance, p.Column].Source = tileImages[block.Id];
140}
141}
142
143private async Task GameLoop()
144{
145Draw(gameState);
146
147while (gameState.GameOver == false)
148{
149int delay = Math.Max(minDelay, maxDelay - (gameState.Score * delayDecrease));
150await Task.Delay(delay);
151gameState.MoveBlockDown();
152Draw(gameState);
153}
154
155GameOverMenu.Visibility = Visibility.Visible;
156FinalScoreText.Text = $"Очки: {gameState.Score}";
157}
158
159private void Window_KeyDown(object sender, KeyEventArgs e)
160{
161if (gameState.GameOver)
162{
163return;
164}
165
166switch (e.Key)
167{
168case Key.Left:
169gameState.MoveBlockLeft();
170break;
171case Key.Right:
172gameState.MoveBlockRight();
173break;
174case Key.Down:
175gameState.MoveBlockDown();
176break;
177case Key.Up:
178gameState.RotateBlockCW();
179break;
180case Key.Z:
181gameState.RotateBlockCCW();
182break;
183case Key.C:
184gameState.HoldBlock();
185break;
186case Key.Space:
187gameState.DropBlock();
188break;
189default:
190return;
191}
192Draw(gameState);
193}
194
195private async void GameCanvas_Loaded(object sender, RoutedEventArgs e)
196{
197await GameLoop();
198}
199
200private async void PlayAgain_Click(object sender, RoutedEventArgs e)
201{
202gameState = new GameState();
203GameOverMenu.Visibility = Visibility.Hidden;
204await GameLoop();
205}
206}