не работает коллизия платформера (например, mario bros)

#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.. я расстроен, следовало бы опубликовать переменные.. я буду иметь это в виду