我正在尝试在 wpf c# 中创建一个 Bricks,但我无法在网格中找到矩形的位置。 我需要矩形的坐标来实现碰撞并在打破砖块时添加点,但我找不到任何函数来从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;
}
}
}
}
你的代码很难阅读。成员名字是意大利语,而我不会说意大利语。而且你发布了太多冗余代码。如果您能够将代码减少到一个最小的工作示例,这样我们就可以只关注碰撞部分,那就太好了。
因此我无法帮助您改进代码(看起来它需要一些。多维数组,嵌套循环等)。例如,您可能应该使用配置有合理
DispatcherTimer
的 DispatcherPriority
。但我可以向您展示如何检查两个 Shape
对象的碰撞:
var firstRectangleShape = new Rectangle();
var secondRectangleShape = new Rectangle();
Rect firstRectangeleShapeBounds = firstRectangleShape.RenderedGeometry.Bounds;
Rect secondRectangeleShapeBounds = secondRectangleShape.RenderedGeometry.Bounds;
bool hasCollision = firstRectangeleShapeBounds.IntersectsWith(secondRectangeleShapeBounds);
只要您有几何图形的边界矩形,您就可以使用此解决方案来检测任何类型形状之间的碰撞。
或者,您必须检查 shape_X 的任何(例如轮廓)点是否位于 shape_Y 的(轮廓)边界内。