столкновение платформера (например, Mario Bros) не работает - PullRequest
1 голос
/ 14 апреля 2011

Я сижу здесь уже несколько часов, пытаясь выяснить, как столкновение может сработать для платформера ... После долгих исследований я нашел что-то полезное в Интернете ... но это пока не работает: / мой персонаж, кажется, прыгает один раз ... а затем застревает на небольшом расстоянии от земли

Это функция, где я загружаю свои платформы из txt (вызывая setupworld) в моем тексте я определяю xstart (где начинается платформа) xend (конец платформы) ystart (низ платформы) 2 неиспользованные переменные и фильтр текстуры (0-4 атм)

каждая платформа создается повторением плиток 2х2 в направлении х 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 .. затем Локи поворачивается к TRUE; остальное - позволить персонажу вернуться на землю (не вызывая гравитации), даже если игрок удерживает нажатой то же самое происходит, когда w не нажата .. и locky сбрасывается

xmovement я добавляю (или убираю) из xpos для движения

пока персонаж не достигает границы или появляется столкновение, он должен совершать обычные движения

if (active)                     // Program Active?
        {
            if (keys[VK_ESCAPE])                
            {
                done=TRUE;              
                glDeleteTextures(1,&texture[0]);
                glDeleteTextures(1,&texture[2]);
                glDeleteTextures(1,&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 && !collisiony)
                    {
                        ypos=ypos-0.2f;
                    }
                }
            }
            if (!keys['W'])
            {
                locky=!locky;
                if(ypos>0.0f && !collisiony)
                {
                    ypos=ypos-0.2f;
                }
            }
            if (keys['A'])
            {
                    if(xpos>0.0f && !collisionx)
                    {
                        xpos=xpos-0.2f;
                    }
            }
            if (keys['D'])
            {       
                    if(xpos< 50.0f && !collisionx)
                    {
                        xpos=xpos+0.2f;
                        xcam=xcam-0.1f;
                    }
            }
            glLoadIdentity();
            glTranslatef(0,-7.0f,-25.0f);

DrawWorld (); // рисует мои платформы, вызывая списки отображения, скомпилированные в списках сборки
DrawChar (); // рисуем символ

                SwapBuffers(hDC);           

            }

Наконец код, где я проверяю на столкновения

inPlatformx для проверки x

- мой персонаж между левой и правой стороной проверяемой платформы -> функция возвращает TRUE и записывается в collisionx

inPlatformy для проверки y

то же самое для inPlatformy


bool inPlatformx(float xpos, BLOCK block, int i){
    return   xpos > block.data[i].xstart &&
             xpos < block.data[i].xend;}
bool inPlatformy(float ypos, BLOCK block, int i){
    return   ypos > block.data[i].ystart &&
             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);

}

}


наконец скриншот 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 && !collisiony)
                {
                    ypos=ypos-0.2f;
                }
            }
                            if (keys['A'])
            {
                    //DetectCollision();
                    if(xpos>0.0f && !collisionx)
                    {
                        xpos2=xpos;
                        xpos=xpos-0.2f;
                    }
                    if(collisionx)
                    {
                        xpos=xpos2;
                    }
            }
            if (keys['D'])
            {       
                    //DetectCollision();
                    if(xpos< 50.0f && !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, который является правильной координатой вершины платформы

но похоже у тебя стало только хуже я все еще в замешательстве ..

о, и говоря о тех предопределенных API и прочем ... так как кто-то сначала показал мне некоторые вещи с переизбытком, я попытался сделать следующий шаг и сам все инициализировать ... я предполагаю, что обнаружение намного проще, используя предопределенные вещи ... но я хочу научиться этому, а не просто заставить одну игру работать :) если у вас есть какие-либо предложения для моего кода, я был бы очень признателен ... и если вы знаете какие-либо хорошие книги для начинающих до продвинутого уровня, я был бы очень признателен

и да .. я знаю .. списки отображения устарели, так как opengl 3.0 ^^

Ответы [ 2 ]

1 голос
/ 14 апреля 2011

Если я не буду правильно следовать вашему коду, как только вы достигнете вершины своего прыжка и установите для locky значение !locky, вы начнете нажимать на оператор else, который никогда не проверяет столкновение.Если вы движетесь в направлении x или -x, вы, вероятно, захотите это сделать, поскольку земля может не находиться в том же месте, что и источник вашего прыжка.

Кроме того, ваша проверка на блокировку проверяет, является ли ypos >= 5.0f, что сразу же произойдет, если вы уже находитесь в какой-то части игрового мира выше отметки 5.0.Вы, вероятно, захотите, чтобы это была переменная, такая как limitY = ypos + 5.0f;, а затем проверьте, если ypos >= limitY, чтобы она работала независимо от источника.

Что касается проблемы, с которой вы сталкиваетесь сейчас, то ее легко отладитьпосмотрите на текущее значение вашей координаты y и посмотрите, есть ли что-нибудь очевидное (например, не выполнение окончательного ypos -= 0.2f), которое является причиной того, что вы прыгаете немного выше земли после прыжка.(Я не вижу очевидной ошибки в том, как вы делаете свой код, хотя я бы не разработал его так, как вы делаете это самостоятельно.)

Если вы разрабатываете это для Windows, вы можетехочу заняться разработкой XNA, которая значительно упрощает обнаружение и разрешение коллизий.

0 голосов
/ 14 апреля 2011

Вы инициализируете locky в true или false? потому что весь код, который я вижу, инвертирует состояние блокировки, поэтому в зависимости от того, как обрабатывается ввод, ваше значение блокировки переключает каждый цикл или, возможно, не синхронизируется с вашими ожиданиями.

Я бы порекомендовал установить для locky значение true и false в явном виде в коде, который вы указали, вместо того, чтобы использовать locky =! Locky, это более понятно о состоянии системы.

...