Jump to content
  • Advertisement
Sign in to follow this  
gretty

Pong Probs: draw sprite & boundaries (Win32)

This topic is 3075 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi I have made a simple Pong game using strictly Win32 C++ functions. But I have run into some problems. Problems: 1. The sprite for the ball/pong circle should be a perfect white circle but its being draw irregularly (as an irregular ellipse). And my rectangles for my player & computer(bats?) are drawn slightly smaller than they should be drawn. I think there something wrong with my draw function but I dont know what? 2. When the ball/pong moves towards/outside the right & bottom boundary the ball doesn't bounce back like it should but it sticks to the boundary & moves along it. I have looked through my code & I cant seem to figure out why this is happening? Does anyone know of any Pong tutorials that are for Win32, not SDL etc? Thanks for reading my post :) Pong Application http://www.mediafire.com/?eghzmdhej3m Application code:
#include <windows.h>
#include <stdio.h>

#define IDS_MOVETIME 1
#define IDS_DIRTIME  2
#define IDS_PONGMOVE 3

static HINSTANCE gInstance;
class OBJECT {
    
    public:
        HRGN rgn;
        HBRUSH hb;
        int x;
        int y;
        int width;
        int height;
        OBJECT(); 
        bool moveTo(HWND hwnd, RECT &clientR, int n, bool &redraw);
        void drawSprite(HDC hdc);   
        void setStats(int X, int Y, int w, int h, COLORREF fillColour);
};

class BALL {
     
   public: 
       HRGN rgn;
       HBRUSH hb;
       int x;
       int y;
       int width;
       int height;
       int hSpeed; // horizontal speed
       int vSpeed; // vertical speed
       BALL();  
       bool moveTo(HWND hwnd, RECT &clientR, bool &redraw);
       bool checkObjectCollision(OBJECT &o);
       void drawSprite(HDC hdc);   
       void setStats(int X, int Y, int w, int h, COLORREF fillColour); 
};

OBJECT player;
OBJECT computer;
BALL pong;
bool gameStart = true;
bool redrawPlayer = true;
bool redrawComp   = true;
bool redrawPong   = true;
int vSpeed = 2;
UINT movementTimer;
UINT directionTimer;
UINT pongMoveTimer;
RECT clientR;

// Functions List //
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void drawBorder(HDC hdc);
void drawObjects(HDC hdc);


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

    //Step 1: Registering the Window Class
    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = gInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+3);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = "My Class";
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    // if registration of main class fails
    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, "Window Registration Failed!", "Error!",
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    // Step 2: Creating the Window
    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        "My Class",
        "Pong",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,500,500,
        NULL, NULL, gInstance, NULL);

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

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

    // Step 3: The Message Loop
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }
    return Msg.wParam;
}

// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
    {
        case WM_CREATE:
        {
            movementTimer  = SetTimer(hwnd,IDS_MOVETIME,50,NULL);
            directionTimer = SetTimer(hwnd,IDS_DIRTIME,12000,NULL);
            pongMoveTimer  = SetTimer(hwnd,IDS_PONGMOVE,50,NULL);
            
            GetClientRect(hwnd,&clientR);
            player.setStats(10,200,50,100,RGB(255,255,255));
            computer.setStats(clientR.right-60,15,50,100,RGB(255,0,0));
            pong.setStats(clientR.right-100,40,20,20,RGB(255,255,255));
        }     
        break;
        case WM_SIZE:
        {
             GetClientRect(hwnd,&clientR);                     // update clientR 
             computer.x   = clientR.right-(computer.width+10); // update computer.x position 
             gameStart    = true;                              // update White Rectangular Border
             redrawPlayer = true;
             redrawComp   = true;
             redrawPong   = true;
             InvalidateRect(hwnd,NULL,true);
             // It is unecessary to update player.x value as it doesn't change
        }     
        break;
        case WM_KEYDOWN:
        {
             switch(LOWORD(wParam)) {
                
                case VK_UP:
                {
                     player.moveTo(hwnd,clientR,-5,redrawPlayer);
                }     
                break;
                case VK_DOWN:
                {
                     player.moveTo(hwnd,clientR,5,redrawPlayer);
                }     
                break;
                default:
                break;                    
             }
        }
        break;
        case WM_TIMER:
        {
            switch(LOWORD(wParam)) {
               
               case IDS_PONGMOVE:
               {    // Move ball/pong & collision check
                    pong.moveTo(hwnd,clientR,redrawPong);
               }     
               break;
               case IDS_MOVETIME:
               {     // Move in direction at vSpeed
                     computer.moveTo(hwnd,clientR,vSpeed,redrawComp);
               }
               break;
               case IDS_DIRTIME:
               {     // change computer pong objects' direction
                     if (vSpeed==2) {
                        vSpeed = -2;   // direction = up
                     }
                     else vSpeed = 2;  // direction = down
               }
               break;
               default:
               break;                    
            } 
        }     
        break;
        case WM_PAINT:
        {
            HDC hdc;
            PAINTSTRUCT ps;
            
            hdc = BeginPaint(hwnd,&ps);
            
            if (gameStart) {
                drawBorder(hdc);
                gameStart = false;
            }
            
            drawObjects(hdc);
            
            EndPaint(hwnd,&ps); 
        }     
        break;
        case WM_CLOSE:
            DeleteObject(player.hb);
            DeleteObject(computer.hb);
            DestroyWindow(hwnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hwnd, msg, wParam, lParam);
    }
    return 0;
}

