views:

95

answers:

2

For this program, I've been using the OpenGL-based reni2D library in Visual C++ 2008 Express Edition. The said library is on this webpage: http://www.involuntaryexercise.com/apps/reni2D.zip

The problem I get happens when trying to make a brick from the sprite structure. I've been using an array of bricks, but at the moment have restricted the program to one brick. When the program runs, the 'ball' object (also a sprite) is supposed to ricochet when it collides with a visible brick. Instead, it collides with things around the top half for some reason.

main.cpp

...

#define BRICKS 10

typedef struct _SPRITE{
    float x,
          y,
          xspeed,
          yspeed,
          w,
          h;
    bool  isVisible;
}Sprite;

...

void sprDraw(Sprite *s) 
{
    raPinCanvas(s->x, s->y);
    raDrawQuad(s->w, s->h);
}

//brickInit initializes bricks with coordinates and dimensions.
void brickInit(Sprite &brick, float &x, float &y)
{
    brick.x = x;
    brick.y = y;
    brick.w = 25;
    brick.h = 15;
    brick.isVisible = true;
}

int collisionSideX(Sprite * a, Sprite * b)
{
    if(/*a->x < b->x*/a->x-a->w > b->x+b->w || a->x+a->w < b->x-b->w)
        return 0;
    else
        return 1;
}

int collisionSideY(Sprite * a, Sprite * b)
{
    if(/*a->y < b->y*/a->y-a->h > b->y+b->h || a->y+a->h < b->y-b->h)
        return 0;
    else
        return 1;
}

int spriteCollision(Sprite * a, Sprite * b)
{   
    if(a->x-a->w > b->x+b->w || a->x+a->w < b->x-b->w)
        return 0;
    if(a->y-a->h > b->y+b->h || a->y+a->h < b->y-b->h)
        return 0;
    return 1;
}

int RA_MAIN()
{
        raInit(640, 480);

        Sprite ball;
        ball.x = 100;
        ball.y = 240;
        ball.w = 10;
        ball.h = 10;
        ball.xspeed = 2;
        ball.yspeed = 2;

        //Set up the bricks before running brickInit.
        float somethingX = 60;
        float somethingY = 350;
        Sprite brick[BRICKS];

        for(int i=0; i<1; i++)
        {   
            //brick[i] is being passed to brickInit by reference.
            brickInit(brick[0], somethingX, somethingY); 
        }

        Sprite paddle1;
        paddle1.x = 320;
        paddle1.y = 45;
        paddle1.w = 50;
        paddle1.h = 10;

    ...    


    while(raRun())
    {
        if(raGetKey(VK_ESCAPE)) 
        {   return 0;   }

        raClear();
        clearScreenComplex();

#pragma region Draw

...

        for(int i=0; i<1; i++)
        {   
          if(brick[i].isVisible)
          {
                sprDraw(&brick[i]); 
          }
        }


#pragma endregion   

...         

        float step = 100;
        for(float i=0; i<step; i+=1.0) 
        {
            ball.x += (ball.xspeed/step);
            ball.y += (ball.yspeed/step);

            if(spriteCollision(&ball, &wallR) || spriteCollision(&ball, &wallL))
            {   ball.xspeed *= -1;  }

            if(spriteCollision(&ball, &wallU) || spriteCollision(&ball, &wallD))
            {   ball.yspeed *= -1;  }
        }

        for(int j=0; j<1; j++)
        {
            if(brick[0].isVisible==true)
            {
                if(collisionSideY(&ball, &brick[0])/* &&                                 collisionSideX(&ball, &brick[j]) == 0*/)
                {   
                    printf("Collision Vertical Y-Axis\n");
                    ball.yspeed *= -1;
                }
                else if(/*collisionSideX(&ball, &brick[j]) == 0 && */collisionSideY(&ball, &brick[0]))
                {   
                    printf("Collision On Both Axes\n"); 
                    ball.xspeed *= -1;
                }
                else
                    printf("No Collision...\n"); 
            }
        }

#pragma endregion



    }
}

reni2D.h

#ifndef __RENI2D_H__
#define __RENI2D_H__

#include <windows.h>


