[OpenGL] Grafika 2D

0

Witam,
mam pewien problem. Chciałbym zacząć pisać "grę" 2D (RPG), jednak nie wiem od czego zacząć. Nie wiem gdzie szukać opisów funkcji itp. Wszystko co znalazlem tyczylo sie C++. Byłbym wdzięczny za kazda pomoc :).

BTW. Jak narysować kwadracik 32x32 i potem nanieść na niego teksture (BMP)?

Thx za wszystko

0

Biblioteka openGL jest "taka sama" pod cpp jak i pascalem więc wszystko co znalazłeś możesz także użyć w swoim programie w Pascalu lub w Delphi

0

Co racja to racja :D... Mógłby ktoś podsunąć link do jakiejś dokumentacji/helpa/tutoriala. Bardzo zależy mi na 2D. Dotychczasowe wyniki były związane z 3D.

0

Nio to podziel się tymi linkami :)

0

Czy ktoś wie jak zrobić, by podczas poruszania się, postać była w centrum ekranu, a mapa przesuwalaby sie? Cos jak np. w Tibii jest (;/). Chodzi mi głównie o algorytm w pseudokodzie.

0

Chyba wiecie mniej wiecej, o co chodzi.. :P macie jakas koncepcje jak wykonac taki sposob poruszania sie?

ja mam dwie:

  1. Mapa pod bohaterem sie przesuwa
  2. Bohater wraz z widokiem sie przesuwa
0

hmm w życiu czegoś takiego nie robiłem, ale jakby miał to tak:
1.Przechowujesz gdzieś aktualną pozycję bohatera na mapie
2.z tej aktualnej pozycji obliczasz ile mapy aktualnie jest widoczne tak aby bohater był w centrum
3.Rysujesz to
4. W momencie zmainy pozycji bohatera odświezasz ekran

0

Albo po prostu ustawiasz obszar obcinania tak, aby środek współżędnych był w centrum ekranu (wartości symetryczne dla x, y i z), a przed "położeniem" boha zerujesz macież widoku, i masz go na środku :P

Masz tu linka do stronki z tutami od podstaw, nawet po polsku ;)

http://www.dimmension3.spine.pl/index.php

0

Wydaje sie proste :P, ale nie jest jak sie nie zna funkcji openGL :/

0
  1. Przykładowa mapa:
    (2;2) (2;1) (2;0) (2;-1) (2;-2)
    (1;2) (1;1) (1;0) (1;-1) (1;-2)
    (0;2) (0;1) x (0;-1) (0;-2)
    (-1;2) (-1;1) (-1;0) (-1;-1) (-1;-2)
    (-2;2) (-2;1) (-2;0) (-2;-1) (2;-2)

x - (0;0) //zawodnik

  1. Gdy zrobię krok do przodu:
    (2;3) (2;2) (2;1) (2;0) (2;-1)
    (1;3) (1;2) (1;1) (1;0) (1;-1)
    (0;3) (0;2) x (0;0) (0;-1)
    (-1;3) (-1;2) (-1;1) (-1;0) (-1;-1)
    (-2;3) (-2;2) (-2;1) (-2;0) (-2;-1)

x - (0;1) //zawodnik

/\ - x := (a;b+1)
/ - x := (a;b-1)
< - x := (a-1;b)

  • x := (a+1;b)

Podstawowym pytaniem, jakie mi się nasuwa, jest: W jaki sposób wyświetlać mapę?

  1. Mogę narysować kwadraty 32x32 i ooteksturować je... troche roboty, ale jak potem odwoływać się do kazdego :/?
  2. Nie mam pomyslu ...
0

HELP !

0

A na przykład umieścić je w tablicy dwówymiarowej, z której wyciągasz podczas rysowania elementy zależne od pozycji boha

0

Juz mam sterowanie...

Teraz problem jest tego typu, że jeśli mam "podloge", a na niej "osobe", to gdy ruszę kamerą "osoba" znika.

Dwie funkcje:

