好吧,我需要一些可靠的OOP建议。设置是这样的:我有一个player对象,里面有处理移动、寻路逻辑等事情的代码。现在我需要给每个player分配一个大的变量和设置表。也就是说,每个玩家可以执行大约40个不同的武器动作,每个武器有6-8个与之相关的变量。我的问题是,哪种数据结构最合适。注意,我不想为每个武器创建一个类,因为在我的游戏中武器永远不会被实例化。
以下是细节:每个玩家都有40种不同的武器,需要按名称拉动。例如:
Weapon #1: Pistol
Weapon #2: Shotgun
Weapon #3: Rifle
Weapon #4: Bow
Weapon #5: RocketLauncher然后,每个武器都有相同的一组变量分配给它。例如:
Pistol.HasBeenUnlocked (true/false)
Pistol.Priority (1-40)
Pistol.AmmoQuantityMax (0-10)
Pistol.AmmoQuantityCurrent (0-10)
Pistol.UIButtonState ("Hidden", "Selected", "Deselected", "CoolOff")
Pistol.CoolOffTimerMax (0.0-5.0)
Pistol.CoolOffOn (true/false)现在,我需要某种数据结构来组织所有这些变量,并使它们易于访问。例如,我希望能够遍历所有40个武器,并根据它们是否被特定玩家解锁来为它们生成按钮。这是我想要做的:
for (int i = 0; i < Player.Weapons.NumberOfWeaponsTotal(); i++) {
if (Player.Weapons.Weapon[i].UIButtonState == "Hidden"){
// don't create a UI button to fire weapon
}
else {
// create a UI button to fire weapon
}
}不同武器的变量名称将是相同的。因此,和Weapons.Rifle.UIButtonState一样,Weapons.Pistol.UIButtonState也将存在。
那么组织这件事的最佳方式是什么呢?二维数组并不美观。一个结构似乎不够健壮。一个类看起来很奇怪。我从来没有使用过类来处理这类事情。我想要确保这与玩家有某种联系,所以当他被摧毁时,这个“物体”也是如此。
发布于 2011-06-24 06:38:19
定义一个包含所有不同武器所具有的所有属性的结构或类类型。创建此武器类型的array40,并将其存储为播放器类型的属性。定义一个into枚举,用作武器数组中的命名索引。在你的代码中使用这些枚举名称来索引武器数组。
在极少数情况下,当您确实需要通过字符串名称查找武器时,您只需扫描武器数组,直到找到与您要查找的武器名称相匹配的武器。捕获该武器的索引并丢弃字符串名,以便所有后续操作都通过索引数组进行。对40个项目进行线性扫描的成本将不会很明显。
如果您确实必须避免扫描列表以查找匹配的名称,则可以构造一个字典来提供按名称的快速查找。您希望字典条目返回特定玩家的武器,因此您需要为每个玩家提供一个不同的字典实例,并将其存储在player对象的一个字段中。如果简单的扫描就足够了(几乎可以肯定是这样),那么就不要费心使用字典方法。
无论您将武器类型定义为结构还是类,它都是结构化类型,并且每次使用它时都会创建此类型的实例。每个播放器40个实例。class和struct之间的主要区别在于内存是在哪里/如何分配的,以及赋值是否复制值。如果您非常小心,从不将数组中的武器赋值给本地武器变量,并且不使用上面的字典或执行任何其他需要共享对相同武器数据的引用的操作,那么struct应该没问题。如果有疑问,可以使用class。
你不需要担心当玩家离开时武器会被丢弃--只要武器数组是唯一长期参考武器的东西,那么当玩家被丢弃时,它们都会被丢弃。适当的封装和最小化不同对象之间的交叉引用在这里会有所帮助。
如果您确定您选择的武器将始终具有相同的变量和相同的操作(方法),那么您可以为所有武器使用单一的武器类型,该类型可以是结构或类。
如果您开始遇到该武器的此操作行为不同的特殊情况,或者此武器具有其他武器都不需要的额外数据,那么您应该考虑根据需要定义基本武器类及其后代以进行专门化。
发布于 2011-06-24 06:24:14
我认为类对于这个场景来说是很理想的。创建一个具有Name、GetAmmoCount()、IsEnabled等常见属性和方法的IWeapon接口,然后为每种类型的武器创建具有所有特定属性的类。(但如果您有8个不同的手枪,具有相同的方法和属性,则可以创建一个泛型Pistol类并相应地设置变量)。
在Player对象中,有一个List<IWeapon>来保存玩家拥有的所有武器。
当Player被销毁时,只需调用列表上的.Empty()方法即可将其全部删除。
持有的武器将是Player类的另一个成员:IWeapon ActiveWeapon。
你可以这样做:
if(ActiveWeapon.GetAmmoCount() > 0) ActiveWeapon.Fire());或者:
this.ActiveWeapon = new Pistol("LaserPistol");
this.Weapons.Add(this.ActiveWeapon);
this.ActiveWeapon = new AssaultRifle();这样做的好处是,在运行时之前,您的Player不必确切知道它们可能拥有哪些类型的武器,您可以轻松地将它们替换为其他类型的武器。
编辑:我找到一个页面,它使用Strategy design pattern:http://hnaser.blogspot.com/2009/07/abc-of-design-patterns.html提供了一个示例
发布于 2011-06-24 13:03:21
免责声明
您可以使用这样的模型来获取您需要的内容。请记住,与任何设计一样,它也可能包含缺陷。它的目的是帮助您解决问题,而不是作为一种解决方案。
武器
这个类代表了你的应用中的一个武器。注意覆盖方法,以便正确地实现比较/搜索/索引。
public class Weapon
{
public Weapon(WeaponName name)
{
Name = name;
}
public WeaponName Name { get; set; }
public int Priority { get; set; }
public int MaxAmmoQuantity { get; set; }
public int CurrentAmmoQuantity { get; set; }
public override string ToString()
{
return Enum.GetName(typeof(WeaponName), Name);
}
public override bool Equals(object obj)
{
if (obj == null) return false;
var other = obj as Weapon;
if (other == null) return false;
return Name == other.Name;
}
public override int GetHashCode()
{
return Name.GetHashCode();
}
}WeaponName
修正了武器名称的选项(假设,如你所说,它们的选项有限)
public enum WeaponName
{
Pistol,
Shotgun,
Rifle,
Bow,
RocketLauncher
}播放器
请注意:
公有类播放器{私有只读IList _ownedWeapons =新列表();受保护武器ActiveWeapon { get;私有集合;}
public IEnumerable OwnedWeapons { get;set;} public event EventHandler WeaponGrabbed;public event EventHandler ActiveWeaponChanged;public void (){ var handler = ActiveWeaponChanged;if (handler != null) handler(this,new WeaponEventArgs( ActiveWeapon ));} public void (武器){ var handler = WeaponGrabbed;if (handler != null) handler(this,new WeaponEventArgs(武器));} public void (WeaponName weaponName) {ActiveWeapon=_ownedWeapons.Where(en22 => )();InvokeActiveWeaponChanged();} public void Grab(武器武器){_ownedWeapons.Add(武器);InvokeWeaponGrabbed(武器);}
}
公共类武器: EventArgs {公共WeaponEventArgs (武器武器){WeaponEventArgs=武器;}
公共武器{ get;set;} }
WeaponsRepository
公共类WeaponRepository { readonly Dictionary> _availableWeapons =新Dictionary>();
公共武器() { _availableWeapons.Add(WeaponName.Pistol,() => new Weapon(WeaponName.Pistol) );_availableWeapons.Add(WeaponName.Shotgun,() => new Weapon(WeaponName.Shotgun) );}公共武器创建(WeaponName name) { return _availableWeaponsname;}公共IEnumerable AvailableWeapons() { return Enum.GetValues(typeof (WeaponName)).Cast();}公有IEnumerable播放器(播放器){WeaponsNotOwnedBy AvailableWeapons().Where(weaponName => !player.OwnedWeapons.Contains(weaponName));}
}
使用
注意:为简洁起见,我省略了WeaponButton
public class WeaponToolbarBuilder
{
private readonly Player _player;
private readonly WeaponRepository _weaponRepository;
private List<WeaponButton> _buttons = new List<WeaponButton>();
public WeaponToolbarBuilder(Player player, WeaponRepository weaponRepository)
{
_player = player;
_weaponRepository = weaponRepository;
_player.ActiveWeaponChanged += _player_ActiveWeaponChanged;
_player.WeaponGrabbed += _player_WeaponGrabbed;
}
void _player_WeaponGrabbed(object sender, WeaponEventArgs e)
{
var weaponButton = _buttons.Where(button => button.WeaponName == e.Weapon.Name).First();
weaponButton.Enable();
}
void _player_ActiveWeaponChanged(object sender, WeaponEventArgs e)
{
var currentActiveButton = _buttons.Where(button => button.Highlighted).First();
currentActiveButton.Highlight(false);
var newActiveButton = _buttons.Where(button => button.WeaponName == e.Weapon.Name);
newActiveButton.Highlight(true);
}
public void BuildToolbar() { ... }
}https://stackoverflow.com/questions/6461268
复制相似问题