changes xd
This commit is contained in:
parent
5b714395f0
commit
ff23702c15
21
bead1.sln
21
bead1.sln
@ -3,20 +3,19 @@ Microsoft Visual Studio Solution File, Format Version 12.00
|
|||||||
# Visual Studio Version 17
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 17.0.31903.59
|
VisualStudioVersion = 17.0.31903.59
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "persistance", "persistance\persistance.csproj", "{5C804F63-B331-4F7B-9C28-1A583594C73B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "persistance", "persistance\persistance.csproj", "{5C804F63-B331-4F7B-9C28-1A583594C73B}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "model", "model\model.csproj", "{41FA02D6-4257-46E6-BAF0-1D975169C05E}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "model", "model\model.csproj", "{41FA02D6-4257-46E6-BAF0-1D975169C05E}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{05D087EA-57EA-4A01-82B5-C36C7242EF80}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tests", "tests\tests.csproj", "{05D087EA-57EA-4A01-82B5-C36C7242EF80}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "view", "view\view.csproj", "{EFD422C5-2A8F-4E7B-8294-1EB93B3F94AA}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
|
||||||
HideSolutionNode = FALSE
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{5C804F63-B331-4F7B-9C28-1A583594C73B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5C804F63-B331-4F7B-9C28-1A583594C73B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5C804F63-B331-4F7B-9C28-1A583594C73B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5C804F63-B331-4F7B-9C28-1A583594C73B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
@ -30,5 +29,15 @@ Global
|
|||||||
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Release|Any CPU.Build.0 = Release|Any CPU
|
{05D087EA-57EA-4A01-82B5-C36C7242EF80}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{EFD422C5-2A8F-4E7B-8294-1EB93B3F94AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{EFD422C5-2A8F-4E7B-8294-1EB93B3F94AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{EFD422C5-2A8F-4E7B-8294-1EB93B3F94AA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{EFD422C5-2A8F-4E7B-8294-1EB93B3F94AA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {60431C7C-5F67-41C9-BE6E-6F4E4B7EF4AB}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|||||||
@ -1,8 +1,11 @@
|
|||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.IO.Pipes;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Snake.Model;
|
namespace Snake.Model;
|
||||||
|
|
||||||
public class SnakeLevel{
|
public class SnakeLevel{
|
||||||
|
public static readonly TimeSpan TickTimeSpan = TimeSpan.FromMilliseconds(500);
|
||||||
public int Size {get; }
|
public int Size {get; }
|
||||||
|
|
||||||
public enum LevelBlock{
|
public enum LevelBlock{
|
||||||
@ -23,6 +26,7 @@ public class SnakeLevel{
|
|||||||
|
|
||||||
public enum GameState{
|
public enum GameState{
|
||||||
Running,
|
Running,
|
||||||
|
Paused,
|
||||||
Dead
|
Dead
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,26 +35,74 @@ public class SnakeLevel{
|
|||||||
public Point SnakeHead {get; private set;}
|
public Point SnakeHead {get; private set;}
|
||||||
private readonly List<Point> _snake;
|
private readonly List<Point> _snake;
|
||||||
// Head is not in snake
|
// Head is not in snake
|
||||||
// Last is closest to the head
|
// First is closest to the head
|
||||||
public ReadOnlyCollection<Point> Snake => _snake.AsReadOnly();
|
public ReadOnlyCollection<Point> Snake => _snake.AsReadOnly();
|
||||||
public int SnakeLength => Snake.Count + 1;
|
public int SnakeLength => Snake.Count + 1;
|
||||||
private readonly List<Point> _eggs;
|
private readonly List<Point> _eggs;
|
||||||
public ReadOnlyCollection<Point> Eggs => _eggs.AsReadOnly();
|
public ReadOnlyCollection<Point> Eggs => _eggs.AsReadOnly();
|
||||||
public SnakeDirection SnakeHeadDirection {get; private set;}
|
public int NewEggRound { get; }
|
||||||
public GameState State {get; private set;}
|
public int EggLimit { get; }
|
||||||
|
private int _round;
|
||||||
|
|
||||||
public SnakeLevel(int size, IEnumerable<Point> obstacles, int snake_start_length){
|
private PeriodicTimer _timer;
|
||||||
|
public int Score { get; private set; }
|
||||||
|
|
||||||
|
public event EventHandler? GameUpdate;
|
||||||
|
public event EventHandler<GameState>? GameStateUpdate;
|
||||||
|
private GameState _state;
|
||||||
|
public GameState State
|
||||||
|
{
|
||||||
|
get => _state;
|
||||||
|
private set
|
||||||
|
{
|
||||||
|
_state = value;
|
||||||
|
GameStateUpdate?.Invoke(this, _state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private SnakeDirection LastDirection = SnakeDirection.Down;
|
||||||
|
private SnakeDirection _SnakeHeadDirection;
|
||||||
|
public SnakeDirection SnakeHeadDirection
|
||||||
|
{
|
||||||
|
get => _SnakeHeadDirection;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
switch (value, LastDirection)
|
||||||
|
{
|
||||||
|
case { value: SnakeDirection.Up or SnakeDirection.Down, LastDirection: SnakeDirection.Left or SnakeDirection.Right}:
|
||||||
|
case { value: SnakeDirection.Left or SnakeDirection.Right, LastDirection: SnakeDirection.Up or SnakeDirection.Down }:
|
||||||
|
_SnakeHeadDirection = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public SnakeLevel(int size, IEnumerable<Point> obstacles, int snake_start_length, int new_egg_round, int egg_limit, TimeProvider time_provider){
|
||||||
this.Size = size;
|
this.Size = size;
|
||||||
|
this.NewEggRound = new_egg_round;
|
||||||
|
this._round = NewEggRound;
|
||||||
|
this.EggLimit = egg_limit;
|
||||||
|
|
||||||
_obstacles = new List<Point>(obstacles);
|
_obstacles = new List<Point>(obstacles);
|
||||||
_eggs = [];
|
_eggs = [];
|
||||||
_snake = [];
|
_snake = [];
|
||||||
|
|
||||||
SnakeHead = (size / 2, snake_start_length-1);
|
SnakeHead = (size / 2, snake_start_length-1);
|
||||||
for(int i=0; i<snake_start_length-1; i++){
|
for(int i= snake_start_length - 2; i>=0; i--){
|
||||||
_snake.Add((size / 2, i));
|
_snake.Add((size / 2, i));
|
||||||
}
|
}
|
||||||
|
|
||||||
SnakeHeadDirection = SnakeDirection.Down;
|
_SnakeHeadDirection = SnakeDirection.Down;
|
||||||
|
LastDirection = SnakeDirection.Down;
|
||||||
|
|
||||||
|
_timer = new PeriodicTimer(TickTimeSpan, time_provider);
|
||||||
|
|
||||||
|
_state = GameState.Paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SnakeLevel(int size, IEnumerable<Point> obstacles, int snake_start_length, int new_egg_round, int egg_limit) : this(size, obstacles, snake_start_length, new_egg_round, egg_limit, TimeProvider.System)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public LevelBlock this[Point p]{
|
public LevelBlock this[Point p]{
|
||||||
@ -93,18 +145,79 @@ public class SnakeLevel{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var first = Snake[0];
|
Point last = _snake.Last();
|
||||||
|
|
||||||
for(int i=_snake.Count-1; i>0; i--){
|
for (int i = Snake.Count - 1; i > 0; i--)
|
||||||
_snake[i-1] = _snake[i];
|
{
|
||||||
|
_snake[i] = _snake[i - 1];
|
||||||
}
|
}
|
||||||
_snake[^1] = SnakeHead;
|
_snake[0] = SnakeHead;
|
||||||
|
|
||||||
if(this[new_snake_head] is LevelBlock.Egg){
|
if(this[new_snake_head] is LevelBlock.Egg){
|
||||||
_snake.Insert(0, first);
|
_snake.Add(last);
|
||||||
_eggs.Remove(new_snake_head);
|
_eggs.Remove(new_snake_head);
|
||||||
|
Score++;
|
||||||
}
|
}
|
||||||
|
|
||||||
SnakeHead = new_snake_head;
|
SnakeHead = new_snake_head;
|
||||||
|
|
||||||
|
if (Eggs.Count < EggLimit && --_round == 0)
|
||||||
|
{
|
||||||
|
_round = NewEggRound;
|
||||||
|
int avail_pos = Size * Size - Eggs.Count - Obstacles.Count - SnakeLength;
|
||||||
|
if (avail_pos > 0)
|
||||||
|
{
|
||||||
|
int pos = Random.Shared.Next(0, avail_pos);
|
||||||
|
Point p = (0, 0);
|
||||||
|
for (int i = 0; i < pos; i++)
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
p = (p.X + 1, p.Y);
|
||||||
|
if (p.X >= Size)
|
||||||
|
{
|
||||||
|
p = (0, p.Y + 1);
|
||||||
|
}
|
||||||
|
} while (this[p] is not LevelBlock.Empty);
|
||||||
|
}
|
||||||
|
_eggs.Add(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LastDirection = SnakeHeadDirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task TickerTask()
|
||||||
|
{
|
||||||
|
while(State == GameState.Running && await _timer.WaitForNextTickAsync())
|
||||||
|
{
|
||||||
|
Tick();
|
||||||
|
GameUpdate?.Invoke(this, EventArgs.Empty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if(State == GameState.Paused)
|
||||||
|
{
|
||||||
|
State = GameState.Running;
|
||||||
|
Task.Run(TickerTask);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Game is not paused");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Pause()
|
||||||
|
{
|
||||||
|
if(State == GameState.Running)
|
||||||
|
{
|
||||||
|
State = GameState.Paused;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Game is not running");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -23,6 +23,8 @@ public class SnakeLevelLoader{
|
|||||||
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])),
|
||||||
level.SnakeStartLength);
|
level.SnakeStartLength,
|
||||||
|
level.NewEggRound,
|
||||||
|
level.EggLimit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4,5 +4,7 @@ public class StoredSnakeLevel{
|
|||||||
public required string LevelName {get; init;}
|
public required string LevelName {get; init;}
|
||||||
public required int Size {get; init;}
|
public required int Size {get; init;}
|
||||||
public required int SnakeStartLength {get; init;}
|
public required int SnakeStartLength {get; init;}
|
||||||
|
public required int NewEggRound { get; init; }
|
||||||
|
public required int EggLimit { get; init; }
|
||||||
public required int[][] Obstacles {get; init;}
|
public required int[][] Obstacles {get; init;}
|
||||||
}
|
}
|
||||||
115
view/Form1.Designer.cs
generated
Normal file
115
view/Form1.Designer.cs
generated
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
namespace view
|
||||||
|
{
|
||||||
|
partial class Form1
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
Canvas = new Panel();
|
||||||
|
btnStart = new Button();
|
||||||
|
panel1 = new Panel();
|
||||||
|
txtScore = new TextBox();
|
||||||
|
label1 = new Label();
|
||||||
|
Canvas.SuspendLayout();
|
||||||
|
panel1.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// Canvas
|
||||||
|
//
|
||||||
|
Canvas.BackColor = Color.White;
|
||||||
|
Canvas.Controls.Add(btnStart);
|
||||||
|
Canvas.Dock = DockStyle.Top;
|
||||||
|
Canvas.Location = new Point(0, 0);
|
||||||
|
Canvas.Name = "Canvas";
|
||||||
|
Canvas.Size = new Size(480, 480);
|
||||||
|
Canvas.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// btnStart
|
||||||
|
//
|
||||||
|
btnStart.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
btnStart.Location = new Point(193, 226);
|
||||||
|
btnStart.Name = "btnStart";
|
||||||
|
btnStart.Size = new Size(94, 29);
|
||||||
|
btnStart.TabIndex = 0;
|
||||||
|
btnStart.Text = "START";
|
||||||
|
btnStart.UseVisualStyleBackColor = true;
|
||||||
|
btnStart.Click += btnStart_Click;
|
||||||
|
//
|
||||||
|
// panel1
|
||||||
|
//
|
||||||
|
panel1.Controls.Add(txtScore);
|
||||||
|
panel1.Controls.Add(label1);
|
||||||
|
panel1.Dock = DockStyle.Bottom;
|
||||||
|
panel1.Location = new Point(0, 486);
|
||||||
|
panel1.Name = "panel1";
|
||||||
|
panel1.Size = new Size(480, 94);
|
||||||
|
panel1.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// txtScore
|
||||||
|
//
|
||||||
|
txtScore.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
txtScore.Location = new Point(64, 9);
|
||||||
|
txtScore.Name = "txtScore";
|
||||||
|
txtScore.ReadOnly = true;
|
||||||
|
txtScore.Size = new Size(404, 27);
|
||||||
|
txtScore.TabIndex = 1;
|
||||||
|
txtScore.TabStop = false;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
label1.AutoSize = true;
|
||||||
|
label1.Location = new Point(12, 12);
|
||||||
|
label1.Name = "label1";
|
||||||
|
label1.Size = new Size(46, 20);
|
||||||
|
label1.TabIndex = 0;
|
||||||
|
label1.Text = "Score";
|
||||||
|
//
|
||||||
|
// Form1
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(480, 580);
|
||||||
|
Controls.Add(panel1);
|
||||||
|
Controls.Add(Canvas);
|
||||||
|
Name = "Form1";
|
||||||
|
Text = "Snake";
|
||||||
|
KeyDown += Form1_KeyDown;
|
||||||
|
PreviewKeyDown += Form1_PreviewKeyDown;
|
||||||
|
Canvas.ResumeLayout(false);
|
||||||
|
panel1.ResumeLayout(false);
|
||||||
|
panel1.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private Panel Canvas;
|
||||||
|
private Panel panel1;
|
||||||
|
private Label label1;
|
||||||
|
private TextBox txtScore;
|
||||||
|
private Button btnStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
178
view/Form1.cs
Normal file
178
view/Form1.cs
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
view/Form1.resx
Normal file
120
view/Form1.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
190
view/MapChooser.Designer.cs
generated
Normal file
190
view/MapChooser.Designer.cs
generated
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
namespace view
|
||||||
|
{
|
||||||
|
partial class MapChooser
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Required designer variable.
|
||||||
|
/// </summary>
|
||||||
|
private System.ComponentModel.IContainer components = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clean up any resources being used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||||
|
protected override void Dispose(bool disposing)
|
||||||
|
{
|
||||||
|
if (disposing && (components != null))
|
||||||
|
{
|
||||||
|
components.Dispose();
|
||||||
|
}
|
||||||
|
base.Dispose(disposing);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Windows Form Designer generated code
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Required method for Designer support - do not modify
|
||||||
|
/// the contents of this method with the code editor.
|
||||||
|
/// </summary>
|
||||||
|
private void InitializeComponent()
|
||||||
|
{
|
||||||
|
lstLevels = new ListBox();
|
||||||
|
groupBox1 = new GroupBox();
|
||||||
|
txtObstacleCount = new TextBox();
|
||||||
|
label4 = new Label();
|
||||||
|
txtEggRounds = new TextBox();
|
||||||
|
label3 = new Label();
|
||||||
|
txtSnakeLength = new TextBox();
|
||||||
|
label2 = new Label();
|
||||||
|
txtSize = new TextBox();
|
||||||
|
label1 = new Label();
|
||||||
|
button1 = new Button();
|
||||||
|
groupBox1.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// lstLevels
|
||||||
|
//
|
||||||
|
lstLevels.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
lstLevels.FormattingEnabled = true;
|
||||||
|
lstLevels.Location = new Point(12, 12);
|
||||||
|
lstLevels.Name = "lstLevels";
|
||||||
|
lstLevels.Size = new Size(270, 384);
|
||||||
|
lstLevels.TabIndex = 0;
|
||||||
|
lstLevels.SelectedIndexChanged += listBox1_SelectedIndexChanged;
|
||||||
|
lstLevels.KeyUp += lstLevels_KeyUp;
|
||||||
|
//
|
||||||
|
// groupBox1
|
||||||
|
//
|
||||||
|
groupBox1.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
groupBox1.Controls.Add(txtObstacleCount);
|
||||||
|
groupBox1.Controls.Add(label4);
|
||||||
|
groupBox1.Controls.Add(txtEggRounds);
|
||||||
|
groupBox1.Controls.Add(label3);
|
||||||
|
groupBox1.Controls.Add(txtSnakeLength);
|
||||||
|
groupBox1.Controls.Add(label2);
|
||||||
|
groupBox1.Controls.Add(txtSize);
|
||||||
|
groupBox1.Controls.Add(label1);
|
||||||
|
groupBox1.Location = new Point(288, 12);
|
||||||
|
groupBox1.Name = "groupBox1";
|
||||||
|
groupBox1.Size = new Size(309, 163);
|
||||||
|
groupBox1.TabIndex = 1;
|
||||||
|
groupBox1.TabStop = false;
|
||||||
|
groupBox1.Text = "Map details";
|
||||||
|
//
|
||||||
|
// txtObstacleCount
|
||||||
|
//
|
||||||
|
txtObstacleCount.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
txtObstacleCount.Location = new Point(133, 119);
|
||||||
|
txtObstacleCount.Name = "txtObstacleCount";
|
||||||
|
txtObstacleCount.ReadOnly = true;
|
||||||
|
txtObstacleCount.Size = new Size(170, 27);
|
||||||
|
txtObstacleCount.TabIndex = 7;
|
||||||
|
txtObstacleCount.TabStop = false;
|
||||||
|
//
|
||||||
|
// label4
|
||||||
|
//
|
||||||
|
label4.AutoSize = true;
|
||||||
|
label4.Location = new Point(6, 122);
|
||||||
|
label4.Name = "label4";
|
||||||
|
label4.Size = new Size(111, 20);
|
||||||
|
label4.TabIndex = 6;
|
||||||
|
label4.Text = "Obstacle count:";
|
||||||
|
//
|
||||||
|
// txtEggRounds
|
||||||
|
//
|
||||||
|
txtEggRounds.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
txtEggRounds.Location = new Point(133, 85);
|
||||||
|
txtEggRounds.Name = "txtEggRounds";
|
||||||
|
txtEggRounds.ReadOnly = true;
|
||||||
|
txtEggRounds.Size = new Size(170, 27);
|
||||||
|
txtEggRounds.TabIndex = 5;
|
||||||
|
txtEggRounds.TabStop = false;
|
||||||
|
//
|
||||||
|
// label3
|
||||||
|
//
|
||||||
|
label3.AutoSize = true;
|
||||||
|
label3.Location = new Point(6, 88);
|
||||||
|
label3.Name = "label3";
|
||||||
|
label3.Size = new Size(121, 20);
|
||||||
|
label3.TabIndex = 4;
|
||||||
|
label3.Text = "New egg rounds:";
|
||||||
|
//
|
||||||
|
// txtSnakeLength
|
||||||
|
//
|
||||||
|
txtSnakeLength.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
txtSnakeLength.Location = new Point(139, 52);
|
||||||
|
txtSnakeLength.Name = "txtSnakeLength";
|
||||||
|
txtSnakeLength.ReadOnly = true;
|
||||||
|
txtSnakeLength.Size = new Size(164, 27);
|
||||||
|
txtSnakeLength.TabIndex = 3;
|
||||||
|
txtSnakeLength.TabStop = false;
|
||||||
|
//
|
||||||
|
// label2
|
||||||
|
//
|
||||||
|
label2.AutoSize = true;
|
||||||
|
label2.Location = new Point(6, 55);
|
||||||
|
label2.Name = "label2";
|
||||||
|
label2.Size = new Size(130, 20);
|
||||||
|
label2.TabIndex = 2;
|
||||||
|
label2.Text = "Snake start length:";
|
||||||
|
//
|
||||||
|
// txtSize
|
||||||
|
//
|
||||||
|
txtSize.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
txtSize.Location = new Point(62, 20);
|
||||||
|
txtSize.Name = "txtSize";
|
||||||
|
txtSize.ReadOnly = true;
|
||||||
|
txtSize.Size = new Size(241, 27);
|
||||||
|
txtSize.TabIndex = 1;
|
||||||
|
txtSize.TabStop = false;
|
||||||
|
//
|
||||||
|
// label1
|
||||||
|
//
|
||||||
|
label1.AutoSize = true;
|
||||||
|
label1.Location = new Point(6, 23);
|
||||||
|
label1.Name = "label1";
|
||||||
|
label1.Size = new Size(39, 20);
|
||||||
|
label1.TabIndex = 0;
|
||||||
|
label1.Text = "Size:";
|
||||||
|
//
|
||||||
|
// button1
|
||||||
|
//
|
||||||
|
button1.Anchor = AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
|
||||||
|
button1.Location = new Point(294, 345);
|
||||||
|
button1.Name = "button1";
|
||||||
|
button1.Size = new Size(303, 51);
|
||||||
|
button1.TabIndex = 2;
|
||||||
|
button1.Text = "Select";
|
||||||
|
button1.UseVisualStyleBackColor = true;
|
||||||
|
button1.Click += button1_Click;
|
||||||
|
//
|
||||||
|
// MapChooser
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(8F, 20F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(609, 404);
|
||||||
|
Controls.Add(button1);
|
||||||
|
Controls.Add(groupBox1);
|
||||||
|
Controls.Add(lstLevels);
|
||||||
|
Name = "MapChooser";
|
||||||
|
Text = "MapChooser";
|
||||||
|
groupBox1.ResumeLayout(false);
|
||||||
|
groupBox1.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private ListBox lstLevels;
|
||||||
|
private GroupBox groupBox1;
|
||||||
|
private TextBox txtSize;
|
||||||
|
private Label label1;
|
||||||
|
private TextBox txtSnakeLength;
|
||||||
|
private Label label2;
|
||||||
|
private TextBox txtEggRounds;
|
||||||
|
private Label label3;
|
||||||
|
private TextBox txtObstacleCount;
|
||||||
|
private Label label4;
|
||||||
|
private Button button1;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
view/MapChooser.cs
Normal file
65
view/MapChooser.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using Snake.Persistance;
|
||||||
|
|
||||||
|
namespace view
|
||||||
|
{
|
||||||
|
public partial class MapChooser : Form
|
||||||
|
{
|
||||||
|
private SnakeLevelLoader _level_loader;
|
||||||
|
public StoredSnakeLevel? SelectedLevel { get; private set; }
|
||||||
|
public MapChooser(SnakeLevelLoader level_loader)
|
||||||
|
{
|
||||||
|
this._level_loader = level_loader;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
foreach (var level in _level_loader.StoredLevels)
|
||||||
|
{
|
||||||
|
lstLevels.Items.Add(level.LevelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (lstLevels.SelectedIndex == -1)
|
||||||
|
{
|
||||||
|
txtEggRounds.Text = "";
|
||||||
|
txtObstacleCount.Text = "";
|
||||||
|
txtSize.Text = "";
|
||||||
|
txtSnakeLength.Text = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var level = _level_loader.StoredLevels[lstLevels.SelectedIndex];
|
||||||
|
txtEggRounds.Text = level.NewEggRound.ToString();
|
||||||
|
txtObstacleCount.Text = level.Obstacles.Length.ToString();
|
||||||
|
txtSize.Text = $"{level.Size}x{level.Size}";
|
||||||
|
txtSnakeLength.Text = level.SnakeStartLength.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void button1_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
ChooseLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void lstLevels_KeyUp(object sender, KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.KeyCode == Keys.Enter)
|
||||||
|
{
|
||||||
|
ChooseLevel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChooseLevel()
|
||||||
|
{
|
||||||
|
if (lstLevels.SelectedIndex == -1)
|
||||||
|
{
|
||||||
|
SelectedLevel = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectedLevel = _level_loader.StoredLevels[lstLevels.SelectedIndex];
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
120
view/MapChooser.resx
Normal file
120
view/MapChooser.resx
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<root>
|
||||||
|
<!--
|
||||||
|
Microsoft ResX Schema
|
||||||
|
|
||||||
|
Version 2.0
|
||||||
|
|
||||||
|
The primary goals of this format is to allow a simple XML format
|
||||||
|
that is mostly human readable. The generation and parsing of the
|
||||||
|
various data types are done through the TypeConverter classes
|
||||||
|
associated with the data types.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
... ado.net/XML headers & schema ...
|
||||||
|
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||||
|
<resheader name="version">2.0</resheader>
|
||||||
|
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||||
|
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||||
|
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||||
|
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||||
|
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||||
|
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||||
|
</data>
|
||||||
|
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
|
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||||
|
<comment>This is a comment</comment>
|
||||||
|
</data>
|
||||||
|
|
||||||
|
There are any number of "resheader" rows that contain simple
|
||||||
|
name/value pairs.
|
||||||
|
|
||||||
|
Each data row contains a name, and value. The row also contains a
|
||||||
|
type or mimetype. Type corresponds to a .NET class that support
|
||||||
|
text/value conversion through the TypeConverter architecture.
|
||||||
|
Classes that don't support this are serialized and stored with the
|
||||||
|
mimetype set.
|
||||||
|
|
||||||
|
The mimetype is used for serialized objects, and tells the
|
||||||
|
ResXResourceReader how to depersist the object. This is currently not
|
||||||
|
extensible. For a given mimetype the value must be set accordingly:
|
||||||
|
|
||||||
|
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||||
|
that the ResXResourceWriter will generate, however the reader can
|
||||||
|
read any of the formats listed below.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.binary.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.soap.base64
|
||||||
|
value : The object must be serialized with
|
||||||
|
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
|
||||||
|
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||||
|
value : The object must be serialized into a byte array
|
||||||
|
: using a System.ComponentModel.TypeConverter
|
||||||
|
: and then encoded with base64 encoding.
|
||||||
|
-->
|
||||||
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:choice maxOccurs="unbounded">
|
||||||
|
<xsd:element name="metadata">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="assembly">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:attribute name="alias" type="xsd:string" />
|
||||||
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="data">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||||
|
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||||
|
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||||
|
<xsd:attribute ref="xml:space" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
<xsd:element name="resheader">
|
||||||
|
<xsd:complexType>
|
||||||
|
<xsd:sequence>
|
||||||
|
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||||
|
</xsd:sequence>
|
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:choice>
|
||||||
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
|
</xsd:schema>
|
||||||
|
<resheader name="resmimetype">
|
||||||
|
<value>text/microsoft-resx</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="version">
|
||||||
|
<value>2.0</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="reader">
|
||||||
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
17
view/Program.cs
Normal file
17
view/Program.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
namespace view
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The main entry point for the application.
|
||||||
|
/// </summary>
|
||||||
|
[STAThread]
|
||||||
|
static void Main()
|
||||||
|
{
|
||||||
|
// To customize application configuration such as set high DPI settings or default font,
|
||||||
|
// see https://aka.ms/applicationconfiguration.
|
||||||
|
ApplicationConfiguration.Initialize();
|
||||||
|
Application.Run(new Form1());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
view/levels.json
Normal file
25
view/levels.json
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"level_name": "Test level",
|
||||||
|
"size": 10,
|
||||||
|
"snake_start_length": 5,
|
||||||
|
"new_egg_round": 3,
|
||||||
|
"egg_limit": 2,
|
||||||
|
"obstacles": [
|
||||||
|
[ 1, 1 ],
|
||||||
|
[ 4, 2 ],
|
||||||
|
[ 6, 9 ]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"level_name": "Cool snake map",
|
||||||
|
"size": 12,
|
||||||
|
"snake_start_length": 3,
|
||||||
|
"new_egg_round": 5,
|
||||||
|
"egg_limit": 3,
|
||||||
|
"obstacles": [
|
||||||
|
[ 2, 3 ],
|
||||||
|
[ 1, 2 ]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
22
view/view.csproj
Normal file
22
view/view.csproj
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net8.0-windows</TargetFramework>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<UseWindowsForms>true</UseWindowsForms>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\model\model.csproj" />
|
||||||
|
<ProjectReference Include="..\persistance\persistance.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="levels.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Loading…
Reference in New Issue
Block a user