2017-02-03 4 views
0

Я пишу игровой движок в C с SDL2, и я пытаюсь использовать бит twiddling для хранения моего текущего направления движения.
Я не совсем уверен, как воспроизвести его, но вот видео показывает ошибку:
https://youtu.be/RnPZaUDPElUПочему игрок иногда двигается в неправильном направлении при переключении направления

А вот проблемный код:

#define BMXSPEED 0x01 
#define BMYSPEED 0x04 

void BEvent (btree_t *t) { 
    SDL_Event event; 
    while (SDL_PollEvent(&event)) { 
     switch (event.type) { 
     case SDL_QUIT: 
      t->run = 0; 
      break; 
     case SDL_KEYDOWN: 
      switch (event.key.keysym.scancode) { 
      case SDL_SCANCODE_ESCAPE: 
       t->run = 0; 
       break; 
      case SDL_SCANCODE_D: 
       if (!event.key.repeat) { 
        t->player->speed |= BMXSPEED; 
       } 
       break; 
      case SDL_SCANCODE_A: 
       if (!event.key.repeat) { 
        t->player->speed |= (BMXSPEED << 1); 
       } 
       break; 
      case SDL_SCANCODE_S: 
       if (!event.key.repeat) { 
        t->player->speed |= BMYSPEED; 
       } 
       break; 
      case SDL_SCANCODE_W: 
       if (!event.key.repeat) { 
        t->player->speed |= (BMYSPEED << 1); 
       } 
       break; 
      } 
      break; 
     case SDL_KEYUP: 
      switch (event.key.keysym.scancode) { 
      case SDL_SCANCODE_D: 
       t->player->speed &= ~BMXSPEED; 
       break; 
      case SDL_SCANCODE_A: 
       t->player->speed &= ~(BMXSPEED << 1); 
       break; 
      case SDL_SCANCODE_S: 
       t->player->speed &= ~BMYSPEED; 
       break; 
      case SDL_SCANCODE_W: 
       t->player->speed &= ~(BMYSPEED << 1); 
       break; 
      } 
      break; 
     } 
    } 

    /* X movement */ 
    if (t->player->speed & BMXSPEED && (t->player->speed & (BMXSPEED << 1)) != (BMXSPEED << 1)) 
     t->player->xspeed += (t->player->xspeedMax - abs(t->player->xspeed))/t->player->xspeedMax; 
    else 
    if (t->player->speed & (BMXSPEED << 1) && (t->player->speed & BMXSPEED) != BMXSPEED) 
     t->player->xspeed -= (t->player->xspeedMax - abs(t->player->xspeed))/t->player->xspeedMax; 
    else 
     t->player->xspeed += (t->player->xspeedMin - t->player->xspeed)/t->player->xspeedMax; 

    /* Y movement */ 
    if (t->player->speed & BMYSPEED && (t->player->speed & (BMYSPEED << 1)) != (BMYSPEED << 1)) 
     t->player->yspeed += (t->player->yspeedMax - abs(t->player->yspeed))/t->player->yspeedMax; 
    else 
    if (t->player->speed & (BMYSPEED << 1) && (t->player->speed & BMYSPEED) != BMYSPEED) 
     t->player->yspeed -= (t->player->yspeedMax - abs(t->player->yspeed))/t->player->yspeedMax; 
    else 
     t->player->yspeed += (t->player->yspeedMin - t->player->yspeed)/t->player->yspeedMax; 

    t->player->rect.x += (int)t->player->xspeed; 
    t->player->rect.y += (int)t->player->yspeed; 
} 

EDIT: После изменения метода направления хранения, я определил, что проблема не связана с сверлением бит. Я подозреваю, что это метод ускорения.

+0

что об использовании отладчика ?? –

ответ

0

Ваш метод ускорения является немного неясным (каламбур), вот 2 предложения:

  • Бит тест может быть упрощена в одном тесте, маскирующие игрока speed с 2-мя битами и проверки для один бит.

  • В случае торможения, вероятно, следует использовать функцию abs с регулировкой для случая торможения.

  • fabs() функция представляется более чем apropriate abs() если xspeed и yspeed элементы значений с плавающей точкой.

  • Использование посреднического указателя для игрока улучшает читаемость:

Вот результирующий код:

Player *p = t->player; 

    /* X movement */ 
    if (p->speed & (BMXSPEED * 3) == BMXSPEED) 
     p->xspeed += (p->xspeedMax - fabs(p->xspeed))/p->xspeedMax; 
    else 
    if (p->speed & (BMXSPEED * 3) == BMXSPEED << 1) 
     p->xspeed -= (p->xspeedMax - fabs(p->xspeed))/p->xspeedMax; 
    else 
     p->xspeed -= copysign((p->xspeedMin - fabs(p->xspeed))/p->xspeedMax, p->xspeed); 

    /* Y movement */ 
    if (p->speed & (BMYSPEED * 3) == BMYSPEED) 
     p->yspeed += (p->yspeedMax - fabs(p->yspeed))/p->yspeedMax; 
    else 
    if (p->speed & (BMYSPEED * 3) == BMYSPEED << 1) 
     p->yspeed -= (p->yspeedMax - fabs(p->yspeed))/p->yspeedMax; 
    else 
     p->yspeed -= copysign((p->yspeedMin - fabs(p->yspeed))/p->yspeedMax, p->yspeed); 
+0

Единственная ошибка заключается в использовании 'fabs()' в методе замедления, он отправит игрока, летевшего влево. – Jameds

+0

@ Jameds: вы, вероятно, хотите уменьшить абсолютное значение 'xspeed' и' yspeed', когда не нажата ни одна клавиша, хотя это поведение вызывает сомнения. Думаю, вы двигаетесь по ровной поверхности с ненулевым трением. Удаление 'fabs()' также дает асимметричное поведение. Я обновил ответ альтернативой. – chqrlie

Смежные вопросы