2009-08-10 16 views
9

सी ++ का उपयोग करते हुए उबंटू पर एसडीएल का उपयोग करके ओपनजीएल प्रोग्रामिंग से परिचित हो रहा है। कुछ देखने और प्रयोग करने के बाद मैं समझना शुरू कर रहा हूं। मुझे एसडीएल के साथ कीबोर्ड ईवेंट हैंडलिंग पर सलाह चाहिए।एसडीएल के साथ एक साथ कई कीप्रेस को कैसे संभालें?

मेरे पास पहला व्यक्ति कैमरा है, और एफडब्ल्यूडी, बैक, स्ट्राफ बाएं और दाएं चल सकता है और माउस का उपयोग करने के लिए बहुत अच्छा है। यहां मेरी प्रक्रिया है Ivents फ़ंक्शन:

void processEvents() 
{ 
    int mid_x = screen_width >> 1; 
int mid_y = screen_height >> 1; 
int mpx = event.motion.x; 
int mpy = event.motion.y; 
float angle_y = 0.0f; 
float angle_z = 0.0f; 

while(SDL_PollEvent(&event)) 
{ 
    switch(event.type) 
    { 
     case SDL_KEYDOWN: 
      switch(event.key.keysym.sym) 
      { 
       case SDLK_ESCAPE: 
        quit = true; 
        break; 
       case SDLK_w: 
        objCamera.Move_Camera(CAMERASPEED); 
        break; 
       case SDLK_s: 
        objCamera.Move_Camera(-CAMERASPEED); 
        break; 
       case SDLK_d: 
        objCamera.Strafe_Camera(CAMERASPEED); 
        break; 
       case SDLK_a: 
        objCamera.Strafe_Camera(-CAMERASPEED); 
        break; 
       default: 
        break; 
      } 
      break; 

     case SDL_MOUSEMOTION: 
      if((mpx == mid_x) && (mpy == mid_y)) return; 

      SDL_WarpMouse(mid_x, mid_y); 

      // Get the direction from the mouse cursor, set a resonable maneuvering speed 
      angle_y = (float)((mid_x - mpx))/1000;  
      angle_z = (float)((mid_y - mpy))/1000; 

      // The higher the value is the faster the camera looks around. 
      objCamera.mView.y += angle_z * 2; 

      // limit the rotation around the x-axis 
      if((objCamera.mView.y - objCamera.mPos.y) > 8) objCamera.mView.y = objCamera.mPos.y + 8; 
      if((objCamera.mView.y - objCamera.mPos.y) <-8) objCamera.mView.y = objCamera.mPos.y - 8; 

      objCamera.Rotate_View(-angle_y); 

      break; 

     case SDL_QUIT: 
      quit = true; 
      break; 

     case SDL_VIDEORESIZE: 
      screen = SDL_SetVideoMode(event.resize.w, event.resize.h, screen_bpp, SDL_OPENGL | SDL_HWSURFACE | SDL_RESIZABLE | SDL_GL_DOUBLEBUFFER | SDL_HWPALETTE); 
      screen_width = event.resize.w; 
      screen_height = event.resize.h; 
      init_opengl(); 
      std::cout << "Resized to width: " << event.resize.w << " height: " << event.resize.h << std::endl; 
      break; 

     default: 
      break; 
    } 
} 
} 

अब यह काम करते समय, इसमें कुछ सीमाएं हैं। सबसे बड़ा और मेरे प्रश्न का उद्देश्य यह है कि ऐसा लगता है कि दबाए गए नवीनतम कुंजी को केवल संसाधित किया जाता है। तो अगर मैं पीछे की तरफ चलने के लिए 'पकड़ रहा हूं' और मैं सही तरीके से स्ट्रैफ़ करने के लिए 'डी' दबाता हूं, तो मैं सही स्ट्रैफ़िंग समाप्त करता हूं लेकिन पीछे नहीं जा रहा हूं।

क्या कोई मुझे एसडीएल के साथ बेहतर कीबोर्ड हैंडलिंग के लिए सही दिशा में इंगित कर सकता है, एकाधिक कुंजीपेशियों के लिए एक बार में समर्थन आदि?

धन्यवाद

उत्तर

12

एक अच्छा तरीका एक कीबोर्ड ("इनपुट") हैंडलर लिखना होगा जो इनपुट घटनाओं को संसाधित करेगा और घटना की स्थिति को किसी प्रकार की संरचना में रखेगा (सहयोगी सरणी अच्छी कुंजी [कुंजीकोड] लगता है)।

