Последние несколько дней я пытался реализовать простое обнаружение столкновений объектов, нарисованных с использованием OpenGL.
С помощью Pearson, Computer Graphics with OpenGL
Мне удалось написать следующую функцию:
void move(){
if(check_collision(sprite,platform1) || check_collision(sprite,platform2)){ //if colliding...
if (downKeyPressed ){ y_Vel += speed; downKeyPressed = false;} //going down
else if(upKeyPressed ){ y_Vel -= speed; upKeyPressed = false;} //going up
else if(rightKeyPressed){ x_Vel -= speed; rightKeyPressed = false;} //going right
else if(leftKeyPressed ){ x_Vel += speed; leftKeyPressed = false;} //going left
} // always glitches on whatever is last else if above?!?!
else{ glTranslatef(sprite.x+x_Vel, sprite.y+y_Vel, 0.0); }
}
Мой спрайт перемещается в соответствии с вводом с клавиатуры (клавиши со стрелками). Если он сталкивается со стационарным объектом, он прекращает движение и остается на своем месте.
Пока что это работает при столкновении с верхней, левой стороной и нижней частью неподвижного объекта. К сожалению (хотя я использую ту же логику), правая часть не работает, и при столкновении спрайт перерисовывается в исходных координатах x / y. Я сбит с толку.
Как выясняется, какая-либо последняя проверка в move()
функция (последняя else-if
) это тот, который не работает … Я поменял местами left
с right
и, конечно же, когда left
тогда последний и тот, который подыгрывает 🙁
Любой совет или идеи о том, как я могу улучшить это и остановить это глюки?
Прошу прощения за мою наивность и любительское кодирование. Я просто самоучка. Благодарю.
Ну, мне кажется, что у вас есть проблема с переводом реального объекта.
Ваш код движения
if(there is a collision)
{
//do stuff
}
else
{
glTranslateF( );
}
Итак, всякий раз, когда происходит столкновение, функция перевода никогда не вызывается.
Мое мнение, что вы должны тянуть glTranslateF()
вызвать из else {...}
Просто звоните каждый раз. Однако кажется, что вы используете точно такую же функцию рисования для каждого прямоугольника, а не только для спрайта игрока. Возможно, вам придется найти способ различать обычные прямоугольники (например, платформы) и прямоугольник игрока. Возможно, самый простой способ реализовать это — это иметь два разных drawSprite
функции: одна для обычных платформ, а другая для игрока. Только позвони move()
функция из функции рисования игрока (возможно, называется drawPlayer()
?)
У меня не хватает времени, чтобы просмотреть весь ваш код, чтобы сделать более образованное и конкретное предложение на данный момент; однако, я буду свободен позже этим вечером, если этот вопрос все еще открыт и нуждается в помощи.
Вы не должны использовать еще, если. Существует вероятность того, что он попадает в одну и ту же сторону сбоку и сверху или снизу. Попытка изменить их на все if, потому что вы хотите проверить каждый из них. или, по крайней мере, изменить это на это.
if( /* check top */)
{
}
else if( /* check bot */)
{
}
if( /* check right */ )
{
}
else if( /* check left */)
{
}
Кроме того, вы должны избегать объявления глобальных переменных, таких как Y_VEL и X_VEL, так как это создает путаницу. Вы можете просто делать это, чтобы ваши ноги промокли, но я бы этого избегал. Создайте класс для каждого объекта, а затем укажите скорости в качестве членов этого класса.
Как вы уже поняли, проблема связана с glTranslate (). Поскольку вы работаете как с позицией спрайта, так и со скоростью, вы должны многократно обновлять позиции, используя скорости. То есть:
sprite.x += x_vel;
sprite.y += y_vel;
и делать это просто все время (то есть по какому-то таймеру или каждому кадру, если scne перерисовывается многократно). Тогда столкновение эквивалентно изменению вектора скорости (x_vel, y_vel) для имитации эффекта столкновения: либо обнулите его, чтобы остановить любое движение, либо измените знак компонента скорости (x_vel = -x_vel)
заставить его отскочить абсолютно эластичным способом или сделать что-то еще, что подходит.
Что происходит сейчас с glTranslate()
в том, что x_vel, y_vel
фактически удерживают смещения от начальной позиции, но не скорости движения.