【问题标题】:Instantiate different classes depending on option in menu根据菜单中的选项实例化不同的类
【发布时间】:2018-01-26 15:09:37
【问题描述】:

我正在开发一款类似于异星工厂的“简单”游戏,但不是基于网格的。 现在我需要某种系统来跟踪我所有不同的建筑类型并让玩家在菜单中选择一种类型。菜单由UI 类处理,该类调用Game 类中的方法来检查金钱和诸如此类的东西。然后Game 类调用World 类来添加玩家选择的任何建筑。我认为至少这是相关的部分。

正如我现在所拥有的那样,为了存储不同的建筑类型,我有一个名为 BuildInstruction 的类,其子类为 BuildingBuildInstructionConnectionBuildInstruction。这些类只包含 Action thingamabobs,当给定世界坐标/两个连接点时,它会返回一个建筑物/连接。

尽管在Game- 和IU- 类中,我都遇到了这种方法的一些问题。我似乎无法以合乎逻辑的方式在类之间划分工作......

我知道这是一个非常模糊的问题,但对我来说有点难以表述。基本上,如果有人知道这类事情的某种常见做法,那就太棒了……我愿意接受所有建议。

谢谢!

顺便说一句,如果有助于理解,这里有一些代码:

这是我用来将某种层次结构中的选项传递给菜单的方法:

public class Category<T>
{
    public string Label { get; private set; }

    public T Me { get; private set; }

    List<Category<T>> children = new List<Category<T>>();

    public IEnumerable<Category<T>> Children => children;

    public bool HasChildren => children.Count() > 0;

    public Category(string label, List<Category<T>> _children)
    {
        Label = label;
        children = _children;
    }

    public Category(string label, T me)
    {
        Label = label;
        Me = me;
    }
}

这是带有子类的BuildInstruction 类和BuildInstruction 对象的静态列表,然后我将它们提供给菜单。

public abstract class BuildInstruction
{
    public static Category<BuildInstruction> BuildInstructions;

    static BuildInstruction()
    {
        BuildInstructions = new Category<BuildInstruction>("Build", new List<Category<BuildInstruction>>()
        {
            new Category<BuildInstruction>("Powergrid", new List<Category<BuildInstruction>>()
            {
                new Category<BuildInstruction>("Powerline", new ConnectionBuildInstruction(
                    (start, end) =>
                    new Powerline(start as IPowerlineConnectable, end as IPowerlineConnectable)
                ))
            }),
            new Category<BuildInstruction>("Logistics", new List<Category<BuildInstruction>>()
            {
                new Category<BuildInstruction>("Pipeline", new ConnectionBuildInstruction(
                    (start, end) =>
                    new Pipeline(start as IPipelineConnectable, end as IPipelineConnectable)
                )),
                new Category<BuildInstruction>("Stockpile", new BuildingBuildInstruction(
                    (worldPos) =>
                    new Stockpile(worldPos)
                ))
            })
        });
    }

    public string Name { get; protected set; }
}

public class BuildingBuildInstruction : BuildInstruction
{
    Func<PointF, Building> BuildFunction;

    public BuildingBuildInstruction(Func<PointF, Building> buildFunction)
    {
        BuildFunction = buildFunction;

    }

    public Building Build(PointF worldPos)
    {
        return BuildFunction(worldPos);
    }
}

public class ConnectionBuildInstruction : BuildInstruction
{
    Func<IConnectable, IConnectable, Connection> BuildFunction;

    public ConnectionBuildInstruction(Func<IConnectable, IConnectable, Connection> buildFunction)
    {
        BuildFunction = buildFunction;
    }

    public Connection Build(IConnectable start, IConnectable end)
    {
        return BuildFunction(start, end);
    }
}

最后是游戏类:

public class Game
{
    World World = new World();

    public Game()
    {

    }

    public void Update()
    {

    }

    public void Draw(Graphics g)
    {
        World.Draw(g);
    }

    //-----------------------------------------------------

    public void BuyBuilding(Building building)
    {
        if (true) //Check money and whatnot...
        {
            if (ConstructBuilding(building))
            {
                //Success, use money and stuff
            }
            else
            {
                //Fail. Feedback!
            }
        }
        else
        {
            //Not enough money or whatnot. Feedback!
        }
    }

    bool ConstructBuilding(Building building)
    {
        return World.AddWorldObject(new ConstructionSite(building));
        //This ConstructionSite class is just a thing that makes it so that 
        //the actual building-process takes some time in-game
    }
}

我认为UI 类只会令人困惑并且代码过多(已经很多?),但它只是调用Game 中的BuyBuilding() 方法。目前,我有 BuyBuilding() 方法采用 Building 对象,但我真的不知道这是否是一个好方法......

附言。 如果这太模糊太荒谬,那么请不要犹豫,删除它,我只是想看看是否有人在某个地方有任何建议或想法......

再次感谢您! :D

【问题讨论】:

  • 我不确定我是否理解了这个问题,但不妨看看抽象工厂设计模式。
  • @KlitosKyriacou 感谢您的早日回复,我会检查一下! ????

标签: c# class oop instantiation


【解决方案1】:

有很多方法可以做到这一点

一个选项是构建类

public class BuildBuilding
{
    public Point Location{get;set;}
    public BuildingType Type{get;set;}

    public void Create(){
        ///logic for creation here
    }
}

这可以让你连接 INotifyPropertyChanged 或其他一些监控功能,然后你的 UI 可以用来设置类的属性,比如鼠标指向位置和菜单输入

如果您不需要那种复杂程度,一个简单的静态创建器函数就可以工作,这就是您尝试过的方法

public abstract class BuildingType 
{

    public static Building Create(Point location, BuildingType type){
        ///logic for creation here
    }
}

在这里,用户界面必须一次性输入所有参数,但只要您没有太复杂的东西,它是可行的

或者您可以定义接口或虚函数来完成子类中的工作

public abstract class BuildingType 
{
    public abstract Building Create(Point location);//logic in child
}

public interface IBuildable
{
    void Create(Point location)
}

其中任何一个都将强制执行一个抽象句柄,您可以使用它来定义一个没有行为的方法句柄,您可以将您的 UI 连接到每种类型,然后在激活时调用通用函数

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-15
    • 2017-09-07
    • 2019-10-31
    • 1970-01-01
    • 1970-01-01
    • 2017-07-31
    • 2014-03-20
    相关资源
    最近更新 更多