Fix game over, add username and persistent scoreboard
This commit is contained in:
parent
17f1d0f108
commit
51cd3adb9c
13 changed files with 247 additions and 17 deletions
42
Tetris/Migrations/20220607174015_initialSetup.Designer.cs
generated
Normal file
42
Tetris/Migrations/20220607174015_initialSetup.Designer.cs
generated
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Tetris.Models;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Tetris.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ScoreContext))]
|
||||||
|
[Migration("20220607174015_initialSetup")]
|
||||||
|
partial class initialSetup
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "7.0.0-preview.4.22229.2");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Tetris.Models.Score", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Points")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Scores");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
Tetris/Migrations/20220607174015_initialSetup.cs
Normal file
35
Tetris/Migrations/20220607174015_initialSetup.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Tetris.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class initialSetup : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Scores",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "INTEGER", nullable: false)
|
||||||
|
.Annotation("Sqlite:Autoincrement", true),
|
||||||
|
Points = table.Column<int>(type: "INTEGER", nullable: false),
|
||||||
|
UserName = table.Column<string>(type: "TEXT", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Scores", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Scores");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
39
Tetris/Migrations/ScoreContextModelSnapshot.cs
Normal file
39
Tetris/Migrations/ScoreContextModelSnapshot.cs
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Tetris.Models;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Tetris.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(ScoreContext))]
|
||||||
|
partial class ScoreContextModelSnapshot : ModelSnapshot
|
||||||
|
{
|
||||||
|
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder.HasAnnotation("ProductVersion", "7.0.0-preview.4.22229.2");
|
||||||
|
|
||||||
|
modelBuilder.Entity("Tetris.Models.Score", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<int>("Points")
|
||||||
|
.HasColumnType("INTEGER");
|
||||||
|
|
||||||
|
b.Property<string>("UserName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("TEXT");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Scores");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,16 @@ public class Game : INotifyPropertyChanged {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool _playing = true;
|
||||||
|
|
||||||
|
public bool Playing {
|
||||||
|
get => _playing;
|
||||||
|
set {
|
||||||
|
_playing = value;
|
||||||
|
OnPropertyChanged("Playing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Grid _grid;
|
private Grid _grid;
|
||||||
|
|
||||||
public Grid Grid => _grid;
|
public Grid Grid => _grid;
|
||||||
|
@ -78,8 +88,14 @@ public class Game : INotifyPropertyChanged {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_grid.PrintTetrominoe(_currentTetrominoe);
|
_grid.PrintTetrominoe(_currentTetrominoe);
|
||||||
|
|
||||||
|
if (Playing) {
|
||||||
_currentTetrominoe = _nextTetrominoe;
|
_currentTetrominoe = _nextTetrominoe;
|
||||||
_nextTetrominoe = GetNewTetrominoe();
|
_nextTetrominoe = GetNewTetrominoe();
|
||||||
|
} else {
|
||||||
|
_currentTetrominoe = null;
|
||||||
|
_nextTetrominoe = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tetrominoe GetNewTetrominoe() {
|
public Tetrominoe GetNewTetrominoe() {
|
||||||
|
@ -87,6 +103,14 @@ public class Game : INotifyPropertyChanged {
|
||||||
return new Tetrominoe(_grid, tetrominoes[_random.Next(tetrominoes.Count)]);
|
return new Tetrominoe(_grid, tetrominoes[_random.Next(tetrominoes.Count)]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveGame() {
|
||||||
|
Console.WriteLine("Game over");
|
||||||
|
using var db = new ScoreContext();
|
||||||
|
var score = new Score{Points = Score, UserName = UserName};
|
||||||
|
db.Scores.Add(score);
|
||||||
|
db.SaveChanges();
|
||||||
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged(string propertyName)
|
protected virtual void OnPropertyChanged(string propertyName)
|
||||||
|
|
11
Tetris/Models/Score.cs
Normal file
11
Tetris/Models/Score.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Tetris.Models;
|
||||||
|
|
||||||
|
public class Score {
|
||||||
|
public int Id { get; set; }
|
||||||
|
public int Points { get; set; }
|
||||||
|
public string UserName { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return UserName + ": " + Points;
|
||||||
|
}
|
||||||
|
}
|
12
Tetris/Models/ScoreContext.cs
Normal file
12
Tetris/Models/ScoreContext.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Tetris.Models;
|
||||||
|
|
||||||
|
public class ScoreContext : DbContext {
|
||||||
|
public DbSet<Score> Scores { get; set; }
|
||||||
|
|
||||||
|
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||||
|
{
|
||||||
|
optionsBuilder.UseSqlite(@"Data Source=.\Resources\db.sl3");
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,11 +20,21 @@
|
||||||
<EmbeddedResource Include="Resources\tetrominoes.json">
|
<EmbeddedResource Include="Resources\tetrominoes.json">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</EmbeddedResource>
|
</EmbeddedResource>
|
||||||
|
<None Remove="Resources\db.sl3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="EntityFramework" Version="6.4.4" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="7.0.0-preview.4.22229.2" />
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0-preview.4.22229.2">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="7.0.0-preview.4.22229.2" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Pastel" Version="3.0.0" />
|
<PackageReference Include="Pastel" Version="3.0.0" />
|
||||||
|
<PackageReference Include="System.Configuration.ConfigurationManager" Version="7.0.0-preview.4.22229.4" />
|
||||||
|
<PackageReference Include="System.Data.SQLite.EF6" Version="1.0.116" />
|
||||||
<PackageReference Include="WriteableBitmapEx" Version="1.6.8" />
|
<PackageReference Include="WriteableBitmapEx" Version="1.6.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,19 @@
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="GameWindow" Width="{Binding Width}" Height="{Binding Height}" KeyDown="UIElement_OnKeyDown">
|
Title="GameWindow" Width="{Binding Width}" Height="{Binding Height}" KeyDown="UIElement_OnKeyDown">
|
||||||
<Grid Background="Black">
|
<Grid Background="Black">
|
||||||
|
<StackPanel>
|
||||||
<TextBlock Text="{Binding ScoreText}" Foreground="White" FontSize="32" />
|
<TextBlock Text="{Binding ScoreText}" Foreground="White" FontSize="32" />
|
||||||
|
<TextBlock Text="{Binding UserNameText}" Foreground="White" FontSize="32" />
|
||||||
|
<TextBlock Text="Scoreboard :" Foreground="White" FontSize="32" Margin="0 10 0 0" />
|
||||||
|
<ListView ItemsSource="{Binding ScoreBoard}" Background="Black" HorizontalAlignment="Left" MaxWidth="500">
|
||||||
|
<ListView.ItemContainerStyle>
|
||||||
|
<Style TargetType="{x:Type ListViewItem}">
|
||||||
|
<Setter Property="Background" Value="Black" />
|
||||||
|
<Setter Property="Foreground" Value="White" />
|
||||||
|
</Style>
|
||||||
|
</ListView.ItemContainerStyle>
|
||||||
|
</ListView>
|
||||||
|
</StackPanel>
|
||||||
<Image Source="{Binding Source}" />
|
<Image Source="{Binding Source}" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
|
@ -13,11 +13,19 @@ public partial class GameWindow
|
||||||
DataContext = new GameViewModel();
|
DataContext = new GameViewModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Start(string userName) {
|
||||||
|
GameViewModel.Game.UserName = userName;
|
||||||
|
Show();
|
||||||
|
}
|
||||||
|
|
||||||
[DllImport("kernel32.dll")]
|
[DllImport("kernel32.dll")]
|
||||||
private static extern bool AttachConsole(int dwProcessId);
|
private static extern bool AttachConsole(int dwProcessId);
|
||||||
|
|
||||||
private void UIElement_OnKeyDown(object sender, KeyEventArgs e)
|
private void UIElement_OnKeyDown(object sender, KeyEventArgs e)
|
||||||
{
|
{
|
||||||
|
if (!GameViewModel.Game.Playing)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (e.Key)
|
switch (e.Key)
|
||||||
{
|
{
|
||||||
// If key is space
|
// If key is space
|
||||||
|
|
|
@ -10,7 +10,12 @@
|
||||||
<Grid>
|
<Grid>
|
||||||
<Image Source="pack://application:,,,/Resources/tetris.png" Stretch="Fill" HorizontalAlignment="Center"
|
<Image Source="pack://application:,,,/Resources/tetris.png" Stretch="Fill" HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Center" />
|
VerticalAlignment="Center" />
|
||||||
|
<StackPanel>
|
||||||
|
<TextBox HorizontalAlignment="Center" VerticalAlignment="Center" TextAlignment="Center" Width="100"
|
||||||
|
Height="20" Margin="0 200 0 0" Name="UserName" Text="{Binding UserName, Mode=TwoWay,
|
||||||
|
UpdateSourceTrigger=LostFocus}" />
|
||||||
<Button Click="StartButton_OnClick" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100"
|
<Button Click="StartButton_OnClick" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100"
|
||||||
Height="50" Content="Start" Margin="0 200 0 0" />
|
Height="50" Content="Start" Margin="0 10 0 0" />
|
||||||
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
|
@ -1,6 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Tetris.Models;
|
||||||
using Tetris.ViewsModels;
|
using Tetris.ViewsModels;
|
||||||
|
|
||||||
namespace Tetris.Views;
|
namespace Tetris.Views;
|
||||||
|
@ -10,8 +12,9 @@ namespace Tetris.Views;
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public partial class MainWindow
|
public partial class MainWindow
|
||||||
{
|
{
|
||||||
public MainWindow()
|
public MainWindow() {
|
||||||
{
|
using var db = new ScoreContext();
|
||||||
|
db.Database.Migrate();
|
||||||
AttachConsole(-1);
|
AttachConsole(-1);
|
||||||
DataContext = new ViewModel();
|
DataContext = new ViewModel();
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
@ -23,7 +26,7 @@ public partial class MainWindow
|
||||||
private void StartButton_OnClick(object sender, RoutedEventArgs e)
|
private void StartButton_OnClick(object sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Start game...");
|
Console.WriteLine("Start game...");
|
||||||
new GameWindow().Show();
|
new GameWindow().Start(((ViewModel) DataContext).UserName);
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,8 +1,7 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System;
|
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Windows.Controls;
|
using System.Linq;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Media.Imaging;
|
using System.Windows.Media.Imaging;
|
||||||
using System.Windows.Threading;
|
using System.Windows.Threading;
|
||||||
|
@ -30,12 +29,11 @@ public class GameViewModel : INotifyPropertyChanged
|
||||||
private readonly int _height = (Game.Grid.MaxGrid.Y + 1) * Multiplier;
|
private readonly int _height = (Game.Grid.MaxGrid.Y + 1) * Multiplier;
|
||||||
private readonly WriteableBitmap _writeableBitmap;
|
private readonly WriteableBitmap _writeableBitmap;
|
||||||
private readonly int _colorLine = 0xFFFFFF;
|
private readonly int _colorLine = 0xFFFFFF;
|
||||||
private bool _isPaused;
|
|
||||||
private uint _countDown;
|
private uint _countDown;
|
||||||
private string _scoreText = "";
|
private string _scoreText = "";
|
||||||
|
private string _userNameText = "";
|
||||||
|
|
||||||
public GameViewModel()
|
public GameViewModel() {
|
||||||
{
|
|
||||||
_writeableBitmap = BitmapFactory.New(_width, _height);
|
_writeableBitmap = BitmapFactory.New(_width, _height);
|
||||||
|
|
||||||
var dispatcherRenderTimer = new DispatcherTimer
|
var dispatcherRenderTimer = new DispatcherTimer
|
||||||
|
@ -67,11 +65,29 @@ public class GameViewModel : INotifyPropertyChanged
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Score> ScoreBoard {
|
||||||
|
get {
|
||||||
|
using var db = new ScoreContext();
|
||||||
|
return db.Scores.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string UserNameText
|
||||||
|
{
|
||||||
|
get => _userNameText;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_userNameText = value;
|
||||||
|
OnPropertyChanged("UserNameText");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void Render(object? sender, EventArgs eventArgs)
|
private void Render(object? sender, EventArgs eventArgs)
|
||||||
{
|
{
|
||||||
_writeableBitmap.Lock();
|
_writeableBitmap.Lock();
|
||||||
_writeableBitmap.Clear(Colors.Black);
|
_writeableBitmap.Clear(Colors.Black);
|
||||||
ScoreText = "Score: " + Game.Score;
|
ScoreText = "Score: " + Game.Score;
|
||||||
|
UserNameText = "Username: " + Game.UserName;
|
||||||
|
|
||||||
var colorGrid = Game.Grid.CGrid;
|
var colorGrid = Game.Grid.CGrid;
|
||||||
for (var x = 0; x < Game.Grid.MaxGrid.X + 1; x++)
|
for (var x = 0; x < Game.Grid.MaxGrid.X + 1; x++)
|
||||||
|
@ -113,7 +129,7 @@ public class GameViewModel : INotifyPropertyChanged
|
||||||
|
|
||||||
private void Update(object? sender, EventArgs eventArgs)
|
private void Update(object? sender, EventArgs eventArgs)
|
||||||
{
|
{
|
||||||
if (_isPaused)
|
if (!Game.Playing)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -135,7 +151,9 @@ public class GameViewModel : INotifyPropertyChanged
|
||||||
|
|
||||||
if (Game.HitTop())
|
if (Game.HitTop())
|
||||||
{
|
{
|
||||||
_isPaused = true;
|
Game.Playing = false;
|
||||||
|
Game.PrintTetrominoe();
|
||||||
|
Game.SaveGame();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -6,6 +6,17 @@ public class ViewModel : INotifyPropertyChanged
|
||||||
{
|
{
|
||||||
public event PropertyChangedEventHandler? PropertyChanged;
|
public event PropertyChangedEventHandler? PropertyChanged;
|
||||||
|
|
||||||
|
private string _userName = "Player";
|
||||||
|
|
||||||
|
public string UserName {
|
||||||
|
get { return _userName; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_userName = value;
|
||||||
|
OnPropertyChanged("UserName");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void OnPropertyChanged(string propertyName)
|
protected virtual void OnPropertyChanged(string propertyName)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
|
Reference in a new issue