I would especially like to find out how this project should be constructed to be "fully MVVM". I did some reading about MVVM and I started to implement some ideas, but I don't fully understand it yet.
The game works, but I would like to get some advice regarding what could be done better/differently. Does it make sense to make such project MVVM in the first place?
MainWindow.xaml.cs:
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
namespace PongGame
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
DataContext = _ball;
RightPad.DataContext = _rightPad;
LeftPad.DataContext = _leftPad;
Ball.DataContext = _ball;
label4.DataContext = _rightPad;
var timer = new DispatcherTimer();
timer.Interval = TimeSpan.FromMilliseconds(10);
timer.Start();
timer.Tick += _timer_Tick;
}
private double _angle = 155;
private double _speed = 5;
private int _padSpeed = 7;
void _timer_Tick(object sender, EventArgs e)
{
if (_ball.Y <= 0) _angle = _angle + (180 - 2*_angle);
if (_ball.Y >= MainCanvas.ActualHeight - 20)_angle = _angle + (180 - 2*_angle);
if (CheckCollision() == true)
{
ChangeAngle();
ChangeDirection();
}
double radians = (Math.PI / 180) * _angle;
Vector vector = new Vector { X = Math.Sin(radians), Y = -Math.Cos(radians) };
_ball.X += vector.X * _speed;
_ball.Y += vector.Y * _speed;
if (_ball.X >= 790)
{
_ball.LeftResult += 1;
GameReset();
}
if (_ball.X <= 5)
{
_ball.RightResult += 1;
GameReset();
}
}
private void GameReset()
{
_ball.Y = 210;
_ball.X = 380;
}
private void ChangeAngle()
{
if (_ball.MovingRight == true) _angle = 270 - ((_ball.Y + 10) - (_rightPad.YPosition + 40));
else if (_ball.MovingRight == false) _angle = 90 + ((_ball.Y + 10) - (_leftPad.YPosition + 40));
}
private void ChangeDirection()
{
if (_ball.MovingRight == true) _ball.MovingRight = false;
else if (_ball.MovingRight == false) _ball.MovingRight = true;
}
private bool CheckCollision()
{
bool collisionResult = false;
if (_ball.MovingRight == true)
collisionResult = _ball.X >= 760 && (_ball.Y > _rightPad.YPosition - 20 && _ball.Y < _rightPad.YPosition + 80);
if (_ball.MovingRight == false)
collisionResult = _ball.X <= 20 && (_ball.Y > _leftPad.YPosition - 20 && _ball.Y < _leftPad.YPosition + 80);
return collisionResult;
}
readonly Ball _ball = new Ball { X = 380, Y = 210 , MovingRight = true};
readonly Pad _leftPad = new Pad { YPosition = 90 };
readonly Pad _rightPad = new Pad { YPosition = 70 };
private void MainWindow_OnKeyDown(object sender, KeyboardEventArgs e)
{
if (Keyboard.IsKeyDown(Key.W)) _leftPad.YPosition -= _padSpeed;
if (Keyboard.IsKeyDown(Key.S)) _leftPad.YPosition += _padSpeed;
if (Keyboard.IsKeyDown(Key.Up)) _rightPad.YPosition -= _padSpeed;
if (Keyboard.IsKeyDown(Key.Down)) _rightPad.YPosition += _padSpeed;
}
}
}
Ball.cs:
using System.ComponentModel;
using PongGame.Annotations;
namespace PongGame
{
class Ball : INotifyPropertyChanged
{
private double _x;
private double _y;
private bool _movingRight;
private int _leftResult;
private int _rightResult;
public double X
{
get { return _x; }
set
{
_x = value;
OnPropertyChanged("X");
}
}
public double Y
{
get { return _y; }
set
{
_y = value;
OnPropertyChanged("Y");
}
}
public bool MovingRight
{
get { return _movingRight; }
set
{
_movingRight = value;
OnPropertyChanged("MovingRight");
}
}
public int LeftResult
{
get { return _leftResult; }
set
{
_leftResult = value;
OnPropertyChanged("LeftResult");
}
}
public int RightResult
{
get { return _rightResult; }
set
{
_rightResult = value;
OnPropertyChanged("RightResult");
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Pad.cs:
using System.ComponentModel;
using System.Linq;
using System.Text;
using PongGame.Annotations;
namespace PongGame
{
class Pad : INotifyPropertyChanged
{
private int _yPosition;
public int YPosition
{
get { return _yPosition; }
set { _yPosition = value;
OnPropertyChanged("YPosition");}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
MinWindow.xaml:
<Window x:Class="PongGame.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=System"
KeyDown="MainWindow_OnKeyDown"
Title="MainWindow" Height="503" Width="824" ResizeMode="NoResize">
<Canvas Width="800" Height="475" Name="MainCanvas" Background="#FFD1D1D1">
<Rectangle Height="80" Width="20" Fill="Blue"
Canvas.Top="{Binding YPosition}"
Name="LeftPad"></Rectangle>
<Rectangle Height="80" Width="20" Fill="Brown"
Canvas.Top="{Binding YPosition}"
Canvas.Left="780"
Name="RightPad"></Rectangle>
<Line X1="400" X2="400" Y2="500" Y1="0" StrokeThickness="2" Stroke="#FFDBB062"></Line>
<Ellipse Width="20" Height="20" Canvas.Left="{Binding X}"
Canvas.Top="{Binding Y}" Name="Ball" DataContext="{Binding Path=ball}" StrokeThickness="0.1" Fill="#FFF84949">
</Ellipse>
<Label Canvas.Left="630" Canvas.Top="34" Content="{Binding Y}" Height="28" Name="label1" />
<Label Canvas.Left="565" Canvas.Top="34" Content="Y of ball" Height="28" Name="label2" />
<Label Canvas.Left="535" Canvas.Top="68" Content="Y of right pad" Height="28" Name="label3" />
<Label Canvas.Left="630" Canvas.Top="68" Content="{Binding YPosition}" Height="28" Name="label4" />
<Label Canvas.Left="638" Canvas.Top="128" Content="{Binding MovingRight}" Height="28" Name="label5" />
<Label Canvas.Left="184" Canvas.Top="34" Content="{Binding X}" Height="28" Name="label6" />
<Label Canvas.Left="119" Canvas.Top="34" Content="X of ball" Height="28" Name="label7" />
<Label Canvas.Left="89" Canvas.Top="68" Content="X of right pad" Height="28" Name="label8" />
<Label Canvas.Left="184" Canvas.Top="68" Content="{Binding YPosition}" Height="28" Name="label9" />
<Label Canvas.Left="349" Canvas.Top="35" Content="{Binding LeftResult}" Height="auto" Name="label10"
FontSize="40" Foreground="Blue"/>
<Label Canvas.Left="421" Canvas.Top="35" Content="{Binding RightResult}" Height="auto" Name="label11"
FontSize="40" Foreground="Brown"/>
</Canvas>
</Window>