hai tùy chọn: nếu trường hợp "đầu vào lồng nhau" nhiều nhất là ba, bốn, tôi chỉ sử dụng cờ. "Giữ một vật? Không thể bắn." Bất cứ điều gì khác là áp đảo nó.
Mặt khác, bạn có thể giữ một ngăn xếp theo từng khóa của trình xử lý sự kiện.
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
}
Hoặc một cái gì đó cho hiệu ứng này :)
Biên tập : ai đó đã đề cập đến các cấu trúc if-other không thể quản lý được. chúng ta sẽ đi theo hướng dữ liệu đầy đủ cho một thói quen xử lý sự kiện đầu vào? Bạn chắc chắn có thể, nhưng tại sao?
Dù sao, vì cái quái gì đó:
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
Chỉnh sửa 2
Kylotan đã đề cập đến ánh xạ khóa, đây là một tính năng cơ bản mà mọi trò chơi nên có (cũng nghĩ về khả năng truy cập). Bao gồm keymapping là một câu chuyện khác nhau.
Thay đổi hành vi tùy thuộc vào tổ hợp phím hoặc trình tự nhấn là hạn chế. Tôi bỏ qua phần đó.
Hành vi có liên quan đến logic trò chơi và không nhập liệu. Đó là khá rõ ràng, đến để nghĩ về nó.
Do đó, tôi đang đề xuất giải pháp sau:
// //>
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]();
}
}
// //<
Điều này có thể được cải thiện theo nhiều cách bởi những người thông minh hơn tôi, nhưng tôi tin rằng đó cũng là một điểm khởi đầu tốt.