Конференция "Игры" » Проблема с класом движка [Delphi, Windows]
 
  • beginerProger (24.03.07 07:51) [0]
    Проблема с класом движка

    Пишу движок. Значит сделал пока процедуры старта окна, инициализации
    OpenGL, вывод текста на екран и тайминг. Всё это в отдельном модуле и одном класе

    TEngine = class
     ....
    end;

    Делаю простой пример. Создаю консольное приложение.
    ПИшу процедуру  рендеринга и обновлений.

    program test;

    uses
     windows, openGL, engine;

    var
     engine: TENG;

    procedure Rendering;
    begin
     WriteText(1,1,'www') ;
    end;

    procedure Update;
    begin
     
    end;

    begin
     Engine := TEng.Create;
     Engine.OnInit   := Init;
     Engine.StartEngine('Semple1',800,600,32,32,0,false);  
     Engine.OnRender := Render;
     Engine.OnUpdate := Update;
     Engine.Loop(50);
    end.

    Всё идёт нормально ,но если я например создаю отдельный модуль и вызываю например
    процедуру  
     WriteText(1,1,'www') ;
    то выбивает ошибку
     Error
    Runtime Error 216 at 00404c62

    почему и как єто исправить?
  • DJ KARIES (24.03.07 10:34) [1]
    Приведи исходники модулей.
    А вообще, судя по коду ошибки 216, это Access violation.
    Скорее всего вызов метода несозданного объекта.
  • beginerProger (24.03.07 10:53) [2]
    Да действительно я тоже так думаю. А как должно быть. как нужно объявлять класс
  • DJ KARIES (24.03.07 16:18) [3]
    Для начала вот перво несоответствие:

    TEngine = class
    ....
    end;

    var
    engine: TENG;

    Без исходного кода трудно что-то сказать.
  • beginerProger (24.03.07 21:00) [4]
    // ########  Модуль движка   ########
    unit eng_core;

    interface

    uses
     windows, messages, OpenGL, eng_utilits;

    const
     // Типы задания координат
     COORD2D          = 0;
     COORD3D          = 1;
     COORD_RESTORE    = 2;

    type
     TOnRender = procedure;
     TOnUpdate = procedure;
     TOnInit = procedure;

    type
     TInput = record
       Keys: array [0..255] of boolean;
     end;

    type
      TGLRenderDevice = class;
    {================================== Engine ====================================}
     TEngine = class
     private
       FOnRender: TOnRender;
       FOnUpdate: TOnUpdate;
       FOnInit: TOnInit;
     public
       constructor Create;
       destructor  Destroy;
     public
       procedure StartEngine(name: PChar; width, height: integer; depth, bpp, stencil: integer; FullScreen: boolean = false);
       procedure Loop(UPS:integer);
       procedure Quit;
       procedure SetCoord(Flag: byte);
       procedure Begin2D;
       procedure End2D;
       procedure Begin3D;
       procedure End3D;
       procedure RenderingBegin;
       procedure RenderingEnd;
       //time
       function GetTime: integer;
       procedure ResetTimer;
       //font
       procedure BuildFont(name: pChar);
       procedure glWrite( X, Y : GLUint; text: PChar; color: integer);
       procedure KillFont();

       function FPS: integer;

       property OnRender: TOnRender read FOnRender write FOnRender;
       property OnUpdate: TOnUpdate read FOnUpdate write FOnupdate;
       property OnInit: TOnInit read FOnInit write FOnInit;

     public
       RenderDevice: TGLRenderDevice;
       h_wc:  WndClassEX;
       h_wnd: HWND;
       m_msg: TMSG;
       //gl
       h_dc: HDC;
       h_rc: HGLRC;
       eFullScreen: boolean;
       ups_time_old: integer;
       ups_time: integer;
       fps_time: Integer;
       fps_cur:  Integer;
    //    FPS:      Integer;
       _FPS: integer;
       Time, Time_delta: integer;
       baseFont : uint;
     end;
    {====================================== GL ====================================}
     TGLRenderDevice = class
     private
       h_rc: HGLRC;
       h_dc: HDC;
       PixelFormat: gluINT;
       GLWND: TEngine;
     public
       procedure Init(var GLWind: TEngine);
       procedure Clear;
       procedure SwapBuffer;
       procedure Finalize;
     end;

    var

     eng: TEngine;
     EENG : ^TEngine;
     GL: TGLRenderDevice;
     ewidth,eheight: integer;
     finished: boolean;
     input: TInput;
     CoordNow : byte;
     CoordLast : byte;

    implementation

    //------------------------------------------------------------------------------
    constructor TEngine.Create;
    begin
     finished := false;
    end;
    //------------------------------------------------------------------------------
    destructor TEngine.Destroy;
    begin
     Quit;

     DestroyWindow(h_wnd);
     UnRegisterClass('Dream',hInstance);
     RenderDevice.Finalize;

     wglMakeCurrent(0, 0);
     wglDeleteContext(h_RC);
     ReleaseDC(h_Wnd, h_DC);

     if eFullscreen then ChangeDisplaySettings(TDevMode(nil^), CDS_FULLSCREEN);

    end;
    //------------------------------------------------------------------------------
    // Изменение размеров окна
    procedure ResizeWin( Width, Height : integer );
    begin
     eWidth := Width;
     eHeight := Height;

     glViewport(0, 0, eWidth, eHeight);    // Установить порт отображения
     glMatrixMode(GL_PROJECTION);          // Установить матрицу проекции
     glLoadIdentity();                     // Востановить
     //  gluPerspective(45.0, eWidth/eHeight, 0.1, 100.0);
     glFrustum( -( eWidth/eHeight ), ( eWidth/eHeight ), -1, 1, 1.0, 100.0 );

     glTranslatef( 0.0, 0.0, -2.0 );
     glMatrixMode(GL_MODELVIEW);           // Установить матрицу отображения
     glLoadIdentity();
     CoordNow := COORD3D;
    end;
    //------------------------------------------------------------------------------
    function WindowProc(_wnd: HWND; _msg:integer; wparam: wparam; lparam: lparam):lresult;stdcall;
    begin
     case _msg of
     WM_CREATE:begin  end;
     WM_DESTROY: begin PostQuitMessage(0); Result:= 0; eng.Free;  exit; end;
     WM_KEYDOWN: begin Input.keys[wparam] := true; end;
     WM_KEYUP:   begin Input.keys[wparam] := false; end;
     WM_PAINT:   begin
                   glClear(GL_DEPTH_BUFFER_BIT OR GL_COLOR_BUFFER_BIT);
                   glClearColor(0,0,0,0);
                   ValidateRect(_wnd,nil); result := 0; exit;
                 end;
     WM_SIZE:    begin ResizeWin(loword(lparam),hiword(lparam)); end;
     end;
     Result := DefWindowProc(_wnd,_msg,wparam,lparam);
    end;
  • beginerProger (24.03.07 21:01) [5]
    //------------------------------------------------------------------------------
    procedure TEngine.StartEngine(name: PChar; width, height: integer; depth, bpp, stencil: integer; FullScreen: boolean = false);
    var
     dwStyle: DWORD;   // Стиль окна
     dwExStyle: DWORD; // Стиль окна
     dmScreenSettings : DEVMODE;
     pfd: TPixelFormatDescriptor;
     nPixelFormat: Integer;
    begin
     ewidth := width;
     eheight:= height;
     ZeroMemory(@h_wc,SizeOf(h_wc));
     h_wc.style        := CS_HREDRAW OR CS_VREDRAW OR CS_OWNDC;
     h_wc.cbSize       := sizeof(h_wc);
     h_wc.lpfnWndProc  := @WindowProc;
     h_wc.hInstance    := hInstance;
     h_wc.hbrBackground:= COLOR_BTNFACE+1;
     h_wc.hCursor      := LoadCursor(0,IDC_ARROW);
     h_wc.lpszClassName:= 'Dream';

     if (RegisterClassEX(h_wc) = 0) then begin MessageBox(0,'Невозможно зарегестрировать класс окна','Error',MB_OK); exit; end;

      // Изменение режима екрана
     if Fullscreen then
     begin
       eFullScreen := fullscreen;
       ZeroMemory(@dmScreenSettings, SizeOf(dmScreenSettings));
       with dmScreenSettings do begin              // Установления параметров екрана
         dmSize       := SizeOf(dmScreenSettings);
         dmPelsWidth  := Width;                    // Ширина окна
         dmPelsHeight := Height;                   // Высота окна
         dmBitsPerPel := Depth;                    // Глубина цвета
         dmFields     := DM_PELSWIDTH or DM_PELSHEIGHT or DM_BITSPERPEL;
       end;

       // Установить полноекраный режим
     if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN) = DISP_CHANGE_FAILED) then
       begin
         MessageBox(0, 'Невозможно перейти в полноекранный режим', 'Error', MB_OK or MB_ICONERROR);
         Fullscreen := False; eFullScreen := fullscreen;
       end;
     end;

     if (FullScreen) then
     begin
       dwStyle   := WS_POPUP OR WS_CLIPCHILDREN OR WS_CLIPSIBLINGS;
       dwExStyle := WS_EX_APPWINDOW;
       ShowCursor(False);
       eFullScreen := fullscreen;
     end
     else
     begin
       dwStyle   :=  WS_SYSMENU OR WS_MINIMIZEBOX OR WS_CLIPCHILDREN OR WS_CLIPSIBLINGS; // <-- Updated 29.12.2006
       dwExStyle := WS_EX_APPWINDOW OR WS_EX_WINDOWEDGE;
       ShowCursor(true);
       eFullScreen := fullscreen;
     end;

     h_wnd := CreateWindowEX(dwExStyle,'Dream',name,dwStyle,0,0,Width,Height,0,0,hInstance,nil );
     h_dc := GetDC(h_wnd);

     with pfd do
     begin
       nSize := SizeOf(TPixelFormatDescriptor); // размер структуры
       nVersion := 1;                            // номер версии
       dwFlags := PFD_DOUBLEBUFFER or PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL; // множество битовых флагов, определяющих устройство и интерфейс
       iPixelType := PFD_TYPE_RGBA; // режим для изображения цветов
       cColorBits := bpp;            // число битовых плоскостей в каждом буфере цвета
       cRedBits := 0;               // число битовых плоскостей красного в каждом буфере RGBA
       cRedShift := 0;              // смещение от начала числа битовых плоскостей красного в каждом буфере RGBA
       cGreenBits := 0;             // число битовых плоскостей зелёного в каждом буфере RGBA
       cGreenShift := 0;            // смещение от начала числа битовых плоскостей зелёного в каждом буфере RGBA
       cBlueBits := 0;              // число битовых плоскостей синего в каждом буфере RGBA
       cBlueShift := 0;             // смещение от начала числа битовых плоскостей синего в каждом буфере RGBA
       cAlphaBits := 0;             // число битовых плоскостей альфа в каждом буфере RGBA
       cAlphaShift := 0;            // смещение от начала числа битовых плоскостей альфа в каждом буфере RGBA
       cAccumBits := 0;             // общее число битовых плоскостей в буфере аккумулятора
       cAccumRedBits := 0;          // число битовых плоскостей красного в буфере аккумулятора
       cAccumGreenBits := 0;        // число битовых плоскостей зелёного в буфере аккумулятора
       cAccumBlueBits := 0;         // число битовых плоскостей синего в буфере аккумулятора
       cAccumAlphaBits := 0;        // число битовых плоскостей альфа в буфере аккумулятора
       cDepthBits := depth;            // размер буфера глубины (ось z)
       cStencilBits := stencil;           // размер буфера трафарета
       cAuxBuffers := 0;            // число вспомогательных буферов
       iLayerType := PFD_MAIN_PLANE;// тип плоскости
       bReserved := 0;              // число плоскостей переднего и заднего плана
       dwLayerMask := 0;            // игнорируется
       dwVisibleMask := 0;          // индекс или цвет прозрачности нижней плоскости
       dwDamageMask := 0;           // игнорируется
     end;

     nPixelFormat := ChoosePixelFormat( H_DC, @pfd ); // запрос системе - поддерживается ли выбранный формат пикселей
     SetPixelFormat( H_DC, nPixelFormat, @pfd );      // устанавливаем формат пикселей в контексте устройства

     RenderDevice := TGLRenderDevice.Create;
     RenderDevice.Init(self);

     ShowWindow(h_wnd,SW_SHOW); SetForegroundWindow(h_Wnd);

     if (Assigned(FOnInit)) then FOnInit;

    end;
    //------------------------------------------------------------------------------
    procedure TGLRenderDevice.Clear;
    begin
     glClear(GL_DEPTH_BUFFER_BIT OR GL_COLOR_BUFFER_BIT);
     glClearColor(0,0,0,0);
    end;
    //------------------------------------------------------------------------------
    procedure TGLRenderDevice.Finalize;
    begin
     wglDeleteContext(h_rc);
     ReleaseDC(GLWnd.h_wnd,GLWnd.h_dc);
    end;
    //------------------------------------------------------------------------------
  • beginerProger (24.03.07 21:02) [6]
    procedure TGLRenderDevice.SwapBuffer;
    begin
     SwapBuffers(h_dc);
    end;
    //------------------------------------------------------------------------------
    procedure TGLRenderDevice.Init(var GLWind: TEngine);
    begin
     GLWnd := GLWind;
     h_dc := GLWnd.h_dc;
     h_rc := wglCreateContext(h_dc);
     ReleaseDC( GLwnd.h_Wnd, h_DC );
     wglMakeCurrent( h_DC, h_rc);
    end;
    //------------------------------------------------------------------------------
    // Задание кординатной системы
    procedure TEngine.SetCoord( Flag : byte );
    begin
     if CoordNow = Flag then exit;
     Case Flag of
       COORD2D : begin
         glPushMatrix();
         glMatrixMode(GL_PROJECTION);  // Установить проекционую матрицу
         glLoadIdentity();             // Очистить стек
         glOrtho(0, eWidth, 0, eHeight, 0, 100);
         glMatrixMode(GL_MODELVIEW);   // Установить матрицу отображения
         glLoadIdentity;
         glTranslatef( 0, 0, -1 );
       end;
       COORD3D : begin
         ResizeWin(eWidth, eHeight );
       end;
       COORD_RESTORE : begin
         SetCoord(CoordLast);
       end;
     end;
     if Flag <> COORD_RESTORE then
     begin
       CoordLast := CoordNow;
       CoordNow := Flag;
     end;
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.Begin2D;
    begin
     SetCoord(COORD2D);
     glDisable(GL_DEPTH_TEST);
     glPushMatrix();
     glTranslatef( 0, 0, -1.0 );
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.End2D;
    begin
     glPopMatrix();
     glEnable(GL_DEPTH_TEST);
     SetCoord(COORD_RESTORE);
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.Begin3D;
    begin
     SetCoord(COORD3D);
     glEnable(GL_DEPTH_TEST);
     glPushMatrix();
     glTranslatef( 0, 0, -1.0 );
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.End3D;
    begin
     glPopMatrix();
     glDisable(GL_DEPTH_TEST);
     SetCoord(COORD_RESTORE);
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.RenderingBegin;
    begin
     glClearColor(0.0, 0.0, 0.0, 0.0); // Установить цвет окна
     glLoadIdentity();                 // Очистить стек
     glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT or GL_STENCIL_BUFFER_BIT);
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.RenderingEnd;
    begin
    RenderDevice.SwapBuffer;
    GlFlush;
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.Quit;
    begin
     finished := true;
    end;
    //------------------------------------------------------------------------------
    function TEngine.GetTime: integer;
    var
     T: LARGE_INTEGER;
     F: LARGE_INTEGER;
    begin
     QueryPerformanceFrequency(Int64(F));
     QueryPerformanceCounter(Int64(T));
     Result:= Trunc(1000 * T.QuadPart / F.QuadPart);
    end;

    procedure TEngine.ResetTimer;
    begin
     ups_time_old := GetTime;
    end;

    function TEngine.FPS: integer;
    begin
     Result := _FPS;
    end;
    //------------------------------------------------------------------------------
    procedure TEngine.Loop(UPS: Integer);
    begin
    //  finished := false;
     ups_time_old := GetTime - 1000 div UPS;
     ups_time := GetTime;
     fps_time := GetTime;

     while not finished do
     begin
       while PeekMessage(m_msg,0,0,0,PM_REMOVE) do
       begin
         if m_msg.message = WM_QUIT then finished := true else begin
           TranslateMessage(m_msg);
           DispatchMessage(m_msg);
         end;
       end;
       while GetTime - ups_time_old >= (1000 div ups) do
       begin
       if (Assigned(FOnUpdate)) then FOnUpdate;
       inc(ups_time_old, 1000 div ups);
       end;
       if (Assigned(FOnRender)) then FOnRender;
       RenderDevice.SwapBuffer;
       if fps_time <= GetTime then
       begin
         fps_time := GetTime + 1000;
         _FPS := fps_cur;
         fps_cur := 0;
       end;
       inc(fps_cur);

     end;
     Destroy;
    end;
    //------------------------------------------------------------------------------
    // Создаём базовый текст
    procedure TEngine.BuildFont(name: PChar);
    var font : HFONT;
    begin
     baseFont := glGenLists(255);
     font := CreateFont(-18, 0, 0, 0, FW_BOLD, 0, 0, 0, ANSI_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE or DEFAULT_PITCH, name);
     SelectObject( h_DC, font );
     wglUseFontBitmaps( h_DC, 0, 256, baseFont );
    end;
    //------------------------------------------------------------------------------
    // Рисуем текст
    procedure TEngine.glWrite(X, Y: GLUint; text : PChar; color: integer);
    begin
    //  glColor3ub(0,20,250);
     SetColor(color);
     Y := eHeight-Y;
     glRasterPos2i(X, Y);
     glPushAttrib(GL_LIST_BIT);
     glListBase(baseFont);
     glCallLists(length(text), GL_UNSIGNED_BYTE, text);
     glPopAttrib();
    end;
    //------------------------------------------------------------------------------
    // Удаляем базовый текст
    procedure TEngine.KillFont();
    begin
     glDeleteLists( baseFont, 255 );
    end;
    end.
  • beginerProger (24.03.07 21:03) [7]
    // #####  Модуль примера для теста  #####  

    unit TestU;

    interface

    uses
     windows, eng_core, eng_utilits;

    procedure pr;

    implementation

    procedure pr;
    begin
     EEng.glWrite(10,10,'www',1);
    end;

    end.
  • beginerProger (24.03.07 21:04) [8]
    // #### Главная программа ##### //
    program Semple1;

    uses
     windows,
     messages,
     OpenGL,
     eng_core in 'Engine\eng_core.pas',
     eng_utilits in 'Engine\eng_utilits.pas',
     TestU in 'TestU.pas';

    var
     ENGsemple: TEngine;
     
    procedure Init;
    begin

    end;

    procedure Menu;
    begin

    ENGsemple.RederingBegin;
    ENGsemple.begin2D;

    pr;
    ENGsemple.glWrite(50,500 - x1,'Engine',white);

    ENGsemple.end2d;
    ENGsemple.RenderingEnd;
    end;

    procedure Render;
    begin
     Menu;
    end;

    procedure Update;
    begin
    if Input.Keys[27] = true then ENGsemple.Quit;
    end;

    begin
     ENGsemple := TEngine.Create;
     ENGsemple.OnInit   := Init;
     ENGsemple.StartEngine('Semple1',800,600,32,32,0,false);  // bpp,depth,stecil
     ENGsemple.BuildFont('Courier');
     ENGsemple.OnRender := Render;
     ENGsemple.OnUpdate := Update;
     ENGsemple.Loop(50);
     ENGsemple.KillFont;
    end.
  • XProger © (24.03.07 21:18) [9]
    > Делаю простой пример. Создаю консольное приложение.
    Где?
  • beginerProger (25.03.07 00:18) [10]
    вот модули движка
    eng_core in 'Engine\eng_core.pas',
    eng_utilits in 'Engine\eng_utilits.pas',
    Это просто модуль
    TestU in 'TestU.pas';

    Вся проблема в том, что Программа работает консольная
    без модуля  TestU in 'TestU.pas';
    а когда вызываю процедуру pr; из этого модуля получется ошибка...
    Почему?
  • Rial © (25.03.07 05:00) [11]
    > [10] beginerProger   (25.03.07 00:18)
    > а когда вызываю процедуру pr; из этого модуля получется
    > ошибка...
    > Почему?

    А потому, что EENG нигде не инициализируется.
    Что в нем лежит - да ничего.

    А вообще надо пересмотреть тебе основную задачу твоего модуля.
    Тут и окна создаются, и OpenGL инициализируется...
    Надо как то уже определить задачу класса.
    Один для окна, другой для графики.

    Код не очень читается. Чаще новые что ли на новые
    строки переходи.
    Воотще критики тут много... но писать лень.
  • beginerProger (25.03.07 15:41) [12]
    Всё заработало. Проблема действительно была такая. Класс просто не создавался.
    Спасибо за советы и за критику.
    Да Дейстивтельно мне надо разбить движок по отдельным модулям и сделаю код более структуированным.
    :)
  • beginerProger (26.03.07 02:21) [13]
    Ещё один глюк при переходе в полноекраній режим 1024х768 всё дёргается
    а при 800х600 обрезается нижняя и правая сторона на пикслей 150.
    Почему. Я в отчаянии ;(
    Что может соедует писать с нуля.
  • homm © (26.03.07 07:04) [14]
    <offtop>
    > Что может соедует писать с нуля.

    Учись ставить запятые.
    </offtop>
 
Конференция "Игры" » Проблема с класом движка [Delphi, Windows]
Есть новые Нет новых   [134430   +2][b:0][p:0.001]