#c #list #collision-detection
#c #Список #обнаружение коллизии
Вопрос:
я сижу здесь уже несколько часов, пытаясь выяснить, как столкновение может работать для платформера .. после проведения большого исследования я нашел кое-что полезное в Интернете.. но это пока не работает: / мой персонаж, кажется, прыгает один раз .. а затем застревает на небольшом расстоянии над землей
Это функция, с помощью которой я загружаю свои платформы из txt (вызывая setupworld) в моем txt я определяю xstart (где начинается платформа) xend (конец платформы) ystart (нижняя часть платформы), 2 неиспользуемые переменные и текстурный фильтр (0-4 атм)
затем каждая платформа создается путем повторения плиток 2×2 в направлении x numblocks = количество платформ (извините за неправильное имя переменной ^^) количество блоков вычисляется путем взятия конечной координаты начальной координаты платформы и деления на 2.0 (мои платформы всегда имеют координаты, делимые на 2 .. например .. 0 — 16 .. или .. 8 — 16 .. )
как вы видите .. структурный блок — это то, куда сохраняются все данные в setupworld (), и это не имеет ничего общего с количеством отображаемых плиток .. извините еще раз за мои странные имена
GLvoid BuildLists()
{
texture[0]=LoadPNG("data/grass.png");
texture[1]=LoadPNG("data/gnd.png");
texture[2]=LoadPNG("data/pilz_test.png");
texture[3]=LoadPNG("data/rockwall.png");
texture[4]=LoadPNG("data/crate.png");
setupworld();
quad[0]=glGenLists(numblocks);
for(int loop=0;loop<numblocks;loop )
{
GLfloat xstart,xend,ystart,u,v,u2,v2;
xstart=block.data[loop].xstart;
xend=block.data[loop].xend;
ystart=block.data[loop].ystart;
//u=block.data[loop].u;
//v=block.data[loop].v;
GLuint filter=block.data[loop].filter;
GLfloat blocks=(xend-xstart)/2.0f;
u=0.0f;
v=0.0f;
u2=1.0f*blocks;
v2=1.0f;
glNewList(quad[loop],GL_COMPILE);
glBindTexture(GL_TEXTURE_2D, texture[filter]);
// Start Drawing Quads
for(int y=0;y<blocks;y )
{
glBegin(GL_QUADS);
glTexCoord2f(u,v);
glVertex3f(xstart,ystart,-1.0f);
glTexCoord2f(u2,v);
glVertex3f(xstart ((y 1)*2.0f),ystart,-1.0f);
glTexCoord2f(u2,v2);
glVertex3f(xstart ((y 1)*2.0f),ystart 2.0f,-1.0f);
glTexCoord2f(u,v2);
glVertex3f(xstart,ystart 2.0f,-1.0f);
glEnd();
}
glEndList();
quad[loop 1]=quad[loop] 1;
}
}
Именно здесь обрабатываются ключевые действия.. detectCollision() вызывает мою функцию, где я (пытаюсь) проверить наличие коллизий
ymovement ypos2= ypos; просто для того, чтобы напомнить последнюю позицию для изменения положения, я прыгаю, пока не достигну 5.0f или не будет обнаружено столкновение в направлении y.. тогда locky становится TRUE; остальное — позволить моему персонажу вернуться на землю (не вызывать гравитации), даже когда игрок удерживает нажатой клавишу w, то же самое происходит, когда w не нажата .. и блокировка сбрасывается
xmovement я добавляю к xpos (или вычитаю из него) для перемещения
пока персонаж не достигает границы или возникает столкновение, он должен выполнять обычное движение
if (active) // Program Active?
{
if (keys[VK_ESCAPE])
{
done=TRUE;
glDeleteTextures(1,amp;texture[0]);
glDeleteTextures(1,amp;texture[2]);
glDeleteTextures(1,amp;texture[1]);
}
if (keys['W'])
{
if(!locky)
{
DetectCollision();
ypos2=ypos;
ypos=ypos 0.2f;
if(ypos>=5.0f)
{
locky=!locky;
}
if(collisiony)
{
ypos=ypos2;
locky=!locky;
}
}
else
{
if(ypos>0.0f amp;amp; !collisiony)
{
ypos=ypos-0.2f;
}
}
}
if (!keys['W'])
{
locky=!locky;
if(ypos>0.0f amp;amp; !collisiony)
{
ypos=ypos-0.2f;
}
}
if (keys['A'])
{
if(xpos>0.0f amp;amp; !collisionx)
{
xpos=xpos-0.2f;
}
}
if (keys['D'])
{
if(xpos< 50.0f amp;amp; !collisionx)
{
xpos=xpos 0.2f;
xcam=xcam-0.1f;
}
}
glLoadIdentity();
glTranslatef(0,-7.0f,-25.0f);
DrawWorld(); //draws my platforms by calling the display lists compiled in build lists
DrawChar(); //draws the character
SwapBuffers(hDC);
}
Finally the code where i check for collisions
inPlatformx for checking x
is my character between left and right side of the platform being checked
-> function returns TRUE and is written into collisionx
inPlatformy for checking y
same for inPlatformy
bool inPlatformx(float xpos, BLOCK block, int i){
return xpos > block.data[i].xstart amp;amp;
xpos < block.data[i].xend;}
bool inPlatformy(float ypos, BLOCK block, int i){
return ypos > block.data[i].ystart amp;amp;
ypos < (block.data[i].ystart 0.2);
}
GLvoid DetectCollision(){
for(int i=0; i<numblocks;i )
{
collisionx=inPlatformx(xpos,block,i);
collisiony=inPlatformy(ypos,block,i);
}
}
finally a screenshot
http://www.grenzlandzocker.de/test.png
Я надеюсь, вы сможете мне помочь .. либо исправить мой код, либо дать мне несколько советов по коллизиям.. поскольку это моя первая игра с opengl: s, если вам нужны дополнительные подробности или информация, пожалуйста, спрашивайте ^^ и заранее спасибо!
if (keys['W'])
{
//DetectCollision();
if(!locky)
{
ypos2=ypos;
ypos=ypos 0.2f;
if(ypos>=5.0f)
{
locky=!locky;
}
if(collisiony)
{
ypos=ypos2;
locky=!locky;
}
}
else
{
if(ypos>0.0f)
{
ypos=ypos-0.2f;
}
}
}
if (!keys['W'])
{
locky=!locky;
if(ypos>0.0f amp;amp; !collisiony)
{
ypos=ypos-0.2f;
}
}
if (keys['A'])
{
//DetectCollision();
if(xpos>0.0f amp;amp; !collisionx)
{
xpos2=xpos;
xpos=xpos-0.2f;
}
if(collisionx)
{
xpos=xpos2;
}
}
if (keys['D'])
{
//DetectCollision();
if(xpos< 50.0f amp;amp; !collisionx)
{
xpos2=xpos;
xpos=xpos 0.2f;
xcam=xcam-0.1f;
}
if(collisionx)
{
xpos=xpos2;
}
}
СПАСИБО 🙂
ну, я только что отредактировал код для перемещения x и столкновения.. так что это работает должным образом.. (несмотря на мерцание (но idc atm :)).. мне интересно, почему прыжки вообще больше не работают.. это просто увеличивается, пока я не застрял .. больше не могу даже встать один раз :/
я поместил свой detectCollision () перед разделом ключей.. который теперь работает для x И y (надеюсь)..
и я также кое-что отредактировал в detectCollision()
у меня был ystart 0.2 вместо ystart 2.0, который является правильной координатой для вершины платформы
но, похоже, что на y стало только хуже, я все еще в полном замешательстве..
о, и говоря об этих предопределенных API и прочем .. поскольку кто-то впервые показал мне некоторые вещи с glut, я попытался сделать следующий шаг и инициализировать все сам.. я думаю, обнаружение намного проще с использованием предопределенных материалов.. но я хочу изучить его, а не просто заставить работать одну игру 🙂 если у вас есть еще какие-либо предложения по моему коду, я был бы очень благодарен .. и если вы знаете какие-нибудь хорошие книги для начинающих до продвинутого уровня, я был бы очень признателен
и да.. я знаю .. списки отображения устарели, начиная с opengl 3.0 ^^
Ответ №1:
Если я не правильно следую вашему коду, как только вы достигнете вершины своего прыжка и установите locky
значение !locky
, вы начнете нажимать на свой else
оператор, который никогда не проверяет наличие коллизии. ЕСЛИ вы двигаетесь в направлении x или -x, вы, вероятно, захотите это сделать, поскольку земля может находиться не в том месте, откуда вы совершили прыжок.
Кроме того, ваша проверка блокировки проверяет, является ли ypos >= 5.0f
, что немедленно произойдет, если вы уже находитесь в какой-то части вашего игрового мира выше отметки 5.0. Вероятно, вы хотите, чтобы это была переменная, такая как limitY = ypos 5.0f;
, а затем проверьте, работает ли ypos >= limitY
, чтобы она работала независимо от источника.
Что касается проблемы, которую вы видите сейчас, ее должно быть легко отладить и посмотреть на текущее значение вашей координаты y и посмотреть, есть ли что-нибудь очевидное (например, невыполнение финала ypos -= 0.2f
), из-за чего вы слегка зависаете над землей после прыжка. (Я не вижу очевидной ошибки в том, как вы выполняете свой код, хотя я бы не стал разрабатывать его так, как вы делаете это сами.)
Если вы разрабатываете это для Windows, вы можете захотеть изучить XNA development, что значительно упрощает обнаружение и разрешение коллизий.
Комментарии:
1. 1: однако XNA предназначен только для C #, и я не нашел его намного лучше, чем другие доступные движки или даже моя собственная оболочка Direct3D.
2. я отредактировал несколько вещей, но я все еще действительно не уверен, что не так .. я опубликовал последние изменения.. я что-то не так понял .. вся эта история с прыжком совершенно сбивает с толку.. есть предложения? :s я расстроен, но, думаю, у каждого начинающего есть свои проблемы.. когда я напоминаю себе, что я начал в прошлые выходные, я очень горжусь тем, что я сделал до сих пор
3. Ваш вызов detectCollision() закомментирован, так что это первая проблема с вашим обновлением 🙂 Ваша логика также по-прежнему неверна с точки зрения того, что вы пытаетесь сделать. Я бы предложил пойти по старой школе.. Достаньте бумагу и ручку, просмотрите свой код, обновите переменные вручную и посмотрите, что происходит кадр за кадром. Я думаю, вы сможете довольно легко исправить логику, как только поймете, почему она не работает должным образом 🙂
4. нет, detectCollision () работает ^^ я просто не показал ту часть, где я это поместил .. это перед разделом key (вот почему они закомментированы там), и да, я, вероятно, должен :/ спасибо за вашу помощь .. и я отредактирую этот вопрос после его исправления
Ответ №2:
Вы инициализируете locky в true или false? потому что весь код, который я вижу, инвертирует состояние locky, поэтому в зависимости от того, как обрабатываются входные данные, ваше значение locky переворачивает каждый цикл или, возможно, не синхронизировано с вашими ожиданиями.
Я бы рекомендовал явно установить для locky значения true и false в показанном вами коде, а не использовать locky =!локи, это проясняет состояние системы.
Комментарии:
1. да, это изначально false.. я расстроен, следовало бы опубликовать переменные.. я буду иметь это в виду