// Main & Drawing functions
void drawBorder(HDC hdc)
{
   // Post: Draw white rectangular border for pong ball to bounce off
   HPEN hP = CreatePen(PS_SOLID,2,WHITE_PEN);
   SelectObject(hdc,hP);
   SetROP2(hdc,R2_NOT);
   SelectObject(hdc,GetStockObject(NULL_BRUSH));  // make inside of rectangle transparent DO I NEED TO DeleteObect this??
   Rectangle(hdc,3,3,clientR.right-3,clientR.bottom-3);
   DeleteObject(hP);  
}

void drawObjects(HDC hdc)
{
   // Post: Draw player, computer &/or pong when necessary
   /*
   bool *drawObject[3] = {&redrawPlayer,&redrawComp,&redrawPong);
   
   for (int i=0; i<3; i++) {
       
       if (&drawObject == true) {
           
   }
   */
   if (redrawPlayer) {
       player.drawSprite(hdc);
       redrawPlayer = false;             
   }
   
   if (redrawComp) {
       computer.drawSprite(hdc);
       redrawComp = false;
   }
   if (redrawPong) {
       pong.drawSprite(hdc);       
       redrawPong = false;           
   } 
}


// Class member functions
OBJECT::OBJECT()
{
   // Constructor
   x      = 0;
   y      = 0;
   width  = 0;
   height = 0;
   rgn    = NULL;
   hb     = NULL;             
}

bool OBJECT::moveTo(HWND hwnd, RECT &clientR, int n, bool &redraw)
{
   // Post: Moves object up or down according to n & updates objects HRGN
   
   // make sure we dont move outside the client window
   if ((y+n)>=5 && (y+height+n)<=(clientR.bottom-5)) {
       
       y += n;
       redraw = true;
       InvalidateRgn(hwnd,rgn,true);
       //rgn = CreateRectRgn(x,y,(x+width),(y+height));
       return true;
   }
   else return false;
}

void OBJECT::drawSprite(HDC hdc)
{
   // Post: draw sprite
   rgn = CreateRectRgn(x,y,(x+width),(y+height));
   FillRgn(hdc,rgn,hb);   
}

void OBJECT::setStats(int X, int Y, int w, int h, COLORREF fillColour)
{
   // Post: Set structures variables 
   x      = X;
   y      = Y;
   width  = w;
   height = h;
   rgn    = CreateRectRgn(x,y,x+width,y+height);
   hb     = CreateSolidBrush(fillColour);             
}

BALL::BALL()
{
   // Constructor
   x      = 0;
   y      = 0;
   width  = 0;
   height = 0;
   rgn    = NULL;
   hb     = NULL; 
   hSpeed = -2;
   vSpeed = -2;       
}

bool BALL::moveTo(HWND hwnd, RECT &clientR, bool &redraw)
{
   // Post: Moves ball/pong up or down according to n & perform collision checking 
   
   x += hSpeed;
   y += vSpeed;
   
   // if collision with player or computer
   if (checkObjectCollision(player) || checkObjectCollision(computer)) {
       //x = x-hSpeed;
       //y = y-vSpeed;
       hSpeed = -hSpeed;
       vSpeed = -vSpeed;
       return false;
   }       
   
   // Check for collisions with rectangular barrier
   if (x < 6) {
        x = 6;
        hSpeed = -hSpeed;
   }
   
   if (x+width > clientR.right-6) {  // this code is not stopping the ball from moving outside the rectangle
        x = clientR.right-6;
        hSpeed = -hSpeed;
   }
   
   if (y < 6) {
        y = 6;
        vSpeed = -vSpeed;
   }
   
   if (y+height > clientR.bottom-6) { // this code is not stopping the ball from moving outside the rectangle
        y = clientR.bottom-7;
        vSpeed = -vSpeed;
   }
   
   redraw = true;
   InvalidateRgn(hwnd,rgn,true);
}

