输入管理器
在本章中,您将会学习到:
- 如何设置输入管理器
- 如何屏蔽触摸
输入管理器
目前而言,在 Note
原型的输入逻辑中还有最后一件缺失的东西: 当两个音符距离非常近并且用户击打了,我们只想要击打被注册在一个音符而不是两个。
这就需要有一个中心实体来协调所有的音符: InputManager
。
让我们设置一个输入管理器,我们只需要在谱面转换器中新增一个 InputManagerEntity
并在游玩模式中实现即可。
class InputManagerEntity: public LevelEntity {
public:
defineArchetypeName("My Input Manager");
};
// ...
string fromTXT(string path) {
// ...
levelData.append(InputManagerEntity()); // 插入一个 InputManager 实体
// ...
}
由于任何带有没有实现的原型名的实体会被忽略,因此我们只需要在游玩模式中实现输入管理器,在其它模式中忽略,就可以只在游玩模式中生成了。
接下来,让我们初始化一个 InputManager
原型:
class InputManager: public Archetype {
public:
static constexpr const char* name = "My Input Manager";
};
// ...
#ifdef play
using namespace playData;
#include"play/Initialization.cpp"
+ #include"play/InputManager.cpp"
#include"play/Stage.cpp"
#include"play/Note.cpp"
#elif tutorial
// ...
// ...
#ifdef play
buffer data, configuration;
build<
// Replace with your archetypes here
Initialization,
+ InputManager,
Stage,
Note
>(configuration, data);
// ...
使用过的触摸
为了屏蔽输入,我们可以使用一个映射表存储所有我们使用过的触摸,并在使用前检查一个触摸是否被使用过。
但我们如果共享可变数据?我们可以使用 LevelMemory
区块来实现:
Map<LevelMemoryId, var, var> usedTouchIds(16);
// ...
现在我们可以实现两种函数来让我们与之交互:
// ...
auto isUsed = [](Touch touch){ return usedTouchIds.indexOf(touch.id) != -1; };
auto markAsUsed = [](Touch touch){ FUNCBEGIN usedTouchIds.set(touch.id, 1); return VOID; };
// ...
最后,在每一帧里我们应该清除使用过的触摸,来让我们的映射表不会无限增长:
// ...
class InputManager: public Archetype {
// ...
SonolusApi touch() {
FUNCBEGIN
usedTouchIds.clear();
return VOID;
}
};
输入屏蔽
有了输入管理器,我们现在可以将输入屏蔽添加到 Note
原型的输入逻辑中了。
但首先,我们需要保证 Note
原型的 touch
回调函数会在输入管理器后执行。我们可以通过设置一个更高的序号来达成这个目的:
class Note: public Archetype {
// ...
int touchOrder = 1;
// ...
};
现在,输入屏蔽就是简单地检查一个触摸是否已经在之前被使用过了,并在使用时标记已使用:
class Note: public Archetype {
// ...
SonolusApi touch() {
FUNCBEGIN
// ...
FOR (i, 0, touches.size, 1) {
// ...
IF (isUsed(touches[i])) CONTINUE; FI
markAsUsed(touches[i]);
// ...
} DONE
return VOID;
}
// ...
};
TIP
本章节中示例的输入管理器只是最基础的输入管理器。
在实际引擎编写中,您可能需要更为复杂的输入管理器,来更好地实现输入屏蔽的功能。
当然,在有多种键型的节奏游戏中,您可能不仅需要实现击打输入管理器,还需要实现滑键输入管理器,这取决于您具体的游戏机制。