Wyswietlanie planszy do rozbudowy Gra cz.3 (prezentacja menu)

0

W bazie opisałem produkcję 3 surowców. Drewno, Kamień, Złoto. Każdy z nich ma wymagany poziom danego surowca, czas budowy (podstawowy). Generalnie chodzi o plansze po wejściu do zamku gdzie można rozbudować różne budynki na różne poziomy. Menu takich budynków jest stałe:

Sala
Gwaria
Strażnica
Skład drewna
Skład kamienia
Skarbiec
Skryjówka 

To tylko przykład. Ale teraz tak, to menu można urozmaicić, że ukrywamy budynki do których budowa wymaga osiągnięcia dancyh poziomów innych budynków. Np żeby wybudować TARG musimy mieć 3 poziom SALI. Mogę zatem wywołać prezentację MENU wpętli:

  1. Zapytaj o ilość budynków w menu (odpowiedz 7)
  2. Dla pierwszej pozycji zapytaj o stan surowców i pokaż wymagany poziom oraz czas
  3. Dla drugiej pozycji menu rób to co powyżej
    ...
    ...
  4. Dla ostatniej pozycji rób to co wyżej.

Na koniec z samego menu mam 8 zapytań SQL ?

Ja zrobiłem na początku to wszystko w jednym zapytaniu SKOMPLIKOWANYM wizualnie bo pełno JOINÓW ale wszystko jest wyświetlone po jednym zapytaniu SQL. Jak powinno się to właściwie wykonać ? Sposobem pierwszym czy drugim ?

1

wszystko zalezy jaka masz strukture bazy
ale jesli masz rozsadna to jedno zapytanie, bez wzgledu na ilosc budunkow (opcji menu) powinno dac rade (czyli opcja 2)
opcja jeden ma ten minus ze jesli bedziesz chcial dodac kolejne budynki, bedziesz musial dokladac tez zapytania
nie wiem jaka masz strukture bazy, ale ja widzialbym to mniej wiecej tak:
(zalozmy ze kazdy gracz na starcie ma wszystkie budynki, poziomu 0 lub 1)

Budynki
Id
Nazwa

BudynkiWymaganeSurowce
BudynekId
Poziom
SurowiecId
Ilosc

BudynkiWymaganeBudynki
BudynkeId
Poziom
WymaganyBudynekId
WymaganyBudynekPoziom

GraczSurowce
GraczId
SurowiecId
Ilosc

GraczBudynki
GraczId
BudynekId
Poziom

select B.*, WS.Poziom from
(
select BWS.BudynekId, BWS.Poziom
from
(select * from GraczBudynki where GraczId = @graczId) as GB
inner join BudynkiWymaganeSurowce BWS on GB.BudynekId = BWS.BudynekId and GB.Poziom+1 = BWS.Poziom
inner join GraczSurowce GS on GB.GraczId = GS.GraczId and BWS.SurowiecId = GS.SurowiecId
group by BWS.BudynekId, bws.poziom
having count(*) = sum(case when GS.Ilosc >= BWS.Ilosc then 1 else 0 end)
) as WS
inner join
(
select BWB.BudynekId, BWB.poziom
from
(select * from GraczBudynki where GraczId = @graczId) as GB
inner join BudynkiWymaganeBudynki BWB on GB.BudynekId = BWB.BudynekId and GB.Poziom+1 = BWB.Poziom
left join GraczBudynki GB2 on GB.GraczId = GB2.GraczId 
       and BWB.WymaganyBudynekId = GB2.BudynekId and BWB.WymaganyBudynekPoziom = GB2.Poziom
group by BWB.BudynekId, BWB.poziom
having count(*) = sum(case when GB2.BudynekId is not null then 1 else 0 end)
) as WB on WS.BudynekId = WB.BudynekId and WS.Poziom = WB.Poziom
inner join Budynki B on WS.BudynekId = B.Id