bool BALL::checkObjectCollision(OBJECT &o)
{
   // Post: Checks for a collision between ball/pong & OBJECT
   
   bool xCollision = false;
   bool yCollision = false;
   
   // find left most object
   if (x <= o.x) {
       // COLLISION, if horizontal distance between this & other object is <= width
       if (abs(x-o.x) <= width) { xCollision = true; }
   }
   // other object = left most object
   else if (abs(x-o.x) <= o.width) { xCollision = true; }
   
   // find upper most object
   if (y <= o.y) {
       // COLLISION, if vertical distance between this & other object is <= height
       if (abs(y-o.y) <= height) { yCollision = true; }
   }
   // other object = upper most object
   else if (abs(y-o.y) <= o.height) { yCollision = true; }
   
   return (xCollision==true && yCollision==true);
}

void BALL::drawSprite(HDC hdc)
{
   // Post: draw sprite
   rgn = CreateEllipticRgn(x,y,(x+width),(y+height));
   FillRgn(hdc,rgn,hb);  
}
  
void BALL::setStats(int X, int Y, int w, int h, COLORREF fillColour)
{
   // Post: Set structures variables 
   x      = X;
   y      = Y;
   width  = w;
   height = h;
   rgn    = CreateEllipticRgn(x,y,x+width,y+height);
   hb     = CreateSolidBrush(fillColour);    
}



Ball draw function & ball collision functions
// ball draw function
void BALL::drawSprite(HDC hdc)
{
   // Post: draw sprite
   rgn = CreateEllipticRgn(x,y,(x+width),(y+height));
   FillRgn(hdc,rgn,hb);  
}

// ball collision functions
bool BALL::moveTo(HWND hwnd, RECT &clientR, bool &redraw)
{
   // Post: Moves ball/pong up or down according to n & perform collision checking 
   
   x += hSpeed;
   y += vSpeed;
   
   // if collision with player or computer
   if (checkObjectCollision(player) || checkObjectCollision(computer)) {
       //x = x-hSpeed;
       //y = y-vSpeed;
       hSpeed = -hSpeed;
       vSpeed = -vSpeed;
       return false;
   }       
   
   // Check for collisions with rectangular barrier
   if (x < 6) {
        x = 6;
        hSpeed = -hSpeed;
   }
   
   if (x+width > clientR.right-6) {  // this code is not stopping the ball from moving outside the rectangle
        x = clientR.right-6;
        hSpeed = -hSpeed;
   }
   
   if (y < 6) {
        y = 6;
        vSpeed = -vSpeed;
   }
   
   if (y+height > clientR.bottom-6) { // this code is not stopping the ball from moving outside the rectangle
        y = clientR.bottom-7;
        vSpeed = -vSpeed;
   }
   
   redraw = true;
   InvalidateRgn(hwnd,rgn,true);
}

bool BALL::checkObjectCollision(OBJECT &o)
{
   // Post: Checks for a collision between ball/pong & OBJECT
   
   bool xCollision = false;
   bool yCollision = false;
   
   // find left most object
   if (x <= o.x) {
       // COLLISION, if horizontal distance between this & other object is <= width
       if (abs(x-o.x) <= width) { xCollision = true; }
   }
   // other object = left most object
   else if (abs(x-o.x) <= o.width) { xCollision = true; }
   
   // find upper most object
   if (y <= o.y) {
       // COLLISION, if vertical distance between this & other object is <= height
       if (abs(y-o.y) <= height) { yCollision = true; }
   }
   // other object = upper most object
   else if (abs(y-o.y) <= o.height) { yCollision = true; }
   
   return (xCollision==true && yCollision==true);
}


Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by gretty
2. When the ball/pong moves towards/outside the right & bottom boundary the ball doesn't bounce back like it should but it sticks to the boundary & moves along it. I have looked through my code & I cant seem to figure out why this is happening?

You need to change
   if (x+width > clientR.right-6) {
x = clientR.right-6;
hSpeed = -hSpeed;
}

..to..
   if (x+width > clientR.right-6) {
x = clientR.right-6-width;
hSpeed = -hSpeed;
}

..and similarly for the Y-axis check.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!