function DrawCharacter(x,y,z : integer) : bool; // rysowanie bohateraz
begin
  glLoadIdentity();
  glColor3f(1.0,1.0,0.0);
  glTranslatef(x,y,-z);
  glBegin(GL_QUADS);
  glBlendFunc(GL_ONE,GL_SRC_ALPHA);
  glVertex2f(-1.0, 1.0);
  glVertex2f( 1.0, 1.0);
  glVertex2f( 1.0,-1.0);
  glVertex2f(-1.0,-1.0);
  glEnd();
  glFlush();
//pomijam result
end;

function GenerateMap(x,y,z : integer) : bool; //generowanie mapy
begin
result := false;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
for i := x to y do
begin
for n := x-2 to y+2 do
begin
  glLoadIdentity();
  glColor3f(1.0,0.0,0.0);
  if n < S then
  glTranslatef(-n*2,i*2,-z)
  else
  glTranslatef(n*2,i*2,-z);
  glBegin(GL_QUADS);
  glVertex2f(-1.0, 1.0);
  glVertex2f( 1.0, 1.0);
  glVertex2f( 1.0,-1.0);
  glVertex2f(-1.0,-1.0);
  glEnd();
end;
end;
glFlush();
result := true;
end;

//dodatkowo
procedure ReSizeGLScene();
begin
  glViewport(L, U, S, H);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0,S/H,0.1,100.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

function InitGL:bool;
begin
  glShadeModel(GL_SMOOTH);
  glClearColor(0.0, 0.0, 0.0, 0.5);
  glClearDepth(1.0);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  Result:=true;
end;

function DrawGLScene():bool;
begin
GenerateMap(-world,world, 56);
DrawCharacter(L,U, 54);
Result := true;
end;
...
    WM_KEYDOWN:
      begin
        if wparam = VK_UP then
        U := U - step;
        if wparam = VK_DOWN then
        U := U + step;
        if wparam = VK_LEFT then
        L := L + step;
        if wparam = VK_RIGHT then
        L := L - step;

         ReSizeGLScene();
...

Cały kod:

program rpg;

uses
  Windows,
  Messages,
  Dialogs,
  SysUtils,
  Forms,
  OpenGL;

var
  i,n : integer;
  h_Rc: HGLRC;
  h_Dc: HDC;
  h_Wnd: HWND;
  keys: array [0..255] of bool;
  Active: bool = true;
  FullScreen:bool = true;
  speed : extended = 0.5;
  S,H : integer;
  U : integer = 0;
  L : integer = 0;
  mapsize, world : integer;
  step : integer = 43;
  
function DrawCharacter(x,y,z : integer) : bool;
begin
  glLoadIdentity();
  glColor3f(1.0,1.0,0.0);
  glTranslatef(x,y,-z);
  glBegin(GL_QUADS);
  glBlendFunc(GL_ONE,GL_SRC_ALPHA);
  glVertex2f(-1.0, 1.0);
  glVertex2f( 1.0, 1.0);
  glVertex2f( 1.0,-1.0);
  glVertex2f(-1.0,-1.0);
  glEnd();
  glFlush();
end;

function GenerateMap(x,y,z : integer) : bool;
begin
result := false;
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
for i := x to y do
begin
for n := x-2 to y+2 do
begin
  glLoadIdentity();
  glColor3f(1.0,0.0,0.0);
  if n < S then
  glTranslatef(-n*2,i*2,-56)
  else
  glTranslatef(n*2,i*2,-56);
  glBegin(GL_QUADS);
  glVertex2f(-1.0, 1.0);
  glVertex2f( 1.0, 1.0);
  glVertex2f( 1.0,-1.0);
  glVertex2f(-1.0,-1.0);
  glEnd();
end;
end;
glFlush();
result := true;
end;

procedure ReSizeGLScene();
begin
  glViewport(L, U, S, H);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0,S/H,0.1,100.0);
  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity;
end;

function InitGL:bool;
begin
  glShadeModel(GL_SMOOTH);
  glClearColor(0.0, 0.0, 0.0, 0.5);
  glClearDepth(1.0);
  glEnable(GL_DEPTH_TEST);
  glDepthFunc(GL_LEQUAL);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
  Result:=true;
end;

function DrawGLScene():bool;
begin
GenerateMap(-world,world, 56);
DrawCharacter(L,U, 54);
Result := true;
end;

function WndProc(hWnd: HWND;
                 message: UINT;
                 wParam: WPARAM;
                 lParam: LPARAM):
                                  LRESULT; stdcall;