प्रत्येक बार जब कीबोर्ड हैंडलर को 'कुंजी दबाया' ईवेंट प्राप्त होता है, तो यह कुंजी को सक्षम (सत्य) के रूप में सेट करता है और जब इसे एक महत्वपूर्ण डाउन इवेंट मिलता है, तो यह इसे अक्षम (गलत) के रूप में सेट करता है।

फिर आप ईवेंट को सीधे खींचने के बिना एक साथ कई कुंजियों की जांच कर सकते हैं, और आप कीबोर्ड को फिर से सबराउटिन में पास किए बिना पूरे फ्रेम में फिर से उपयोग करने में सक्षम होंगे।

कुछ फास्ट छद्म कोड: आप SDL2 उपयोग कर रहे हैं तो SDL_GetKeyboardState का उपयोग

class KeyboardHandler { 
    handleKeyboardEvent(SDL Event) { 
     keyState[event.code] = event.state; 
    } 

    bool isPressed(keyCode) { 
     return (keyState[keyCode] == PRESSED); 
    } 

    bool isReleased(keyCode) { 
     return (keyState[keyCode] == RELEASED); 
    } 

    keyState[]; 
} 

... 

while(SDL Pull events) 
{ 
    switch(event.type) { 
     case SDL_KEYDOWN: 
     case SDL_KEYUP: 
       keyHandler.handleKeyboardEvent(event); 
      break; 
     case SDL_ANOTHER_EVENT: 
       ... 
      break; 
    } 
} 

// When you need to use it: 
if(keyHandler.isPressed(SOME_KEY) && keyHandler.isPressed(SOME_OTHER_KEY)) 
    doStuff(TM); 
+0

सच एक अच्छा समाधान है, यह लगभग सभी अपने खेल में इस्तेमाल किया जा सकता – devsaw

3

के बजाय केवल keydown घटनाओं को देखते हुए किसी भी समाधान है जो कई कुंजियों के बारे में एक ही बार में देखभाल किया जा रहा है दोनों keydown और KeyUp घटनाओं पर विचार करना करने के लिए जा रहा है, और राज्य का ट्रैक रखने प्रश्न में चाबियाँ।

तो बजाय (स्यूडोकोड):

on keydown: 
    case left_key: 
     object.setMovement(left) 
    case forward_key: 
     object.setMovement(forward) 

बजाय आप और अधिक की तरह (फिर स्यूडोकोड) कुछ होगा:

on keydown: 
    case left_key: 
     keystates[left] = true 
     object.updateMovement(keystates) 
    case forward_key: 
     keystates[forward] = true 
     object.updateMovement(keystates) 

on keyup: 
    case left_key: 
     keystates[left] = false 
     object.updateMovement(keystates) 
    case forward_key: 
     keystates[forward] = false 
     object.updateMovement(keystates) 

फिर updateMovement दिनचर्या keystates को देखो और यह पता लगाने होगा एक एक साथ सभी आंदोलन कुंजी के राज्यों के आधार पर समग्र आंदोलन।

16

एसडीएल सभी चाबियों की वर्तमान स्थिति का ट्रैक रखता है। आप के माध्यम से इस राज्य का उपयोग कर सकते हैं:

SDL_GetKeyState()

तो, प्रत्येक यात्रा आप कुंजी राज्य के आधार पर आंदोलनों को अपडेट कर सकते हैं। आंदोलन को सुगम बनाने के लिए आपको अपडेट के बीच के समय के आधार पर आंदोलन परिमाण को अद्यतन करना चाहिए।

3

मिलता है।

उदाहरण:

const Uint8 *keyboard_state_array = SDL_GetKeyboardState(NULL); 

SDL_PollEvent(&event); 

if(event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) 
{ 
    // Move centerpoint of rotation for one of the trees: 
    if (keyboard_state_array[SDL_SCANCODE_UP] && !(keyboard_state_array[SDL_SCANCODE_DOWN])) 
    { 
     --location.y; 
    } 
    else if (!keyboard_state_array[SDL_SCANCODE_UP] && keyboard_state_array[SDL_SCANCODE_DOWN]) 
    { 
     ++location.y; 
    } 

    if (keyboard_state_array[SDL_SCANCODE_RIGHT] && !keyboard_state_array[SDL_SCANCODE_LEFT]) 
    { 
     ++location.x; 
    } 
    else if (!keyboard_state_array[SDL_SCANCODE_RIGHT] && keyboard_state_array[SDL_SCANCODE_LEFT]) 
    { 
     --location.x; 
    } 
} 
संबंधित मुद्दे