สองตัวเลือก: หากกรณี "อินพุตซ้อน" มีอย่างน้อยสาม, สี่รายการฉันจะใช้แฟล็ก "จับวัตถุ? ไม่สามารถยิงได้" สิ่งอื่นใดที่เอาชนะมันได้
มิฉะนั้นคุณสามารถเก็บสแต็คของตัวจัดการเหตุการณ์ต่อคีย์อินพุตต่อคีย์
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
}
หรือบางสิ่งบางอย่างกับผลกระทบนี้ :)
แก้ไข : มีคนพูดถึงการสร้าง if-else ที่ไม่สามารถจัดการได้ พวกเราจะไปกับข้อมูลเต็มรูปแบบสำหรับการจัดการเหตุการณ์การป้อนข้อมูล? คุณทำได้อย่างแน่นอน แต่ทำไม
อย่างไรก็ตามสำหรับ heck ของมัน:
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
แก้ไข 2
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]();
}
}
// //<
นี่อาจปรับปรุงได้หลายวิธีโดยคนฉลาดกว่าฉัน แต่ฉันเชื่อว่ามันเป็นจุดเริ่มต้นที่ดี