I'm trying to create a Bricks in WPF C#, but I can't find the position of my rectangles in a grid.
I need the coordinates of the rectangles to implement the collisions and add points when break the brick, but I can't find any function to find the position from the cs.
MainWindows.xaml
<Window x:Class="gioco.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:gioco"
mc:Ignorable="d"
Title="Bricks" Height="450" Width="813" Loaded="window_Loaded"
PreviewKeyDown="Chiusura">
<Canvas x:Name="playground" Background="Black" MouseMove="MouseMoving" Cursor="Arrow">
<Rectangle x:Name="Player" Height="10" Canvas.Left="330" Stroke="White" Canvas.Top="390" Width="141" Fill="#FFD8EDFF"/>
<Rectangle x:Name="ball" Height="14" Canvas.Left="393" Stroke="White" Canvas.Top="340" Width="14" Fill="#FFD8EDFF"/>
<TextBlock x:Name="boxOver" Canvas.Left="187" Canvas.Top="107" Text="Game Over!" TextWrapping="Wrap" Height="146" Width="420" FontSize="72" FontWeight="Bold" FontStyle="Italic" FontFamily="Arial Rounded MT Bold" Foreground="Red"/>
<TextBlock x:Name="Punti" Canvas.Left="10" Canvas.Top="10" TextWrapping="Wrap" Height="39" Width="91" Foreground="White" FontSize="24"/>
<Button x:Name="butStart" Content="S t a r t" Canvas.Left="223" Canvas.Top="107" Height="183" Width="354" Background="{x:Null}" FontSize="36" FontWeight="Bold" FontStyle="Italic" FontFamily="Copperplate Gothic Bold" Click="butStart_Click" Margin="0,-2,0,0" BorderBrush="{x:Null}" Foreground="White"/>
<Rectangle x:Name="HP1" Height="23" Canvas.Left="755" Canvas.Top="338" Width="23" Fill="#FFC80000" RadiusX="11.5" RadiusY="11.5" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-89.743"/>
<TranslateTransform X="27.874" Y="28"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="HP2" Height="23" Canvas.Left="783" Canvas.Top="338" Width="23" Fill="#FFC80000" RadiusX="11.5" RadiusY="11.5" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-89.743"/>
<TranslateTransform/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle x:Name="HP3" Height="23" Canvas.Left="811" Canvas.Top="338" Width="23" Fill="#FFC80000" RadiusX="11.5" RadiusY="11.5" RenderTransformOrigin="0.5,0.5">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="-89.743"/>
<TranslateTransform X="-27.874" Y="-28"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<Grid x:Name="GridBlocks" Height="253" Width="800">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
</Grid>
<TextBlock x:Name="boxRestart" Canvas.Left="252" Canvas.Top="197" Text="Press Space to restart" TextWrapping="Wrap" Height="29" Width="296" FontSize="22" FontWeight="Bold" FontStyle="Italic" FontFamily="Copperplate Gothic Bold" Foreground="White"/>
</Canvas>
</Window>
MainWindows.xaml.cs
using System;
using System.Timers;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
namespace gioco
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
Rectangle[,] rectangle = new Rectangle[20, 23];
Timer timer1 = new Timer(20);
int ballY = 0;
int ballX = 0;
int BallSpeedX = 2;
int BallSpeedY = 2;
double PlayerX;
double PlayerY;
int score = 0;
int life = 3;
bool inizio = false;
bool pausa = false;
public MainWindow()
{
InitializeComponent();
GridBlocks.Visibility = Visibility.Hidden;
}
private void window_Loaded(object sender, RoutedEventArgs e)
{
ball.Visibility = Visibility.Hidden;
Player.Visibility = Visibility.Hidden;
boxRestart.Visibility = Visibility.Hidden;
//prepara il campo di gioco e avvia il timer
PlayerX = (playground.ActualWidth / 2) - (Player.ActualWidth / 2); //imposta la posizione del giocatore
PlayerY = playground.ActualHeight - Player.ActualHeight - 20; //imposta la posizione del giocatore
Canvas.SetTop(Player, PlayerY); //sistema la racchetta alle coordinate Y scelte
Canvas.SetLeft(Player, PlayerX); //sistema la racchetta alle coordinate X scelte
boxOver.Visibility = Visibility.Hidden; //gamer over reso invisibile
//posiziona pallina a centro schermo
ballX = (int)(playground.ActualWidth / 2);
ballY = (int)(playground.ActualHeight / 2);
HP1.Visibility = Visibility.Hidden;
HP2.Visibility = Visibility.Hidden;
HP3.Visibility = Visibility.Hidden;
for(int i = 0; i < 20; i++)
{
for (int j = 0; j < 23; j++)
{
rectangle[i, j] = new Rectangle();
GridBlocks.Children.Add(rectangle[i, j]);
Grid.SetRow(rectangle[i, j], i);
Grid.SetColumn(rectangle[i, j], j);
rectangle[i, j].VerticalAlignment = VerticalAlignment.Stretch;
rectangle[i, j].HorizontalAlignment = HorizontalAlignment.Stretch;
rectangle[i, j].Fill = new SolidColorBrush(Color.FromArgb(255, 216, 237, 255));
}
}
}
private void moveBallTimer_Tick(object sender, EventArgs e)
{
ballY += BallSpeedY;
ballX += BallSpeedX;
Dispatcher.BeginInvoke((Action)delegate ()
{
Canvas.SetTop(ball, ballY);
Canvas.SetLeft(ball, ballX);
Punti.Text = score.ToString(); //visualizza punti
});
//pallina contro bordo left
if (ballX <= 0)
{
//inverte direzione X
BallSpeedX = -BallSpeedX;
}
//pallina contro bordo right
if ((ballX + ball.ActualWidth) >= playground.ActualWidth)
{
//inverte direzione X
BallSpeedX = -BallSpeedX;
}
//pallina contro bordo top
if (ballY <= 0)
{
//inverte direzione Y
BallSpeedY = -BallSpeedY;
}
//pallina sotto racchetta
if ((ballY + ball.ActualHeight) >= playground.ActualHeight)
{
life--;
timer1.Stop();
PlayerX = (playground.ActualWidth / 2) - (Player.ActualWidth / 2);
PlayerY = playground.ActualHeight - Player.ActualHeight - 20;
ballX = (int)(playground.ActualWidth / 2);
ballY = (int)(playground.ActualHeight / 2);
inizio = true;
if (life <= 2)
{
Dispatcher.Invoke(() =>
{
HP1.Visibility = Visibility.Hidden;
});
ballX = (int)(playground.ActualWidth / 2);
ballY = (int)(playground.ActualHeight / 2);
}
if (life <= 1)
{
Dispatcher.Invoke(() => {
HP2.Visibility = Visibility.Hidden;
});
ballX = (int)(playground.ActualWidth / 2);
ballY = (int)(playground.ActualHeight / 2);
}
if (life <= 0)
{
ballX = (int)(playground.ActualWidth / 2);
ballY = (int)(playground.ActualHeight / 2);
Dispatcher.Invoke(() => {
HP3.Visibility = Visibility.Hidden;
});
Dispatcher.Invoke(() =>
{
ball.Visibility = Visibility.Hidden;
});
//game over
timer1.Stop();
Dispatcher.BeginInvoke((Action)delegate ()
{
boxOver.Visibility = Visibility.Visible;
boxRestart.Visibility = Visibility;
Player.Visibility = Visibility.Hidden;
inizio = true;
});
}
}
//pallina contro blocco
if ((ballY + ball.ActualHeight) >= PlayerY
&& (((ballX + ball.ActualWidth) >= PlayerX
&& (ballX + ball.ActualWidth) <= (PlayerX + Player.ActualWidth))
|| (ballX >= PlayerX && ballX <= (PlayerX + Player.ActualWidth))))
{
BallSpeedX++;
BallSpeedY++;
BallSpeedY = -BallSpeedY;
score += 10; //10 punti ogni volta che racchetta tocca pallina
}
}
private void MouseMoving(object sender, MouseEventArgs e)
{
Point position = e.GetPosition(this);
PlayerX = position.X;
Canvas.SetLeft(Player, PlayerX);
}
private void Chiusura(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
pausa = !pausa;
if (pausa)
{
timer1.Enabled = false;
Mouse.OverrideCursor = Cursors.Arrow;
}
else
{
timer1.Enabled = true;
Mouse.OverrideCursor = Cursors.None;
}
}
if (e.Key == Key.Space)
{
if (inizio)
{
boxRestart.Visibility = Visibility.Hidden;
boxOver.Visibility = Visibility.Hidden;
Player.Visibility = Visibility;
ball.Visibility = Visibility;
HP1.Visibility = Visibility;
HP2.Visibility = Visibility;
HP3.Visibility = Visibility;
Punti.Visibility = Visibility;
score = 0;
timer1.Enabled = true;
if (life == 3)
HP1.Visibility = Visibility;
if (life >= 2)
HP2.Visibility = Visibility;
if (life >= 1)
HP3.Visibility = Visibility;
BallSpeedX = 2;
BallSpeedY = 2;
inizio = false;
}
}
}
private void butStart_Click(object sender, RoutedEventArgs e)
{
butStart.Visibility = Visibility.Hidden;
timer1.Elapsed += moveBallTimer_Tick;
ball.Visibility = Visibility.Visible;
Player.Visibility = Visibility.Visible;
Mouse.OverrideCursor = Cursors.None;
inizio = true;
HP1.Visibility = Visibility;
HP2.Visibility = Visibility;
HP3.Visibility = Visibility;
GridBlocks.Visibility = Visibility;
Algoritmo.CreaNuovoLivello(rectangle);
}
private void butStop_Click(object sender, RoutedEventArgs e)
{
timer1.Enabled = true;
}
}
}
Algoritmo.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Shapes;
namespace gioco
{
static class Algoritmo
{
public static bool ControlloFine(Rectangle[,] rectangles)
{
bool c = true;
for (int i = 0; i < 20; i++)
{
for(int j = 0; j < 23; j++)
{
if (rectangles[i, j].Visibility != System.Windows.Visibility.Hidden)
{
c = false;
break;
}
}
if (!c)
break;
}
return c;
}
public static void CreaNuovoLivello(Rectangle[,] rectangles)
{
Random random = new();
int e = random.Next(0,4);
bool c = true;
switch (e)
{
case 0:
for (int i = 0; i < 20; i++)
{
c = !c;
for (int j = 0; j < 23; j++)
{
if (c)
{
rectangles[i, j].Visibility = System.Windows.Visibility.Visible;
}
else
{
rectangles[i, j].Visibility = System.Windows.Visibility.Hidden;
rectangles[1,2].
}
}
}
break;
case 1:
for (int i = 0; i < 20; i++)
{
c = !c;
for (int j = 0; j < 23; j++)
{
if (c)
{
rectangles[i, j].Visibility = System.Windows.Visibility.Visible;
}
else
{
rectangles[i, j].Visibility = System.Windows.Visibility.Hidden;
}
c = !c;
}
}
break;
case 2:
c = !c;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 23; j++)
{
if (c)
{
rectangles[i, j].Visibility = System.Windows.Visibility.Visible;
}
else
{
rectangles[i, j].Visibility = System.Windows.Visibility.Hidden;
}
c = !c;
}
}
break;
case 3:
int d = 0;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 23; j++)
{
if (c || d > 2)
{
rectangles[i, j].Visibility = System.Windows.Visibility.Visible;
d++;
}
else
{
rectangles[i, j].Visibility = System.Windows.Visibility.Hidden;
d = 0;
}
c = !c;
}
}
break;
case 4:
int f = 0;
for (int i = 0; i < 20; i++)
{
for (int j = 0; j < 23; j++)
{
if (f < 3)
{
rectangles[i, j].Visibility = System.Windows.Visibility.Visible;
}
else
{
rectangles[i, j].Visibility = System.Windows.Visibility.Hidden;
if (f == 3)
f = 0;
}
f++;
}
}
break;
default:
break;
}
}
}
}
t would have been nice if you had been able to reduce the code to a minimal working example where we can focus on the collision part alone.
Because of this I'm not able to help you to improve your code (it looks like it needs some. Multidimensional arrays, nested loops etc.). For example, you likely should use the
DispatcherTimerconfigured with a reasonableDispatcherPriority. But I can show how you can check for the collision of twoShapeobjects:As long you have the bounding rectangle of the geometry, you can use this solution to detect collision between any kind of shape.
Alternatively, you would have to check if any of the (e.g. outline) points of shape_X is located inside the (outline) bounds of shape_Y.