1
votes

i've been sitting here for hours now trying to figure out how collision could work for a platformer.. after doing a lot of research i found something useful in the internet.. but it doesn't work yet :/ my character seems to jump one time.. and then gets stuck a short distance above the ground

This is the function where i load my platforms from txt (by calling setupworld) in my txt i define xstart (where the platform starts) xend (end of platform) ystart (bottom of platform) 2 unnused variables and the texture filter (0-4 atm)

each platform is then created by repeating 2x2 tiles in x direction numblocks= number of platforms (sry for the bad variable name ^^) number of blocks is calculated by taking the end coordinate of the platform - start coordinate and dividing by 2.0 (my platforms always have coordinates dividable by 2.. like.. 0 - 16.. or.. 8 - 16.. )

as u see.. the structure block is where all the data is saved to in setupworld() and it has nothing to do with the number of tiles displayed.. sry again for my weird names


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;
}

}


This is where the key actions are processed.. DetectCollision() calls my function where i (try to) check for collisions

ymovement ypos2=ypos; is just to remind the last position for repositioning i jump until i reach 5.0f or a collision in y-direction is detected.. then locky turns TRUE; the else is to let my character get back to ground (cause no gravity) even when the player keeps w pressed the same thing happens when w is not pressed.. and locky is being reset

xmovement i add to (or subtract from) xpos for movement

as long as the character doesn't reach the border or a collision appears it should do the normal movement

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(); //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 &&
             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);

}

}


finally a screenshot http://www.grenzlandzocker.de/test.png

I hope u can help me.. either fix my code or give me some tips on collisions.. since it's my first game with opengl :s if u need any more detail or infos please ask ^^ and thanks in advance !


                            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;
                    }
            }

THANKS :) well i just edited the code for x movement and collision.. so it works properly.. (despite the flickering (but idc atm :) ).. i'm wondering why jumping doesn't work at all anymore.. it's just increasing till i'm stuck.. can't even get up once anymore :/ i put my detectCollision() in front of they key section.. which works for x AND y now (hopefully).. and i also edited something in DetectCollision() i had ystart+0.2 instead of ystart+2.0 which is the correct coordinate for the platforms top

but looks like it just got worse at y i'm still totally confused..

oh and talking about those predefined api's and stuff.. since somebody first showed me some things with glut i tried to make the next step and initialize everything myself.. i guess detection is much easier using predefined stuff.. but i want to learn it and not just get one game to work :) if u have any more suggestions for my code i would be really grateful.. and if u know any good books for starters till advanced lvl i would really appreciate

and yes.. i know.. display lists are deprecated since opengl 3.0 ^^

2

2 Answers

1
votes

Unless I am not following your code correcty, once you reach the apex of your jump and set your locky to !locky, you start hitting your else statement, which never checks for collision. IF you are moving in the x or -x direction, you likely want to be doing this as the ground may not be in the same place as your origin of the jump.

Additionally, your locky check is checking if the ypos >= 5.0f , which will immediately be the case if you are already on some part of your game world above the 5.0 mark. You likely want this to be a variable such as limitY = ypos + 5.0f; and then check if ypos >= limitY, so it works regardless of origin.

As for the issue you are seeing now, it should be easy to debug and look at the current value of your y coordinate and see if there is anything obvious (such as not executing a final ypos -= 0.2f ) which is cause for you floating slightly above the ground after a jump. (I don't see an obvious error in the way you are doing your code, although I would not have designed it in the way you are doing it yourself.)

If you are developing this for Windows you may want to look into XNA development, which makes collision detection and resolution a lot easier.

0
votes

Are you initializing locky to true or false? because all the code i can see inverts the state of locky, so depending on how the input is processed, your locky value is flipping every loop or possibly being set out of sync with your expectations.

I would recommend setting locky to true and false explicitly in the code you've shown, rather than using locky=!locky, it's clearer about the state of the system.