[英]C# Windows Form Application Function Loop
我必须将我在控制台应用程序中创建的RPG游戏转换为用于编程简介类的Windows窗体应用程序。 一切都按预期进行,但后来我不得不改变战斗系统。 以下是调用战斗功能和战斗功能的按钮点击事件:
private void btStoryProgression_Click(object sender, EventArgs e)
{
{...}
else if (flagControl == 20)
{
Enemy enemy = new Enemy("Hellhound", "Oblivion Cave", 1);
if (combat(player, enemy) == true)
{
Lines.Text += "You won!\n";
player.itemList.Add(new Item("Fruit", 22));
}
else
{
Lines.Text = "YOU DIED.";
Lines.Text += "GAME OVER.";
return;
}
}
}
bool combat(Player player, Enemy enemy)
{
Lines.Text = enemy.getName() + " appeared!\n";
int damage;
bool battle = true;
int battleChoice = 0, itemChoice = -1;
turns = 0;
Lines.Text += "What are you going to do?";
buttonVisibility();
buttonChoices("Attack", "Item");
while (battle)
{
if (player.getSpeed() > enemy.getSpeed())
{
//Player turn
if (battleChoice == 1)
{
Lines.Text = player.getName() + " attacked!\n";
if (player.getAccuracy() < 100)
{
Random rnd = new Random();
if (rnd.Next(1, 100) > player.getAccuracy())
{
Lines.Text += "The attack missed!\n";
goto enemyturn;
}
}
damage = player.getAtk() - enemy.getDef();
if (damage < 0)
damage = 0;
enemy.setHP(enemy.getHP() - damage);
if (enemy.getHP() < 0)
enemy.setHP(0);
Lines.Text += "You dealt " + damage + " damage to " + enemy.getName();
Lines.Text += "Enemy HP is now " + enemy.getHP();
if (enemy.getHP() == 0)
return true;
}
else if (battleChoice == 2)
{
Lines.Text += "Your items: ";
foreach (Item item in player.itemList)
{
Lines.Text += item.getName();
}
Lines.Text += "Choose a number based on the order the items appeared";
try
{
do
{
itemChoice = Convert.ToInt32(Console.ReadLine());
itemChoice--;
} while (itemChoice > player.itemList.Count());
}
catch (FormatException)
{
Console.WriteLine("SOMETHING WRONG!!");
}
Lines.Text += "Player HP was: " + player.getHP();
player.setHP(player.getHP() + player.itemList[itemChoice].getRecoverQtd());
Lines.Text += "Player HP is now: " + player.getHP();
player.itemList.RemoveAt(itemChoice);
}
enemyturn:
//Enemy turn
if (battleChoice != 0)
{
Lines.Text += enemy.getName() + " attacked!\n";
damage = enemy.getAtk() - player.getDef();
if (damage < 0)
damage = 0;
player.setHP(player.getHP() - damage);
if (player.getHP() < 0)
player.setHP(0);
Lines.Text += enemy.getName() + " dealt " + damage + " damage to " + player.getName();
Lines.Text += player.getName() + " HP is now " + player.getHP();
}
if (player.getHP() == 0)
return false;
turns++;
}
else
{
enemyturn:
//Enemy turn
if (battleChoice != 0)
{
Lines.Text += enemy.getName() + " attacked!\n";
damage = enemy.getAtk() - player.getDef();
if (damage < 0)
damage = 0;
player.setHP(player.getHP() - damage);
if (player.getHP() < 0)
player.setHP(0);
Lines.Text += enemy.getName() + " dealt " + damage + " damage to " + player.getName();
Lines.Text += player.getName() + " HP is now " + player.getHP();
if (player.getHP() == 0)
return false;
}
//Player turn
if (battleChoice == 1)
{
Lines.Text += player.getName() + " attacked!\n";
if (player.getAccuracy() < 100)
{
Random rnd = new Random();
if (rnd.Next(1, 100) > player.getAccuracy())
{
Lines.Text += "The attack missed!";
goto enemyturn;
}
}
damage = player.getAtk() - enemy.getDef();
if (damage < 0)
damage = 0;
enemy.setHP(enemy.getHP() - damage);
if (enemy.getHP() < 0)
enemy.setHP(0);
Lines.Text += "You dealt " + damage + " damage to " + enemy.getName();
Lines.Text += "Enemy HP is now " + enemy.getHP();
if (enemy.getHP() == 0)
return true;
}
else if (battleChoice == 2)
{
Lines.Text += "Your items: ";
for (int i = 0; i < player.itemList.Count; ++i)
{
Lines.Text += player.itemList[i].getName();
}
Lines.Text += "Choose a number based on the order the items appeared";
}
turns++;
}
return true;
}
基本上,当我按下按钮并且调用战斗时,整个功能被跳过,直到找到一些松散的“其他”,或者,如果我限制每次比较,程序就会冻结。 我做了一些搜索,我看到人们建议使用Delegate或BackgroundWorker,但我仍然对使用它们感到困惑。 这个链接是我发现的最接近我的问题,但它也无法帮助我(也许是因为我是新手......)。
你能帮我吗? 先感谢您 :)
你的第一个问题是你的计算战斗的方法正在GUI线程上运行。 由于它很忙,它实际上无法真正完成更新GUI和GUI冻结的工作。 您永远不应该在GUI线程上执行长时间运行的任务。
你可以使用async和await来修改它,方法是创建一个新的异步方法,然后只需在按钮内运行它:
private async Task RunCombat()
{
Enemy enemy = new Enemy("Hellhound", "Oblivion Cave", 1);
//this next line will run async now and will not block your gui thread.
bool combatResult = await Task.Run(() => combat(player, enemy));
if (combatResult)
{
Lines.Text += "You won!\n";
player.itemList.Add(new Item("Fruit", 22));
}
else
{
Lines.Text = "YOU DIED.";
Lines.Text += "GAME OVER.";
return;
}
然后只需在按钮单击中调用此方法,而不是您已有的方法。 一旦你这样做,你将无法再在你的战斗方法中使用Lines.Text +=
,因为它将在不同的线程上运行。
我将在表单类声明的上方创建一个名为LineAppenderDelegate
的委托:
public delegate void LineAppenderDelegate(string lineToAdd);
然后创建一个AppendLine
方法:
private void AppendLine(string lineToAdd)
{
if(InvokeRequired) //if we are not on the gui thread
{
//re-call the same method on the gui thread
LineAppenderDelegate d = new LineAppenderDelegate(AppendLine);
Invoke(d, new object[]{lineToAdd});
}
else //we are on the gui thread and can just do the work
{
Lines.Text += lineToAdd;
}
}
并使用它来添加行。 这个方法基本上检查你是否在正确的线程上与gui进行交互。 如果你不是,它会回想起gui线程上的方法。 如果你是,它只是做它的工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.