Lesson 1: Making game in C++
#1
Rainbow 
Hey,

I'm just bored and i want to write small (maybe) tutorial.
In this lesson i will tell how to create window.

You need the following things:

C++ knowledge
DirectX SDK 2010 ( You can find it on Microsoft site )
Some math ( not now )
Visual C++ 2010 or 2012 ( I will use Express 2010 )
Some time

So, lets start!

Making new project and creating window


Open your VC++ and click "Create new project". Choose "Win32 Application".
Call it as you want. I'll call it "MyTest".
If you'll open MyTest.cpp file, you'll see this code:
Code:
// as.cpp : Defines the entry point for the application. // #include "stdafx.h" #include "as.h" #define MAX_LOADSTRING 100 // Global Variables: HINSTANCE hInst; // current instance TCHAR szTitle[MAX_LOADSTRING]; // The title bar text TCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name // Forward declarations of functions included in this code module: ATOM MyRegisterClass(HINSTANCE hInstance); BOOL InitInstance(HINSTANCE, int); LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM); int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow) { UNREFERENCED_PARAMETER(hPrevInstance); UNREFERENCED_PARAMETER(lpCmdLine); // TODO: Place code here. MSG msg; HACCEL hAccelTable; // Initialize global strings LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); LoadString(hInstance, IDC_AS, szWindowClass, MAX_LOADSTRING); MyRegisterClass(hInstance); // Perform application initialization: if (!InitInstance (hInstance, nCmdShow)) { return FALSE; } hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_AS)); // Main message loop: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return (int) msg.wParam; } // // FUNCTION: MyRegisterClass() // // PURPOSE: Registers the window class. // // COMMENTS: // // This function and its usage are only necessary if you want this code // to be compatible with Win32 systems prior to the 'RegisterClassEx' // function that was added to Windows 95. It is important to call this function // so that the application will get 'well formed' small icons associated // with it. // ATOM MyRegisterClass(HINSTANCE hInstance) { WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_AS)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszMenuName = MAKEINTRESOURCE(IDC_AS); wcex.lpszClassName = szWindowClass; wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL)); return RegisterClassEx(&wcex); } // // FUNCTION: InitInstance(HINSTANCE, int) // // PURPOSE: Saves instance handle and creates main window // // COMMENTS: // // In this function, we save the instance handle in a global variable and // create and display the main program window. // BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) { HWND hWnd; hInst = hInstance; // Store instance handle in our global variable hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (!hWnd) { return FALSE; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; } // // FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM) // // PURPOSE: Processes messages for the main window. // // WM_COMMAND - process the application menu // WM_PAINT - Paint the main window // WM_DESTROY - post a quit message and return // // LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { int wmId, wmEvent; PAINTSTRUCT ps; HDC hdc; switch (message) { case WM_COMMAND: wmId = LOWORD(wParam); wmEvent = HIWORD(wParam); // Parse the menu selections: switch (wmId) { case IDM_ABOUT: DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About); break; case IDM_EXIT: DestroyWindow(hWnd); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } break; case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // TODO: Add any drawing code here... EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); } return 0; } // Message handler for about box. INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) { UNREFERENCED_PARAMETER(lParam); switch (message) { case WM_INITDIALOG: return (INT_PTR)TRUE; case WM_COMMAND: if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL) { EndDialog(hDlg, LOWORD(wParam)); return (INT_PTR)TRUE; } break; } return (INT_PTR)FALSE; }

Now, you need to remove all useless code. Such as 'About' method.
Keep only WinProc and WinMain . You don't need another methods.
Or just use this clean code. I have included "windows.h" and "windowsx.h" to get less code and another stuff.
Code:
#include <windows.h> #include <windowsx.h> // required #include "stdafx.h" LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd) { } LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { //return 0; return DefWindowProc (hWnd, message, wParam, lParam); }


It is just empty project. Nothing special. Lets create real window!

CreateWindow method creates just empty window without buttons and another stuff. Just empty window with title.
Lets create it.
Okay now, lets see, which functions we do need.
Code:
MSG msg; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, L"Window name", NULL}; RegisterClassEx(&wc);
This code prepares window and sets owner.

Code:
// create new window HWND hMainWnd = CreateWindow(L"Empty Window", L"Window title there", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL);

Finally, it is there! CreateWindow method. It creates blank window.

