【发布时间】:2021-12-15 13:01:54
【问题描述】:
我使用 WPF(Flappy Bird 的克隆)在 C# 中制作了我的第一款游戏,代码隐藏如下:
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
namespace FlappyBirdWPF
{
public partial class MainWindow : Window
{
private readonly MediaPlayer player = new MediaPlayer();
private readonly MediaPlayer player2 = new MediaPlayer();
private readonly DispatcherTimer gameTimer = new DispatcherTimer();
private readonly Random pipePos = new Random();
private double highscore = double.Parse(File.ReadAllText(@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\highscore.txt"));
private double score, counter = 5;
private int gravity = 8;
private Rect birdHitbox;
private bool isGameOver;
public MainWindow()
{
InitializeComponent();
gameTimer.Tick += MainEventTimer;
gameTimer.Interval = TimeSpan.FromMilliseconds(20);
StartGame();
}
private void MainEventTimer(object sender, EventArgs e)
{
txtScore.Content = $"Score: {score}";
txtHighscore.Content = $"Highscore: {highscore}";
gameOver.Content = "";
birdHitbox = new Rect(Canvas.GetLeft(bird), Canvas.GetTop(bird), bird.Width - 12, bird.Height - 15);
Canvas.SetTop(bird, Canvas.GetTop(bird) + gravity);
if (Canvas.GetTop(bird) < -10 || Canvas.GetTop(bird) > 370) EndGame();
foreach (var img in MyCanvas.Children.OfType<Image>())
{
if ((string)img.Tag == "obs1" || (string)img.Tag == "obs2" || (string)img.Tag == "obs3")
{
Canvas.SetLeft(img, Canvas.GetLeft(img) - counter);
if (Canvas.GetLeft(img) < -60)
{
Canvas.SetLeft(img, 800);
if ((string)img.Tag == "obs1")
{
Canvas.SetTop(obs1Top, pipePos.Next(150, 350) * -1);
Canvas.SetTop(obs1Bot, Canvas.GetTop(obs1Top) + 500);
}
if ((string)img.Tag == "obs2")
{
Canvas.SetTop(obs2Top, pipePos.Next(150, 350) * -1);
Canvas.SetTop(obs2Bot, Canvas.GetTop(obs2Top) + 500);
}
if ((string)img.Tag == "obs3")
{
Canvas.SetTop(obs3Top, pipePos.Next(150, 350) * -1);
Canvas.SetTop(obs3Bot, Canvas.GetTop(obs3Top) + 500);
}
counter += 0.1;
score += 0.5;
player2.Open(new Uri(@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\audio\blip.wav"));
player2.Play();
}
Rect pipeHitbox = new Rect(Canvas.GetLeft(img), Canvas.GetTop(img), img.Width, img.Height);
if (birdHitbox.IntersectsWith(pipeHitbox)) EndGame();
}
if ((string)img.Tag == "cloud")
{
Canvas.SetLeft(img, Canvas.GetLeft(img) - 2);
if (Canvas.GetLeft(img) < -250) Canvas.SetLeft(img, 550);
}
if ((string)img.Tag == "ground")
{
Canvas.SetLeft(img, Canvas.GetLeft(img) - counter);
if (Canvas.GetLeft(img) < -525)
{
if (img.Name == "ground1") Canvas.SetLeft(img, 510);
if (img.Name == "ground2") Canvas.SetLeft(img, Canvas.GetLeft(ground1) + 524);
}
}
}
}
private void KeyIsDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space && !isGameOver)
{
bird.RenderTransform = new RotateTransform(-20, bird.Width / 2, bird.Height / 2);
gravity = -8;
}
if (e.Key == Key.R)
{
StartGame();
}
if (e.Key == Key.Escape && isGameOver)
{
Application.Current.Shutdown();
}
}
private void KeyIsUp(object sender, KeyEventArgs e)
{
bird.RenderTransform = new RotateTransform(5, bird.Width / 2, bird.Height / 2);
gravity = 8;
}
private void StartGame()
{
MyCanvas.Focus();
player.Open(new Uri(@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\audio\bgm.wav"));
player.Play();
bird.Source = new BitmapImage(new Uri($"assets/images/bird.png", UriKind.RelativeOrAbsolute));
isGameOver = false;
score = 0;
counter = 5;
int cloudGap = 250;
Canvas.SetTop(bird, 190);
foreach (var img in MyCanvas.Children.OfType<Image>())
{
if ((string)img.Tag == "obs1") Canvas.SetLeft(img, 500);
if ((string)img.Tag == "obs2") Canvas.SetLeft(img, 800);
if ((string)img.Tag == "obs3") Canvas.SetLeft(img, 1100);
if ((string)img.Tag == "cloud")
{
Canvas.SetLeft(img, 250 + cloudGap);
cloudGap = 850;
}
if (img.Name == "ground1")
{
Canvas.SetLeft(img, 0);
}
if (img.Name == "ground2")
{
Canvas.SetLeft(img, 520);
}
}
gameTimer.Start();
}
private void EndGame()
{
if (score > highscore)
{
highscore = score;
using (StreamWriter file = new StreamWriter(@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\highscore.txt"))
{
file.Write(highscore.ToString());
}
}
player.Stop();
player.Open(new Uri(@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\audio\boom.wav"));
player.Play();
gameTimer.Stop();
isGameOver = true;
bird.Source = new BitmapImage(new Uri($"assets/images/deadBird.png", UriKind.RelativeOrAbsolute));
gameOver.Content = " Game over! \n Press 'R' to play again.\n" +
"...or press 'Esc' to quit... loser.";
}
}
}
在某些情况下,您可以看到我能够成功地使用 $"assets/images/deadBird.png" 之类的东西来引用文件而无需指定整个本地路径,但在某些情况下,我不被允许这样做并且必须使用完整路径喜欢@"C:\Users\nikan\source\repos\Flappy Cat\Flappy Cat\assets\audio\boom.wav"。有解决方法吗?任何建议都值得赞赏,我只在 c# 中工作了大约 2 个月!
【问题讨论】:
-
你为什么在所有这些地方都使用 Uri?
-
作为资产的文件通常位于相对于可执行文件的位置,而不是在当前工作目录中。您必须找到一种方法来获取可执行文件所在的目录(可能是 Reflection.Assembly.GetEntryAssembly().Location),然后使用 System.IO.Path 中的函数来形成文件的路径(Combine、GetFullPath 、GetDirectoryName 等)。尝试前进的道路。不要硬编码斜线。
-
当前工作目录应该由应用程序的用户控制,而不是开发者。应该只处理用户应该使用和可能修改的文件,而不是应用程序提供的文件(例如 Word 应用程序的 Word 文档、Excel 应用程序的 Excel 文件、电影播放器的任何电影文件)应该被处理通过当前工作目录。当前工作目录可以更改为用户选择的任何内容。不要以编程方式弄乱当前工作目录,除非是为了帮助用户找到用户自己的文件。
-
与您的程序一起部署的只读文件通常位于相对于您的可执行文件的位置,可能位于子文件夹中。当您在开发过程中启动应用程序时,当前工作目录和可执行文件目录通常恰好是同一个文件夹,但不要因此而误以为您制作了一个有缺陷的应用程序。