179 lines
7.4 KiB
C#
179 lines
7.4 KiB
C#
using Snake.Model;
|
|
using Snake.Persistance;
|
|
|
|
namespace view
|
|
{
|
|
public partial class Form1 : Form
|
|
{
|
|
Graphics graphics;
|
|
int line_width = 2;
|
|
SnakeLevel? CurrentLevel;
|
|
SnakeLevelLoader level_loader;
|
|
|
|
public Form1()
|
|
{
|
|
InitializeComponent();
|
|
graphics = Canvas.CreateGraphics();
|
|
level_loader = new SnakeLevelLoader(Path.Combine(Directory.GetCurrentDirectory(), "levels.json"));
|
|
}
|
|
|
|
private void Form1_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (CurrentLevel == null) return;
|
|
switch (e.KeyCode)
|
|
{
|
|
case Keys.Up:
|
|
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Up;
|
|
break;
|
|
case Keys.Down:
|
|
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Down;
|
|
break;
|
|
case Keys.Left:
|
|
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Left;
|
|
break;
|
|
case Keys.Right:
|
|
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Right;
|
|
break;
|
|
case Keys.Escape:
|
|
CurrentLevel.Pause();
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
private void Draw(SnakeLevel level)
|
|
{
|
|
var canvas_size = Math.Min(Canvas.Width, Canvas.Height);
|
|
|
|
|
|
graphics.Clear(Color.White);
|
|
double cell_size = (double)(canvas_size - (level.Size + 1) * line_width) / level.Size;
|
|
// vertical lines
|
|
for (int i = 0; i <= level.Size; i++)
|
|
{
|
|
int x = (int)(i * (cell_size + line_width));
|
|
graphics.FillRectangle(Brushes.Black, x, 0, line_width, canvas_size);
|
|
}
|
|
// horizontal lines
|
|
for (int i = 0; i <= level.Size; i++)
|
|
{
|
|
int y = (int)(i * (cell_size + line_width));
|
|
graphics.FillRectangle(Brushes.Black, 0, y, canvas_size, line_width);
|
|
}
|
|
// Ssnake
|
|
foreach (var pos in level.Snake)
|
|
{
|
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
|
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
|
graphics.FillRectangle(Brushes.Green, x, y, (int)cell_size, (int)cell_size);
|
|
}
|
|
// snake head
|
|
int snake_head_x = (int)(cell_size * level.SnakeHead.X + line_width * (level.SnakeHead.X + 1));
|
|
int snake_head_y = (int)(cell_size * level.SnakeHead.Y + line_width * (level.SnakeHead.Y + 1));
|
|
graphics.FillRectangle(Brushes.Red, snake_head_x, snake_head_y, (int)cell_size, (int)cell_size);
|
|
switch (level.SnakeHeadDirection)
|
|
{
|
|
case SnakeLevel.SnakeDirection.Up:
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x + (int)cell_size / 2, snake_head_y + (int)cell_size);
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x, snake_head_y + (int)cell_size / 2);
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x + (int)cell_size, snake_head_y + (int)cell_size / 2);
|
|
break;
|
|
case SnakeLevel.SnakeDirection.Down:
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x + (int)cell_size / 2, snake_head_y + (int)cell_size);
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x, snake_head_y + (int)cell_size / 2);
|
|
graphics.DrawLine(Pens.Black, snake_head_x + (int)cell_size / 2, snake_head_y, snake_head_x + (int)cell_size, snake_head_y + (int)cell_size / 2);
|
|
break;
|
|
case SnakeLevel.SnakeDirection.Left:
|
|
graphics.DrawLine(Pens.Black, snake_head_x, snake_head_y + (int)cell_size / 2, snake_head_x + (int)cell_size, snake_head_y + (int)cell_size / 2);
|
|
break;
|
|
case SnakeLevel.SnakeDirection.Right:
|
|
graphics.DrawLine(Pens.Black, snake_head_x, snake_head_y + (int)cell_size / 2, snake_head_x + (int)cell_size, snake_head_y + (int)cell_size / 2);
|
|
break;
|
|
|
|
}
|
|
|
|
// obstacles
|
|
foreach (var pos in level.Obstacles)
|
|
{
|
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
|
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
|
graphics.FillRectangle(Brushes.Black, x, y, (int)cell_size, (int)cell_size);
|
|
}
|
|
|
|
//eggs
|
|
foreach (var pos in level.Eggs)
|
|
{
|
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
|
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
|
graphics.FillRectangle(Brushes.Pink, x, y, (int)cell_size, (int)cell_size);
|
|
}
|
|
}
|
|
|
|
private void btnStart_Click(object sender, EventArgs e)
|
|
{
|
|
if (CurrentLevel is null || CurrentLevel.State != SnakeLevel.GameState.Running)
|
|
{
|
|
var MapChooser = new MapChooser(this.level_loader);
|
|
MapChooser.ShowDialog();
|
|
if (MapChooser.SelectedLevel != null)
|
|
{
|
|
CurrentLevel = level_loader.LoadLevel(MapChooser.SelectedLevel);
|
|
CurrentLevel.GameStateUpdate += CurrentLevel_GameStateUpdate;
|
|
CurrentLevel.GameUpdate += CurrentLevel_GameUpdate;
|
|
}
|
|
else
|
|
{
|
|
CurrentLevel = null;
|
|
}
|
|
}
|
|
if (CurrentLevel != null)
|
|
{
|
|
CurrentLevel.Start();
|
|
this.Focus();
|
|
}
|
|
}
|
|
|
|
private void CurrentLevel_GameUpdate(object? sender, EventArgs e)
|
|
{
|
|
this.Invoke(() =>
|
|
{
|
|
if (CurrentLevel != null)
|
|
{
|
|
Draw(CurrentLevel);
|
|
txtScore.Text = CurrentLevel.Score.ToString();
|
|
}
|
|
});
|
|
}
|
|
|
|
private void CurrentLevel_GameStateUpdate(object? sender, SnakeLevel.GameState e)
|
|
{
|
|
this.Invoke(() =>
|
|
{
|
|
if (CurrentLevel == null) return;
|
|
switch (e)
|
|
{
|
|
case SnakeLevel.GameState.Running:
|
|
btnStart.Visible = false;
|
|
Draw(CurrentLevel);
|
|
break;
|
|
case SnakeLevel.GameState.Paused:
|
|
btnStart.Visible = true;
|
|
break;
|
|
case SnakeLevel.GameState.Dead:
|
|
btnStart.Visible = true;
|
|
MessageBox.Show($"Skill issue.\nScore: {CurrentLevel.Score}", "Snake", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
|
|
{
|
|
if(CurrentLevel?.State is SnakeLevel.GameState.Running)
|
|
{
|
|
e.IsInputKey = true;
|
|
}
|
|
}
|
|
}
|
|
}
|