-
Проблема с класом движка
Пишу движок. Значит сделал пока процедуры старта окна, инициализации 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
почему и как єто исправить?
-
Приведи исходники модулей. А вообще, судя по коду ошибки 216, это Access violation. Скорее всего вызов метода несозданного объекта.
-
Да действительно я тоже так думаю. А как должно быть. как нужно объявлять класс
-
Для начала вот перво несоответствие:
TEngine = class .... end;
var engine: TENG;
Без исходного кода трудно что-то сказать.
-
// ######## Модуль движка ######## 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;
-
//------------------------------------------------------------------------------ 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; //------------------------------------------------------------------------------
-
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.
-
// ##### Модуль примера для теста #####
unit TestU;
interface
uses windows, eng_core, eng_utilits;
procedure pr;
implementation
procedure pr; begin EEng.glWrite(10,10,'www',1); end;
end.
-
// #### Главная программа ##### // 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.
-
> Делаю простой пример. Создаю консольное приложение. Где?
-
вот модули движка eng_core in 'Engine\eng_core.pas', eng_utilits in 'Engine\eng_utilits.pas', Это просто модуль TestU in 'TestU.pas';
Вся проблема в том, что Программа работает консольная без модуля TestU in 'TestU.pas'; а когда вызываю процедуру pr; из этого модуля получется ошибка... Почему?
-
> [10] beginerProger (25.03.07 00:18) > а когда вызываю процедуру pr; из этого модуля получется > ошибка... > Почему?
А потому, что EENG нигде не инициализируется. Что в нем лежит - да ничего.
А вообще надо пересмотреть тебе основную задачу твоего модуля. Тут и окна создаются, и OpenGL инициализируется... Надо как то уже определить задачу класса. Один для окна, другой для графики.
Код не очень читается. Чаще новые что ли на новые строки переходи. Воотще критики тут много... но писать лень.
-
Всё заработало. Проблема действительно была такая. Класс просто не создавался. Спасибо за советы и за критику. Да Дейстивтельно мне надо разбить движок по отдельным модулям и сделаю код более структуированным. :)
-
Ещё один глюк при переходе в полноекраній режим 1024х768 всё дёргается а при 800х600 обрезается нижняя и правая сторона на пикслей 150. Почему. Я в отчаянии ;( Что может соедует писать с нуля.
-
<offtop> > Что может соедует писать с нуля.
Учись ставить запятые. </offtop>
|