Warsztat.GDCompo!ProjektyMediaArtykułyQ&AForumOferty pracyPobieranie

Opisz napotkaną sytuację, a redakcja niezwłocznie znajdzie rozwiązanie!

wyślij anuluj

MapEditor

Tekst został importowany z Warsztatowych artykułów. Jego oryginalnym autorem jest [email protected]. Jeżeli został importowany poprawnie, usuń ten szablon!

Przed przeczytaniem tego musiscie się zapoznać z tymi artykułami : http://www.warsztat.gd/tutorials.php?x=view&id=127 http://www.warsztat.gd/articles.php?x=view&id=6 W tym drugim przede wszystkim chodzi mi o umiejętność stworzenia własnego formatu. Po zapoznaniu sie z tym, umiecie budować mapę do gry z kafli zmieniając wartości poszczegulnych elementów tablicy( np. int Mapa[40][30] = 7;). To jest wygodne jak mapa jest mała ale jeśli mamy zamiar robic wieeelką , zajęło by nam to wieki. Dlatego najlepszym rozwiązaniem tej sytuacji jest stworzenie Edytora Mapy. Jest to oddzielny program który łaczy elementy tej tablicy w prosty sposób i zapisuje je do pliku a potem nasza gra to wczytuje. Ponieważ taki MapEditor moze zajmowac kolo 800 linijek kodu to najlepiej jest sobie zrobic 3 pliki:

MapEditor.cpp (w nim bedzie wiekszosc kodu)
MapEditor.h (w nim beda definicje zmiennych i funkcji)
MapEditor.rc (w nim budujemu okna dialogowe)

A więc do dzięła!.( program będzie pisany w c++\WinApi) Stwórzcie proste okno z menu w którym bedzie można otworzyć okno dialogowe (chyba nie musze tego wyjasniać :P ) Zakładam że już umiecie co nieco w Winapi więc nie musze wszystkiego wyjaśniać. w Oknie dialogowym wyświetlcie elementy z których chcecie budować mapę dla przykładu(moje 3 elementy to czarny żółty i czerwony kwadrat)

teraz tworzymy zmienna statyczna globalną, aby wiedziec jaki element był wybrany ( static int JakiElement ) zdefiniujmy ją w pliku MapEditor.h Musimy teraz tak obsłuzyć komunikat WM_LBUTTONUP zeby po kliknięciu na czarny kwadrat zmienna JakiElement była równa 1, a po kliknięciu na czerwony 2 itp. to będzie coś w tym stylu :

case WM_LBUTTONUP: lx = LOWORD(lParam); ly = HIWORD(lParam); for(int i=0;i<4;i++) // zakładam że w 1 rzędzie w oknie dialogowym mieszczą sie 4 elementy {if((lx > i*32) && (lx < i*32+32) & (ly > 0) && (ly < 32)) // a tutaj ze elementy są wielkości 32x32 // i są od siebie oddalone o 0 pikseli {JakiElement= i+1; // nie mozemy naopsiac tak : JakiElement = i; bo w pętli i najpierw ma wartośc 0 InvalidateRect(hwnd,NULL,TRUE); // odświeżamy okienko :D }} break;

oczywiście to ma być zrobione w procedurze okna dialogowego a nie w głównej procedurze okna :P A wieć wybieranie elementów mamy z głowy. Zajmijmy się teraz rysowanie elementów w głownym oknie. Zdefiniujmy sobie najpierw globalną dwu wymiarową tablicę intów( int Mapa[40][30] ) ( napisałem [40][30] bo taka sama tablica jest w artykule o tworzeniu mapy z kafli(link na górze) i sądze że tak łatwiej załapcie o co biega :P) Ok Teraz obsłużmy WM_LBUTTONDOWN w głownym oknie.

case WM_LBUTTONDOWN: x = LOWORD(lParam); y = HIWORD(lParam); // tego chyba nie msuze wyjasniać break;

Załóżmy ze nasze elementy bedą wielkosci 32x32.

case WM_LBUTTONDOWN: x = LOWORD(lParam); y = HIWORD(lParam); if((x < 32) && (y < 32) && (y > 0) && (x > 0) ) { //kod.... } break;

Już wyjasniam w ludzkim języku znaczy to coś takiego : Jeśli po kliknięciu lewego klawisza myszy , kursor bedzie w miejscu większym od 0 dla x i większym od 0 dla y ale mniejszym od 32 dla x i mniejszym dla 32 dla y to wykona sie podany kod ( x i y to osie jak coś ...) Fajnie tylko to jest tylko jeden element a nam chodzi o troszke więcej. A więc skorzystamy z cudownej rzeczy jaką daje nam c++ a mianowicie "pętla for":P To będzie cos takiego :

case WM_LBUTTONDOWN: x = LOWORD(lParam); y = HIWORD(lParam); for(int ix = 32; ix < 1500; ix +=32) // to 1500 to liczba do której ma działać pętla { //Najlepiej walnąć jakąś dużą liczbę i oląć to :D for(int ii = 32; ii < 1500; ii +=32) { if((x < ii) && (y < ix) && (y > (ix-32)) && (x > (ii-32)) ) { //KOD....................... }}} zmienna1 = 1; InvalidateRect(hwnd,NULL,TRUE); break;

Wydaję mi się że to nie jest jakieś skomplikowane i raczej to rozumiecie. Teraz musmy pobrać jaki element naszej tablicy Mapa[40][30] był zmieniony i jaką ma wartość:

case WM_LBUTTONDOWN: x = LOWORD(lParam); y = HIWORD(lParam); for(int ix = 32; ix < 1500; ix +=32) { for(int ii = 32; ii < 1500; ii +=32) { if((x < ii) && (y < ix) && (y > (ix-32)) && (x > (ii-32)) ) { x = (ix-32); y = (ii-32); //dlatego odejmuje 32 bo pętla ii i ix na początku maja 32 a nie 0 Mapa[x/32][y/32] = JakiElement; //NAJWAZNIEJSZE SZAJSTWO W TYM KDOZIE :P //dlaczego dziele przez 32?([x/32]) bo nie zapominajmy ze nasze elementy mają //wielkości 32x32 !!! }}} InvalidateRect(hwnd,NULL,TRUE); break;

Ok fajnie teraz moćemy zmieniać elementy naszej tablicy i jest fajnie ale co z tego jak nie widzimy jaki element gdzie jest :P Trzeba sie teraz pobawić w WM_PAINT :D a więc tak najpierw nad WM_PAINT walimy to \/ żeby nie mrygał nam ekran podczas zmieniania elementów:

case WM_ERASEBKGND: return 1; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; HDC hdcMem; hdc=BeginPaint(hwnd,&ps); hdcMem=CreateCompatibleDC(hdc); SelectObject(hdcMem, trawa); //nie musze wyjaśniać DeleteDC(hdcMem); EndPaint(hwnd, &ps); } break;

tylko w SelectObiect pojawia sie bitmapa trawa a to sie bierze stąd:

HBITMAP trawa; //................. case WM_CREATE: trawa = (HBITMAP)LoadImage(NULL,"Elementy.bmp",IMAGE_BITMAP,0,0,LR_LOADFROMFILE); break;

teraz serce albo jak kto woli wątroba naszego programu:

case WM_ERASEBKGND: return 1; case WM_PAINT: { PAINTSTRUCT ps; HDC hdc; HDC hdcMem; hdc=BeginPaint(hwnd,&ps); hdcMem=CreateCompatibleDC(hdc); SelectObject(hdcMem, trawa); for(int i=0;i<40;i++){ for(int ii=0;ii<30;ii++){ //wielkosci tablicy 40 i 30 for(int io=0;io<30;io++){ // ilość elementów np. trawa = 1, drzewo = 2 itp. int t = Mapa[i][ii]; if(t==io){ BitBlt(hdc,i*32,ii*32,32,32,hdcMem,t*32,0,SRCCOPY); }}}} DeleteDC(hdcMem); EndPaint(hwnd, &ps); } break;

Jak wszystko wwalicie w całość to bedziecie mieć wasz MapEditor ale bedzie on rysowal tylko mapę wielkosci ekranu :/ dlatego należało by zając sie przesuwaniem tej mapy. do tego może byc wiele sposobów ja preferuję 2 :
- paski przesuwania (scrollbar)
- przesuwanie ekranu strzałkami( i to wam teraz objaśnie)

Najpierw robimy 2 zmienne statyczne ( static int GdzieX,GdzieY ) i obsługujemy WM_KEYDOWN:

WM_KEYDOWN: //....................... if(wParam==VK_DOWN){ GdzieX++; } if(wParam==VK_UP){ GdzieX--; } if(wParam==VK_RIGHT){ GdzieY++; } if(wParam==VK_LEFT){ GdzieY--; } InvalidateRect(hwnd,NULL,TRUE); break; //.........................

Teraz musimy to uwzględnic w naszej funkcji rysującej:

for(int i=0;i<40;i++){ for(int ii=0;ii<30;ii++){ for(int io=0;io<30;io++){ int t = Mapa[i][ii]; if(t==io){ BitBlt(hdc,i*32 - GdzieX ,ii*32 - GdzieY ,32,32,hdcMem,t*32,0,SRCCOPY); }}}} Ok teraz mapa bedzie się przesuwać ale jak przesuniecie ją np w prawo i będzie chcięli narysować coś na niej to elementy będą rysowane w tym miejscu w którym na początku była mapa ( no bo przesuwamy tylko obraz ale tabklica Mapa[40][30] jest w tym samym miejscu!) musimy to uwzględnić w WM_LBUTTONDOWN case WM_LBUTTONDOWN: //kod...... Mapa[x/32-(GdzieX/32)][y/32-(GdzieY/32)] = JakiElement; //kod...... break;

i teraz bedzie wszystko ok bedzie nam rysować po przesuwaniu :D !!!! Teraz został nam tylko zapis tej Mapy. po Przeczytaniu artykułu o tworzeniu własnego formatu zróbcie format np. *.map a zapisujcie do niego tablice tak :

//funkcja zapisująca blabla.... WriteFile(handle,Mapa,sizeof(Mapa),&dword,0); //...... i tak samo w funkcjii wczytującej w grze albo w MapEdytorze: //...... ReadFile(handle,Mapa,sizeof(Mapa),&dword,0); //......

***************************GRATULACJE******************************

To koniec tej długiej, męczącej i nudnej lekcjii o tworzeniu MapEditora , możesz juz isć grać w GTA sa :D

[email protected]

Tekst dodał:
Adam Sawicki
28.12.2006 13:03

Ostatnia edycja:
Adam Sawicki
28.12.2006 13:03

Kategorie:

Aby edytować tekst, musisz się zalogować.

# Edytuj Porównaj Czas Autor Rozmiar
#1 edytuj 28.12.2006 13:03 Adam Sawicki 9.18 KB
Zwykły
Do sprawdzenia
Do akceptacji
  • ~Virgo 07 sierpnia 2007 11:35
    Najbardziej mnie w tym artykule przerażało to, że przez cały czas jak go czytałem to miałem nieodzowne wrażenie, że został napisany przez trzyletnie dziecko. Chodzi mi tu o styl autora...
  • ~west 17 grudnia 2007 09:30
    bardzo ubogie,a ja chce tworzyć mapy do gta 3
  • Napisz komentarz:
    Aby dodać swój komentarz, musisz się zalogować.
Licencja Creative Commons

Warsztat używa plików cookies. | Copyright © 2006-2017 Warsztat · Kontakt · Regulamin i polityka prywatności
build #ff080b4740 (Tue Mar 25 11:39:28 CET 2014)