#ifdef __cplusplus
extern "C" {
#endif

void testBaked(unsigned int list);

/**********************************************************************/
//SYSTEM
/**********************************************************************/
//overrides main, just use this instead of main
#define RA_MAIN() \
    main(HINSTANCE hInstance,HINSTANCE hPrev,char *cmd,int showCmd) \
//init engine
void raInit(int width,int height);
//use:
//while(raRun()) {
       //game stuff
//}
int raRun();
/**********************************************************************/
void raPinCanvas(float x,float y);
void raRotateCanvas(float a) ;
void raMovePen(float x,float y);
void raRotatePen(float a);
//returns penX and penY, useful after a couple of rotations
float raPenX();
float raPenY();
//drawing happens back to front order, transparency works this way, slower but easier
void raDrawQuad(float w,float h);

/**********************************************************************/
//INPUT
/**********************************************************************/
//returns key state, use virtual key codes, for example "raGetKey(VK_ESCAPE), VK_UP,VK_LEFT,VK_SPACE"
//if you need a keycode for a character use VkKeyScan('a')
int raGetKey(int key);

//return mouse cursor position X/Y
//clamps to window size
int raGetMouseX();
int raGetMouseY();
//return 1 if mouse left/right button is pressed 0 otherwise
int raGetLeftClick();
int raGetRightClick();

//return the delta mouse movement amount on X/Y
//independent of cursor position, may be negative (ie left drag)
int raGetMouseNudgeX();
int raGetMouseNudgeY() ;

/**********************************************************************/


/**********************************************************************/
//UTILITY
/**********************************************************************/
//returns random number in given range
int raRand(int min,int max);

/**********************************************************************/


/**********************************************************************/
//SETTINGS and STATES
/**********************************************************************/
//shows or hides mouse cursor (THE ARROW)
void raSetShowCursor(int yesNo);
//sets the screen clear color, 0-255
void raSetClearColor(float r,float g,float b);
//sets the color primitives will be drawn with
//if used with raUseTextures, the color will be multiplied with the texture
//0-255
void raSetDrawColor(float r,float g,float b,float a);
//turns wireframe mode on or off with 1-0
void raSetUseWireframe(int yesNo);


//SAMPLER
unsigned int raGetSamplerFromFile(char filename[]);
unsigned int raGetSamplerWidth(unsigned int s);
unsigned int raGetSamplerHeight(unsigned int s);
void raSetSampler(unsigned int brushImg);
//where to sample from img, default is 0,0-1,1 
void raSetSamplerArea(float sU,float sV,float sW,float sH);
/**********************************************************************/


/**********************************************************************/
//DRAWING COMMANDS
/**********************************************************************/
//Clears the screen with the color defined by raSetClearColor
void raClear();

/**********************************************************************/

#ifdef __cplusplus
}
#endif
#endif
+1  A: 

Run your game in the debugger. Put a break point in your collision detection algorithm. See what happens.

If you still can't figure it out, then come back here and post the minimum amount of code necessary.

Niki Yoshiuchi
The teacher who made the library told me this can't be debugged.
Gregory R. Morton
A programming teacher who says that a specific piece of code cannot be debugged.... yeah right ... To me this is a red flag regarding his own programming skills and/or the quality of his library.
Niels Basjes
Anything can be debugged.
Charles Salvia
@Charles Can the teacher who tells you the library they made can't be debugged be debugged?
djacobson
+2  A: 

I always go for clean, simple, readable code first and then debug.

The code you put here is too complex: Make sure there is only 1 place where behaviour is coded.

Two examples:

  • Why does spriteCollision reimplement the formulas from both collisionSideX and collisionSideY?? This is confusing and seems redundant code.
  • Why do you have separate loops for collisions with the various types of objects (walls & bricks)? These loops are also inconsistent. You are moving AND checking for colissions in the first loop. Yet in the second loop you are only checking.

This is much too complex: Make it simple!

Make sure the basic structure of your program is dead easy to understand. Set that up first and then fill in the blanks.

Perhaps this meta code makes it a bit clearer to you:

Setup the stuff
while (running) 
{
    move ball
    if colission 
    {
       determine new direction and speed
    }
}

The tricky bit will be determining the edge cases (quite literary in your case): What is the new direction if you collide with two (or 3) objects at the same time?

Good luck with your homework.

Niels Basjes
You're right. I've had some confusion with organizing the code.
Gregory R. Morton
I took out the collisionX and Y functions and replaced them with spriteCollision. For the most part it works without bumping into any nonexistent blocks. The ball occasionally gets stuck inside the brick during collsion(it manages to move out of it.) That's currently my main hurdle in trying to get full collision. Also FYI: the origins are in the middle of the sprites.
Gregory R. Morton