SDL collision bounds problem

hey guys I seem to be having a problem with the bounds checking/collision detection in my game,

when the ball is on the platform and collides with the left most bound the ball indeed hits the "wall" and bounces off it but when the ball is in the air it seems to break this condition and moves past the "wall" or bounds

here is a video displaying what is happening below

https://youtu.be/1X-hrsIwzXs

I'll include the full code below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332

#include <iostream>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

using namespace std;

const int HEIGHT = 500;
const int WIDTH = 800;

SDL_Renderer* renderer;
SDL_Window* window;
SDL_Event event;
bool ballDown,ballUp;
bool ballLeft,ballRight;
bool platformOne,platformTwo;
bool ballDropped;
bool ballFalling;
bool jumping;
bool jumpDown;

// ball
SDL_Texture* ballTexture;
SDL_Surface* ballSurface;
SDL_Rect* ballSrcRect;
SDL_Rect* ballDstRect;

// platform
SDL_Texture* platformTexture;
SDL_Surface* platformSurface;
SDL_Rect* platformSrcRect;
SDL_Rect* platformDstRect;

// platformTwo
SDL_Texture* platformTextureTwo;
SDL_Rect* platformTwoSrcRect;
SDL_Rect* platformTwoDstRect;

void initGame(){

   if(SDL_Init(SDL_INIT_EVERYTHING) < 0){

      cout << "failed to init" << endl;
   }
   if(IMG_Init(IMG_INIT_PNG) < 0){

     cout << "failed to init image" << endl;
   }

   window = SDL_CreateWindow("platforms",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED,WIDTH,HEIGHT,SDL_WINDOW_RESIZABLE);
   renderer = SDL_CreateRenderer(window,-1,0);
   SDL_SetRenderDrawColor(renderer,255,255,255,255);
   ballDown = true;
   ballUp = false;
   ballLeft = false;
   ballRight = false;

   ballDropped = false;
   ballFalling = false;

   jumping = false;
   jumpDown = false;

   platformOne = true;
   platformTwo = false;

   ballSrcRect = new SDL_Rect;
   ballDstRect = new SDL_Rect;

   platformDstRect = new SDL_Rect;
   platformSrcRect = new SDL_Rect;

   platformTwoDstRect = new SDL_Rect;
   platformTwoDstRect = new SDL_Rect;

   ballSurface = IMG_Load("bb.png");
   ballTexture = SDL_CreateTextureFromSurface(renderer,ballSurface);

   platformSurface = IMG_Load("platform.png");
   platformTexture = SDL_CreateTextureFromSurface(renderer,platformSurface);

   platformTextureTwo = SDL_CreateTextureFromSurface(renderer,platformSurface);

   ballDstRect->x = 30;
   ballDstRect->y = 10;
   ballDstRect->h =70;
   ballDstRect->w = 70;

   platformDstRect->x = 0;
   platformDstRect->y = 400;
   platformDstRect->w = 300;
   platformDstRect->h = 60;

   platformTwoDstRect->x = 470;
   platformTwoDstRect->y = 350;
   platformTwoDstRect->w = 300;
   platformTwoDstRect->h = 60;

}

bool collision(){

  cout << "collision" << endl;
  if(ballDstRect->y + ballDstRect->h >= platformDstRect->y && platformOne){

    cout << "colission platform one" << endl;
    ballDown = false;

    return true;
  }
  if(ballDstRect->y + ballDstRect->h >= platformTwoDstRect->y && platformTwo){

   cout << "colide platform 2" << endl;
     ballDown = false;

    return true;
  }
  cout << "return collision falsr" << endl;
  return false;

}

void move();
void renderGame();

// drop ball allow no user input
void ballDrop(){


  while(true){

     move();
     renderGame();
     SDL_Delay(1);
     //cout << "while" << endl;

     if(collision()){

        //cout << "collision£££££££££" << endl;
        break;
     }
  }

  ballDropped = true;
  return;

}

bool collisionBounds(){

   if(ballDstRect->x <= 0){

    //cout << "here" << endl;
    ballLeft = false;
    ballDstRect->x += 2;
    return true;
  }
  return false;
}

