दो विकल्प: यदि "नेस्टेड इनपुट" मामले सबसे अधिक तीन, चार हैं, तो मैं सिर्फ झंडे का उपयोग करूंगा। "किसी वस्तु को पकड़ना? आग नहीं लग सकती।" कुछ भी हो वह इसे खत्म कर रहा है।
अन्यथा, आप ईवेंट हैंडलर्स के प्रति-इनपुट-कुंजी स्टैक रख सकते हैं।
Actions.Empty = () => { return; };
if(IsPressed(Keys.E)) {
keyEventHandlers[Keys.E].Push(Actions.Empty);
keyEventHandlers[Keys.LeftMouseButton].Push(Actions.Empty);
keyEventHandlers[Keys.Space].Push(Actions.Empty);
} else if (IsReleased(Keys.E)) {
keyEventHandlers[Keys.E].Pop();
keyEventHandlers[Keys.LeftMouseButton].Pop();
keyEventHandlers[Keys.Space].Pop();
}
while(GetNextKeyInBuffer(out key)) {
keyEventHandlers[key].Invoke(); // we invoke only last event handler
}
या इस प्रभाव के लिए कुछ :)
संपादित करें : किसी ने असहनीय का उल्लेख किया है, अन्यथा निर्माण करता है। क्या हम रूटीन हैंडलिंग से संबंधित इनपुट इवेंट के लिए पूर्ण डेटा-चालित जा रहे हैं? आप निश्चित रूप से कर सकते हैं, लेकिन क्यों?
वैसे भी, इस के लिए:
void BuildOnKeyPressedEventHandlerTable() {
onKeyPressedHandlers[Key.E] = () => {
keyEventHandlers[Keys.E].Push(Actions.Empty);
keyEventHandlers[Keys.LeftMouseButton].Push(Actions.Empty);
keyEventHandlers[Keys.Space].Push(Actions.Empty);
};
}
void BuildOnKeyReleasedEventHandlerTable() {
onKeyReleasedHandlers[Key.E] = () => {
keyEventHandlers[Keys.E].Pop();
keyEventHandlers[Keys.LeftMouseButton].Pop();
keyEventHandlers[Keys.Space].Pop();
};
}
/* get released keys */
foreach(var releasedKey in releasedKeys)
onKeyReleasedHandlers[releasedKey].Invoke();
/* get pressed keys */
foreach(var pressedKey in pressedKeys)
onKeyPressedHandlers[pressedKey].Invoke();
keyEventHandlers[key].Invoke(); // we invoke only last event handler
संपादित करें २
Kylotan ने मुख्य मानचित्रण का उल्लेख किया है, जो एक बुनियादी विशेषता है जिसे हर खेल में होना चाहिए (पहुंच के बारे में भी सोचना चाहिए)। कीमैपिंग सहित एक अलग कहानी है।
एक प्रमुख प्रेस संयोजन या अनुक्रम के आधार पर व्यवहार को बदलना सीमित है। मैंने उस हिस्से की अनदेखी की।
व्यवहार खेल तर्क से संबंधित है न कि इनपुट से। जो काफी हद तक स्पष्ट है, यह सोचने में आ रहा है।
इसलिए, मैं निम्नलिखित समाधान प्रस्तावित कर रहा हूं:
// //>
void Init() {
// from config file / UI
// -something events should be set automatically
// quake 1 ftw.
// name family key keystate
"+forward" "movement" Keys.UpArrow Pressed
"-forward" Keys.UpArrow Released
"+shoot" "action" Keys.LMB Pressed
"-shoot" Keys.LMB Released
"jump" "movement" Keys.Space Pressed
"+lstrafe" "movement" Keys.A Pressed
"-lstrafe" Keys.A Released
"cast" "action" Keys.RMB Pressed
"picknose" "action" Keys.X Pressed
"lockpick" "action" Keys.G Pressed
"+crouch" "movement" Keys.LShift Pressed
"-crouch" Keys.LShift Released
"chat" "user" Keys.T Pressed
}
void ProcessInput() {
var pk = GetPressedKeys();
var rk = GetReleasedKeys();
var actions = TranslateToActions(pk, rk);
PerformActions(actions);
}
void TranslateToActions(pk, rk) {
// use what I posted above to switch actions depending
// on which keys have been pressed
// it's all about pushing and popping the right action
// depending on the "context" (it becomes a contextual action then)
}
actionHandlers["movement"] = (action, actionFamily) => {
if(player.isCasting)
InterruptCast();
};
actionHandlers["cast"] = (action, actionFamily) => {
if(player.isSilenced) {
Message("Cannot do that when silenced.");
}
};
actionHandlers["picknose"] = (action, actionFamily) => {
if(!player.canPickNose) {
Message("Your avatar does not agree.");
}
};
actionHandlers["chat"] = (action, actionFamily) => {
if(player.isSilenced) {
Message("Cannot chat when silenced!");
}
};
actionHandlers["jump"] = (action, actionFamily) => {
if(player.canJump && !player.isJumping)
player.PerformJump();
if(player.isJumping) {
if(player.CanDoubleJump())
player.PerformDoubleJump();
}
player.canPickNose = false; // it's dangerous while jumping
};
void PerformActions(IList<ActionEntry> actions) {
foreach(var action in actions) {
// we pass both action name and family
// if we find no action handler, we look for an "action family" handler
// otherwise call an empty delegate
actionHandlers[action.Name, action.Family]();
}
}
// //<
लोगों द्वारा मुझसे बेहतर तरीके से इसे कई तरीकों से बेहतर बनाया जा सकता है, लेकिन मेरा मानना है कि यह एक अच्छा शुरुआती बिंदु है।