begin
  if message=WM_SYSCOMMAND then
    begin
      case wParam of
        SC_SCREENSAVE,SC_MONITORPOWER:
          begin
            result:=0;
            exit;
          end;
      end;
    end;
  case message of
    WM_ACTIVATE:
      begin
        if (Hiword(wParam)=0) then
          active:=true
        else
          active:=false;
        Result:=0;
      end;
    WM_CLOSE:
      Begin
        PostQuitMessage(0);
        result:=0
      end;
    WM_KEYDOWN:
      begin
        keys[wParam] := TRUE;
        if wparam = VK_UP then
        U := U - step;
        if wparam = VK_DOWN then
        U := U + step;
        if wparam = VK_LEFT then
        L := L + step;
        if wparam = VK_RIGHT then
        L := L - step;

         ReSizeGLScene();

        result:=0;
      end;
    WM_KEYUP:
      begin
    	keys[wParam] := FALSE;
      result:=0;
      end;
    WM_SIZE:
      begin
    	//ReSizeGLScene(mapsize,mapsize);
        H := HIWORD(lparam);
        S := LOWORD(lparam);
        ReSizeGLScene();
        result:=0;
      end
    else
      begin
      	Result := DefWindowProc(hWnd, message, wParam, lParam);
      end;
    end;
end;


