Я работаю над ролевой игрой играющего для забавы и практиковать шаблоны разработки. Я хотел бы, чтобы плееры смогли преобразоваться в различных животных. Например, Друид смог формировать сдвиг в гепарда. Прямо сейчас я - планирование использования шаблона "декоратор", чтобы сделать это, но мой вопрос - как я делаю его так, чтобы, когда друид находится в форме гепарда, они могли только получить доступ к навыкам для гепарда? Другими словами, они не должны мочь получить доступ к своим нормальным навыкам Друида.
Используя шаблон "декоратор" кажется, что даже у гепарда формируются, мой друид сможет получить доступ к их нормальным навыкам друида.
class Druid : Character
{
// many cool druid skills and spells
void LightHeal(Character target) { }
}
abstract class CharacterDecorator : Character
{
Character DecoratedCharacter;
}
class CheetahForm : CharacterDecorator
{
Character DecoratedCharacter;
public CheetahForm(Character decoratedCharacter)
{
DecoratedCharacter= decoratedCharacter;
}
// many cool cheetah related skills
void CheetahRun()
{
// let player move very fast
}
}
теперь использование классов
Druid myDruid = new Druid();
myDruid.LightHeal(myDruid); // casting light heal here is fine
myDruid = new CheetahForm(myDruid);
myDruid.LightHeal(myDruid); // casting here should not be allowed
Hmmmm... теперь, когда я думаю об этом, будет myDruid быть неспособным нам Druid
написания/навыки класса, если класс не является вниз литым? Но даже если это имеет место, там лучший способ гарантировать это myDruid
в этой точке заблокирован из всех Druid
связанные написания/навыки, пока это не брошено к a Druid
(так как в настоящее время это находится в CheetahForm
)
Dependency Walker (depends.exe) wqs изначально записан для устранения неполадок DLL, но его режим профилирования полезнее. Он может использоваться для сбора большого количества информации о создании процессов. Было бы интересно посмотреть, какие DLL нужны, и какие из них были загружены в момент приглашения UAC. Также вполне возможно, что в выходных данных Depenceny Walker явно упоминается UAC.
-121--4144567-Скомпилировать класс C # в собственной библиотеке классов C # (DLL), а затем в проекте VB добавить ссылку на библиотеку C # DLL. Затем можно использовать класс в проекте VB.
Однако если требуется включить исходный код класса C # в проект VB, необходимо преобразовать класс из C # в VB. Существуют различные методы для этого, такие как интерактивный инструмент Преобразовать C # в VB.NET
-121--3527909-Вы не должны иметь заклинания и навыки в качестве метода в классе. Они должны представлять собой набор объектов периодов и навыков, доступ к которым осуществляется через интерфейс Character (или, возможно, Creature). Тогда ваш CheetaForm может переопределить методы getSkills getSpells, чтобы вернуть новую измененную коллекцию соответствующих навыков.
Возможно, вместо того, чтобы помещать набор навыков для Друида в класс Друида, вы могли бы перенести этот набор навыков в сам декоратор.
Druid myDruid = new Druid();
myDruid = new StandardDruid(myDruid);
Игнорируя класс с ужасным названием "StandardDruid", я надеюсь, вы понимаете, к чему я клоню:)
У такой схемы есть свои плюсы, а именно то, что весь ваш код, основанный на навыках, будет последовательно содержаться внутри декораторов, а не половина внутри исходного класса Друид, а остальные навыки в декораторах. Если бы у вас был другой класс, который мог бы трансформироваться в друида, вы могли бы легко сделать это без дублирования кода.
Я бы решил эту проблему, изменив метод LightHeal
на виртуальный, а затем переопределив его в классе CheetahForm
на либо генерировать исключение, либо показывать пользователю сообщение о том, что он не может этого сделать прямо сейчас:
class Druid : Character
{
// many cool druid skills and spells
virtual void LightHeal(Character target) { }
}
abstract class CharacterDecorator : Character
{
Character DecoratedCharacter;
}
class CheetahForm : CharacterDecorator
{
Character DecoratedCharacter;
public CheetahDecorator(Character decoratedCharacter)
{
DecoratedCharacter= decoratedCharacter;
}
// many cool cheetah related skills
void CheetahRun()
{
// let player move very fast
}
override void LightHeal(Character target)
{
ShowPlayerMessage("You cannot do that while shape shifted.");
}
}
Каждый раз, когда я играю в игру, которая включает этот тип сценария (например, World of Warcraft), пользовательский интерфейс изменяется, чтобы предотвратить использование этих заклинаний , но пользователь по-прежнему может попытаться сотворить эти заклинания с помощью макросов, и поэтому такая обработка помогает остановить это.
Я не думаю, что есть способ «спрятать» метод без использования интерфейса
вместо класса для описания CheetahForm
, поскольку ссылка на него только показать методы, доступные из интерфейса
.
Вместо того, чтобы делать Druid производным классом от Character, рассмотрите возможность использования объекта типа шаблон. Во-первых, разделите навыки, специфичные для классов персонажей, на их собственные объекты:
abstract class Skill
{
void Perform();
}
class LightHeal : Skill
{
public void Perform()
{
// stuff...
}
}
class CheetahRun : Skill
{
public void Perform()
{
// stuff...
}
}
// other skill classes...
Теперь избавьтесь от производных классов персонажей, сделав вместо этого следующее:
class CharacterType
{
public readonly List<Skill> Skills = new List<Skill>();
}
class Character
{
public IEnumerable<Skill> Skills { get { return mType.Skills; } }
private CharacterType mType;
}
«Классы» ваших персонажей теперь могут быть созданы как объекты ]:
CharacterType druid = new CharacterType();
druid.Skills.Add(new LightHeal());
CharacterType cheetah = new CharacterType();
cheetah.Skills.Add(new CheetahRun());
Теперь, изменив mType
в Персонаже
с druid
на cheetah
, вы можете фактически изменить его класс и поменять доступные навыки.
Я бы просто создал свойство в классе друида "Форма" и проверил бы при наложении заклинания, трансформируется ли друид или нет.
Как насчет этого?
interface ISkillState { ... }
interface ISkill { ... }
interface IForm
{
Collection<ISkill> skills { get; set; }
Dictionary<ISkill,ISkillState> skillStates { get; set; }
}
class Character
{
private IForm actualForm;
private Collection<IForm> currentForms;
...
}
и например:
class Spell : ISkill {}
class SpellState : ISkillState {}
Извините, что сообщаю вам, ребята, но вы все ошибаетесь, пытаясь использовать молоток по предмету, который не является гвоздем :-P
Чтобы решить вашу проблему с mikedev, вам нужно выйти за рамки ООП, поскольку ООП не может решить эту проблему должным образом. Взгляните на Entity Systems / Component Systems.
Сначала вам следует прочитать http://www.devmaster.net/articles/oo-game-design/
Тогда ваше путешествие в мир игрового дизайна начнется.