Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишу игровой движок на C++. 003

Войти
Регистрация
Восстановить пароль
Оценить эту запись

Пишу игровой движок на C++. 003

Запись от 532235 размещена 03.11.2017 в 01:25

Прежде чем что-то делать, нужно подготовиться. А именно написать всякие логеры и прочие вещи.
Главное это выводить информацию об ошибках.

Я как-то делал консоль на основе Windows окна. В этом проекте я сделаю так же.

Естественно, нужно написать независимую от ОС оболочку.

План действий, на эту запись:

1. Сделать окно вывода (пока без ввода команд)
2. Сделать функции вывода, логер.
3. Создать базовое окно (которое в будущем можно выбрать для рисования).

=============================
1. Окно вывода - class gtOutputWindow
=============================

Делаю абстрактный класс gtOutputWindow. Для него нужен файл gtOutputWindow.h Так же нужно будет добавить #include <gtOutputWindow.h> в gost.h

содержание файла
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#pragma once
#ifndef __GT_OUTPUT_WINDOW_H__
#define __GT_OUTPUT_WINDOW_H__
 
/*
    Окно для вывода текстовой информации
*/
 
//  чтобы не захламлять глобальный namespace
namespace gost{
 
    //  Окно для вывода текстовой информации
    class gtOutputWindow {
    public:
 
        //  Прежде чем использовать нужно вызвать Init
        virtual void    init( void ) = 0;
 
        //  При завершении работы нужно вызвать этот метод
        virtual void    shutdown( void ) = 0;
 
        //  Возвратит true если инициализирован
        virtual bool    isInit( void ) = 0;
 
        //  Если окно невидимо, покажет его
        virtual void    show( void ) = 0;
 
        //  Сделает окно невидимым (спрячет, или сделает прозрачным, зависит от реализации)
        virtual void    hide( void ) = 0;
 
        //  Напечатает текст
        virtual void    print( const gtString& ) = 0;
 
        //  Установит заголовок
        virtual void    setWindowText( const gtString& ) = 0;
        
    };
 
}
 
#endif
В проекте движка создам класс gtOutputWindowWin32. Он производный от gtOutputWindow.
.h
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
//  GOST
 
#pragma once
#ifndef __GT_OUTPUT_WINDOW_WIN32_H__
#define __GT_OUTPUT_WINDOW_WIN32_H__
 
/*
    Реализация для Windows
*/
 
namespace gost{
 
    //  Реализация для Windows
    class gtOutputWindowWin32 GT_FINAL : public gtOutputWindow {
 
        //  true если был вызван init()
        bool m_isInit;
 
        //  Window handle
        HWND m_hWnd;
        WNDCLASS m_wc;
 
        //  Ширина окна
        s32 m_windowWidth;
 
        //  Высота окна
        s32 m_windowHeight;
 
        //  Оконная процедура
        static LRESULT CALLBACK
            OutWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
 
    public:
 
        //  Конструктор
        gtOutputWindowWin32( void );
 
        //  Деструктор
        ~gtOutputWindowWin32( void );
 
        //  Инициализация
        void    init( void ) GT_FINAL;  //  по сути если класс объявлен как final то нет смысла писать его для методов. ну да ладно, буду говнокодить
 
        //  Завершение работы
        void    shutdown( void ) GT_FINAL;
 
        //  Возвратит true если инициализирован
        bool    isInit( void ) GT_FINAL;
 
        //  Если окно невидимо, покажет его
        void    show( void ) GT_FINAL;
 
        //  Сделает окно невидимым (спрячет, или сделает прозрачным, зависит от реализации)
        void    hide( void ) GT_FINAL;
 
        //  Напечатает текст
        void    print( const gtString& ) GT_FINAL;
 
        //  Установит заголовок
        void    setWindowText( const gtString& ) GT_FINAL;
 
    };
 
}
 
#endif
.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//  GOST
 
#include "stdafx.h"
 
/*
    Реализация для Windows
*/
 
gtOutputWindowWin32::gtOutputWindowWin32( void ) : m_isInit( false ),
m_hWnd( nullptr ), m_windowHeight( 0 ), m_windowWidth( 0 ){
    memset( &m_wc, 0, sizeof( m_wc ) );
}
gtOutputWindowWin32::~gtOutputWindowWin32( void ){}
 
