Archived
1
0
Fork 0

Fix game over, add username and persistent scoreboard

This commit is contained in:
Ethanell 2022-06-07 19:48:44 +02:00
parent 17f1d0f108
commit 51cd3adb9c
13 changed files with 247 additions and 17 deletions

View 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
}
}
}

View 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");
}
}
}

View 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
}
}
}

View file

@ -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);
_currentTetrominoe = _nextTetrominoe;
_nextTetrominoe = GetNewTetrominoe(); if (Playing) {
_currentTetrominoe = _nextTetrominoe;
_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
View 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;
}
}

View 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");
}
}

View file

@ -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>

View file

@ -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">
<TextBlock Text="{Binding ScoreText}" Foreground="White" FontSize="32" /> <StackPanel>
<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>

View file

@ -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

View file

@ -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" />
<Button Click="StartButton_OnClick" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" <StackPanel>
Height="50" Content="Start" Margin="0 200 0 0" /> <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"
Height="50" Content="Start" Margin="0 10 0 0" />
</StackPanel>
</Grid> </Grid>
</Window> </Window>

View file

@ -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();
} }
} }

View file

@ -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();
} }
} }
} }

View file

@ -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));