void move(){

   // cout << "MOVE!!!!!!!!!!!!!!!!!!!!" << endl;

   if(ballDown){

      ballDstRect->y++;
   }
   if(ballRight){

     ballDstRect->x++;
   }
   if(ballLeft){

     ballDstRect->x--;
   }
   if(jumpDown){
      //cout << "JUMP DOWN" << endl;
     ballDstRect->y++;
   }

   // check which platform

//   cout << "ball x : " << ballDstRect->x << endl;
//   cout << "ball x + w :" << ballDstRect->x + ballDstRect->w << endl;
//   cout << "platform x + w : " << platformDstRect->x + platformDstRect->w << endl;
//   cout << "platformTwo x : " << platformTwoDstRect->x << endl;
//   cout << "platformRwo x + w : " << platformTwoDstRect->x + platformTwoDstRect->w << endl;




   if((ballDstRect->x <= (platformDstRect->x + platformDstRect->w)) &&
      (ballDstRect->x >= platformDstRect->x)){

      //cout << "PLATFORM ONE" << endl;
      //cout << "ball x + w :" << ballDstRect->x + ballDstRect->w << endl;
      //cout << "platform x + w : " << platformDstRect->x + platformDstRect->w << endl;
      platformOne = true;
      platformTwo = false;
      return;
   }

   //cout << "TEST TEST test" << endl;

    if(!jumping)
        //cout << "!!!! JUMPING" << endl;

   if((ballDstRect->x + ballDstRect->w < platformTwoDstRect->x) && (ballDstRect->x >= platformDstRect->x +
    platformDstRect->w) && (!jumping) ){

        //cout << "OFF PLATFORM" << endl;
        ballDown = true;
        ballFalling = true;
        platformOne = false;
        platformTwo = false;
        return;
    }

   if(ballDstRect->x >= (platformDstRect->x + platformDstRect->w)){

      //cout << "PLATFORM TWO" << endl;
      platformOne = false;
      platformTwo = true;
      return;
   }
}

void renderGame(){

  SDL_RenderClear(renderer);

  SDL_RenderCopy(renderer,ballTexture,NULL,ballDstRect);
  SDL_RenderCopy(renderer,platformTexture,NULL,platformDstRect);
  SDL_RenderCopy(renderer,platformTextureTwo,NULL,platformTwoDstRect);

  SDL_RenderPresent(renderer);
}

void falling(bool &quit){

  if(ballFalling){

    for(int i = ballDstRect->x; i < HEIGHT+10; i++){


        ballDstRect->y++;
        renderGame();
        SDL_Delay(1);

    }
      quit = true;
  }

}


void jump(){

    ballDstRect->y-=2;
}


int SDL_main(int argc,char* argv[])
{

    initGame();

    bool quit = false;


    while(!quit){

        SDL_PollEvent(&event);

        if(!ballDropped){

            ballDrop();
        }

        if(event.type == SDL_QUIT){
            //cout << "quit" << endl;
            quit = true;
        }
        if(event.type == SDL_KEYDOWN){

            switch(event.key.keysym.sym){

        case SDLK_RIGHT:
            ballLeft = false;
            ballRight = true;
            break;
        case SDLK_LEFT:
            ballRight = false;
            ballLeft = true;
            break;
        case SDLK_UP:
            jump();
            renderGame();
            //cout << "UP" << endl;
            jumping = true;
            jumpDown = true;
            break;

            }
            if(!collision() || !collisionBounds()){
            move();
            }
            falling(quit);
        }
        if(event.type == SDL_KEYUP && jumpDown){

            switch(event.key.keysym.sym){

          case SDLK_UP:
            ballDrop();
            jumpDown = false;
            jumping = false;
            //cout << "down" << endl;
            break;
            }
            if(!collision() || !collisionBounds()){
            move();
            }
            falling(quit);
        }

        SDL_Delay(1);
        renderGame();
    }
}
The || and && operators only evaluates the second operand expression if it is necessary in order to decide the result.

This causes problems in the following code.

1
2
3
if (!collision() || !collisionBounds()) {
	move();
}

If !collision() returns true, meaning the ball does not collide with any of the platforms, then it will not call the collisionBounds() because it already knows that the result of the || is going to be true.
Last edited on
Hi Peter,

I tried removing the logical or and used logical and, but now the ball doesn't seem to move at all when I use &&

**edit

I removed the || and just checked for collisionBounds and called the collision function in inside this block,seemed to kind of do the job I mean kind of because it's still very buggy,I will post a new video showing what I mean by buggy,thanks Peter

1
2
3
4
if(!collisionBounds()){
            move();
            collision();
            }
Last edited on
what is the condition under which you want it to move() ?
say that in english.
then turn that english into the expression you want.
I can take a guess, but you need to do this for yourself -- its one of the 3 or 4 techniques that I use when dealing with conditions. This method sometimes leads to suboptimal logic but its part of the (get it working, then make it fast) approach. This is the get it working piece, you can tune it after.

given the nature of this code, you may discover that one or both of your functions are not doing exactly what you expected. Collision by the way has some typos. like falsr and 2 distinct prints that maybe should say things the same way (?).

if everything is doing exactly what you wanted, and you are sure of it, you can test the short circuit problem manually:
bool col = !collision();
cout << col
col = !collisionBounds();
cout << col
see which of those is messing you up, then print what it did inside the functions, see what you got vs what you expected...
Last edited on
https://youtu.be/Mg15gXeUFZ8

here is the video illustrating the bugs,

Jonnin I would like the ball to move when there is no bounds collision(against the right wall) the ball should be able to move under any other conditions,well to add on to that when I noticed when I jump sometimes the ball keeps on moving right or left without me even pushing the right or left key,so the ball should not move horizontally in either direction when the key is not pressed but should move when that key is pressed be it jumping or not.

given the nature of this code, you may discover that one or both of your functions are not doing exactly what you expected. Collision by the way has some typos. like falsr and 2 distinct prints that maybe should say things the same way (?).


I removed the call to collision and the code seems to be the exact same thing,starting to think maybe the collision function isn't needed in the first place?


see which of those is messing you up, then print what it did inside the functions, see what you got vs what you expected...


good iea never thought about that
Last edited on
looks like I was wrong the collision function was actually vital,seems like I have got past the bug for now(fingers crossed)

what is the condition under which you want it to move() ?
say that in english.
then turn that english into the expression you want.
I can take a guess, but you need to do this for yourself -- its one of the 3 or 4 techniques that I use when dealing with conditions. This method sometimes leads to suboptimal logic but its part of the (get it working, then make it fast) approach. This is the get it working piece, you can tune it after.


I never thought of it directly like that before but yes that is actually very good advice,would you advise to write it on a piece of paper etc then try to implement it with code?

constructive criticism is always welcome if anybody wants to point out any flaws in my code( and yes I know one flaw is don't free the memory/resources used I still need to implement a function that does this)

thanks


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

bool collision(){

  if(ballDstRect->y + ballDstRect->h >= platformDstRect->y && platformOne){

    cout << "colission platform one" << endl;
    ballDown = false;
    ballDstRect->y = platformDstRect->y - ballDstRect->h; // line that fixed the bug

    return true;
  }
  if(ballDstRect->y + ballDstRect->h >= platformTwoDstRect->y && platformTwo){

   cout << "colide platform 2" << endl;
     ballDown = false;
     ballDstRect->y = platformTwoDstRect->y - ballDstRect->h; // also fixed the bug

    return true;
  }
  cout << "return collision false" << endl;
  return false;

}



I never thought of it directly like that before but yes that is actually very good advice,would you advise to write it on a piece of paper etc then try to implement it with code?

I hesitate to comment. If the logic is like 5 conditions, you need to write it down and go over it a bit. If its 2 conditions like you have, you can do it in your head maybe, or maybe writing it will help you, that depends on how your mind works -- I can do a fair bit in my head before going to paper, but that has burned me plenty of times too. I tend to give it one or 2 goes in my head and then write if it still is broken, or directly to writing it down if its more than 2 or 3 basic conditions. But everyone is different on what they need here. In your case the logic was fine, but the functions had a bug -- which I suspected, given the simplicity of the logical test.

if that text is not just to debug the thing, you might want to clean it up, its inconsistent and typos. If its for debug, whatever.



Thanks Jonnin :)

yes the text is just for debugging I will have to replace them with some comments when it's finished
Topic archived. No new replies allowed.