procedure KillGLWindow;
begin
  if FullScreen then
    begin
      ChangeDisplaySettings(devmode(nil^),0);
      showcursor(true);
    end;
  if h_rc<> 0 then
    begin
      if (not wglMakeCurrent(h_Dc,0)) then
        MessageBox(0,'Release of DC and RC failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
      if (not wglDeleteContext(h_Rc)) then
        begin
          MessageBox(0,'Release of Rendering Context failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
          h_Rc:=0;
        end;
    end;
  if (h_Dc=1) and (releaseDC(h_Wnd,h_Dc)<>0) then
    begin
      MessageBox(0,'Release of Device Context failed.',' Shutdown Error',MB_OK or MB_ICONERROR);
      h_Dc:=0;
    end;
  if (h_Wnd<>0) and (not destroywindow(h_Wnd))then
    begin
      MessageBox(0,'Could not release hWnd.',' Shutdown Error',MB_OK or MB_ICONERROR);
      h_Wnd:=0;
    end;
  if (not UnregisterClass('OpenGL',hInstance)) then
    begin
      MessageBox(0,'Could not unregister class.','SHUTDOWN ERROR',MB_OK or MB_ICONINFORMATION);
    end;
end;


function CreateGlWindow(title:Pchar; width,height,bits:integer;FullScreenflag:bool):boolean stdcall;
var
  Pixelformat: GLuint;
  wc:TWndclass;
  dwExStyle:dword;
  dwStyle:dword;
  pfd: pixelformatdescriptor;
  dmScreenSettings: Devmode;
  h_Instance:hinst;
  WindowRect: TRect;
begin
  WindowRect.Left := 0;
  WindowRect.Top := 0;
  WindowRect.Right := width;
  WindowRect.Bottom := height;
  h_instance:=GetModuleHandle(nil);
  FullScreen:=FullScreenflag;
  with wc do
    begin
      style:=CS_HREDRAW or CS_VREDRAW or CS_OWNDC;
      lpfnWndProc:=@WndProc;
      cbClsExtra:=0;
      cbWndExtra:=0;
      hInstance:=h_Instance;
      hIcon:=LoadIcon(0,IDI_WINLOGO);
      hCursor:=LoadCursor(0,IDC_ARROW);
      hbrBackground:=0;
      lpszMenuName:=nil;
      lpszClassName:='OpenGl';
    end;
  if  RegisterClass(wc)=0 then
    begin
      MessageBox(0,'Failed To Register The Window Class.','Error',MB_OK or MB_ICONERROR);
      Result:=false;
      exit;
    end;
  if FullScreen then
    begin
      ZeroMemory( @dmScreenSettings, sizeof(dmScreenSettings) );
      with dmScreensettings do
        begin
          dmSize := sizeof(dmScreenSettings);
          dmPelsWidth  := width;
	        dmPelsHeight := height;
          dmBitsPerPel := bits;
          dmFields     := DM_BITSPERPEL or DM_PELSWIDTH or DM_PELSHEIGHT;
        end;

      if (ChangeDisplaySettings(dmScreenSettings, CDS_FULLSCREEN))<>DISP_CHANGE_SUCCESSFUL THEN
        Begin

          if MessageBox(0,'This FullScreen Mode Is Not Supported. Use Windowed Mode Instead?'
                                             ,'GL',MB_YESNO or MB_ICONEXCLAMATION)= IDYES then
                FullScreen:=false
          else
            begin
              MessageBox(0,'Program will now close.','Error',MB_OK or MB_ICONERROR);
              Result:=false;
              exit;
            end;
          end;
    end;
  if FullScreen then
    begin
      dwExStyle:=WS_EX_APPWINDOW;
      dwStyle:=WS_POPUP or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
      Showcursor(false);
    end
  else
    begin
      dwExStyle:=WS_EX_APPWINDOW or WS_EX_WINDOWEDGE;
      dwStyle:=WS_OVERLAPPEDWINDOW or WS_CLIPSIBLINGS or WS_CLIPCHILDREN;
    end;
  AdjustWindowRectEx(WindowRect,dwStyle,false,dwExStyle);
  H_wnd:=CreateWindowEx(dwExStyle,
                               'OpenGl',
                               Title,
                               dwStyle,
                               0,0,
                               WindowRect.Right-WindowRect.Left,
                               WindowRect.Bottom-WindowRect.Top,
                               0,
                               0,
                               hinstance,
                               nil);
  if h_Wnd=0 then
    begin
      KillGlWindow();
      MessageBox(0,'Window creation error.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  with pfd do
    begin
      nSize:= SizeOf( PIXELFORMATDESCRIPTOR );
      nVersion:= 1;
      dwFlags:= PFD_DRAW_TO_WINDOW
        or PFD_SUPPORT_OPENGL
        or PFD_DOUBLEBUFFER;
      iPixelType:= PFD_TYPE_RGBA;
      cColorBits:= bits;
      cRedBits:= 0;
      cRedShift:= 0;
      cGreenBits:= 0;
      cBlueBits:= 0;
      cBlueShift:= 0;
      cAlphaBits:= 0;
      cAlphaShift:= 0;
      cAccumBits:= 0;
      cAccumRedBits:= 0;
      cAccumGreenBits:= 0;
      cAccumBlueBits:= 0;
      cAccumAlphaBits:= 0;
      cDepthBits:= 16;
      cStencilBits:= 0;
      cAuxBuffers:= 0;
      iLayerType:= PFD_MAIN_PLANE;
      bReserved:= 0;
      dwLayerMask:= 0;
      dwVisibleMask:= 0;
      dwDamageMask:= 0;
    end;
  h_Dc := GetDC(h_Wnd);
  if h_Dc=0 then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t create a GL device context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  PixelFormat := ChoosePixelFormat(h_Dc, @pfd);
  if (PixelFormat=0) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t Find A Suitable PixelFormat.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  if (not SetPixelFormat(h_Dc,PixelFormat,@pfd)) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t set PixelFormat.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  h_Rc := wglCreateContext(h_Dc);
  if (h_Rc=0) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t create a GL rendering context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  if (not wglMakeCurrent(h_Dc, h_Rc)) then
    begin
      KillGLWindow();
      MessageBox(0,'Cant''t activate the GL rendering context.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  ShowWindow(h_Wnd,SW_SHOW);
  SetForegroundWindow(h_Wnd);
  SetFOcus(h_Wnd);
  ReSizeGLScene();
  if (not InitGl()) then
    begin
      KillGLWindow();
      MessageBox(0,'initialization failed.','Error',MB_OK or MB_ICONEXCLAMATION);
      Result:=false;
      exit;
    end;
  Result:=true;
end;


function WinMain(hInstance: HINST;
		 hPrevInstance: HINST;
		 lpCmdLine: PChar;
		 nCmdShow: integer):
     integer; stdcall;
var
  msg: TMsg;
  done: Bool;

begin
  done:=false;
    FullScreen:=false;
  if not CreateGLWindow('Vecco''s OpenGL Framework',Screen.WorkAreaWidth-40,Screen.WorkAreaHeight-40,16,FullScreen) then
    begin
      Result := 0;
      exit;
    end;
  while not done do
    begin
      if (PeekMessage(msg, 0, 0, 0, PM_REMOVE)) then
        begin
          if msg.message=WM_QUIT then
            done:=true
          else
            begin
	          TranslateMessage(msg);
	          DispatchMessage(msg);
	        end;
        end
      else
        begin

          if (active and not(DrawGLScene()) or keys[VK_ESCAPE]) then
            done:=true
          else
            SwapBuffers(h_Dc);

          if keys[VK_F1] then
            begin
            Keys[VK_F1] := false;
            KillGLWindow();
            FullScreen := not FullScreen;
            if not CreateGLWindow('Vecco''s OpenGL Framework',Screen.WorkAreaWidth-40,Screen.WorkAreaHeight-40,16,fullscreen) then
              Result := 0;
            end;
        end;
    end;
  killGLwindow();
  result:=msg.wParam;
end;

begin
world := 10;
mapsize :=10;
WinMain(hInstance, hPrevInst, CmdLine, CmdShow );
end.

Głównie z NeHe

0

Nie wiedzieć czemu programiki z OpenGL zaczęły się u mnie wywalać, więc nie mogę skompilować, ale na moje oko tutaj może być problem:

GenerateMap(-world,world, 56);
DrawCharacter(L,U, 54);

Nie bardzo pamiętam jak się układały wsp w OGL, i czy tu przypadkiem nie rysujesz bohatera pod mapą, ale chyba jest OK. (dawno nie wrzucałem nic ręcznie, polegam bardziej na 3Dmax + loader :) )
Za to zastanawia mnie czemu dwa razy wywołujesz glFlush(); zamiast wyciągnąć to poza te funkcje

function DrawGLScene():bool;
begin
GenerateMap(-world,world, 56);
DrawCharacter(L,U, 54);
glFlush();
Result := true;
end;

Może przez to się uwala, a nawet jeśli nie to i tak teoretycznie powinno się raz przepuszczać scenę przez "magiel", ponoć tak szybciej działa.

0

z glFlush() to jest taka sprawa, ze testowalem "co by bylo, gdyby" :D...

Gdzies wyłapałem ze "DEPTH" jest pod 3D, wiec u mnie depth jest zbędny, ale nie wiem jak zaimplementować 2D.

0

Nie zostawiajcie mnie :P

0

Arcyciekawa sytuacja..

0

to weź książkę i się ucz bo pytania są nie na poziomie... Proponował bym biblioteke allegro na początek - 100 razy proście jej użyć niż OGLa lub DXa- można w niej tylko robić w 2d (tzn. funkcje jakie znam odnoszą się do grafy 2d samemu można wszytko dodać :P) I się ucz i rysuj i myśl...

co do mapy:

int tab[100][100]; // masz mape i zapełniasz ją liczbami "1" - jak liczba jeden to daj taka teksturę jak liczba 2 to taką itp.
for(int i=0; i<10000; i++)
tab[i]=1;

for (int i=0; i<100; i++)
for(int j=0; j<100; j++)
if (tab[i][j]==1)
PSEUDOKOD rysuj(obrazek(1), i32-player_x, j32-player_y); // rysuje obrazek w miejscu i32 j32 (wtedy obrazki tez muszą mieć 32x32px)

//rysuj gracza;
rysuj(gracz, pol_ekranu_x, pol_ekranu_y)

0

Jak chcesz ni siłe tego OGL to zapoznaj się z glut lub z SDL - łatwiej się pisze ponieważ masz trszkę wyższy poziom abstrakcji i nie musisz myśleć o funkcjach systemowych :)

0

to weź książkę i się ucz bo pytania są nie na poziomie... Proponował bym biblioteke allegro na początek - 100 razy proście jej użyć niż OGLa

Coś ci się chyba pomyliło Allegro jest pod C++ .Dla delphi raczej jest Omega ewentualnie Delphix . Tam ten problem można byłoby rozwiązać jedną linijka kodu:)

if OisRight in form1.OmegaInput.Keyboard.States then  
   begin
   OmegaSprite.WorldX :=OmegaSprite.WorldX + 6 ;
   Player.X:= Player.X +6;
   end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1