C# WPF 实现躲避球小游戏
By
jerryxjr1220
at 2023-09-28 • 0人收藏 • 432人看过
其实用的游戏底层与前面的五子棋是同一个,渲染不同而已,要是贴上不同图像可以模拟更多平面游戏,坦克大战,超级玛丽这种都不是问题。
竖过来,就变成《是男人就挑战100层》
//Model using System; using System.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel; namespace WPFFlight.Models; public partial class GameObject: ObservableObject { public enum ObjectTypes { Space, Rock, Bullet, Enemy, Player, } [ObservableProperty] private ObjectTypes _blockType; [ObservableProperty] private int _xPos; [ObservableProperty] private int _yPos; [ObservableProperty] private int _xPosActual; [ObservableProperty] private int _yPosActual; [ObservableProperty] private int _blockSize; [ObservableProperty] private int _speed; protected override void OnPropertyChanged(PropertyChangedEventArgs e) { base.OnPropertyChanged(e); switch(e.PropertyName) { case "XPos": XPosActual = XPos * BlockSize; break; case "YPos": YPosActual = YPos * BlockSize; break; } } public GameObject(string _type, int _x, int _y, int _speed=1, int _blockSize=20) { switch (_type) { case "S": BlockType = ObjectTypes.Space; break; case "R": BlockType = ObjectTypes.Rock; break; case "B": BlockType = ObjectTypes.Bullet; break; case "E": BlockType = ObjectTypes.Enemy; break; case "P": BlockType = ObjectTypes.Player; break; default: throw new ArgumentException(); } Speed = _speed; BlockSize = _blockSize; XPos = _x; YPos = _y; } public GameObject() { } }
//ViewModel using System; using System.ComponentModel; using System.Globalization; using System.Threading; using System.Windows.Data; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging.Messages; using WPFFlight.Models; namespace WPFFlight.ViewModels; public partial class MainViewModel: ObservableObject { [ObservableProperty] private BindingList<GameObject> _uiLayout; [ObservableProperty] private int _blockSize; [ObservableProperty] private int _speed; [ObservableProperty] private int _level; public string[,] GameLayout { get; set; } public MainViewModel() { GameLayout = new string[10, 20] { {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "R", "R", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S"}, {"S", "P", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "R", "S", "S", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "R", "S", "S", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "R", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "R", "S"}, {"S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S", "S"}, }; BlockSize = 20; Speed = 1; Level = 1; UiLayout = new BindingList<GameObject>(); RenderLayout(); //发送消息 //WeakReferenceMessenger.Default.Send(new CustomizedMessage(new MessageModel())); } public void RenderLayout() { UiLayout.Clear(); for (int x = 0; x < 10; x++) { for (int y = 0; y < 20; y++) { var current = GameLayout[x, y]; UiLayout.Add(new GameObject(current, y, x, Speed, BlockSize)); } } } public void Move() { int px = 0; int py = 0; for (int j = 0; j < 10; j++) { for (int i = 1; i < 20; i++) { if (GameLayout[j, i] == "P") { px = j; py = i; GameLayout[j, i - 1] = "S"; continue; } GameLayout[j, i-1] = GameLayout[j, i]; } var rand = new Random(); var r = rand.Next(0, 21-Level); GameLayout[j, 19] = r < 19-Level ? "S" : "R"; } GameLayout[px, py] = "P"; RenderLayout(); } public void MoveDown() { int px = 0; for (int j = 0; j < 10; j++) { if (GameLayout[j, 1] == "P") { px = j; GameLayout[j, 1] = "S"; } } if (px >= 9) GameLayout[px, 1] = "P"; else GameLayout[px+1, 1] = "P"; RenderLayout(); } public void MoveUp() { int px = 0; for (int j = 0; j < 10; j++) { if (GameLayout[j, 1] == "P") { px = j; GameLayout[j, 1] = "S"; } } if (px <= 0) GameLayout[px, 1] = "P"; else GameLayout[px-1, 1] = "P"; RenderLayout(); } } public class BorderValueConverter : IValueConverter { public int Offset { get; set; } = 2; public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return int.Parse(value.ToString()) - Offset; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { throw new NotImplementedException(); } } //定义消息 // public class CustomizedMessage : ValueChangedMessage<MessageModel> // PropertyChangedMessage // RequestMessage ( Async + ..) // { // public CustomizedMessage(MessageModel value) : base(value) // { // } // }
<hc:GlowWindow x:Class="WPFFlight.Views.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:model="clr-namespace:WPFFlight.Models" xmlns:vm="clr-namespace:WPFFlight.ViewModels" xmlns:view="clr-namespace:WPFFlight.Views" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local="clr-namespace:WPFFlight" xmlns:hc="https://handyorg.github.io/handycontrol" d:DataContext="{d:DesignInstance Type=vm:MainViewModel}" mc:Ignorable="d" Title="Flight Fight" Height="240" Width="400" ResizeMode="NoResize" FontFamily="JetBrains Mono" FontSize="{StaticResource TextFontSize}"> <Window.Resources> <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> <!--<vm:BorderValueConverter Offset="0" x:Key="BorderValueConverter" />--> </Window.Resources> <hc:SimplePanel> <ScrollViewer x:Name="scrollViewer" VerticalScrollBarVisibility="Auto"> <Grid Background="Black" Margin="0, 5"> <ItemsControl ItemsSource="{Binding UiLayout}" MouseWheel="MainWindow_OnMouseWheel" > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <Canvas /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemContainerStyle> <Style TargetType="ContentPresenter"> <Setter Property="Canvas.Left" Value="{Binding XPosActual}" /> <Setter Property="Canvas.Top" Value="{Binding YPosActual}" /> </Style> </ItemsControl.ItemContainerStyle> <ItemsControl.ItemTemplate> <DataTemplate> <Border BorderBrush="DarkGray" BorderThickness="0"> <Border x:Name="UiCanvas" Width="{Binding BlockSize}" Height="{Binding BlockSize}" /> </Border> <DataTemplate.Triggers> <DataTrigger Binding="{Binding BlockType}" Value="0"> <Setter TargetName="UiCanvas" Property="Background" Value="Black"></Setter> </DataTrigger> <DataTrigger Binding="{Binding BlockType}" Value="1"> <Setter TargetName="UiCanvas" Property="Background" Value="Chocolate"></Setter> <Setter TargetName="UiCanvas" Property="CornerRadius" Value="8"></Setter> </DataTrigger> <DataTrigger Binding="{Binding BlockType}" Value="2"> <Setter TargetName="UiCanvas" Property="Background" Value="Red"></Setter> <Setter TargetName="UiCanvas" Property="CornerRadius" Value="10"></Setter> </DataTrigger> <DataTrigger Binding="{Binding BlockType}" Value="3"> <Setter TargetName="UiCanvas" Property="Background" Value="Cyan"></Setter> <Setter TargetName="UiCanvas" Property="CornerRadius" Value="9"></Setter> </DataTrigger> <DataTrigger Binding="{Binding BlockType}" Value="4"> <Setter TargetName="UiCanvas" Property="Background" Value="White"></Setter> <Setter TargetName="UiCanvas" Property="CornerRadius" Value="9"></Setter> </DataTrigger> </DataTemplate.Triggers> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </Grid> </ScrollViewer> </hc:SimplePanel> </hc:GlowWindow>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging.Messages; using HandyControl.Controls; using WPFFlight.Models; using WPFFlight.ViewModels; using MessageBox = HandyControl.Controls.MessageBox; namespace WPFFlight.Views; /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : GlowWindow { private MainViewModel mainViewModel; public MainWindow() { InitializeComponent(); #region 注册并接受消息 //WeakReferenceMessenger.Default.Register<CustomizedMessage>(this, (o, m) => { MessageBox.Show("Received!"); }); #endregion mainViewModel = new MainViewModel(); this.DataContext = mainViewModel; } private void MainWindow_OnMouseWheel(object sender, MouseWheelEventArgs e) { if(e.Delta>0) mainViewModel.MoveUp(); else mainViewModel.MoveDown(); mainViewModel.Move(); } }
3 个回复 | 最后更新于 2023-10-07
登录后方可回帖
优化后版本《是男人就上100层》