1. Wow.. Just wow.. Te komentarze są naprawdę dobre O.o
2. W kodzie zauważyłem, że praktycznie w ogóle nie stosujesz możliwości omijania "klamerek". Wiele warunków i pętli ma w sobie tylko jedną operację, a mimo to i tak znajdują się tam klamerki. Przykładowo:
for(int i=1 ; i<=record_slowdown[0] ; i++)
{
if(record_slowdown[i])
{
record_slowdown[i] += record_pause;
}
}
Można zapisać tak:
for(int i=1 ; i<=record_slowdown[0] ; i++)
if(record_slowdown[i])
record_slowdown[i]+=record_pause;
Chyba, że to po prostu dla czytelności.. kwestia gustu.
3. Używasz zdecydowanie za dużo if'ów, a za mało switch'ów.. zwłasza w miejscach gdzie aż się prosi o switcha.. Przykład:
if(can_put) //wypisywanie znakow jesli w tym miejscu jest powerup
{
if(cells.powerups[w-1][h-1] == 1)
{
for(int q=0 ; q<screen.Size ; q++)
show_part+='I';
}
//...
else
{
for(int q=0 ; q<screen.Size ; q++)
show_part+=' ';
}
}
Można zastąpić prostym switch'em:
if(can_put) //wypisywanie znakow jesli w tym miejscu jest powerup
{
char tempChar;
switch(cells.powerups[w-1][h-1]) //Przy okazji możemy uniknąć ciągłego odwoływania się do tej wartości.. pobieramy ją tylko raz.. a nie kilka razy jak w przypadku if'ów
{
case 1: tempChar='I'; break;
case 2: tempChar='D'; break;
case 3: tempChar='?'; break;
case 4: tempChar='?'; break;
case 5: tempChar='?'; break;
case 6: tempChar=char(3); break;
case 7: tempChar='B'; break;
default: tempChar=' '; break;
}
for(int q=0 ; q<screen.Size ; q++) show_part+=tempChar;
}
4. Zauważyłem, że tworzysz wiele zmiennych w jednej klasie typu:
ball.bomb_radius
ball.harmless
ball.go_through
ball.record_slowdown
Jest kilka rzeczy, do których się przyczepię.. opierając się właśnie na takich zmiennych
a) Jeżeli masz zmienną czasową (typowy timer), która zawiera w sobie czas działania danego bonusu to siłą rzeczy, jeżeli timer osiągnie zero to bonus będzie nieaktywny.. nie potrzebujesz dodatkowych zmiennych typu bool, aby to stwierdzić.
b) Dlaczego by nie przedstawić bonusów w postaci klas, które by dziedziczyły od głównej klasy bonus? Przy okazji byś troszeczkę pobawił z dziedziczeniem x) Jak by to miało wyglądać? W klasie Ball znajdowałby się wskaźnik do konkretnego bonusu. Jeżeli wskaźnik wskazywałby na adres nullptr to bonus nie byłby aktywny. A jeżeli bonus zostanie zebrany to możesz przypisać do tego wskaźnika (nazwijmy go CurrentBonus) adres konkretnego bonusu, a potem wywołać metodę (wirtualną) CurrentBonus->Reset(); która by "resetowała" zebrany bonus czyniąc go aktywnym (to rozwiązanie by pomogło uniknąć tworzenia czegoś takiego: CurrentBonus=new Bonus_GoThrough()). Oczywiście w pętli logiki umieszczałbyś coś takiego:
if(CurrentBonus) CurrentBonus->Update();
c) Jeżeli nie podoba ci się rozwiązanie z podpunktu b) to możesz stworzyć tablicę dla takich zmiennych i odwoływać się do poszczególnych zmiennych przez enumerację (ale to już kwestia estetyczna).
5. W ramach ułatwienia sobie życia możesz stworzyć funkcję (wykorzystującą bibliotekę windows.h), która umożliwiałaby ustawianie kursora w konsoli podając tylko konkretne współrzędne.. dzięki temu, mógłbyś uniknąć wielu komplikacji i dbaniu dosłownie o każdą kratkę. (tu za dużo spacji.. tam za mało.. a jak jest bonus to trzeba zabrać jeszcze jedną). Jednak to już od ciebie zależy, czy wykorzystasz ten pomysł.
5.5 Skoro już jestem w temacie renderu.. zauważyłem jedną rzecz.. (nie jestem pewien do końca.. jednak wydaje mi się, że -> ) Stosujesz olbrzymie tablice w celu przechowywania bonusów.. To jest chyba największy minus twojego kodu i jego największa wada.. Powinieneś przechowywać bonusy w jakimś "pojemniku" (np. std::vector). A przez "bonusy" mam na myśli przede wszystkim współrzędne. Dlaczego to wszystko? W celu uniknięcia takich "rozwiązań":
void Cells::clear_powerups()
{
for(int h=Wall_Lenght-1 ; h>=0 ; h--)
{
for(int w=0 ; w<Wall_Lenght ; w++)
{
powerups[w][h] = -1;
}
}
}
Przecież wyczyszczenie powerup'ów mogłoby wyglądać tak:
Powerups.Clear(); //O ile Powerups byłby wektorem ze współrzędnymi
Ale jak już mówiłem.. nie wiem czy do końca zrozumiałem ten fragment kodu.. możliwe, że robi on coś zupełnie innego.
6. Ten punkt powinien ci się spodobać najbardziej x)
Jest on odpowiedzią na pytanie: "Jest jakis sposob, zeby poruszac platforma bez przerwy po pierwszym kroku?"
Ano jest.. tylko wymaga użycia biblioteki windows.h, ale skoro i tak ją "includujesz" zgaduję, że nie będzie ci to przeszkadzać. Powiem więcej.. skoro biblioteki conio.h używasz tylko dla getch() to już teraz możesz ją "usunąć" z kodu. A więc najlepiej będzie mi to pokazać na przykładzie..
Przekopiuj sobie ten kod do jakiegoś pliku .cpp i skompiluj za pomocą jakiegoś kompilatora..
Aby zobaczyć efekt naciskaj klawisze [LShift] oraz [O].. Możesz nacisnąć też obydwa.
//To jest potrzebne by została wykryta funkcja: GetConsoleWindow();
#define _WIN32_WINNT 0x0500
#include <iostream>
#include <windows.h>
int main()
{
//Ustawiamy uchwyt do okna (HWND), tak aby wskazywał na naszą konsolę (konsola to też okno).
HWND Hwnd = GetConsoleWindow();
while(true)
{
system("cls");
// Tutaj posługuję się stałą dla lewego shifta.. jednak możesz też bez problemu użyć "kodu" liczbowego.
// Left Shift Key O
if(GetAsyncKeyState(VK_LSHIFT) & GetAsyncKeyState(0x4F)) //Operator bitowy AND (&) pozwala tworzyć kombinacje.. dzięki niemu możemy sprawdzić czy został naciśnięty [LShift] oraz klawisz [O].
std::cout<<"[LShift]+[O] Is preesed..\n";
else if(GetAsyncKeyState(0x4F))
std::cout<<"[O] Is preesed..\n";
else if(GetAsyncKeyState(VK_LSHIFT))
std::cout<<"[LShift] Is preesed..\n";
}
std::cin.get();
}
Jeżeli chciałbyś więcej "kodów" do poszczególnych klawiszy to tu masz link z całą listą:
https://msdn.microsoft.com/en-us/library/dd375731(v=vs.85).aspx
7. No to chyba tyle ode mnie.. Mam nadzieję, że ta "krótka" wypowiedź ci w jakiś sposób pomogła.
PS Animacja spirali rządzi! xD