Code:
// show it ShowWindow(hMainWnd, ShowCmd); UpdateWindow(hMainWnd); // handle all window messages there while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }

This part of code is requried too. It handles every window messages and shows it.

Code:
return 0;

It's just WinMain return value; Requried too.
This code you must have:
Code:
#include <windows.h> #include <windowsx.h> // required #include "stdafx.h" // class LPCWSTR WIN_MAIN = L"MAIN_WINDOW"; LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd) { MSG msg; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, WIN_MAIN, NULL}; RegisterClassEx(&wc); // create new window HWND hMainWnd = CreateWindow(WIN_MAIN, L"Window title there", WS_OVERLAPPEDWINDOW, 100, 100, 300, 300, NULL, NULL, hInstance, NULL); // show it ShowWindow(hMainWnd, ShowCmd); UpdateWindow(hMainWnd); // handle all window messages there while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return(0); } LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProc (hWnd, message, wParam, lParam); }

But if you'll click F5, it will show. But if you close it, it will just minimize window.
IMPORTANT NOTE: "WIN_MAIN" string MUST be same for CreateWindow and WNDCLASSEX. Else window won't show. ( It's LPCWSTR type ).

Changing window size, title, etc

You can change window sizes, window names, background colors. Lets create some variables for it!
X and Y are position data of window.
Window size data contains in "CreateWindow" method.
Code:
HWND hMainWnd = CreateWindow(WIN_MAIN, TITLE(LPCWSTR type), WS_OVERLAPPEDWINDOW, X(int), Y(int), WIDTH(int), HEIGHT(int), NULL, NULL, hInstance, NULL);

Lets create variables for it.
Code:
#include <windows.h> #include <windowsx.h> // required #include "stdafx.h" // class LPCWSTR WIN_MAIN = L"MAIN_WINDOW"; // size int SCREEN_WIDTH; int SCREEN_HEIGHT; // position int SCREEN_POS_X; int SCREEN_POS_Y; LPCWSTR WIN_TITLE; LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd) { // variables sets there ( c++ basics ) // size of window SCREEN_WIDTH = 1024; SCREEN_HEIGHT = 768; // position of window SCREEN_POS_X = 0; SCREEN_POS_Y = 0; // title of the window WIN_TITLE = L"Windowed program ^_^"; // L prefix is required ( C++ basics ) // Window creation MSG msg; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, WIN_MAIN, NULL}; RegisterClassEx(&wc); // create new window HWND hMainWnd = CreateWindow(WIN_MAIN, WIN_TITLE, WS_OVERLAPPEDWINDOW, SCREEN_POS_X, SCREEN_POS_Y, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); // show it ShowWindow(hMainWnd, ShowCmd); UpdateWindow(hMainWnd); // handle all window messages there while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return(0); } LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { return DefWindowProc (hWnd, message, wParam, lParam); }

Press F5, and you will see 1024x768 sized window. Lets fix exit now.
We will need only WindowProc method. This method is unique handler of all window's messages. ( use google to see them all ).
I will use WM_DESTROY msg.
To exit application i will use PostQuitMessage call.
Use UINT message to catch WM_DESTROY.
You must get that:
Code:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { //catch program quitting case WM_DESTROY: // quit PostQuitMessage(0); return(0); } return DefWindowProc (hWnd, message, wParam, lParam); }

Now program will quit normaly.

Last important step is - looping. ( realtime ).
As you can see in this code ( in WinMain )
Code:
// handle all window messages there while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }

It works only when message caught. We need to make it working for real-time. ( always ).
Just add second loop.
Code:
while(TRUE) { while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } }

But, it's not done. We need to add loopquitting there. Or program will not close ( again ).
I will use WM_QUIT message. Note: you can't use WM_DESTROY there. It's a loop.
Example:
Code:
// real time looping while(TRUE) { while(GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } // use only after translate/dispatching msg. if(msg.message == WM_QUIT) break; }
This looping will need for our game.
Note: Bug can happen because of GetMessage method. Use PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) if happened.
Code:
Code:
#include <windows.h> #include <windowsx.h> // required #include "stdafx.h" // class LPCWSTR WIN_MAIN = L"MAIN_WINDOW"; int SCREEN_WIDTH; int SCREEN_HEIGHT; int SCREEN_POS_X; int SCREEN_POS_Y; LPCWSTR WIN_TITLE; LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int ShowCmd) { // size of window SCREEN_WIDTH = 1024; SCREEN_HEIGHT = 768; // position of window SCREEN_POS_X = 0; SCREEN_POS_Y = 0; // title of the window WIN_TITLE = L"Windowed program ^_^"; // L prefix is required ( C++ basics ) // Window creation MSG msg; WNDCLASSEX wc = {sizeof(WNDCLASSEX), CS_VREDRAW|CS_HREDRAW|CS_OWNDC, WindowProc, 0, 0, hInstance, NULL, NULL, (HBRUSH)(COLOR_WINDOW+1), NULL, WIN_MAIN, NULL}; RegisterClassEx(&wc); // create new window HWND hMainWnd = CreateWindow(WIN_MAIN, WIN_TITLE, WS_OVERLAPPEDWINDOW, SCREEN_POS_X, SCREEN_POS_Y, SCREEN_WIDTH, SCREEN_HEIGHT, NULL, NULL, hInstance, NULL); // show it ShowWindow(hMainWnd, ShowCmd); UpdateWindow(hMainWnd); // real time loop while(TRUE) { while(GetMessage(&msg, NULL, 0, 0)) //PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } // game loop can be there if(msg.message == WM_QUIT) break; // game loop can be there // recommended there } return(0); } LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { switch(message) { case WM_DESTROY: PostQuitMessage(0); return(0); } return DefWindowProc (hWnd, message, wParam, lParam); }

You will see this:
[Image: C3OuV.png]

End of tutorial. In next tutorial i'll tell about directx, and making something in window!


This tutorial was written by me.
Thanks for reading!
C++/Obj-Cdeveloper. Neko engine wip
Steam: Click
Reply

#2
Added screenshot.
C++/Obj-Cdeveloper. Neko engine wip
Steam: Click
Reply

#3
(02-03-2013, 19:30)SailorMoon Wrote: Added screenshot.
Cute smiley detected.
:p

nice tutorial
[Image: b_560_95_1.png]
[Image: hax0r3ez.gif]
Reply

#4
It's called 'as' because i just pressed random keys, lol
C++/Obj-Cdeveloper. Neko engine wip
Steam: Click
Reply

#5
I dont think you can teach someone how to make a Game with C++/DirectX with some threads correctly.
But well done though.
[Image: ctoc.jpg]
Reply

#6
Sooo. Why do you need to include stdafx.h?
[Image: compiling.png][Image: aLKA8og_460sa.gif]
Reply

#7
(02-04-2013, 15:12)Ich1994 Wrote: Sooo. Why do you need to include stdafx.h?

Some compilers are giving errors about "Maybe you forgot to include "stdafx.h""?
C++/Obj-Cdeveloper. Neko engine wip
Steam: Click
Reply



Possibly Related Threads…
Thread Author Replies Views Last Post
  What game have you bought in the last week? RaZ 12 12,286 12-05-2013, 16:29
Last Post: Nekochan
  Making an apocalyptic themed Minecraft map AZUMIKKEL 54 41,239 08-31-2013, 02:54
Last Post: AZUMIKKEL
  [GAME]The Letter Game Bandarigoda123 65 43,098 08-08-2013, 21:05
Last Post: AZUMIKKEL
  [Release] AntiRage for Infected Game Mode yokai134 17 19,869 08-04-2013, 22:22
Last Post: yokai134
  ESTRANGED best indie game I've seen so far Arteq 0 3,847 08-03-2013, 14:03
Last Post: Arteq
  [HELP] bo2 - FD1 - dis-attach the console from the game masis 8 7,983 07-17-2013, 23:01
Last Post: surtek
Smile [Release] Map & Game Type Changer Plugin (Fixed) 30mba 31 29,051 07-10-2013, 16:27
Last Post: 26hz
  Selling steam account for a game! Strentin 3 5,738 06-18-2013, 07:49
Last Post: xfxtroll
  Making a Heli's angles match my angles? akillj 1 4,129 06-16-2013, 15:01
Last Post: Yamato
  Help Using chat outside in game Bandarigoda123 1 4,185 06-09-2013, 12:46
Last Post: Nekochan

Forum Jump:


Users browsing this thread:
1 Guest(s)

Forum Powered By MyBB, Theme by © 2002-2026 Melroy van den Berg.