no idea speedrun
This commit is contained in:
parent
e2c9116575
commit
a2726c715c
@ -163,7 +163,7 @@ public class SnakeLevel : IDisposable{
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Event handlers
|
#region Event handlers
|
||||||
private void _timer_Tick(object? sender)
|
private void _timer_Tick(object? state)
|
||||||
{
|
{
|
||||||
Tick();
|
Tick();
|
||||||
GameUpdate?.Invoke(this, EventArgs.Empty);
|
GameUpdate?.Invoke(this, EventArgs.Empty);
|
||||||
@ -171,7 +171,7 @@ public class SnakeLevel : IDisposable{
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
public void Tick(){
|
private void Tick(){
|
||||||
if (!_disable_snake_movement)
|
if (!_disable_snake_movement)
|
||||||
{
|
{
|
||||||
Point new_snake_head = (0, 0);
|
Point new_snake_head = (0, 0);
|
||||||
@ -279,10 +279,10 @@ public class SnakeLevel : IDisposable{
|
|||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region IDisposable
|
#region IDisposable
|
||||||
private bool disposedValue;
|
private bool _disposed_value;
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (!disposedValue)
|
if (!_disposed_value)
|
||||||
{
|
{
|
||||||
if (disposing)
|
if (disposing)
|
||||||
{
|
{
|
||||||
@ -292,7 +292,7 @@ public class SnakeLevel : IDisposable{
|
|||||||
|
|
||||||
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
|
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
|
||||||
// TODO: set large fields to null
|
// TODO: set large fields to null
|
||||||
disposedValue = true;
|
_disposed_value = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,28 +5,33 @@ using Snake.Model;
|
|||||||
namespace Snake.Persistance;
|
namespace Snake.Persistance;
|
||||||
|
|
||||||
public class SnakeLevelLoader{
|
public class SnakeLevelLoader{
|
||||||
|
#region Fields
|
||||||
|
private readonly string SaveFileName;
|
||||||
|
private List<StoredSnakeLevel>? _stored_levels;
|
||||||
|
#endregion
|
||||||
|
|
||||||
public readonly string SaveFileName;
|
#region Properties
|
||||||
|
public ReadOnlyCollection<StoredSnakeLevel> StoredLevels => _stored_levels?.AsReadOnly()
|
||||||
|
?? throw new InvalidOperationException("Can not query stored levels before loading the data");
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
public SnakeLevelLoader(string saveFileName){
|
public SnakeLevelLoader(string saveFileName){
|
||||||
SaveFileName = saveFileName;
|
SaveFileName = saveFileName;
|
||||||
if(!File.Exists(SaveFileName)){
|
if(!File.Exists(SaveFileName)){
|
||||||
throw new FileNotFoundException("Save file not found", SaveFileName);
|
throw new FileNotFoundException("Save file not found", SaveFileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
public async Task ReadAllDataAsync()
|
public async Task ReadAllDataAsync()
|
||||||
{
|
{
|
||||||
string file_content = await File.ReadAllTextAsync(SaveFileName);
|
string file_content = await File.ReadAllTextAsync(SaveFileName);
|
||||||
_stored_levels = JsonSerializer.Deserialize<List<StoredSnakeLevel>>(file_content, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower })
|
_stored_levels = JsonSerializer.Deserialize<List<StoredSnakeLevel>>(file_content, new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower })
|
||||||
?? throw new JsonException("Failed to deserialize stored levels");
|
?? throw new JsonException("Failed to deserialize stored levels");
|
||||||
|
|
||||||
await Task.Delay(2000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<StoredSnakeLevel>? _stored_levels;
|
|
||||||
public ReadOnlyCollection<StoredSnakeLevel> StoredLevels => _stored_levels?.AsReadOnly()
|
|
||||||
?? throw new InvalidOperationException("Can not query stored levels before loading the data");
|
|
||||||
|
|
||||||
public SnakeLevel LoadLevel(StoredSnakeLevel level){
|
public SnakeLevel LoadLevel(StoredSnakeLevel level){
|
||||||
return new SnakeLevel(level.Size,
|
return new SnakeLevel(level.Size,
|
||||||
level.Obstacles.Select(a => new Point(a[0], a[1])),
|
level.Obstacles.Select(a => new Point(a[0], a[1])),
|
||||||
@ -34,4 +39,5 @@ public class SnakeLevelLoader{
|
|||||||
level.NewEggRound,
|
level.NewEggRound,
|
||||||
level.EggLimit);
|
level.EggLimit);
|
||||||
}
|
}
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
namespace view
|
namespace view
|
||||||
{
|
{
|
||||||
partial class Form1
|
partial class MainForm
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Required designer variable.
|
/// Required designer variable.
|
||||||
@ -3,19 +3,19 @@ using Snake.Persistance;
|
|||||||
|
|
||||||
namespace view
|
namespace view
|
||||||
{
|
{
|
||||||
public partial class Form1 : Form
|
public partial class MainForm : Form
|
||||||
{
|
{
|
||||||
#region Fields
|
#region Fields
|
||||||
const int line_width = 2; // Width of the table lines
|
const int line_width = 2; // Width of the table lines
|
||||||
SnakeLevel? CurrentLevel; // Current game state
|
SnakeLevel? _current_level; // Current game state
|
||||||
SnakeLevelLoader level_loader; // Level loader
|
SnakeLevelLoader _level_loader; // Level loader
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructor
|
#region Constructor
|
||||||
public Form1()
|
public MainForm()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
level_loader = new SnakeLevelLoader(Path.Combine(Directory.GetCurrentDirectory(), "levels.json"));
|
_level_loader = new SnakeLevelLoader(Path.Combine(Directory.GetCurrentDirectory(), "levels.json"));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@ -25,7 +25,7 @@ namespace view
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void Draw()
|
private void Draw()
|
||||||
{
|
{
|
||||||
if (CurrentLevel == null) return;
|
if (_current_level == null) return;
|
||||||
|
|
||||||
using Graphics canvas_graphics = Canvas.CreateGraphics();
|
using Graphics canvas_graphics = Canvas.CreateGraphics();
|
||||||
|
|
||||||
@ -35,31 +35,31 @@ namespace view
|
|||||||
graphics.Clear(Color.White);
|
graphics.Clear(Color.White);
|
||||||
var canvas_size = Math.Min(Canvas.Width, Canvas.Height);
|
var canvas_size = Math.Min(Canvas.Width, Canvas.Height);
|
||||||
|
|
||||||
double cell_size = (double)(canvas_size - (CurrentLevel.Size + 1) * line_width) / CurrentLevel.Size;
|
double cell_size = (double)(canvas_size - (_current_level.Size + 1) * line_width) / _current_level.Size;
|
||||||
// vertical lines
|
// vertical lines
|
||||||
for (int i = 0; i <= CurrentLevel.Size; i++)
|
for (int i = 0; i <= _current_level.Size; i++)
|
||||||
{
|
{
|
||||||
int x = (int)(i * (cell_size + line_width));
|
int x = (int)(i * (cell_size + line_width));
|
||||||
graphics.FillRectangle(Brushes.Black, x, 0, line_width, canvas_size);
|
graphics.FillRectangle(Brushes.Black, x, 0, line_width, canvas_size);
|
||||||
}
|
}
|
||||||
// horizontal lines
|
// horizontal lines
|
||||||
for (int i = 0; i <= CurrentLevel.Size; i++)
|
for (int i = 0; i <= _current_level.Size; i++)
|
||||||
{
|
{
|
||||||
int y = (int)(i * (cell_size + line_width));
|
int y = (int)(i * (cell_size + line_width));
|
||||||
graphics.FillRectangle(Brushes.Black, 0, y, canvas_size, line_width);
|
graphics.FillRectangle(Brushes.Black, 0, y, canvas_size, line_width);
|
||||||
}
|
}
|
||||||
// Ssnake
|
// Ssnake
|
||||||
foreach (var pos in CurrentLevel.Snake)
|
foreach (var pos in _current_level.Snake)
|
||||||
{
|
{
|
||||||
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
||||||
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 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);
|
graphics.FillRectangle(Brushes.Green, x, y, (int)cell_size, (int)cell_size);
|
||||||
}
|
}
|
||||||
// snake head
|
// snake head
|
||||||
int snake_head_x = (int)(cell_size * CurrentLevel.SnakeHead.X + line_width * (CurrentLevel.SnakeHead.X + 1));
|
int snake_head_x = (int)(cell_size * _current_level.SnakeHead.X + line_width * (_current_level.SnakeHead.X + 1));
|
||||||
int snake_head_y = (int)(cell_size * CurrentLevel.SnakeHead.Y + line_width * (CurrentLevel.SnakeHead.Y + 1));
|
int snake_head_y = (int)(cell_size * _current_level.SnakeHead.Y + line_width * (_current_level.SnakeHead.Y + 1));
|
||||||
graphics.FillRectangle(Brushes.Red, snake_head_x, snake_head_y, (int)cell_size, (int)cell_size);
|
graphics.FillRectangle(Brushes.Red, snake_head_x, snake_head_y, (int)cell_size, (int)cell_size);
|
||||||
switch (CurrentLevel.SnakeHeadDirection)
|
switch (_current_level.SnakeHeadDirection)
|
||||||
{
|
{
|
||||||
case SnakeLevel.SnakeDirection.Up:
|
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 + (int)cell_size / 2, snake_head_y + (int)cell_size);
|
||||||
@ -85,7 +85,7 @@ namespace view
|
|||||||
}
|
}
|
||||||
|
|
||||||
// obstacles
|
// obstacles
|
||||||
foreach (var pos in CurrentLevel.Obstacles)
|
foreach (var pos in _current_level.Obstacles)
|
||||||
{
|
{
|
||||||
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
||||||
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
||||||
@ -93,7 +93,7 @@ namespace view
|
|||||||
}
|
}
|
||||||
|
|
||||||
//eggs
|
//eggs
|
||||||
foreach (var pos in CurrentLevel.Eggs)
|
foreach (var pos in _current_level.Eggs)
|
||||||
{
|
{
|
||||||
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
int x = (int)(cell_size * pos.X + line_width * (pos.X + 1));
|
||||||
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
int y = (int)(cell_size * pos.Y + line_width * (pos.Y + 1));
|
||||||
@ -107,24 +107,24 @@ namespace view
|
|||||||
#region Form event handlers
|
#region Form event handlers
|
||||||
private void Form1_KeyDown(object sender, KeyEventArgs e)
|
private void Form1_KeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel == null) return;
|
if (_current_level == null) return;
|
||||||
switch (e.KeyCode)
|
switch (e.KeyCode)
|
||||||
{
|
{
|
||||||
case Keys.Up:
|
case Keys.Up:
|
||||||
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Up;
|
_current_level.SnakeHeadDirection = SnakeLevel.SnakeDirection.Up;
|
||||||
break;
|
break;
|
||||||
case Keys.Down:
|
case Keys.Down:
|
||||||
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Down;
|
_current_level.SnakeHeadDirection = SnakeLevel.SnakeDirection.Down;
|
||||||
break;
|
break;
|
||||||
case Keys.Left:
|
case Keys.Left:
|
||||||
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Left;
|
_current_level.SnakeHeadDirection = SnakeLevel.SnakeDirection.Left;
|
||||||
break;
|
break;
|
||||||
case Keys.Right:
|
case Keys.Right:
|
||||||
CurrentLevel.SnakeHeadDirection = SnakeLevel.SnakeDirection.Right;
|
_current_level.SnakeHeadDirection = SnakeLevel.SnakeDirection.Right;
|
||||||
break;
|
break;
|
||||||
case Keys.Escape:
|
case Keys.Escape:
|
||||||
if (CurrentLevel.State == SnakeLevel.GameState.Running)
|
if (_current_level.State == SnakeLevel.GameState.Running)
|
||||||
CurrentLevel.Pause();
|
_current_level.Pause();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -132,31 +132,31 @@ namespace view
|
|||||||
|
|
||||||
private void btnStart_Click(object sender, EventArgs e)
|
private void btnStart_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel is null || CurrentLevel.State == SnakeLevel.GameState.Dead)
|
if (_current_level is null || _current_level.State == SnakeLevel.GameState.Dead)
|
||||||
{
|
{
|
||||||
var MapChooser = new MapChooser(this.level_loader);
|
var MapChooser = new MapChooser(this._level_loader);
|
||||||
MapChooser.ShowDialog();
|
MapChooser.ShowDialog();
|
||||||
if (MapChooser.SelectedLevel != null)
|
if (MapChooser.SelectedLevel != null)
|
||||||
{
|
{
|
||||||
CurrentLevel = level_loader.LoadLevel(MapChooser.SelectedLevel);
|
_current_level = _level_loader.LoadLevel(MapChooser.SelectedLevel);
|
||||||
CurrentLevel.GameStateUpdate += CurrentLevel_GameStateUpdate;
|
_current_level.GameStateUpdate += CurrentLevel_GameStateUpdate;
|
||||||
CurrentLevel.GameUpdate += CurrentLevel_GameUpdate;
|
_current_level.GameUpdate += CurrentLevel_GameUpdate;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentLevel = null;
|
_current_level = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CurrentLevel != null)
|
if (_current_level != null)
|
||||||
{
|
{
|
||||||
CurrentLevel.Start();
|
_current_level.Start();
|
||||||
this.Focus();
|
this.Focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
|
private void Form1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel?.State is SnakeLevel.GameState.Running)
|
if (_current_level?.State is SnakeLevel.GameState.Running)
|
||||||
{
|
{
|
||||||
e.IsInputKey = true;
|
e.IsInputKey = true;
|
||||||
}
|
}
|
||||||
@ -165,7 +165,7 @@ namespace view
|
|||||||
private void Form1_Shown(object sender, EventArgs e)
|
private void Form1_Shown(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
btnEndGame.Visible = false; // It will trigger a whole repaint the first time it is shown unless this is done
|
btnEndGame.Visible = false; // It will trigger a whole repaint the first time it is shown unless this is done
|
||||||
level_loader.ReadAllDataAsync().ContinueWith((task) =>
|
_level_loader.ReadAllDataAsync().ContinueWith((task) =>
|
||||||
{
|
{
|
||||||
if (!this.IsDisposed) // The form can be closed before the file is loaded
|
if (!this.IsDisposed) // The form can be closed before the file is loaded
|
||||||
{
|
{
|
||||||
@ -188,7 +188,7 @@ namespace view
|
|||||||
|
|
||||||
private void button1_Click(object sender, EventArgs e)
|
private void button1_Click(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
CurrentLevel = null;
|
_current_level = null;
|
||||||
btnEndGame.Visible = false;
|
btnEndGame.Visible = false;
|
||||||
Canvas.Refresh();
|
Canvas.Refresh();
|
||||||
txtScore.Text = "";
|
txtScore.Text = "";
|
||||||
@ -196,13 +196,13 @@ namespace view
|
|||||||
|
|
||||||
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel != null)
|
if (_current_level != null)
|
||||||
{
|
{
|
||||||
if (CurrentLevel.State == SnakeLevel.GameState.Running)
|
if (_current_level.State == SnakeLevel.GameState.Running)
|
||||||
{
|
{
|
||||||
CurrentLevel.Pause();
|
_current_level.Pause();
|
||||||
}
|
}
|
||||||
CurrentLevel = null;
|
_current_level = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -211,17 +211,17 @@ namespace view
|
|||||||
#region Game event handlers
|
#region Game event handlers
|
||||||
private void CurrentLevel_GameUpdate(object? sender, EventArgs e)
|
private void CurrentLevel_GameUpdate(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel == null) return;
|
if (_current_level == null) return;
|
||||||
this.Invoke(() =>
|
this.Invoke(() =>
|
||||||
{
|
{
|
||||||
Draw();
|
Draw();
|
||||||
txtScore.Text = CurrentLevel.Score.ToString();
|
txtScore.Text = _current_level.Score.ToString();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CurrentLevel_GameStateUpdate(object? sender, SnakeLevel.GameState e)
|
private void CurrentLevel_GameStateUpdate(object? sender, SnakeLevel.GameState e)
|
||||||
{
|
{
|
||||||
if (CurrentLevel == null) return;
|
if (_current_level == null) return;
|
||||||
this.Invoke(() =>
|
this.Invoke(() =>
|
||||||
{
|
{
|
||||||
switch (e)
|
switch (e)
|
||||||
@ -237,7 +237,7 @@ namespace view
|
|||||||
break;
|
break;
|
||||||
case SnakeLevel.GameState.Dead:
|
case SnakeLevel.GameState.Dead:
|
||||||
btnStart.Visible = true;
|
btnStart.Visible = true;
|
||||||
MessageBox.Show($"Skill issue.\nScore: {CurrentLevel.Score}", "Snake", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
MessageBox.Show($"Skill issue.\nScore: {_current_level.Score}", "Snake", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -11,7 +11,7 @@ namespace view
|
|||||||
// To customize application configuration such as set high DPI settings or default font,
|
// To customize application configuration such as set high DPI settings or default font,
|
||||||
// see https://aka.ms/applicationconfiguration.
|
// see https://aka.ms/applicationconfiguration.
|
||||||
ApplicationConfiguration.Initialize();
|
ApplicationConfiguration.Initialize();
|
||||||
Application.Run(new Form1());
|
Application.Run(new MainForm());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user