heh, wkrecilem sie w ta query, wiec juz ja skonczylem :)
zapewnia dowolnosc jesli chodzi o ilosc surowcow oraz zapewnia latwa skalowalnosc - mozesz dodawac kolejne surowne i warunki, bez zmian w strukturze bazy czy zapytania
zalozylem ze w GraczSurowce sa dla danego gracza wpisy dla kazdego surowca (chocby zero), wiec jesli dodajesz kolejny surowiec, do tej tabeli trzeba dopisac dla kazdego gracza ze ma tego surowca zero (czy inne wartosc)

0

na początek mam sytuację taką:

Baza opisująca skład drewna czyli ile potrzeba surowca na każdy kolejny poziom oraz ile czasu buduje się każdy poziom:

Pole Opis
id_mine_stone klucz
level poziom budynku
req_wood ile potrzeba drewna na poziom np: 1
req_stone ile potrzeba kamienia na poziom np: 1
req_gold ile potrzeba zlota na poziom np: 1
population ile pracownikow przybywa
output ile mamy godzinnej produkcji przy np poziomie 1
point ile zyskamy punktow majac ten poziom budynku
build_time czas w sekundach budowy danego poziomu

I jest jeszcze tabela która zestawia użytkownika z jego zamkami które posiada:

Pole Opis
id_castles klucz
castle_name nazwa zamku
id_users id uzytkownika z bazy users
store_wood który poziom skladu drewna
store_stones który poziom skladu kameinia
store_gold ktory poziom skarbca
Przykladowe menu pokazuje:
Budynek | Wymagania surowcow | Czas Budowy | Rozkaz |
Sklad drewna (Poziom 26) |Drewno: 29443 - Kamien: 20229  - Zloto: 12469 | Czas: 07:55:24 | Rozbuduj na poziom 2
Sklad kamienia (Poziom 28) | Drewno: 24106 - Kamien: 48716 - Zloto: 17733 | Czas: 09:13:19 | Rozbuduj na poziom 2
Skarbiec (Poziom 29) | Drewno: 45323 - Kamien: 69115 - Zloto: 12469 | Czas: 11:26:51 | Rozbuduj na poziom 2

Tak wlasnie prezentuje się menu i teraz zamiast wysweitlać menu dynamicznie i każdą pozycję menu pytać później o stan budynku wymagania to napisałem jedno zapytanie ale ten minus o którym piszesz to taki że jak dodam budynek to na sztywno w pliku reprezentującym wyświetlanie stanu posiadłości muszę dodać kod.

Zapytanie SQL:

 
SELECT id_castles,castle_name,id_users,store_wood,store_stones,store_gold, 
mine_wood.req_wood AS mine_wood_req_wood, 
mine_wood.req_stone AS mine_wood_req_stone, 
mine_wood.req_gold AS mine_wood_req_gold,
mine_wood.build_time AS mine_wood_build_time,

mine_stone.req_wood AS mine_stone_req_wood, 
mine_stone.req_stone AS mine_stone_req_stone, 
mine_stone.req_gold AS mine_stone_req_gold,
mine_stone.build_time AS mine_stone_build_time,

mine_gold.req_wood AS mine_gold_req_wood, 
mine_gold.req_stone AS mine_gold_req_stone,
mine_wood.req_gold AS mine_gold_req_gold,
mine_gold.build_time AS mine_gold_build_time
	
FROM castles_users 

LEFT JOIN mine_wood ON (mine_wood.level = store_wood + 1)
LEFT JOIN mine_stone ON (mine_stone.level = store_stones + 1)
LEFT JOIN mine_gold ON (mine_gold.level = store_gold + 1)

WHERE id_castles = 1

Tabele dla kamienia, drewna i złota są analogiczne.
natomiast część pliku odpowiedzialna za prezentacje jest taka:

 
foreach ($result as $row) {}

	echo "<tr>";

	echo "<td>Sklad drewna (Poziom $row[store_wood])</td>";
	echo "<td>Drewno: $row[mine_wood_req_wood]</td>";
	echo "<td>Kamien: $row[mine_wood_req_stone]</td>";
	echo "<td>Zloto: $row[mine_wood_req_gold]</td>";
	echo "<td>Czas: " . date('H:i:s',mktime(0,0,$row[mine_wood_build_time])) . "</td>";
	echo "<td>Rozbuduj na poziom </td>";

	echo "</tr><tr>";

	echo "<td>Sklad kamienia (Poziom $row[store_stones])</td>";
	echo "<td>Drewno: $row[mine_stone_req_wood]</td>";
	echo "<td>Kamien: $row[mine_stone_req_stone]</td>";
	echo "<td>Zloto: $row[mine_stone_req_gold]</td>";
	echo "<td>Czas: " . date('H:i:s',mktime(0,0,$row[mine_stone_build_time])) . "</td>";
	echo "<td>Rozbuduj na poziom </td>";

	echo "</tr><tr>";

	echo "<td>Skarbiec (Poziom $row[store_gold])</td>";
	echo "<td>Drewno: $row[mine_gold_req_wood]</td>";
	echo "<td>Kamien: $row[mine_gold_req_stone]</td>";
	echo "<td>Zloto: $row[mine_gold_req_gold]</td>";
	echo "<td>Czas: " . date('H:i:s',mktime(0,0,$row[mine_gold_build_time])) . "</td>";
	echo "<td>Rozbuduj na poziom </td>";


	echo "</tr>";

Czy podążanie tą drogą będzie prawidłowe ?

1

robienie osobnej tabelki dla kazdego budynku, wg mnie jest bez sensu, bo mocno komplikuje dodawanie kolejnych budynkow, rozdyma niepotrzebnie zapytania
mysle ze spokojnie da sie zunifikowac cechy budynkow, tak aby mogly siedziec w jednej (ewentualnie dwoch tabelach)
poza tym juz masz jeden blad: mine_wood.req_gold AS mine_gold_req_gold, i przy takim podejsciu wydaje mi sie ze latwiej o wiecej takich bledow
kopalnia drewna, kamieni i zlota jesli chodzi o cechy nie roznia sie od siebie, poza tym jaki surowiec produkuja
podobnie inne budynki maja wspolne cechy: level, wymagane surowce, population, point, build_time
maja tylko inne cechy "output" i tu moze przydac sie druga tabelka, ktora pomoze nam zunifikowac te cechy
informacja o tym ile danemu graczowi na godzine przyrasta danego surowca i tak bedzie w innej tabeli trzymana, bo wplyw na to moga miec nie tylko budynki (albo nie tylko kopalnie) - zalezy od komplikacji gry
w twojej koncepcji wiedze ze jedynym kryterium rozbudowy budynku na kolejny poziom sa tylko surowce, a ja pokazalem ci jak mozna dodac warunki na posiadanie innego budynku na odpowiednim poziomie

generalnie im bardziej uda ci sie zunifikowac informacje o obiektach podobnego typu, tym lepiej, stworzysz bardziej elastyczny silnik, na ktorym latwo postawisz nie tylko gre z rycezami, ale i ze statkami kosmicznymi etc.
pomysl o unifikacji takze w kontekscie jednostek, bedziesz robil osobne tabele dla piechoty, łucznikow, jazdy, artylerii? po co, skoro ich glowne cechy to atak, obrona, ruchliwosc, a inne bardzie specyficzne moga byc interpretowane po stronie aplikacji, czyli np. typ piechoty z pikami, ma jakis bonus do walki z jazda, ale przeciwko kusznikom brak mu oslony i ma minus
poza tym pamietaj ze baza danych to przede wszystkich skład danych, logika jak interpretowac pewne dane powinna byc po stronie kodu aplikacji

0

Zakładam, że w jednej tabeli wstawiłem wszystkie surowce bo faktycznie tabele są identyczne i dla surowców i dla budynków i dla jednostek rycerzy czy machin wojennych.

ID LEVEL REQ WOOD REQ STONE TYPE ID
1 1 30 40 1
2 2 40 50 1
3 3 50 60 1
4 1 30 40 2
5 2 40 50 2
6 3 50 60 2
7 1 30 40 3
8 2 40 50 3
9 3 50 60 3

Jak w jednym zapytaniu wybrać najlepiej wszystkie informacje dla danego poziomu rozbudowy.
TYPE 1 | drewno
TYPE 2 | kamień
TYPE 3 | złoto
W tabeli danej posiadłości mamy informację, że zamek jest rozbudowny na poziom:
drewno (poziom3) | pokaż dane dla poziomu 4
kamień (poziom 6) | pokaż dane dla poziomu 7
złoto (poziom 2) | pokaż dane dla poziomu 3

Zapytanie powinno być takie. Wybierz ile potrzeba drewna dla składu drewna na poziom 4 oraz ile potrzeba kamienia dla składu kamienia na poziomie 7 oraz ile potrzeba złota dla skarbca na poziomie 3.
To jak złożyć takie zapytanie używając jednej tabeli ? Kilka selectó w jednym query ?

0

troche nie ogarniam tej twojej tabelki, ale...
"Zapytanie powinno być takie. Wybierz ile potrzeba drewna dla składu drewna na poziom 4 oraz ile potrzeba kamienia dla składu kamienia na poziomie 7 oraz ile potrzeba złota dla skarbca na poziomie 3."
musisz zrobic trzy zapytania:

  1. ile potrzeba drewna dla składu drewna na poziom 4
  2. ile potrzeba kamienia dla składu kamienia na poziomie 7
  3. ile potrzeba złota dla skarbca na poziomie 3
    pozniej wyniki tych trzech musisz polaczyc tak zeby ci odpowiadalo, nie wiem czy chcesz dostac 3 rekordy, jazdy dla innego surowca, czy jeden rekord z trzema kolumnami
0

Tabelka przedstawia parametry wymagane na kolejny poziom budowy czyli: dla jakiego poziomu trzeba ile drewna ile kamienia i złota a na końcu pole TYPE ID oznacza czego dotyczą dane (składu drewna,składu kamienia, składu złota) i zgadzam się, że trzeba by dać wtedy 3 zapytania. tylko wcześniej pisałeś, że lepiej zrobić to na jednym zapytaniu. Bo lepiej mieć więcej tabelek, przejrzysty schemat i jedno zapytanie niż jedna tabela i dużo zapytań. Kwestia wyboru jeden SELECT czy kilka ? co radzisz ?

0

odpowiem jak "profesjonalny" bazodanowiec: to zalezy...
ale tak serio, to na prawde zalezy od wielu czynnikow
przede wszystkim piszesz konkretna gre i ukierunkowany na nia soft, czy chcesz stworzyc bardziej uniwersalny engine gry?
jesli te 3 (czy nawet kilka wiecej) zapytani zadasz do bazy za jednym razem, lub chociaz na jednym polaczeniu to i tak lepiej niz connection per query
wiec to gdybanie nie ma sensu, bo ten "jeden select" bedzie zlozony i bez testow, ciezko powiedziec, ktore rozwizanie bedzie lepsze
lepiej stworz sobie cala mechanike gry, wszystkie zaleznosci i wzory, a nastepnie zacznij projektowac baze danych, a jesli ma to byc bardziej uniwersalny engine, to juz popelniles blad zakladajac jakie i ile jest typow surowcow
przyslowiowo "zabierasz sie od d... strony do tego"
a bardziej obrazowo to tak jakbys mial wspolne wiadro klockow lego i dorwal kilka garsci, a pozniej myslal co da sie z tego zbudowac, zamiast pomyslec co chcesz zbudowac i starac sie znalezc odpowiednie klocki

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