Warsztat.GD

Programowanie => Językoznawstwo => C++ => Wątek zaczęty przez: Frondeus w Luty 20, 2008, 19:36:41

Tytuł: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: Frondeus w Luty 20, 2008, 19:36:41
Witam , mam problem:

Otoz chcialem zobic mini gre 2d w obiektach z uzyciem DirectDraw.(W VC 08)
Aby bylo ladniej klasy byly w pliku naglowkowym, metody tych klas w lpiku .cpp zas WinMain normalnie. Same metody Directa znalazlem w internecie na http://stud.wsi.edu.pl/ (Game c++reator) i "wlozylem" je w  obiekty.
Jednak mam problem linkera(dodaje ze dolaczylem ddraw.lib), i nie wiem w ktorej lini mam blad bo tam nie pisze, moze ktos zna przyczyne?
Podaje kod zrodlowy oraz same bledy co wyskoczyly:

Main.cpp:
#include <windows.h>
#include <ddraw.h>
#include "Game.h"
bool UtworzOknoDlaDD(HWND *hWnd, LPSTR lpszTyt);

LRESULT CALLBACK ProcOkna(HWND hOkno, UINT uMsg, WPARAM wPar, LPARAM lPar)
{

 switch(uMsg) {

  case WM_KEYDOWN:
  if(wPar == VK_ESCAPE) DestroyWindow(hOkno);
break;

  case WM_DESTROY:
     PostQuitMessage(0);
  break;

 };
 return DefWindowProc(hOkno,uMsg,wPar,lPar);
}

int WINAPI WinMain(HINSTANCE hProgram, HINSTANCE, LPSTR, int swPokaz)
{
if (!UtworzOknoDlaDD(&hOkno,"Gra")) return false;
 ShowWindow(hOkno,swPokaz);

   CGame *pGame = CGame::Obiekt();
   pGame->UruchomGre();

  MSG msg;
 for(;;){
if (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) {
if (msg.message == WM_QUIT) break;
TranslateMessage(&msg);
DispatchMessage(&msg);

  }
  else {

}
}

  pGame->ZakonczGre();
   return static_cast<int>(msg.wParam);
}

bool UtworzOknoDlaDD(HWND *hWnd, LPSTR lpszTyt)
{
 HINSTANCE hProg = GetModuleHandle(NULL);

 WNDCLASS wc;
 wc.lpszClassName = "Game";
 wc.hInstance     = hProg;
 wc.lpfnWndProc   = ProcOkna;
 wc.style         = 0;
 wc.hIcon         = LoadIcon(NULL,IDI_WINLOGO);
 wc.hCursor       = LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
 wc.lpszMenuName  = NULL;
 wc.cbClsExtra    = 0;
 wc.cbWndExtra    = 0;
 if(!RegisterClass(&wc)) return false;

 *hWnd = CreateWindowEx(0,"Game",lpszTyt,WS_POPUP,
                        50,50,300,200,
                        NULL,NULL,hProg,NULL);
 if(*hWnd==NULL) return false;
 else return true;
}

Game.h:
extern HWND hOkno;

   
//--------------Grafika--------------
class C2D{ //interfejs
private:
                      //Uchwyt głównego okna aplikacji
LPDIRECTDRAW lpDD;              //Wskaźnik do obiektu DirectDraw
LPDIRECTDRAWSURFACE lpDDEkran;  //Wskaźnik na powierzchnię ekranu
LPDIRECTDRAWSURFACE lpDDBufor;  //Wskaźnik do tylniego bufora
LPDIRECTDRAWSURFACE lpDDTlo;  //Wskaźnik do powierzchni tła

public:
C2D(){
LPDIRECTDRAW lpDD = NULL;              //Wskaźnik do obiektu DirectDraw
LPDIRECTDRAWSURFACE lpDDEkran = NULL;  //Wskaźnik na powierzchnię ekranu
LPDIRECTDRAWSURFACE lpDDBufor = NULL;  //Wskaźnik do tylniego bufora
LPDIRECTDRAWSURFACE lpDDTlo = NULL;  //Wskaźnik do powierzchni tła
}
bool UtworzObiektyDD();
void ZwolnijObiektyDD();
LPDIRECTDRAWSURFACE UtworzPowierzchnieZPliku(LPSTR nazwa);
//void PokazEfekt();
};
/*
class C3D{ //Samo mowi za siebie
private:
public:
};
*/
class CGraph{
private:
C2D* m_p2D;

public:
CGraph(){
m_p2D = new C2D;
}

void mUruchomG(int typ){
switch (typ){
case 1:

m_p2D->UtworzObiektyDD();
break;
}
}

void mZakonczG(int typ){
switch (typ){
case 1:

m_p2D->ZwolnijObiektyDD();
break;
}
}
/*void mPokazEfekty(int typ){
switch (typ){
case 1:

m_p2D->PokazEfekt();
break;
}
}*/
~CGraph() {}
};
//-------------Dzwiek-----------
class CSound{
private:
public:
CSound(){

}
~CSound() {}
};
//-----------------Sterowanie AI itp.-------------
class CNet{
private:
public:
CNet(){

}
~CNet() {}
};


