我正在C#中進行一個簡單的RPG類型的遊戲,它主要是一個原型,只是測試想法(我知道代碼可以改進並且在地方很粗糙,它的工作)。c#RPG從列表中移除
我目前遇到了與戰鬥系統的障礙。
當前,您控制1個字符。你可以面對3個敵人。這是一個基於回合的ATB系統,這部分工作正常。一旦玩家轉向,他們可以選擇攻擊並使用它。
我想添加一個新功能來對時間造成影響。但是,這打破了戰鬥。
我做了一個類來表示一個DOT效果:
public class DoT
{
public int Duration { get; set; }
public int Elapsed { get; set; }
public int Damage { get; set; }
public Enemy Target { get; set; }
public String DName { get; set; }
public DoT()
{
Duration = 3;
Elapsed = 0;
DName = "";
}
public void Tick()
{
Elapsed++;
}
}
這被添加到能力在創建時,而這部分的工作,我可以添加一個DOT效果的能力。
在戰鬥系統中,當選擇攻擊時,我創建了一個名爲DOTS的DOT效果列表。當用戶選擇的攻擊,如果攻擊具有附着到其上的DOT效果,將被添加到的DOT效果列表:
try
{
string s = ((Control)sender).Text;//Stores name of label that triggered the event
int i = s.Length;//can't remember why I added this
if (playerTarget != null)//check that we have a target
{
if (currentTurn.owner == c && canAttack)//if the current turn is ours and we can attack
{
if (c.GetAbility(s).AbilityCost <= c.currentMP)//if we have enough MP for the attack
{
if(c.GetAbility(s).DamageOverTime!=null)//checks if the attack has a DOT effect
{
c.GetAbility(s).DamageOverTime.Target = playerTarget;//the DOT now targets the target
AddDOT(c.GetAbility(s).DamageOverTime);//Adds the DOT effect to DOTS
//Trace statements I was using for debugging
UpdateTest("Added "+ c.GetAbility(s).AbilityName + " to DOT");
UpdateTest("Time left- " + (c.GetAbility(s).DamageOverTime.Duration-c.GetAbility(s).DamageOverTime.Elapsed).ToString());
}
currentTurn.ability = c.GetAbility(s);//Sets the current ability to be used
UseTurn();//Executes a turn
}
else
{
MessageBox.Show("Not enough MP!");
}
}
}
else
{
MessageBox.Show("You must select a target!");
}
}
catch (Exception ex)
{
MessageBox.Show("Error" + ex.ToString());
}
,增加了一個DOT效果的方法是這樣的:
public void AddDOT(DoT d)
{
int exists = 0;
if (DOTS.Count > 0)
{
foreach (DoT dot in DOTS)
{
if (dot.Equals(d))
{
dot.Elapsed = 0;
exists++;
}
}
if(exists==0)
{
DOTS.Add(d);
}
}
else
{
DOTS.Add(d);
}
這是爲了停止應用相同DOT的倍數,如果它已經在那裏,我們只是重置當前DOT流逝的時間。
我也必須在每一輪申請DOT效果的方法:
public void UpdateDots()
{
try
{
if (DOTS.Count > 0)//Check that we have a DOT
{
foreach (DoT d in DOTS)//Loop through each DOT
{
DotDamage(d);//Apply the DOT damage to the DOT's target
d.Tick();//call the tick method of DOT to add 1 to elapsed
//Trace statement to help debug
UpdateTest("Duration on " + d.DName + " is " + (d.Duration - d.Elapsed).ToString());
if (d.Elapsed == d.Duration)//Check if we have ticks left
{
DOTS.Remove(d);//If not, remove the DOT effect
}
}
}
else
{
UpdateTest("No DOTS active");//Trace statement
}
}
catch(Exception ex)
{
MessageBox.Show(ex.ToString());
}
的UpdateDots方法在這裏被稱爲在代碼中使用轉:
public void UseTurn()
{
UpdateDots();//Execute any DOT effects
pause.Tick += new EventHandler(PauseTick);//just a timer to delay each turn, I need to move this
UpdateTest("Owner is..."+currentTurn.owner.characterName);//Trace statement
if (currentTurn.owner == c)//Checks if the current turn is by the player (c=player)
{
if (currentTurn.ability.DamageOverTime == null)//if we aren't applying a DOT
{
if (currentTurn.ability.MultiTarget == false)//If it is single target
{
Attack(c, playerTarget, currentTurn.ability);//Single target attack
}
else
{
MultiAttack(playerTargets, currentTurn.ability);//Multi target attack
}
}
lblPlayerTimer.Width = 0;//Resets the label showing the players ATB bar
currentTurn.owner = null;//Free the current owner to be claimed by other characters
canAttack = false;//Can no longer attack
playerTimer.Start();//Start the players timer again
UpdateAbilities();//Simply used to update the display of abilities
}
else if(currentTurn.owner is Enemy)//If an enemy is attacking
{
Enemy en = (Enemy)currentTurn.owner;//Get the details of the enemy attacking
string n = en.characterName;//this was from previous code
Label l = new Label();
l = Controls.Find(en.timer.lblName ,true).FirstOrDefault() as Label;//Get the label being used as the enemy timer
PickEnemyAttack(en);//Select an attack for the enemy
Attack(en, c, currentTurn.ability);//Execute attack for enemy
l.Width = 0;//Reset the enemy ATB bar
currentTurn.owner = null;//Free up the current turn
//This part is just used to cause a short delay before the next turn
pause.Start();
enemyCanAttack = false;
en.timer.Start();
}
ShowTurn();//Updates display of the current turn
turnCount += 1;
CheckWinner();//Checks if the player has won, or lost
}
問題時,我申請了一個DOT,它被應用並且傷害了敵人。它繼續打勾,直到DOT到期,此時所有定時器都停止。如果沒有DOT效果,那麼戰鬥正常。
這似乎是從DOTS中刪除DOT時造成的。它拋出一個無效操作異常,指出該集合已被修改。是因爲我刪除了一個項目,但是因爲我在ForEach循環中,使用枚舉來刪除這些混亂?
正如你所看到的,我不是一個列表專家,我看不到這個問題,我希望有一個更專業的眼睛可以幫助我解決這個問題。
謝謝。
[InvalidOperationException移除arrayList中的元素後可能的重複](https://stackoverflow.com/questions/12987799/invalidoperationexception-after-re- moving-an-element-in-an-arraylist) – mjwills