////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 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.
// 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; // Handle for the back buffer
HDC game_dc = NULL; // Handle for the game device context (main dc)
HDC obj_dc = NULL; // Handle for the object buffer. Keeps track of the current bitmap.
HBITMAP back_bmp = NULL;
HBITMAP old_bmp = NULL;
// 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;
// MCI Objects
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
// Used for FillRect() in the game loop. Keeps the background blue.
HBRUSH BLUE = CreateSolidBrush(RGB(0, 0, 100));
// 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);
obj_dc = CreateCompatibleDC(back_dc);
back_bmp = CreateCompatibleBitmap(game_dc, WIDTH, HEIGHT);
old_bmp = (HBITMAP)SelectObject(back_dc, back_bmp);
// Loading Music & Sound Effects
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))
{
WinLostMessage(); // Get a Random Winning/Loosing Message for the Player
ResetGame(); // Reset Game Data
ShowWindow(hDlgStart, SW_SHOWNORMAL); // Show Start Menu
}
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 onto Back Buffer
SelectObject(obj_dc, bmpLPad);
BitBlt(back_dc, LPad_x, LPad_y, LPad_cx, LPad_cy, obj_dc, 0, 0, SRCCOPY);
// Paint Current RPad Position onto Back Buffer
SelectObject(obj_dc, bmpRPad);
BitBlt(back_dc, 776, RPad_y, RPad_cy, RPad_cy, obj_dc, 0, 0, SRCCOPY);
// Paint Current Ball Position onto Back Buffer
SelectObject(obj_dc, bmpBall);
BitBlt(back_dc, ball_x, ball_y, ball_cx, ball_cy, obj_dc, 0, 0, SRCCOPY);
// Send back_dc to game_dc
BitBlt(game_dc, 0, 0, WIDTH, HEIGHT, back_dc, 0, 0, SRCCOPY);
// Erase Back Buffer
BitBlt(back_dc, 0, 0, WIDTH, HEIGHT, back_dc, 0, 0, BLACKNESS);
// Set Back Buffer Color to Blue
FillRect(back_dc, &rect, BLUE);
// Set Score on the Window Title
SetScore();
// lock framerate to 33 milliseconds (30fps)
while((GetTickCount() - start_time) < 33);
}
}
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:
{
// Validate 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:
{
ResetGame(); // Reset Game Data
// 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 recto;
GetWindowRect(hDlgStart, &recto);
int xSize = (recto.right - recto.left);
int ySize = (recto.bottom - recto.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);
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
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Function: ResetGame()
// Purpose: Reset game data when starting a new game or finishing a game session.
// Dates: December 15, 2004
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
inline void ResetGame()
{
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
}
Whoever answers this gets a cookie (unwanted black background behind start menu)
Game rocks. Nothing wrong with it but a black background when the game first starts. Behind the start menu is a black screen that is ontop of the blue screen that is suppose to be there. When I click "start game" the black background is replaced with the blue background for good. I just learned double buffering so I wonder if it has something to do with the back buffer not setting to blue before it draws on the game_dc.
Moving FillRect(back_dc, &rect, BLUE); around the loop didn't do any good.
Any help is appreciated.
Ok, I think maybe I found your problem. When you call FillRect, you are passing the address of a global variable 'rect', as the rectangle to be filled. You set 'rect' to the dimensions of the window in your GetPhysics method, but that doesn't get called unless Active == true. So, you are passing an uninitialized rectangle to FillRect. The rectangle you are passing is probably invalid, so no blue color gets drawn at all. When you select the start option, Active gets set to true, and so GetPhysics will initialize you rect variable, and the blue starts getting drawn. So, somewhere in your code, you need to initialize your rect variable in a way that is not dependent on whether your game is active or not.
Also, I think there is a problem with the order in which you do your draw operations. Since you draw your blue background at the end a frame render, wont that mean that the first frame drawn wont have the blue background?
I don't have all the files to compile your program, so I can't be sure that what I've said is correct. But, if I understand your code correctly, this should fix you problem.
Also, I think there is a problem with the order in which you do your draw operations. Since you draw your blue background at the end a frame render, wont that mean that the first frame drawn wont have the blue background?
I don't have all the files to compile your program, so I can't be sure that what I've said is correct. But, if I understand your code correctly, this should fix you problem.
Yep, that was it :) In the physics function, I gave it a new rect name called "prect". I assigned the physics stuff to that. For the game loop, I passed it all to "rect" and did a GetClientRect() before the loop. I load the game, a flash of black happens quickly, but it sets itself to blue while the game menu is shown. To stop the black flash, I put FillRect() in the beginning like you mentioned. The first frame would pick it up immediately and it did.
Thanks for the help. I probably can't mail a cookie but I can give you a point :)
Thanks for the help. I probably can't mail a cookie but I can give you a point :)
The problem is caused by the WM_PAINT handler doing nothing but telling Windows that whatever is currently drawn is perfectly fine.
Try puting a
RedrawWindow(hWnd, NULL, NULL, RDW_INTERNALPAINT);
before the while (!done) loop.
Also, this statement:
while((GetTickCount() - start_time) < 33);
should be changed to:
while((GetTickCount() - start_time) < 33) Sleep(1);
This is unlikely to slow your program down noticeably, but without the Sleep your CPU usage will always be 100% which is totally unnecessary and will make laptop users very unhappy when they get hot and the battery goes flat very quick or something.
btw, the only thing you have to do for double-buffering is to change EVERY statement that draws to your DC to draw to a different DC, then have ONE single place in your program where you draw that whole DC to the one you were previously drawing to. It's that simple.
Try puting a
RedrawWindow(hWnd, NULL, NULL, RDW_INTERNALPAINT);
before the while (!done) loop.
Also, this statement:
while((GetTickCount() - start_time) < 33);
should be changed to:
while((GetTickCount() - start_time) < 33) Sleep(1);
This is unlikely to slow your program down noticeably, but without the Sleep your CPU usage will always be 100% which is totally unnecessary and will make laptop users very unhappy when they get hot and the battery goes flat very quick or something.
btw, the only thing you have to do for double-buffering is to change EVERY statement that draws to your DC to draw to a different DC, then have ONE single place in your program where you draw that whole DC to the one you were previously drawing to. It's that simple.
Thanks for the tips. I'll definitely add what you mentioned. I didn't notice any speed differences, but could it for a slower computer? Just curious.
By the way, this is a bit off subject. You guys did enough, so it's up to you. When I minimize the game by clickign on the tab below in the toolbar, and max it back up, the scores went extremely high. This does not happen when I click to another window. But minimizing it from the toolbar is causing a score of 5 go to 65 in seconds. I tried inactive checking but that didn't do any good.
By the way, this is a bit off subject. You guys did enough, so it's up to you. When I minimize the game by clickign on the tab below in the toolbar, and max it back up, the scores went extremely high. This does not happen when I click to another window. But minimizing it from the toolbar is causing a score of 5 go to 65 in seconds. I tried inactive checking but that didn't do any good.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement