- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我已经开始使用 C#/XNA 编写 2d JRPG 引擎代码,我对类结构和游戏事件有一些疑问。
在“游戏制作者”类型的环境中,您有一个游戏脚本,它根据用户输入运行事件等。这通常不是 OO,也没有对类等的引用。
现在在我自己的引擎中,编写游戏事件代码的最佳方式是什么?
假设您在屏幕上与 NPC 互动,该事件将如何用 OO 语言处理?我假设我会在角色类中有一个事件,并且我假设该事件将分配给加载 map 的部分,但该事件将链接到哪里?哪个类将包含事件逻辑?
编辑:我应该指出,我不想将它变成一个完全可定制的引擎供其他人使用,因此完整的脚本语言实现并不是我真正想要的。
class Character {
...
public delegate void InteractionEventHandler(object sender, EventArgs e);
...
public event InteractionEventHandler Interact;
...
}
class Map {
public Map(){
...
//add a new character to the NPC collection
newchar.Interact += ???
...
}
}
目前我的类结构相当简陋,因为我需要在进一步解决之前解决这个问题,但它看起来像这样。
Main 类包含 Map 类的一个实例。
Map 类通过内容管道加载 xml 中的 map 。
map 实例包含对 map 中包含的所有对象和 NPC 的引用。
Map 类创建这些对象的新实例,它们都继承自 Drawable 类,其中包含将对象绘制到屏幕所需的基本方法和属性。这些实例都被添加到 Map 类中的一个集合中。
Character 类是从 Drawable 类继承的类之一,将包含 Interact 事件。
正如我所说,该项目基于固定时间步长的 XNA 框架,因此引擎在每个时间点运行 Main 类中的 Update 和 Draw 方法。
更新方法包含处理玩家输入的逻辑。因此玩家可以移动到 map 上的 NPC 并按下交互按钮。逻辑检查玩家面前的 NPC 并触发其交互事件...然后会发生什么?
最佳答案
事件不应附加任何逻辑;它们只是一条消息,一种告诉感兴趣的组件发生了什么的技术,但是如何处理事件是所述组件(又名监听器)的责任。在您的情况下,这是您的 NPC。
但我不明白您关于“事件不是 OO”的论点,是什么让您相信这一点?不能面向对象的事件是怎么回事?
现在关于如何处理事件和整个流程,我没有使用 C# 的经验,但我已经完成了 C++ 的分享,这是我反复使用的一种方法,它足够灵活,可以满足我的需求:
我有一个事件元类,每个特定 事件都可以从中继承(即,UI 事件、NPC 事件等)。还有一个 EventManager 可以创建和销毁所有事件(“Emitters”,需要触发事件的组件,将为实例调用管理器,即 GameObjects),最重要的是,它有处理队列。
Emitter 对象会将事件“ Hook ”到队列,EventManager 会将它们分派(dispatch)给“Listeners”。现在,Listener 对事件感兴趣,因此可以将自己注册到某些事件或其类型。一旦管理器向这些监听器分派(dispatch)了一个事件,它们就可以从那里执行与该事件相关的逻辑。
最终,我必须保留子类化的事件元类的设计对我来说不是很灵活,而且是一项乏味的工作,所以我采用了另一种方法,我可以将属性任意附加到事件对象,并且处理组件必须知道如何处理它。这当然会对性能产生影响,但在某种程度上这对我来说是必要的,因为我在 Lua 中触发和处理事件逻辑,而不是在 C++ 中。
如果您正在制作一款 RPG 游戏,那么事件和脚本几乎是您游戏的主体,在开始编写代码之前,您确实需要对这两个方面进行清晰的设计。我建议阅读有关 Gamedev.net 的事件处理文章一开始。
最后,我不确定它是否对你有帮助,但我在用 C++/Lua 制作网络游戏时发布了一次关于事件的帖子,考虑到网络的性质,设计可能比你需要的更复杂游戏,但你可以看看here无论如何。
更新:我将向您展示我将如何使用我的系统的示例,但我必须首先明确:您使用 C# 和 XNA 是有原因的,而我不能误以为 XNA 提供了您所需要的东西,所以我建议不要使用我的事件管理系统或任何人的事件管理系统,因为我的事件管理系统与 C++ 及其模板机制紧密耦合,可能对您没有用。该框架应该可以满足您的需求,因此请先检查一下。
// singleton
class EventManager {
public:
Event* createEvt<EventType*>();
void subscribe(Event*, Listener*);
void hook(Event*);
void update();
}
class Listener {
// tells evt manager we want to listen to these events
void register(Event* someEvtType, Handler* myMethod);
// adds event to the queue (called by the EventManager)
void enqueue(Event* someEvt);
// processes events in the queue
void process();
protected:
// calls every subscribed handler to process the event
// a handler is only a functor that is bound to an event
// when calling "register()"
void dispatch(Event*);
map<Event*, list<Handler*>> myHandlers; // an event could have multiple handlers (methods)
}
class GameObject : public Listener {
}
class NPC : public GameObject {
protected:
void walkTo(NPCEvent_Walk* evt);
void talk(NPCEvent_Talk* evt);
}
// inside wherever you're gonna trigger the event, i presumed on mouseclick here
void InputManager::mouseClicked(MouseEvent* evt) {
// we want the NPC to move
NPCEvent_Walk* evtWalk = EventManager->createEvt<NPCEvent_Walk>();
evtWalk->setX(...);
evtWalk->setY(...);
// and talk
NPCEvent_Talk* evtTalk = EventManager->createEvt<NPCEvent_Talk>();
evtTalk->setText(...);
// when the master queue is empty, these events will be
// dispatched to their registered Listeners which will
// process them on their own terms
EventManager->hook(evtWalk);
EventManager->hook(evtTalk);
}
// as an NPC, i'd like to be notified of NPCEvents
NPC::NPC() {
register(NPCEvent_Walk*, &NPC::walkTo);
register(NPCEvent_Talk*, &NPC::talk);
}
void NPC::walkTo(NPCEvent_Walk*) {
// move it
// ...
// are we done?
// return true;
// if we need more updates, return false and we will be called again
// return false;
}
void NPC::talk(NPCEvent_Talk*) {
// update UI components or whatever
// ...
return true;
}
显然,这段代码将无法工作,因为它缺少所有实现细节,甚至在语法上也不正确,但它应该会给您一个想法。但是,正如我上面所说,如果您使用的是 XNA,则不需要执行此操作。
关于c# - 引擎脚本和类结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4089900/
我目前正在尝试基于哈希表构建字典。逻辑是:有一个名为 HashTable 的结构,其中包含以下内容: HashFunc HashFunc; PrintFunc PrintEntry; CompareF
如果我有一个指向结构/对象的指针,并且该结构/对象包含另外两个指向其他对象的指针,并且我想删除“包含这两个指针的对象而不破坏它所持有的指针”——我该怎么做这样做吗? 指向对象 A 的指针(包含指向对象
像这样的代码 package main import "fmt" type Hello struct { ID int Raw string } type World []*Hell
我有一个采用以下格式的 CSV: Module, Topic, Sub-topic 它需要能够导入到具有以下格式的 MySQL 数据库中: CREATE TABLE `modules` ( `id
通常我使用类似的东西 copy((uint8_t*)&POD, (uint8_t*)(&POD + 1 ), back_inserter(rawData)); copy((uint8_t*)&PODV
错误 : 联合只能在具有兼容列类型的表上执行。 结构(层:字符串,skyward_number:字符串,skyward_points:字符串)<> 结构(skyward_number:字符串,层:字符
我有一个指向结构的指针数组,我正在尝试使用它们进行 while 循环。我对如何准确初始化它并不完全有信心,但我一直这样做: Entry *newEntry = malloc(sizeof(Entry)
我正在学习 C,我的问题可能很愚蠢,但我很困惑。在这样的函数中: int afunction(somevariables) { if (someconditions)
我现在正在做一项编程作业,我并没有真正完全掌握链接,因为我们还没有涉及它。但是我觉得我需要它来做我想做的事情,因为数组还不够 我创建了一个结构,如下 struct node { float coef;
给定以下代码片段: #include #include #define MAX_SIZE 15 typedef struct{ int touchdowns; int intercepti
struct contact list[3]; int checknullarray() { for(int x=0;x<10;x++) { if(strlen(con
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Empty “for” loop in Facebook ajax what does AJAX call
我刚刚在反射器中浏览了一个文件,并在结构构造函数中看到了这个: this = new Binder.SyntaxNodeOrToken(); 我以前从未见过该术语。有人能解释一下这个赋值在 C# 中的
我经常使用字符串常量,例如: DICT_KEY1 = 'DICT_KEY1' DICT_KEY2 = 'DICT_KEY2' ... 很多时候我不介意实际的文字是什么,只要它们是独一无二的并且对人类读
我是 C 的新手,我不明白为什么下面的代码不起作用: typedef struct{ uint8_t a; uint8_t* b; } test_struct; test_struct
您能否制作一个行为类似于内置类之一的结构,您可以在其中直接分配值而无需调用属性? 前任: RoundedDouble count; count = 5; 而不是使用 RoundedDouble cou
这是我的代码: #include typedef struct { const char *description; float value; int age; } swag
在创建嵌套列表时,我认为 R 具有对列表元素有用的命名结构。我有一个列表列表,并希望应用包含在任何列表中的每个向量的函数。 lapply这样做但随后剥离了列表的命名结构。我该怎么办 lapply嵌套列
我正在做一个用于学习目的的个人组织者,我从来没有使用过 XML,所以我不确定我的解决方案是否是最好的。这是我附带的 XML 文件的基本结构:
我是新来的 nosql概念,所以当我开始学习时 PouchDB ,我找到了这个转换表。我的困惑是,如何PouchDB如果可以说我有多个表,是否意味着我需要创建多个数据库?因为根据我在 pouchdb
我是一名优秀的程序员,十分优秀!