//  Инициализация
void    gtOutputWindowWin32::init( void ){
 
    //  ненужно инициализировать повторно
    if( m_isInit ) return;
 
    //  Нужно создать windows окно
    m_wc.lpfnWndProc   = ( WNDPROC )OutWndProc;
    m_wc.hInstance     = GetModuleHandle( 0 );
    m_wc.hIcon         = NULL;//LoadIcon( wc.hInstance, MAKEINTRESOURCE(IDI_ICON1));
    m_wc.hCursor       = LoadCursor (NULL,IDC_ARROW);
    m_wc.hbrBackground = (struct HBRUSH__ *)COLOR_WINDOW;
    m_wc.lpszMenuName  = NULL;
    m_wc.lpszClassName = L"OUTPUTWINDOW";
 
    //  если не можем зарегестрировать класс то завершение работы
    if( !RegisterClass (&m_wc) ){
        MessageBox( 0, L"Can not initialize Output Window", L"Error", MB_ICONERROR );
        return;
    }
 
    // Стиль окна
    s32 style = WS_POPUPWINDOW | WS_CAPTION | WS_MINIMIZEBOX;
 
    //  размер окна
    RECT rect;
    rect.left = 0;
    rect.right = 540;
    rect.top = 0;
    rect.bottom = 450;
 
    //  обновляем размер в соответствии со стилем
    AdjustWindowRect( &rect, style, FALSE );
 
    HDC hDC = GetDC( GetDesktopWindow() );
    s32 swidth = GetDeviceCaps( hDC, HORZRES );
    s32 sheight = GetDeviceCaps( hDC, VERTRES );
    ReleaseDC( GetDesktopWindow(), hDC );
 
    m_windowWidth = rect.right - rect.left + 1;
    m_windowHeight = rect.bottom - rect.top + 1;
 
    m_hWnd = CreateWindowEx( NULL, m_wc.lpszClassName,
        L"Output", style,
        ( swidth - 600 ) / 2, ( sheight - 450 ) / 2 , rect.right - rect.left + 1, rect.bottom - rect.top + 1,
        NULL, NULL, m_wc.hInstance, 
        
        //  Полезная вещь. Класс сможет иметь доступ к оконной процедуре
        this );
 
    if( !m_hWnd ){
        MessageBox( 0, L"Can not create Output Window", L"Error", MB_ICONERROR );
        return;
    }
 
    //  всё инициализировано
    m_isInit = true;
}
 
//  Завершение работы
void    gtOutputWindowWin32::shutdown( void ){
    DestroyWindow( m_hWnd );    m_hWnd = nullptr;
    UnregisterClass( m_wc.lpszClassName, m_wc.hInstance );
    m_isInit = false;
}
 
//  Возвратит true если инициализирован
bool    gtOutputWindowWin32::isInit( void ){
    return m_isInit;
}
 
//  Если окно невидимо, покажет его
void    gtOutputWindowWin32::show( void ){
    if( m_isInit ){
        ShowWindow( m_hWnd, SW_SHOWNORMAL );
        UpdateWindow( m_hWnd );
    }
}
 
//  Сделает окно невидимым (спрячет, или сделает прозрачным, зависит от реализации)
void    gtOutputWindowWin32::hide( void ){
    if( m_isInit )
        ShowWindow( m_hWnd, SW_HIDE );
}
 
//  Напечатает текст
void    gtOutputWindowWin32::print( const gtString& ){
}
 
//  Установит заголовок
void    gtOutputWindowWin32::setWindowText( const gtString& text ){
    if( m_isInit )
        SetWindowText( m_hWnd, (wchar_t*)text.data() );
}
 
 
LRESULT CALLBACK gtOutputWindowWin32::OutWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ){
 
    //  После этого класс имеет доступ к оконной процедуре
    gtOutputWindowWin32*    output = nullptr;
    if( !output ){
        if( uMsg == WM_NCCREATE ){
            output = static_cast<gtOutputWindowWin32*>( reinterpret_cast<CREATESTRUCT*>(lParam)->lpCreateParams );
            SetLastError(0);
            if (!SetWindowLongPtr(hWnd, -21, reinterpret_cast<LONG_PTR>( output )))
                if (GetLastError() != 0)             return FALSE;
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
        }
        else{
            output = reinterpret_cast<gtOutputWindowWin32*>(GetWindowLongPtr(hWnd, -21));
        }
    }
 
    switch( uMsg ){
        case WM_SYSCOMMAND:
            if( wParam == SC_CLOSE ){
                PostQuitMessage( 0 );
            }
            break;
        case WM_CREATE:
            break;
    }
 
    return DefWindowProc( hWnd, uMsg, wParam, lParam );
}
Теперь можно делать запуск DLL и увидеть как создаётся это окно.
Добавляю в stdafx.h (перед #include <gost.h>) макрос #define GT_EXPORTS

Открываю файл gost.cpp и пишу

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*
    Черновой вариант. Только чтобы убедиться что окно вывода работает
*/
 
gtOutputWindowWin32 output;
 
GT_API void InitializeGoSTEngine( void ){
    output.init();
    output.show();
}
 
GT_API void ShutownGoSTEngine( void ){
    output.shutdown();
}
Теперь можно начать построение. При построении dll создастся .lib файл. Нужно заранее создать папку lib
Рядом с include создаю папку lib
Внутри этой папки создаю ещё одну с именем x86

Иду в параметры проекта и настраиваю (General)
Имя для Debug версии gost_d
Имя для Release версии gost

В поле Output Directory пишу ../lib/x86/

Туда же будет лететь .dll файл. А нужно сделать так чтобы все исполняемые модули были в одной папке.
Рядом с include и lib папками создам папку bin32

В параметрах проекта (Linker) указываю Output File - ../bin32/$(TargetName)$(TargetExt)

Теперь при построении все файлы окажутся в нужных папках.

=========================

Хотел многое написать, но, уже много букв. Проведу тест - запущу .dll с окном вывода, и на этом пока всё

=========================

Нужно создать новый проект. Проще консольный. Указываю директории include и lib/x86. Так же папку для вывода exe

Пишу

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <gost.h>
 
#pragma comment(lib, "gost_d.lib")
 
 
int main(){
 
    InitializeGoSTEngine();
 
    while( true );
 
    ShutownGoSTEngine();
 
 
    return 0;
}
Готово. Если запустить программу, то она вызовет функцию из DLL и DLL создаст окно.

Окно не будет реагировать, так как пока не была вызвана оконная процедура.
Размещено в Игровой движок
Просмотров 266 Комментарии 0
Всего комментариев 0

Комментарии

 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru