# Thread: Collision of two rects?

1. ## Collision of two rects?

Hey, I'm trying to make a recreation of breakout for a little practice with images. I'm doing pritty well, but my collision detection is not working quite right. It detects for X collisions fine, but my Y collision algorithim does not work.

I wrote my collision algorithim out in psuedocode:
Check if the ball's y plus half the ball's height is less than or equal to the rects y plus the rects height.
And check if the ball's y minus half the ball's height is greater than or equal to the rects y minus the rects height.

Heres the collision code:

Code:
``` if(BALL_INFO.x < 0) {
if(BALL_INFO.x - BALL_INFO.width <= PAD_INFO[0].x) {

if(BALL_INFO.y + (BALL_INFO.height / 2) <= PAD_INFO[0].y + (PAD_INFO[0].height / 2) && BALL_INFO.y - (BALL_INFO.height / 2)  >= PAD_INFO[0].y - (PAD_INFO[0].height / 2))
BALL_INFO.dx = BeginX;
}
}```
Heres the entire program (Lots of stuff is from the forgers tutorial, with some changes.

Code:
```#include <windows.h>
#ifndef defs.h
#include "defs.h"
#endif

HBITMAP ScreenDisplay_Object = NULL;

HBITMAP gBALL = NULL;

const char g_szClassName[] = "myWindowClass";

const int BeginX = -10;
const int BeginY = 0;

const int ID_TIMER = 1;

typedef struct _BALLINFO {
int width;
int height;
int x;
int y;

int dx;
int dy;
}BALLINFO;

BALLINFO   BALL_INFO;
int CPI = 0;

void Bumprect(RECT* prc) {
if(BALL_INFO.x < 0) {
BALL_INFO.x = 0;
BALL_INFO.dx = BeginX;
if(BALL_INFO.dy < 82)
BALL_INFO.dy+= BeginY;
else
if(BALL_INFO.dy > -82 && BALL_INFO.dy <= 0)
BALL_INFO.dy-=BeginY;
} else
if(BALL_INFO.x + BALL_INFO.width >= prc->right) {
BALL_INFO.x = prc->right - BALL_INFO.width;
BALL_INFO.dx = -BeginX;
}

if(BALL_INFO.y < 0) {
BALL_INFO.y = 0;
BALL_INFO.dy = BeginY;
if(BALL_INFO.dx < 82 && BALL_INFO.dx >= 0)
BALL_INFO.dx+=BeginX;
else
if(BALL_INFO.dx > -82 && BALL_INFO.dy <= 0)
BALL_INFO.dx-=BeginY;
} else
if(BALL_INFO.y + BALL_INFO.height >= prc->bottom) {
BALL_INFO.y = prc->bottom - BALL_INFO.height;
BALL_INFO.dy = -BeginY;
}
}

if(BALL_INFO.x < 0) {
if(BALL_INFO.x - BALL_INFO.width <= PAD_INFO[0].x) {
if(BALL_INFO.y + (BALL_INFO.height / 2) <= PAD_INFO[0].y + (PAD_INFO[0].height / 2) && BALL_INFO.y - (BALL_INFO.height / 2)  >= PAD_INFO[0].y - (PAD_INFO[0].height / 2))
BALL_INFO.dx = BeginX;
}
}

if(BALL_INFO.x >= 0) {
if(BALL_INFO.x + BALL_INFO.width >= PAD_INFO[1].x) {
BALL_INFO.dx = -BeginX;
}
}
}

void UpdateBall(RECT* prc) {
BALL_INFO.x += BALL_INFO.dx;
BALL_INFO.y += BALL_INFO.dy;

Bumprect(prc);
}

void DrawBall(HDC hdc, RECT* rct) { //More preporely, this could just as well be called Draw
HDC hdcBuffer = CreateCompatibleDC(hdc);
HBITMAP hbmNew = CreateCompatibleBitmap(hdc, rct->right, rct->bottom);
HBITMAP hbmOldBuffer = (HBITMAP)SelectObject(hdcBuffer, hbmNew);

HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, gBALL);
FillRect(hdcBuffer, rct, (HBRUSH)GetStockObject(BLACK_BRUSH));

HDC hdcMem2 = CreateCompatibleDC(hdc);

HDC hdcMem3 = CreateCompatibleDC(hdc);

BitBlt(hdcBuffer, BALL_INFO.x, BALL_INFO.y, BALL_INFO.width, BALL_INFO.height, hdcMem, 0, 0, SRCAND);

SelectObject(hdcMem, gBALL);
BitBlt(hdcBuffer, BALL_INFO.x, BALL_INFO.y, BALL_INFO.width, BALL_INFO.height, hdcMem, 0, 0, SRCPAINT);

//Render everything
BitBlt(hdc, 0, 0, rct->right, rct->bottom, hdcBuffer, 0, 0, SRCCOPY);

SelectObject(hdcMem, hbmOld);
DeleteDC(hdcMem);

SelectObject(hdcMem2, hbmOld2);
DeleteDC(hdcMem);

SelectObject(hdcMem3, hbmOld3);
DeleteDC(hdcMem);

SelectObject(hdcBuffer, hbmOldBuffer);
DeleteDC(hdcBuffer);
DeleteObject(hbmNew);
}

void DrawPaddle(HDC hdc, HWND hwnd) {
BITMAP bm;
PAINTSTRUCT ps;

HDC hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(hdcMem, ScreenDisplay_Object);

GetObject(ScreenDisplay_Object, sizeof(bm), &bm);

SelectObject(hdcMem, hbmOld); //81
DeleteDC(hdcMem);

EndPaint(hwnd, &ps);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {

case WM_CLOSE:
DestroyWindow(hwnd);
break;

case WM_DESTROY:
DeleteObject(ScreenDisplay_Object);
PostQuitMessage(0);
break;

case WM_CREATE: {
BITMAP bm;

if(gBALL == NULL)
MessageBox(hwnd, "Could not load object!", "Error!", MB_OK | MB_ICONEXCLAMATION);

GetObject(gBALL, sizeof(bm), &bm);
ZeroMemory(&BALL_INFO, sizeof(gBALL));
BALL_INFO.width = bm.bmWidth;
BALL_INFO.height = bm.bmHeight;
BALL_INFO.dx = BeginX;
BALL_INFO.dy = BeginY;
BALL_INFO.x = 377;
BALL_INFO.y = 260;

MessageBox(hwnd, "Could not load object!", "Error!", MB_OK | MB_ICONEXCLAMATION);

MessageBox(hwnd, "Could not load object!", "Error!", MB_OK | MB_ICONEXCLAMATION);

SetTimer(hwnd, ID_TIMER, 45, NULL);
}
break;

case WM_TIMER: {
RECT rcClient;
HDC hdc = GetDC(hwnd);

GetClientRect(hwnd, &rcClient);

ScreenDisplay_Object = gBALL;
UpdateBall(&rcClient);
DrawBall(hdc, &rcClient);

ReleaseDC(hwnd, hdc);
}
break;

default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;

wc.cbSize        = sizeof(WNDCLASSEX);
wc.style         = 0;
wc.lpfnWndProc   = WndProc;
wc.cbClsExtra    = 0;
wc.cbWndExtra    = 0;
wc.hInstance     = hInstance;
wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wc.lpszClassName = g_szClassName;

if(!RegisterClassEx(&wc)) {
MessageBox(NULL, "Window Registration Failed!", "Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}

hwnd = CreateWindowEx(WS_EX_CLIENTEDGE, g_szClassName, "PONG!", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);

if(hwnd == NULL) {
MessageBox(NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}

ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);

while(GetMessage(&Msg, NULL, 0, 0) > 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}

return Msg.wParam;
}```
Basicaly this creates a ball that gets sent to the left, and it should collide with the first paddle (0)... But it doesnt, it just goes straight into the first paddle. Bah, damn my poor applied math skills -,-.

Anyone see why this doesnt collide proporely?

(Also as an offnote, is there any way to more efficiently render my scene? It seems to me I'm creating far to many hdcs, when only two should be needed for double buffering, but the hdc doesnt seem to like having several instances refer to it with select object.

2. Just a pedantic note . . .
Code:
`#ifndef defs.h`
defs.h isn't a valid #define name.

3. -,- Forgot the underscores.

4. Personal, I'm hopelessly lost in my applied mathmaitcs. But because of that, I tend to avoid using math functions until I understand them.

So, I came up with this instead of my above version (And this one works ^^)
Code:
```BOOL Collide(int I) {
int BALLRECT[3];

BALLRECT[0] = BALL_INFO.x + (BALL_INFO.width / 2); 	//Right
BALLRECT[1] = BALL_INFO.x - (BALL_INFO.width / 2); 	//Left
BALLRECT[2] = BALL_INFO.y - (BALL_INFO.height / 2); 	//Bottom
BALLRECT[3] = BALL_INFO.y + (BALL_INFO.height / 2);	//Top

return false;
else
return true;
}

if(Collide(0) == 1) {
BALL_INFO.dx = -BeginX;
}

if(Collide(1) == 1) {
BALL_INFO.dx = +BeginX;
}
}```
Alot bigger, but it works :P. But I still dont understand my function didint. It did basicaly the same thing... didint it?

5. Collision of rectangles can be done by reversing what you have done. Instead of testing for all points inside, it takes less tests to test for all points outside.

6. Yes, the rectangle outside a rectangle test is much easier.
Then overlap is just !outside()

7. Rect'm? It damn hear killed'm!

Quzah.