////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Program: Pong Frenzy
// Author: Phillip Vaira
// Dates: December 6, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// PREPROCESSOR DIRECTIVES
#include <windows.h> // Win32 Header
#include <windowsx.h> // Win32 Macros
#include <iostream> // C++ Functions
#include <string> // Strings
#include "resource.h" // Resource Header
#include <mmsystem.h> // Multimedia System
#include "Header.h" // Main Header File
// MACROS
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)
// GLOBALS
const char g_szClassName[] = "ParentClassWindow"; // Class Name
const char g_szWinTitle[] = "Pong Frenzy"; // Window Title
const long int WIDTH = 800, HEIGHT = 600; // Width & Height Size
char PScoreBuffer[20] = "", CScoreBuffer[20] = "", Buffer[50] = ""; // Score & General Char Buffers
bool Active = false, Multiplayer = false, keys[256]; // Paddles are able to move when Active is true.
int SPEED = 22, DIFFICULTY = 17, MaxWins = 10; // when the player clicks Start Game in menu.
char szFileName[] = "c:\\song.mp3";
// Ball Coords
int ball_x = 300; // Starting x pos of ball
int ball_y = 300; // Starting y pos of ball
const int ball_cx = 50; // Width of ball
const int ball_cy = 50; // Height of Ball
// LPad Coords
int LPad_x = 0; // Default x value of LPad. Keeps the left pad on the left.
int LPad_y = 180; // Pad Position
const int LPad_cx = 17; // Width of left pad
const int LPad_cy = 119; // Height of left pad
// RPad Coords
int RPad_x = 776; // Default x value of RPad. Keeps the right pad on the right.
int RPad_y = 180; // RPad Position
const int RPad_cx = 17; // Width of RPad
const int RPad_cy = 119; // Height of RPad
int PlayerScore = 0; // Keeps Track of the Player's Score
int ComputerScore = 0; // Keeps Track of the Computer's Score
// For Back Buffering
HDC back_dc = NULL;
HDC game_dc = NULL;
HBITMAP back_bmp = NULL;
HBITMAP old_bmp = NULL;
RECT back_rect = {0, 0, WIDTH, HEIGHT};
// HANDLES
HWND g_hWnd = NULL; // Global Handle for Parent Window
HINSTANCE g_hInstance = NULL; // Global Handle for Programsss's Instance
HBITMAP bmpLPad, bmpRPad, bmpBall = NULL; // Handles to Bitmaps
RECT rect; // Stores the main window's rectangle (dimensions)sss
HWND hDlgOptions = NULL, hDlgStart = NULL;
CMP3_MCI CMP3; // MCI Object For background music
CMP3_MCI MP3_Ball; // MCI Object for HITBALL.wav
CMP3_MCI MP3_GameOver; // MCI Object for GAMEOVER.wav
// WINMAIN
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc; // Window Class Structure Variable
HWND hWnd = NULL; // Handle to Parent Window
MSG Msg; // Message Structure Variable
bool done = FALSE; // Determines if Game Loop should End. Default: False
// Setting Background Color of Parent Window
LOGBRUSH Brush;
Brush.lbColor = RGB(0, 0, 100); // RGB Color Value
Brush.lbHatch = 0; // Hatch Value
Brush.lbStyle = BS_SOLID; // Brush Style
HBRUSH hBrush = CreateBrushIndirect(&Brush); // hBrush = Brush;
// Registering Class Window
wc.cbClsExtra = 0; // Extra Class Info Space
wc.cbWndExtra = 0; // Extra Window Info Space
wc.cbSize = sizeof(WNDCLASSEX); // Size of the Window Class Structure
wc.hbrBackground = hBrush; // Using Color created from LOGBRUSH
wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Cursor Icon
wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEICON)); // Window Icon (32x32)
wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_GAMEICON)); // Window Icon (16x16)
wc.hInstance = hInstance; // Instance of the Application
wc.lpfnWndProc = WndProc; // WndProc to Use
wc.lpszClassName = g_szClassName; // Class Name
wc.lpszMenuName = NULL; // Menu Name
wc.style = CS_VREDRAW | CS_HREDRAW | CS_OWNDC | CS_DBLCLKS; // Style
// If Registering Class Window Fails, Alert the User and Close the Application
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, "Registering Class Window Failed!", "Error...", MB_OK | MB_ICONEXCLAMATION);
return 0;
}
// Creating Parent Window
if (!(hWnd = CreateWindowEx(NULL, g_szClassName, g_szWinTitle, WS_CAPTION | WS_BORDER |
WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, WIDTH, HEIGHT, NULL,
LoadMenu(hInstance, MAKEINTRESOURCE(MAIN_MENU)), hInstance, NULL)))
{
MessageBox(NULL, "Creating Parent Window Failed!", "Error...", MB_OK | MB_ICONEXCLAMATION);
return 0;
}
g_hWnd = hWnd; // Globally Assign Parent's Window Handle
g_hInstance = hInstance; // Globally Assign Application's Instance
// Show & Update Window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Get a Device Context for hWnd
game_dc = GetDC(hWnd);
// Load Bitmaps before Game Loop Begins
bmpLPad = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_LPAD));
bmpRPad = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_RPAD));
bmpBall = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_BALL));
// For double buffering
back_dc = CreateCompatibleDC(game_dc);
back_bmp = CreateCompatibleBitmap(game_dc, WIDTH, HEIGHT);
old_bmp = (HBITMAP)SelectObject(back_dc, back_bmp);
CMP3.Load("Audio\\song.mp3"); // load background song
MP3_Ball.Load("Audio\\HITBALL.wav"); // load HITBALL.wav
MP3_GameOver.Load("Audio\\GAMEOVER.wav"); // load GAMEOVER.wav
CMP3.Play(); // Play background song before game loop begins.
// Seed Random Number Generator
srand(GetTickCount());
// Game Loop
while (!done)
{
DWORD start_time = GetTickCount();
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
// Did the Player Decide to Quit? If so, Exit the Game Loop.
if (Msg.message == WM_QUIT)
{
done = TRUE;
}
else if ((PlayerScore == MaxWins) || (ComputerScore == MaxWins))
{
done = TRUE;
}
else
{
TranslateMessage(&Msg); // Translate any Accelerator Keys
DispatchMessage(&Msg); // Send to WndProc
}
}
else
{
if (Active == true) // Only Get Player's Input/Physics/Collision/AI/Painting
{ // when Active Is set to true.
if ( KEYDOWN('W') || KEYDOWN('S') || KEYDOWN(VK_ESCAPE) || KEYDOWN(VK_UP) || KEYDOWN(VK_DOWN) )
{
// Input
GetPlayerInput();
}
// Physics & Collision
GetPhysics();
// GetAI
GetAI();
}
// Paint Current LPad Position
SelectObject(back_dc, bmpLPad);
BitBlt(game_dc, LPad_x, LPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
// Paint Current RPad Position
SelectObject(back_dc, bmpRPad);
BitBlt(game_dc, 776, RPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
// Paint Current Ball Position
SelectObject(back_dc, bmpBall);
BitBlt(game_dc, ball_x, ball_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
SetScore(); // Set Score on the Window Title
// lock framerate to 33 milliseconds (30fps)
while((GetTickCount() - start_time) < 33);
}
}
WinLostMessage(); // Get a Random Winning/Loosing Message for the Player
ReleaseDC(hWnd, game_dc); // Release the Device Context
Active = false; // Stop game activation
CMP3.Stop(); // Stop the background music if it is still playing.
MP3_Ball.Stop(); // Stop HITBALL.wav if it is still playing.
MP3_GameOver.Stop(); // Stop GAMEOVER.wav if it is still playing.
return Msg.wParam;
}
// Parent Window Procedure
LRESULT CALLBACK WndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HWND hDlgAbout = NULL; // Handle to the About Dialog & Start Menu Dialog
switch (Msg)
{
case WM_CREATE:
{
// Centering Parent Window
RECT rect;
GetWindowRect(hWnd, &rect);
int xSize = (rect.right - rect.left);
int ySize = (rect.bottom - rect.top);
int x = (GetSystemMetrics(SM_CXSCREEN) - xSize) / 2;
int y = (GetSystemMetrics(SM_CYSCREEN) - ySize) / 2;
SetWindowPos(hWnd, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
// Load the Start Menu after Execution
hDlgStart = CreateDialog(NULL, MAKEINTRESOURCE(IDD_STARTMENU), hWnd, (DLGPROC)StartDlg);
ShowWindow(hDlgStart, SW_SHOWNORMAL);
}
break;
case WM_PAINT:
{
InvalidateRect(hWnd, NULL, FALSE);
// Validating the window
game_dc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
}
break;
case WM_CLOSE:
{
// Destroy Parent Window upon Close-up
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
{
// Destroy Program
PostQuitMessage(WM_QUIT);
}
break;
case WM_COMMAND:
{
// Menu Commands
switch (LOWORD(wParam))
{
// EXIT
case IDR_FILEEXIT:
{
// Does the Player wish to Quit?
if (MessageBox(NULL, "Are you sure you want to quit?", "Exiting Pong Frenzy",
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
PostQuitMessage(WM_QUIT); // Quit Game
}
else
{
return DefWindowProc(hWnd, Msg, wParam, lParam); // Else, Do Nothing
}
}
break;
// New Game
case IDR_FILENEW:
{
Active = false; // Pause Game
PlayerScore = 0; // Reset Player Score to 0
ComputerScore = 0; // Reset Computer Score to 0
ball_x = 300; // Reset Starting x pos of ball
ball_y = 300; // Reset Starting y pos of ball
LPad_x = 0; // Reset Default x value of LPad. Keeps the left pad on the left.
LPad_y = 180; // Reset Pad Position
RPad_x = 776; // Reset Default x value of RPad. Keeps the right pad on the right.
RPad_y = 180; // Reset RPad Position
SPEED = 22; // Reset starting Speed of the Ball
DIFFICULTY = 17; // Reset starting Difficulty to Normal
MaxWins = 10; // Reset starting Max Wins
// Load the Start Menu
hDlgStart = CreateDialog(NULL, MAKEINTRESOURCE(IDD_STARTMENU), hWnd, (DLGPROC)StartDlg);
ShowWindow(hDlgStart, SW_SHOWNORMAL);
}
break;
// ABOUT
case IDR_FILEABOUT:
{
Active = false; // Pause Game
hDlgAbout = CreateDialog(NULL, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)AboutDlg);
ShowWindow(hDlgAbout, SW_SHOWNORMAL);
}
break;
}
}
break;
default: return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// About Dialog Procedure
//
BOOL CALLBACK AboutDlg(HWND hDlgAbout, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
{
// Closing the About Dialog...
Active = true; // Activate the Game
EndDialog(hDlgAbout, wParam);
return TRUE;
}
break;
}
}
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Start Menu Dialog Procedure
//
BOOL CALLBACK StartDlg(HWND hDlgStart, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_MOVE:
{
// If the Player Moves the Start Menu, Move it Back to the Center!! HAHA.
RECT rect;
GetWindowRect(hDlgStart, &rect);
int xSize = (rect.right - rect.left);
int ySize = (rect.bottom - rect.top);
int x = (GetSystemMetrics(SM_CXSCREEN) - xSize) / 2;
int y = (GetSystemMetrics(SM_CYSCREEN) - ySize) / 2;
SetWindowPos(hDlgStart, 0, x, y, 0, 0, SWP_NOZORDER | SWP_NOSIZE);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDC_STARTGAME:
{
// Close Dialog when Player clicks Start Game
PlaySound(MAKEINTRESOURCE(IDW_BEEP3), 0, SND_RESOURCE | SND_ASYNC);
Active = true;
EndDialog(hDlgStart, wParam);
return TRUE;
}
break;
case IDC_OPTIONS:
{
PlaySound(MAKEINTRESOURCE(IDW_BEEP3), 0, SND_RESOURCE | SND_ASYNC);
// Load Options Dialog
hDlgOptions = CreateDialog(NULL, MAKEINTRESOURCE(IDD_OPTIONS), g_hWnd, (DLGPROC)OptionsDlg);
SetDlgItemText(hDlgOptions, IDC_MAXWINS, "10");
ShowWindow(hDlgOptions, SW_SHOW);
// Setting Difficulty Combo Box in the Options Dialog
const char *LIST[] = { "Easy", "Normal", "Bring it on!" };
for (int i = 0; i < 4; i++)
{
SendMessage(GetDlgItem(hDlgOptions, IDC_DIFFICULTYLEVEL), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(LIST));
}
// Setting Number of Players Combo Box in the Options Dialog
const char *NUMPLAYERS[] = { "One Player", "Two Players" };
for (int j = 0; j < 2; j++)
{
SendMessage(GetDlgItem(hDlgOptions, IDC_PLAYERS), CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(NUMPLAYERS[j]));
}
SendMessage(GetDlgItem(hDlgOptions, IDC_DIFFICULTYLEVEL), CB_SETCURSEL, 1, 0); // Default Selection: Normal
SendMessage(GetDlgItem(hDlgOptions, IDC_PLAYERS), CB_SETCURSEL, 0, 0); // Default Selection: 1 Player
return TRUE;
}
break;
case IDC_EXIT:
{
// Exit the Game
// Does the Player wish to Quit?
if (MessageBox(NULL, "Are you sure you want to quit?", "Exiting Pong Frenzy",
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
PostQuitMessage(WM_QUIT); // Quit Game
}
else
{
return TRUE; // Else, Do Nothing
}
}
break;
}
}
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Options Menu Dialog Procedure
//
BOOL CALLBACK OptionsDlg(HWND hDlgOptions, UINT Msg, WPARAM wParam, LPARAM lParam)
{
switch (Msg)
{
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDOK:
{
char Difficulty_Buffer[20];
char MaxWins_Buffer[20];
char Player_Buffer[20];
SendDlgItemMessage(hDlgOptions, IDC_DIFFICULTYLEVEL, WM_GETTEXT, 20, (LPARAM) Difficulty_Buffer);
if (strcmp(Difficulty_Buffer, "Easy") == 0)
{
SPEED = 17;
DIFFICULTY = 14;
}
else if (strcmp(Difficulty_Buffer, "Normal") == 0)
{
SPEED = 22;
DIFFICULTY = 17;
}
else if (strcmp(Difficulty_Buffer, "Bring it on!") == 0)
{
SPEED = 33;
DIFFICULTY = 20;
}
else
{
SPEED = 17;
DIFFICULTY = 14;
}
// Setting Max Wins in the Options Dialog
SendDlgItemMessage(hDlgOptions, IDC_PLAYERS, WM_GETTEXT, 20, (LPARAM) Player_Buffer);
if (strcmp(Player_Buffer, "One Player") == 0)
{
Multiplayer = false;
}
else if (strcmp(Player_Buffer, "Two Players") == 0)
{
Multiplayer = true;
}
else
{
Multiplayer = false;
}
// Setting Max Wins in the Options Dialog
GetDlgItemText(hDlgOptions, IDC_MAXWINS, MaxWins_Buffer, sizeof(MaxWins_Buffer));
// If the MaxWins text field is empty or "0", set default back to 10.
if ((strcmp(MaxWins_Buffer, "") == 0) || (strcmp(MaxWins_Buffer, "0") == 0))
{
MaxWins = 10;
}
else
{
// MaxWins = MaxWins_Buffer
MaxWins = atoi(MaxWins_Buffer);
if ( (MaxWins < 500) )
{
// No code needed here.
}
else
{
// If number of wins is too high, alert player and reset to 10.
MessageBox(NULL, "Your max number of wins may be too high.", "Pong Frenzy", MB_OK | MB_ICONEXCLAMATION);
SetDlgItemText(hDlgOptions, IDC_MAXWINS, "10"); // Set default back.
SetFocus(GetDlgItem(hDlgOptions, IDC_MAXWINS)); // Set focus back on text field
return TRUE; // Don't close options.
}
}
// Closing the Options Dialog. Save data here.
EndDialog(hDlgOptions, wParam);
return TRUE;
}
break;
case IDCANCEL:
{
// Canceling & Closing the Options Dialog. Don't save any data here.
EndDialog(hDlgOptions, wParam);
return TRUE;
}
break;
}
}
}
return FALSE;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: GetPlayerInput()
// Purpose: Determine what the player is requesting via keyboard.
// Dates: December 7, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void GetPlayerInput()
{
// Get Player's Movements
if (KEYDOWN('W')) // Did the player press up?
{
LPad_y = LPad_y - 15;
}
if (KEYDOWN('S')) // Did the player press down?
{
LPad_y = LPad_y + 15;
}
if (Multiplayer == true)
{
// Get Second Player's Movements
if (KEYDOWN(VK_UP)) // Did the second player press up?
{
RPad_y = RPad_y - 15;
}
if (KEYDOWN(VK_DOWN)) // Did the second player press down?
{
RPad_y = RPad_y + 15;
}
}
if (KEYDOWN(VK_ESCAPE))
{
// Does the Player wish to Quit?
if (MessageBox(NULL, "Are you sure you want to quit?", "Exiting Pong Frenzy",
MB_YESNO | MB_ICONQUESTION) == IDYES)
{
PostQuitMessage(WM_QUIT); // Quit Game
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: GetPhysics()
// Purpose: Set the game physics and collision.
// Dates: December 7, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void GetPhysics()
{
GetClientRect(g_hWnd, &rect);
InvalidateRect(g_hWnd, NULL, TRUE);
CMP3_MCI CMP3Ball;
// Collision - Stop LPad if at the bottom of the screen.
if ((LPad_y + 172) > HEIGHT)
LPad_y = HEIGHT - 172;
// Collision - Stop LPad if at top of screen.
if ((LPad_y) < 0)
LPad_y = 0;
// Collision - Stop RPad if at the bottom of the screen.
if ((RPad_y + 172) > HEIGHT)
RPad_y = HEIGHT - 172;
// Collision - Stop RPad if at top of screen.
if ((RPad_y) < 0)
RPad_y = 0;
static bool ball_moveRight = false; // Should the ball be moving right?
static bool ball_moveUp = true; // Should the ball be moving upward?
// Collision Checking with X Axis
if (ball_x > rect.right - ball_cx) { ball_x -= SPEED; ball_moveRight = false; PlayerScore++;}
if (ball_x < rect.left) { ball_x += SPEED; ball_moveRight = true; ComputerScore++; }
// Collision Checking with Y Axis
if (ball_y > rect.bottom - ball_cy) { ball_y -= SPEED; ball_moveUp = true; }
if (ball_y < (rect.top - ball_y)) { ball_y += SPEED; ball_moveUp = false; }
// Check Current Boolean States
if (ball_moveRight == true)
ball_x += SPEED;
else
ball_x -= SPEED;
if (ball_moveUp == true)
ball_y -= SPEED;
if (ball_moveUp == false)
ball_y += SPEED;
// If the Ball hits LPad...
if (ball_x < LPad_cx && ball_y >= LPad_y && ball_y <= LPad_y + LPad_cy
|| ball_x < LPad_cx && ball_y + ball_cy >= LPad_y && ball_y <= LPad_y +
LPad_cy )
{
ball_x += SPEED; ball_moveRight = true;
MP3_Ball.Play();
}
//If the Ball hits RPad...
if (ball_x + ball_cx >= RPad_x && ball_y >= RPad_y && ball_y <= RPad_y + RPad_cy ||
ball_x + ball_cx>= RPad_x && ball_y + ball_cy >= RPad_y && ball_y + ball_cy <= RPad_y + RPad_cy)
{
ball_x -= SPEED; ball_moveRight = false;
MP3_Ball.Play();
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: GetAI()
// Purpose: Computer determines where to go to prevent the player from scoring a point.
// If the game session is two players, ignore the AI.
// Dates: December 9, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void GetAI()
{
if (Multiplayer == false)
{
// Computer AI
if (RPad_y < ball_y)
{
RPad_y = RPad_y + DIFFICULTY - 3;
}
else
{
RPad_y = RPad_y - DIFFICULTY;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: WinLostMessage()
// Purpose: After the player wins or looses, congradulate him with random messages.
// Dates: December 9, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void WinLostMessage()
{
if (PlayerScore == MaxWins)
{
int RandNum = rand()%6;
switch (RandNum)
{
case 0: MP3_GameOver.Play();
MessageBox(NULL, "Good job! You won! Now get a life.", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 1: MP3_GameOver.Play();
MessageBox(NULL, "Congratulations! You did it!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 2: MP3_GameOver.Play();
MessageBox(NULL, "And the crowd cheers! You win!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 3: MP3_GameOver.Play();
MessageBox(NULL, "You win the next generation console system! Just kidding. You win!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 4: MP3_GameOver.Play();
MessageBox(NULL, "You rule!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
default:MP3_GameOver.Play();
MessageBox(NULL, "You win!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
}
}
else if (ComputerScore == MaxWins)
{
int RandNum = rand()%6;
switch (RandNum)
{
case 0: MP3_GameOver.Play();
MessageBox(NULL, "What the heck was that?! You lost.", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 1: MP3_GameOver.Play();
MessageBox(NULL, "You can do better!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 2: MP3_GameOver.Play();
MessageBox(NULL, "Maybe next time! Til then, you lost!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 3: MP3_GameOver.Play();
MessageBox(NULL, "How can you achieve in life if you can't defeat Pong Frenzy?", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
case 4: MP3_GameOver.Play();
MessageBox(NULL, "No comment. You lost.", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
break;
default:MP3_GameOver.Play();
MessageBox(NULL, "You lost!", "Pong Frenzy", MB_OK | MB_ICONINFORMATION);
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: SetScore()
// Purpose: Keeps the window titel bar updated with the latest scores.
// Dates: December 11, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void SetScore()
{
sprintf(PScoreBuffer, ("%d"), PlayerScore); // Convert PlayerScore from int to char.
sprintf(CScoreBuffer, ("%d"), ComputerScore); // Convert ComputerScore from int to char
// Display the New Window Title that has the Current Score
if (Multiplayer == false)
{
sprintf(Buffer, "Pong Frenzy ::: Player: %d, Computer: %d :::", PlayerScore, ComputerScore);
}
else
{
sprintf(Buffer, "Pong Frenzy ::: Player 1: %d, Player 2: %d :::", PlayerScore, ComputerScore);
}
SetWindowText(g_hWnd, Buffer); // Set Window Title to Show Current Scores
}
Double buffering - need help
This is my pong code. Three bitmaps (lpad, rpad, and the ball) are continuely flickering. I spent maybe 10 hours on finding the reason. I looked at code examples on some sites, and still, I'm at the same point where I was 9 hours ago. Please help! Thanks :)
I see you created 2 DC's game_dc and back_dc but your drawing straight to your game_dc, to do backbuffering you need draw all the sprites to your back_dc then bitblt the entire back_dc to your game_dc all at once to prevent flickering
Can you give me some code example of what you mean? I understand enough to make two BitBlt()'s, but the BitBlt() function requires two dc handles. For example,
BitBlt(back_dc, LPad_x, LPad_y, WIDTH, HEIGHT, *WHAT GOES HERE?*, 0, 0, SRCCOPY);
BitBlt(game_dc, LPad_x, LPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
Would this method work, or are you thinking of a different way?
BitBlt(back_dc, LPad_x, LPad_y, WIDTH, HEIGHT, *WHAT GOES HERE?*, 0, 0, SRCCOPY);
BitBlt(game_dc, LPad_x, LPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
Would this method work, or are you thinking of a different way?
Quote:Original post by philvaira
Can you give me some code example of what you mean? I understand enough to make two BitBlt()'s, but the BitBlt() function requires two dc handles. For example,
BitBlt(back_dc, LPad_x, LPad_y, WIDTH, HEIGHT, *WHAT GOES HERE?*, 0, 0, SRCCOPY);
BitBlt(game_dc, LPad_x, LPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
Would this method work, or are you thinking of a different way?
the two DC are the destinatiuon and source
-first you draw all your sprites to your backbuffer(back_DC)
-then you flip your backbuffer to screen
BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_DC, 0, 0, SRCCOPY);
I'm starting to understand this... bear with me.
This code below then should not draw out individually, but all of them get sent to the back_dc in one shot, then use only one BitBlt() to throw it onto the screen?
This code below then should not draw out individually, but all of them get sent to the back_dc in one shot, then use only one BitBlt() to throw it onto the screen?
// Paint Current LPad Position SelectObject(back_dc, bmpLPad); BitBlt(game_dc, LPad_x, LPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY); // Paint Current RPad Position SelectObject(back_dc, bmpRPad); BitBlt(game_dc, 776, RPad_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY); // Paint Current Ball Position SelectObject(back_dc, bmpBall); BitBlt(game_dc, ball_x, ball_y, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
To my previous post, is it something like this? Currently, nothing is updating. You can see blocks upon blocks of the ball/lpad/rpad moving around, and so forth. I suppose it needs a page refresh if this code is correct?
Object DC = Takes hold of the current selected object.
obj_dc = CreateCompatibleDC(back_dc);
Bugs i found: Screen is black and not its origional blue background color. Full screen is flickering too.
Object DC = Takes hold of the current selected object.
obj_dc = CreateCompatibleDC(back_dc);
Bugs i found: Screen is black and not its origional blue background color. Full screen is flickering too.
// Paint Current LPad Position SelectObject(obj_dc, bmpLPad); BitBlt(back_dc, LPad_x, LPad_y, WIDTH, HEIGHT, obj_dc, 0, 0, SRCCOPY); // Paint Current RPad Position SelectObject(obj_dc, bmpRPad); BitBlt(back_dc, 776, RPad_y, WIDTH, HEIGHT, obj_dc, 0, 0, SRCCOPY); // Paint Current Ball Position SelectObject(obj_dc, bmpBall); BitBlt(back_dc, ball_x, ball_y, WIDTH, HEIGHT, obj_dc, 0, 0, SRCCOPY); // Send back_dc to game_dc BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
ok, this is diffrent, you seem to be using your backbuffer to hold textures, you need at lest 3 HDC to make this work, i usally have HDC for every texture but your way works too
HDC game_dc, back_dc and, texture_DC
// replace all the LPad_width,LPad_HEIGHT,ball_WIDTH and so on with the dimentions of the sprite, not the screen
// Paint Current LPad Position
SelectObject(texture_dc, bmpLPad);
BitBlt(back_dc, LPad_x, LPad_y, LPad_width, LPad_HEIGHT, texture_dc, 0, 0, SRCCOPY);
//Paint Current RPad Position
SelectObject(texture_dc, bmpRPad);
BitBlt(back_dc, 776, RPad_y, RPad_WIDTH, RPad_HEIGHT, texture_dc, 0, 0, SRCCOPY);
// Paint Current Ball Position
SelectObject(texture_dc, bmpBall);
BitBlt(back_dc, ball_x, ball_y, ball_WIDTH, ball_HEIGHT, texture_dc, 0, 0, SRCCOPY);
//flip
BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_DC, 0, 0, SRCCOPY);
HDC game_dc, back_dc and, texture_DC
// replace all the LPad_width,LPad_HEIGHT,ball_WIDTH and so on with the dimentions of the sprite, not the screen
// Paint Current LPad Position
SelectObject(texture_dc, bmpLPad);
BitBlt(back_dc, LPad_x, LPad_y, LPad_width, LPad_HEIGHT, texture_dc, 0, 0, SRCCOPY);
//Paint Current RPad Position
SelectObject(texture_dc, bmpRPad);
BitBlt(back_dc, 776, RPad_y, RPad_WIDTH, RPad_HEIGHT, texture_dc, 0, 0, SRCCOPY);
// Paint Current Ball Position
SelectObject(texture_dc, bmpBall);
BitBlt(back_dc, ball_x, ball_y, ball_WIDTH, ball_HEIGHT, texture_dc, 0, 0, SRCCOPY);
//flip
BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_DC, 0, 0, SRCCOPY);
Cool, so we're thinking the same thing :) Only thing now is how do I get each demensions of the bitmaps? I know it has to do with BITMAP bm; but I never used this before, and knowing how to select each object with it.
I took the demensions by looking at my art files in the game folder. I placed them in here. I compiled, and noticed the screen is still flashing and the bitmaps aren't erasing as they move. It looks like a ball is ontop of another ball - keeps happening going up and down the screen etc.
Is there suppose to be a FillRect(screencolor) in this?
I took the demensions by looking at my art files in the game folder. I placed them in here. I compiled, and noticed the screen is still flashing and the bitmaps aren't erasing as they move. It looks like a ball is ontop of another ball - keeps happening going up and down the screen etc.
Is there suppose to be a FillRect(screencolor) in this?
// Paint Current LPad Position SelectObject(obj_dc, bmpLPad); BitBlt(back_dc, LPad_x, LPad_y, 17, 119, obj_dc, 0, 0, SRCCOPY); // Paint Current RPad Position SelectObject(obj_dc, bmpRPad); BitBlt(back_dc, 776, RPad_y, 17, 119, obj_dc, 0, 0, SRCCOPY); // Paint Current Ball Position SelectObject(obj_dc, bmpBall); BitBlt(back_dc, ball_x, ball_y, 42, 42, obj_dc, 0, 0, SRCCOPY); // Send back_dc to game_dc BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
not sure how to get the dimention of a bitmap outer than manulay entering the size, note that if you just remeber it you can have only one bitmap with all your sprite on it and select the sprite you want using
BitBlt(game_dc, 0, 0, 64, 64, back_dc,//the x source goes here//, //y source here//, SRCCOPY);
if your still having problems make a hdc for every bitmap, i made a wraper class for this purpos, just go
texture goo("file.bmp");
and use goo.tex as the source dc
class texture{
private:
HBITMAP hbit;
BITMAP bmp;
public:
HDC tex;
texture(LPCTSTR Fname){
tex= CreateCompatibleDC(NULL);
hbit = (HBITMAP)LoadImage(NULL,Fname,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbit,sizeof(bmp),&bmp);
SelectObject(tex,hbit);
}
~texture(){
DeleteDC(tex);
DeleteObject(hbit);
}
};
BitBlt(game_dc, 0, 0, 64, 64, back_dc,//the x source goes here//, //y source here//, SRCCOPY);
if your still having problems make a hdc for every bitmap, i made a wraper class for this purpos, just go
texture goo("file.bmp");
and use goo.tex as the source dc
class texture{
private:
HBITMAP hbit;
BITMAP bmp;
public:
HDC tex;
texture(LPCTSTR Fname){
tex= CreateCompatibleDC(NULL);
hbit = (HBITMAP)LoadImage(NULL,Fname,IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
GetObject(hbit,sizeof(bmp),&bmp);
SelectObject(tex,hbit);
}
~texture(){
DeleteDC(tex);
DeleteObject(hbit);
}
};
i dont know why its still flickering but use
BitBlt(back_dc,0,0,WIDTH,HEIGHT,back_dc,0,0,BLACKNESS);
to erase the backbuffer
BitBlt(back_dc,0,0,WIDTH,HEIGHT,back_dc,0,0,BLACKNESS);
to erase the backbuffer
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement