Strona 1 z 2

Proszę o pomoc...

: 22 sty 2014, 22:24
autor: m4tyo
:cry: Witam, od ponad pół roku tworze gre w blenderze. Nagle natknąłem sie na pewiem problem ktorego nie moge rozwiązać, i nie wiem jak rozwiązać. Czy skrypt w pythonie czy kostki logiczne... A mianowicie mam dwa problemy:

1) Gdy postać dojdzie do pewnego etapu [miejsca] na planszy w grze, chcę by w menu ukazał się, bądź odblokował kolejny level do przejścia ( NP. 2 lvl ), a przy tym, by w menu na przycisku ( Kontynuuj ) był dostępny najnowszy odblokowany poziom.

2) Potrzebuję systemu Zapisz i Wczytaj ( Save & Load ) lecz po wielu tutorialach, poszukiwaniach jestem załamany, znalazłem coś ( skrypty python ) ale są one jedynie na pewną wartość ( property ). Ja bym chciał by zapisywały cały stan gry ( miejsce postaci w grze, stan zdrowia, pociski w pistolecie, zabici i obecni wrogowie, ogólnie każdy stan wraz z ekwipunkiem ). I tu pytanie - Czy jest to wogóle możliwe.

Bardzo prosiłbym o pomoc. Bardzo zależy mi na pierwszym pytaniu, więc jeżeli drugie pytanie jest nie wykonalne, to prosiłbym o pomoc w pierwszym ( Pomoc taką jak dla zielonego, z każdym wytłumaczeniem ). Obiecuje, że gdy gra wyjdzie to umiesze wasze nazwiska.

Re: Proszę o pomoc...

: 23 sty 2014, 0:59
autor: Nersael
Jest to możliwe, zrobiłem i pomogę.
Jutro dam dokładną odpowiedz jak to zrobić. Dziś już nie dam rady(zmęczenie).
Ale jeśli nie sypiasz po nocy to możesz zajrzeć do tematu gier ukończonych i tam pobrać grę work and drive. Zamieściłem ją jako plik blend, a tam znajdziesz odpowiedz na swoje pytanie.

Ale jeśli możesz poczekać to jutra dam odpowiedz, może nawet Tutorial się uda zrobić.

Re: Proszę o pomoc...

: 23 sty 2014, 1:39
autor: lukaszfito
Hmm... pierwszy problem jest dość prosty. Wystarczy zapisać do pliku jakie poziomy są odblokowane. Plik najlepiej ukryć gdzieś w folderach gry albo nadać mu niepozorną nazwę (np. "game.ico" :shock: ). Kiedyś zrobiłem podobnie, bo zapisywałem w takim pliku osiągnięcia gracza.

Co do drugiego problemu, to tak jak powiedział Nersael - jest to możliwe. A ja dodam, że pewnie jest kilka sposobów - ja bym zrobił po prostu zapis zmiennych podzielonych na grupy (każda grupa to inny obiekt: gracz, wróg_1, wróg_2 itd.).

Mogę pomóc z zaszyfrowaniem pliku save :P bo dobrze by było, jakby gracze nie mogli wchodzić do notatnika i samowolnie zmieniać zawartości. Planowałem zrobić o tym poradnik na Tromanie, ale najpierw muszę skończyć ten o LoD-ach.

Re: Proszę o pomoc...

: 23 sty 2014, 11:44
autor: Nersael
Jak już wspomniał Łukaszfito możliwości jest dużo. Przedstawię sposób z jakiego ja korzystam i dodam, że nie wiem czy jest to sposób najlepszy, ale u mnie sprawdza się.
Postaram się przedstawić schemat jak najprościej. Dla lepszego zrozumienia napiszę trzy skrypty, ale można to zrobić w jednym dodając na przykład uruchamianie po wciśnięciu klawisza lub najechaniu i kliknięciu myszką na dany obiekt. Ale na razie o zapisie i odczycie.
Skrypt zapisu:
from GameLogic import*

scene = getCurrentScene()
cont = getCurrentController()
owner = cont.owner

player_position = owner.position # tworzymy pozycje do zapisu
player_orientation = owner.orientation
player_live = owner['zycie']
player_przedmiot1 = owner['przedmiot1']

### tworzymy dane do zapisu
save_data = {'player_position_x':player_position[0],'player_position_y':player_position[1],'player_position_z':player_position[2],'player_live':player_live,'player_przedmiot1':owner['przedmiot1']}


try: # dobrze jest korzystać z try bo nie zawsze np: win pozwala programom na zapis odczyt i mogą powstać dziwne bledy
plik = open('save_load_file', 'wb') # otwieramy plik do zapisu
import pickle # importujemy pickle
pickle.dump(save_data, plik) # zapisujemy nasze save_data do pliku
plik.close() # zamykamy plik
except:
print('błąd zapisu do pliku') # ale w końcowej produkcji lepiej napisać pass
#pass

### drugi skrypt

from GameLogic import*

scene = getCurrentScene()
cont = getCurrentController()
owner = cont.owner

### próbujemy otworzyć plik
try:
plik = open('save_load_file', 'rb') # otwieramy plik do czytania
import pickle # importujemy pickle
data = pickle.load(plik) # wczytujemy dane z pliku
#print(dane) # jesli chcesz to przy produkcji mozesz patrzec jakie dane sa zapisane(czasem sie zapomina)
save_data = data # przyporządkujemy dane z pliku do naszej save_data
plik.close() # zamykamy plik
except:
print('błąd odczytu z pliku')
#pass

### przyporządkowanie zapisu
owner.position[0] = save_data['player_position_x']
owner.position[1] = save_data['player_position_y']
owner.position[2] = save_data['player_position_z']
owner['zycie'] = save_data['player_live']
owner['przedmiot1'] = save_data['player_przedmiot1']

Ale jeśli mowa o uaktualnieniu stanu gry to skrypt wygląda tak:
from GameLogic import*

scene = getCurrentScene()
cont = getCurrentController()
owner = cont.owner

# zmienil sie poziom gracza
player_level = owner['level']

### probujemy otworzyc plik
try:
plik = open('save_load_file', 'rb') # otwieramy plik do czytania
import pickle # importujemy pickle
data = pickle.load(plik) # wczytujemy dane z pliku
#print(dane) # jesli chcesz to przy produkcji mozesz patrzec jakie dane sa zapisane(czasem sie zapomina)
save_data = data # przyporządkujemy dane z pliku do naszej save_data
plik.close() # zamykamy plik

save_data['player_level'] = player_level # uaktualnienie poziomu gracza lub jakiejs innej rzeczy

plik = open('save_load_file', 'wb') # otwieramy plik do zapisu
import pickle # importujemy pickle
pickle.dump(save_data, plik) # zapisujemy nasze save_data do pliku
plik.close() # zamykamy plik
except:
print('błąd odczytu i zapisu pliku')
#pass

############################################################

To jest tylko przykład, nie robiłem orientacji bo trochę więcej trzeba pisania, ale na podstawie pozycji na pewno dasz sobie radę i z tym.
Kiedyś bardzo długo szukałem rozwiązania jak to zrobić, i najgorsze jest to, że nie wpadłem na pomysł aby zapytać :cry:
plik blend do pobrania
http://dysk.onet.pl/link/6o96K
Mam nadzieję, że to pomoże

Re: Proszę o pomoc...

: 23 sty 2014, 12:25
autor: Nersael
Jeszcze jak pamiętam(a to różnie bywa) to jeśli otwierasz blendera(skrót na pulpicie do programu), a później wybierasz otwórz i plik blend, lub wybierasz Recent to może się ten plik zapisywać tam gdzie masz zainstalowanego blendera.
Jak otwierasz klikając na plik .blend to zapis/odczyt odbywa się tam gdzie ten plik się znajduje.

Mówię o tym bo sam kiedyś się zastanawiałem skąd są problemy z tego wynikające.

Re: Proszę o pomoc...

: 23 sty 2014, 14:15
autor: lukaszfito
Widzę jeden błąd, pobierasz orientation i nie zapisujesz tego do pliku - sprawdziłem też co się stanie, jeśli zapiszemy to w ten sposób, no i pojawia się błąd. Rozwiązanie jest proste: orientation trzeba rozłożyć tak jak position (tylko na 9 elementów). Mam też małe ulepszenie Twojego skryptu Nersael, wystarczy trochę zmienić dodawanie wartości do zmiennej save_data, by do zapisu dodać wszystkie obiekty ze sceny, które chce się zapisać, takie obiekty muszą mieć specjalną zmienną property o nazwie "zapisz" (typu string - jej wartość to unikalna nazwa):

Kod: Zaznacz cały

# pobieramy wszystkie obiekty sceny
objects = scene.objects
save_data={}
# sprawdzamy każdy obiekt gry w pętli
for ob in objects:
    if "zapisz" in ob.getPropertyNames():  # jeśli obiekt ma zmienną "zapisz"
        klasa_obiektu = ob["zapisz"] # pobierz unikalną nazwę ze zmiennej "zapisz"
        if klasa_obiektu == "player": # jeśli unikalną nazwą jest "player" - czyli zmienne gracza
            # tu dodajemy zmienne dla gracza
            save_data[klasa_obiektu+'_position_x'] = ob.position[0]
            save_data[klasa_obiektu+'_position_y'] = ob.position[1]
            save_data[klasa_obiektu+'_position_z'] = ob.position[2]
            save_data[klasa_obiektu+'_orientation1'] = ob.orientation[0][0]
            save_data[klasa_obiektu+'_orientation2'] = ob.orientation[0][1]
            save_data[klasa_obiektu+'_orientation3'] = ob.orientation[0][2]
            save_data[klasa_obiektu+'_orientation4'] = ob.orientation[1][0]
            save_data[klasa_obiektu+'_orientation5'] = ob.orientation[1][1]
            save_data[klasa_obiektu+'_orientation6'] = ob.orientation[1][2]
            save_data[klasa_obiektu+'_orientation7'] = ob.orientation[2][0]
            save_data[klasa_obiektu+'_orientation8'] = ob.orientation[2][1]
            save_data[klasa_obiektu+'_orientation9'] = ob.orientation[2][2]
            save_data[klasa_obiektu+'_live'] = ob['zycie']
            save_data[klasa_obiektu+'_przedmiot1'] = ob['przedmiot1']
            save_data[klasa_obiektu+'_level'] = ob['level']
        elif klasa_obiektu[:10] == "przeciwnik": # jeśli unikalna nazwa to "przeciwnik" lub "przeciwnik_dodaj_co_chcesz" itp.
            # tu dodajemy zmienne dla przeciwnika
            save_data[klasa_obiektu+'_position_x'] = ob.position[0]
            save_data[klasa_obiektu+'_position_y'] = ob.position[1]
            save_data[klasa_obiektu+'_position_z'] = ob.position[2]
            save_data[klasa_obiektu+'_orientation1'] = ob.orientation[0][0]
            save_data[klasa_obiektu+'_orientation2'] = ob.orientation[0][1]
            save_data[klasa_obiektu+'_orientation3'] = ob.orientation[0][2]
            save_data[klasa_obiektu+'_orientation4'] = ob.orientation[1][0]
            save_data[klasa_obiektu+'_orientation5'] = ob.orientation[1][1]
            save_data[klasa_obiektu+'_orientation6'] = ob.orientation[1][2]
            save_data[klasa_obiektu+'_orientation7'] = ob.orientation[2][0]
            save_data[klasa_obiektu+'_orientation8'] = ob.orientation[2][1]
            save_data[klasa_obiektu+'_orientation9'] = ob.orientation[2][2]


Jeśli chodzi o nazwy przeciwników, to sprawdzamy pierwsze 10 znaków, bo słowo "przeciwnik" ma ich właśnie 10, a pozostałe mogą być dowolne, więc możemy nazywać ich dość dowolnie, np.: "przeciwnik_Zenon", "przeciwnik1", "przeciwnik.001" itp.

Specjalnie nie użyłem nazwy obiektu, gdyż przy użyciu addObject() nazwy się duplikują i przy wczytywaniu wszystko się pomiesza.

Re: Proszę o pomoc...

: 23 sty 2014, 19:17
autor: m4tyo
Dzięki chłopak za tak szybką pomoc ! Jutro jeszcze coś napisze, bo teraz nie mam głowy do pisania. Mam po prostu jeszcze dwa elementy do wyjaśnienia:

1) Gra Work and Drive, jest mi znana, wczoraj w nia zagrałem ;) - Ale okazało się, że gdy wchodze do Dealer Car to gra mi się wyłącza i nic nie mogę zrobić, więc uznałem ją za "Niedoróbke" :D Popraw ten element, bo jakby nie patrzeć, przejechałbym sie samochodem ! Albo, stworz mi osobną mapkę tylko z samochodem, bym mógł pojezdzic :P

2) Co do tych skryptów i pomocy, to jestem wdzięczny ! Ale chciałbym spytać, Panowie skupiliście uwagę na moim problemie nr. 2 ( Bardziej skomplikowanym wg. mnie). A czy moglibyscie wyjaśnić, albo porobić parę screenów co do problemu numer 1 ? "To znaczy - Jeśli obiekt znajduje się w tym miejscu, to w menu pokazuje się nowy poziom gry" no i oczywiscie pod przyciskiem "kontynuuj".

Dacie rade wyjaśnić mi to ? Tylko tego brakuje, by gre jak najszybciej wydać ;/

A no i bym był zapomniał... Dzięki Bardzo jeszcze raz ! GG 7819880 Skype matiosization/adieen śmiało piszcie, możecie nawet mi tam wyjaśniać moje problemy :) ! Dzieki Bogu sa tacy ludzie jak wy :)

Re: Proszę o pomoc...

: 23 sty 2014, 19:27
autor: m4tyo
lukaszfito pisze:Mogę pomóc z zaszyfrowaniem pliku save :P bo dobrze by było, jakby gracze nie mogli wchodzić do notatnika i samowolnie zmieniać zawartości. Planowałem zrobić o tym poradnik na Tromanie, ale najpierw muszę skończyć ten o LoD-ach.


Jasne, ze smaczkiem skorzystam z pomocy !

Nersael, zaczynam pomału rozumieć save And Load, ale co z Uaktualnienie stanu gry, nadal nie pojmuje jak to funkcjonuje, więc pobrałem, ten plik co zamieściłeś no i próbuję klikać "3" czyli uaktualnienie, a co to daje ?!

Re: Proszę o pomoc...

: 23 sty 2014, 20:15
autor: lukaszfito
Nersael stworzył skrypt wykorzystujący pickle, co oznacza, że zapis do pliku jest w postaci binarnej i zwykłym notatnikiem nie dodasz sobie życia w grze :P save jest już bezpieczny :D . Co do pierwszego problemu to rozwiązanie jest takie jak przy drugim, tylko coś musi wykryć, że gracz przeszedł poziom. Nie mówiłeś sporo o swojej grze, jak wyglądają poziomy więc możemy tylko przypuszczać co dobrze jest zrobić w wypadku Twojej gry m4tyo. Musisz po prostu dodać jeden sensor, który odpali skrypt zapisu gdzie kończy się poziom. Może to być Collision ustawiony na materiał. Jeśli gracz dotknie materiału, to powinien odpalić się skrypt, który:
1. wczyta plik poziomów
2. sprawdzi czy poziom jest odblokowany
- jeśli nie jest, to zmieni wartość (tak żeby był odblokowany) i zapisze to do pliku.

Każdy z przycisków w menu powinien wczytać plik zapisu i być dostępny (lub widoczny) tylko gdy jego poziom jest odblokowany.
Przycisk kontynuuj podobnie, tylko powinien sprawdzić który jest najwyższy w hierarchii i go odpalić. Poziomy w Twojej grze mają odblokowywać się kolejno, czy mogą być odblokowywane w różnej kolejności? ..a może masz drzewko poziomów i przejście jednego odblokowuje parę poziomów?

Re: Proszę o pomoc...

: 23 sty 2014, 20:47
autor: lukaszfito
m4tyo napisałeś na moim wątku o Red End pytanie o instalator, odpowiem tutaj żeby nie mieszać tematów ;) . Korzystam z Inno Setup Compiler, który jest darmowy tak jak Blender, więc możesz z niego skorzystać do stworzenia instalki :D . Ma wbudowany kreator więc problemów raczej mieć nie będziesz - wystarczy ściągnąć i postępować według kreatora 8-) .

A co do numerów gadu, skyp itp. nie widzę z tym problemu, ale jeśli będziemy rozmawiać na forum, to więcej osób z tego skorzysta :P Mam nadzieję, że rozwiążemy Twoje problemy i na końcu pokażesz jak połączyłeś wszystkie porady ze sobą - żeby każdy kto tu zajrzy mógł jak najlepiej z tego skorzystać :mrgreen: