This article is currently in the process of being translated into Spanish (~98% done).
In this article series, we're building a complete Snake game from scratch. It makes sense to start with the Introduction and then work your way through the articles one by one, to get the full understanding.
If you want to get the complete source code for the game at once, to get started modifying and learning from it right now, consider downloading all our samples!
Improving SnakeWPF: Making it look more like a game
Durante los últimos artículos, hemos creado un juego Snake genial en WPF. Hemos implementado toda la mecánica del juego y el resultado es un juego completamente funcional. Sin embargo, definitivamente se pueden hacer muchas mejoras, porque la implementación actual es mínima. Por lo tanto, en los próximos artículos, haré varias mejoras en nuestro juego SnakeWPF; en este artículo, me centraré en hacer que nuestro juego se vea más como un juego real.
Como se ve ahora, con su barra de título / borde predeterminada al estilo de Windows, nuestra implementación no se parece mucho a un juego. Sin embargo, anteriormente necesitábamos la barra de título para mostrar la información de puntaje / velocidad, y como una buena ventaja, obtuvimos automáticamente los botones predeterminados de Windows para minimizar / maximizar / cerrar la ventana:
En este punto, me gustaría eliminar por completo la barra de título predeterminada de Windows y, en su lugar, implementar nuestra propia barra de estado superior, que debería mostrar la puntuación y la velocidad actuales, así como un botón de cierre personalizado. Todo debe coincidir con el aspecto actual del juego. Afortunadamente para nosotros, esto es bastante fácil de lograr con WPF.
Agregar una barra de título personalizada.
El primer paso es agregar un par de propiedades y un nuevo evento a la declaración de Windows. Ahora debería verse así:
<Window x:Class="WpfTutorialSamples.Games.SnakeWPFSample"
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:WpfTutorialSamples.Games"
mc:Ignorable="d"
Title="SnakeWPF - Score: 0" SizeToContent="WidthAndHeight" ContentRendered="Window_ContentRendered" KeyUp="Window_KeyUp"
ResizeMode="NoResize" WindowStyle="None" Background="Black" MouseDown="Window_MouseDown">
Los cambios están todos en la última línea. Configuramos ResizeMode en NoResize y WindowStyle en None . Esto eliminará por completo la barra de título, así como los bordes predeterminados alrededor de la ventana; eso no es un problema para nosotros, porque el área principal de nuestro juego ya tiene un borde negro de 5 px.
También notará que me he suscrito a un nuevo evento: el evento MouseDown . La razón es que, dado que perdemos la barra de título predeterminada, el usuario ya no puede arrastrar el juego de un punto de la pantalla a otro. Afortunadamente para nosotros, es fácil recrear este comportamiento, por ejemplo por nuestra cuenta, barra de título personalizada. Sin embargo, dado que no se parece a la barra de título normal, el usuario puede estar confundido sobre dónde arrastrar, por lo que decidí simplemente arrastrar toda la superficie de la ventana. Entonces, en su Código subyacente, defina el controlador de eventos Window_MouseDown de esta manera:
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
Con eso en su lugar, su ventana se puede arrastrar sin importar dónde use el ratón. El siguiente paso es agregar nuestra barra de título personalizada, que debe mostrar la puntuación y la velocidad, así como un botón de cierre. La parte interna de la ventana XAML ahora debería verse así:
<DockPanel Background="Black">
<Grid DockPanel.Dock="Top" Name="pnlTitleBar">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="Consolas" />
<Setter Property="Foreground" Value="White" />
<Setter Property="FontSize" Value="24" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
</Grid.Resources>
<WrapPanel Margin="10,0,0,0">
<TextBlock>Score:</TextBlock>
<TextBlock Name="tbStatusScore">0</TextBlock>
</WrapPanel>
<WrapPanel Grid.Column="1">
<TextBlock>Speed:</TextBlock>
<TextBlock Name="tbStatusSpeed">0</TextBlock>
</WrapPanel>
<Button Grid.Column="2" DockPanel.Dock="Right" Background="Transparent" Foreground="White" FontWeight="Bold" FontSize="20" BorderThickness="0" Name="btnClose" Click="BtnClose_Click" Padding="10,0">X</Button>
</Grid>
<Border BorderBrush="Black" BorderThickness="5">
<Canvas Name="GameArea" ClipToBounds="True" Width="400" Height="400">
</Canvas>
</Border>
</DockPanel>
Y no olvide definir el controlador de eventos BtnClose_Click :
private void BtnClose_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
Anteriormente implementamos un método llamado UpdateGameStatus () , que actualizó la propiedad Título de la ventana; este método debe cambiarse para usar los nuevos TextBlock:
private void UpdateGameStatus()
{
this.tbStatusScore.Text = currentScore.ToString();
this.tbStatusSpeed.Text = gameTickTimer.Interval.TotalMilliseconds.ToString();
}
Te contaré todo lo que acabamos de hacer, pero primero, veamos cómo se ve el juego ahora:
Se ve un poco más fresco, ¿verdad? Pero analicemos lo que acabamos de hacer: como puede ver, el control Border original con el GameArea Canvas dentro de él ahora ha sido rodeado por un DockPanel . Esto nos facilita adjuntar nuestra nueva barra de título, en forma de panel Cuadrícula , en la parte superior de la Ventana.
The Grid utiliza varias técnicas de WPF geniales que se han discutido en otra parte de este tutorial: Usamos ColumnDefinition para dividir el área en dos áreas de igual tamaño (para la puntuación y la velocidad), además de un tamaño automático tercera columna para el botón de cierre. También notará que utilizamos los Style de WPF para aplicar el mismo aspecto visual a todos los controles TextBlock: la misma fuente, tamaño, color y peso personalizados se aplican a todos ellos, gracias a un estilo definido en la cuadrícula, dirigido a los controles TextBlock .
Observe también lo fácil que es personalizar el control Button utilizado para cerrar la ventana, para que coincida completamente con el resto del aspecto del juego, simplemente usando las propiedades estándar: ¡WPF es tan flexible!
Resumen
En este artículo, hemos hecho que nuestra implementación de la Serpiente en WPF (SnakeWPF) se parezca mucho más a un juego, eliminando el aspecto estándar de Windows y aplicando nuestra propia barra de título personalizada. En los próximos artículos, haremos aún más mejoras.