//--------------------------GRA----------------------
class CGame
{
   
   private:

      CGame() //Konstruktor
      {
         ms_pGame = this;
m_pGraph = new CGraph;
//m_pSound = new CSound;
// m_pNet = new CNet;
      }

      static CGame* ms_pGame;
  CGraph* m_pGraph;
      //CSound* m_pSound;
  //CNet* m_pNet;


  public:
   
      static CGame* Obiekt() //Konstruktor
      {
         if (ms_pGame == NULL) CGame();

         return ms_pGame;
      }

      void Kill() //Destruktor
      {
         if(ms_pGame)
            delete ms_pGame;
         ms_pGame = 0;
      }

void UruchomGre();
void ZakonczGre();
void Graj();

      ~CGame() { }

};

CGame* CGame::ms_pGame = NULL;

Game.cpp:
#include <windows.h>
#include <ddraw.h>
#include "Game.h"
 HWND hOkno; 
// -----------------------CGame-----------------
void CGame::UruchomGre()
{
m_pGraph->mUruchomG(1);
//m_pSound->mUruchomS();
//m_pNet->mUruchomN();
}
void CGame::ZakonczGre()
{
m_pGraph->mZakonczG(1);
}
void CGame::Graj()
{
//m_pGraph->mPokazEfekty(1);


}
//------------------------CGraph----------------
//----------2D------------
bool C2D::UtworzObiektyDD()
{
 //Utworzenie głównego obiektu DirectDraw
 if ( DirectDrawCreate(NULL,&lpDD,NULL) != DD_OK) {
    MessageBox(hOkno,"Nie dało się utworzyć obiektu DD","Błąd",0);
    ZwolnijObiektyDD();  return false;
 }
 lpDD->SetCooperativeLevel(hOkno, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
 lpDD->SetDisplayMode(1024, 768, 16);

 //Utworzenie powierzchni ekranu
 DDSURFACEDESC ddsd;
 ddsd.dwSize            = sizeof(ddsd);
 ddsd.dwFlags           = DDSD_CAPS|DDSD_BACKBUFFERCOUNT;
 ddsd.ddsCaps.dwCaps    = DDSCAPS_PRIMARYSURFACE|DDSCAPS_COMPLEX|DDSCAPS_FLIP;
 ddsd.dwBackBufferCount = 1;
 if ( lpDD->CreateSurface(&ddsd,&lpDDEkran,NULL) != DD_OK) {
    MessageBox(hOkno,"Nie dało się utworzyć buforów ekranu","Błąd",0);
    ZwolnijObiektyDD();  return false;
 }

 //Pobranie wskaźnika do tylniego bufora
 ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;
 lpDDEkran->GetAttachedSurface(&ddsd.ddsCaps,&lpDDBufor);

//---------------OBIEKTY-------------------------------

 
 lpDDTlo = UtworzPowierzchnieZPliku("..\\Grafika\\Tlo.bmp");
 if (lpDDTlo==NULL) {
    MessageBox(hOkno,"Nie dało się wczytać bitmapy tła","Błąd",0);
    ZwolnijObiektyDD();  return false;
 }


//-------------------------------------------------------
 


 return true;
}
void C2D::ZwolnijObiektyDD()
{
//-----------ZWOLNIJ OBIEKTY----------------

 if(lpDDTlo   != NULL) lpDDTlo->Release();    lpDDTlo   = NULL;
//---------------------------------------------------------


 if(lpDDEkran != NULL) lpDDEkran->Release();  lpDDEkran = NULL;
 if(lpDD      != NULL) lpDD->Release();       lpDD = NULL;
}
LPDIRECTDRAWSURFACE C2D::UtworzPowierzchnieZPliku(LPSTR nazwa)
{
 LPDIRECTDRAWSURFACE lpDDNowa;
 DDSURFACEDESC ddsd;
 HBITMAP bitmapa;
 BITMAP bmp;
 HDC pomoc;
 HDC hdc;

 bitmapa = (HBITMAP) LoadImage(NULL,nazwa,IMAGE_BITMAP,0,0,LR_LOADFROMFILE);
 if(bitmapa==NULL) return NULL;
 pomoc = CreateCompatibleDC(NULL);
 SelectObject(pomoc,bitmapa);

 GetObject(bitmapa,sizeof(bmp),&bmp);
 ddsd.dwSize         = sizeof(ddsd);
 ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
 ddsd.dwWidth = bmp.bmWidth;  ddsd.dwHeight = bmp.bmHeight;
 if( lpDD->CreateSurface(&ddsd,&lpDDNowa,NULL) != DD_OK) return NULL;

 if(lpDDNowa->GetDC(&hdc) == DD_OK) {
   BitBlt(hdc,0,0, bmp.bmWidth, bmp.bmHeight, pomoc,0,0,SRCCOPY);
   lpDDNowa->ReleaseDC(hdc);
 }
 DeleteDC(pomoc);  DeleteObject(bitmapa);
 return lpDDNowa;
}
/*
void C2D::PokazEfekt()
{
 lpDDBufor->BltFast(0,0,lpDDTlo,NULL,DDBLTFAST_WAIT);
 lpDDEkran->Flip(NULL,DDFLIP_WAIT);

}
*/
//------------------------CSound----------------

//------------------------CNetwork--------------

Linker:
------ Build started: Project: Game, Configuration: Release Win32 ------
Compiling...
cl : Command line warning D9035 : option 'Wp64' has been deprecated and will be removed in a future release
game.cpp
main.cpp
Generating Code...
Linking...
game.obj : error LNK2005: "private: static class CGame * CGame::ms_pGame" (?ms_pGame@CGame@@0PAV1@A) already defined in main.obj
Release/Window.exe : fatal error LNK1169: one or more multiply defined symbols found

Window - 2 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Z gory dziekuje za pomoc.
(Ojc, chyb zlamalem 2 Przykazanie "Jak nie lamic", ale siedze nad tym kodem od tygodnia i nic nie dziala)
Tytuł: Odp: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: raver w Luty 20, 2008, 19:56:55
W Game.h skasuj CGame* CGame::ms_pGame = NULL;

A w Game.cpp dodaj
CGame* CGame::ms_pGame = 0;

Dzieje się tak ponieważ nie możesz robić deklaracji w plikach *.h (ponieważ tworzysz jeden obiekt wiele razy).

@down: tworzysz wiele razy wskaźnik do sinlgetona... tak po za tym, to pewnie nawet nie spawdziłeś...
Tytuł: Odp: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: Frondeus w Luty 20, 2008, 21:04:33
Jeden obiekt wiele razy?
singletony sie tworzy jeden raz.
Tytuł: Odp: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: Khaine w Luty 20, 2008, 21:36:50
sie tworzy jeden raz... taka jest zasada singletona, co nie zmienia faktu, ze mozesz taka klase tworzyc wiele razy - kompilator Ci nie zabroni.

ms_pGame jest statatyczne. Jesli dolaczysz plik naglowkowy wiecej niz jeden raz (a masz wnim ms_pGame = 0) to wtedy ponownie zostanie przypisana wartosc do pola statycznego. Stad Twoj error. Wyglada na to, ze w pliku main.cpp includowales Game.h i potem jeszcze gdzies. Main.cpp pierwszy sie skompilowal wiec ms_pGame = 0 zaszlo i juz wiecej razy nie powinno sie to powtorzyc.

Zatem tak jak mowil poprzednik: zrob to w Game.cpp.
Tytuł: Odp: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: Frondeus w Luty 21, 2008, 09:54:22
Dziekuje za wyjasnienie.
Tytuł: Odp: Direct Draw, Obiekty i linker.
Wiadomość wysłana przez: shyha w Luty 21, 2008, 11:07:02
I nastepnym razem nie wklejaj calego kodu.