• 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
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-C developer. Neko engine wip
Steam: Click
[-] The following 4 users say Thank You to Nekochan for this post:
  • 99IRock, aosma8, barata, Pozzuh
  Reply
#2
Added screenshot.
C++/Obj-C developer. 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-C developer. 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-C developer. 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 2,685 12-05-2013, 16:29
Last Post: Nekochan
  Making an apocalyptic themed Minecraft map AZUMIKKEL 54 10,304 08-31-2013, 02:54
Last Post: AZUMIKKEL
  [GAME]The Letter Game Bandarigoda123 65 8,725 08-08-2013, 21:05
Last Post: AZUMIKKEL
  [Release] AntiRage for Infected Game Mode yokai134 17 6,686 08-04-2013, 22:22
Last Post: yokai134
  ESTRANGED best indie game I've seen so far Arteq 0 999 08-03-2013, 14:03
Last Post: Arteq
  [HELP] bo2 - FD1 - dis-attach the console from the game masis 8 2,268 07-17-2013, 23:01
Last Post: surtek
Smile [Release] Map & Game Type Changer Plugin (Fixed) 30mba 31 10,423 07-10-2013, 16:27
Last Post: 26hz
  Selling steam account for a game! Strentin 3 1,582 06-18-2013, 07:49
Last Post: xfxtroll
  Making a Heli's angles match my angles? akillj 1 868 06-16-2013, 15:01
Last Post: Yamato
  Help Using chat outside in game Bandarigoda123 1 1,136 06-09-2013, 12:46
Last Post: Nekochan

Forum Jump:


Users browsing this thread: 1 Guest(s)