using System; using System.ComponentModel; using System.Drawing; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Threading; using Tetris.Models; using Color = System.Drawing.Color; namespace Tetris.ViewsModels; public class GameViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler? PropertyChanged; private const int RendererHertz = 5; private const int GameRendererHertz = (1 / RendererHertz) * 1000; private const int Width = 25; private const int Height = 50; private readonly WriteableBitmap _writeableBitmap; private const int GridWidth = 25; private const int GridHeight = 50; private static readonly Grid Grid = new(new Color[GridWidth, GridHeight]); private readonly Tetrominoe _currentTetrominoe = new(Grid, "J", new Point(25 / 2, 0), 0, Color.Aqua); public GameViewModel() { _writeableBitmap = BitmapFactory.New(Width, Height); var dispatcherRenderTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, GameRendererHertz) }; dispatcherRenderTimer.Tick += Render; dispatcherRenderTimer.Start(); var dispatcherUpdateTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, 100) }; dispatcherUpdateTimer.Tick += Update; dispatcherUpdateTimer.Start(); } public ImageSource Source => _writeableBitmap; public Tetrominoe CurrentTetrominoe => _currentTetrominoe; private void Render(object? sender, EventArgs eventArgs) { _writeableBitmap.Lock(); _writeableBitmap.Clear(Colors.Black); for (var x = 0; x < GridWidth; x++) { for (var y = 0; y < GridHeight; y++) { var color = Grid.CGrid[x, y]; _writeableBitmap.SetPixel(x, y, color.R, color.G, color.B); } } var tetrominoeWidth = _currentTetrominoe.Shape.GetLength(0); var tetrominoeHeight = _currentTetrominoe.Shape.GetLength(1); for (int x = 0; x < tetrominoeWidth; x++) { for (int y = 0; y < tetrominoeHeight; y++) { if (!_currentTetrominoe.Shape[x, y]) continue; var color = _currentTetrominoe.Color; _writeableBitmap.SetPixel(_currentTetrominoe.Coordinates.X + x, _currentTetrominoe.Coordinates.Y + y, color.R, color.G, color.B); } } _writeableBitmap.Unlock(); } private void Update(object? sender, EventArgs eventArgs) { _currentTetrominoe.GoDown(); } }