Iron 1.2.1 i trochę informacji o nim

Wydałem lekko poprawioną wersję Irona. Nowa wersja usuwa przede wszystkim błędy bezpieczeństwa (za wyłapanie kilku z nich serdecznie dziękuję DeXTeD'owi z forumweb.pl :)), ale poprawia też np. nieaktualizowany od prawie pół roku, skrypt sprawdzania aktualizacji dla skryptu. Zarówno ten wbudowany jak i jego wersję online, dla osób których serwery nie pozwalają na otwieranie zewnętrznych plików funkcją file_get_contents.

Ponadto postanowiłem w końcu ogarnąć jakiekolwiek strony informacyjne, download etc dla Irona. Znajdują się one w nowym podmenu w menu "Projekty" na górze strony. Będzie toto stopniowo rozbudowywane.

Pozdrawiam :)

IronCMS 1.2

Wreszcie, po naprawdę sporym opóźnieniu, udało mi się skończyć wersję 1.2 mojego CMS-a. Skrypt miał być wprawdzie gotowy ponad 2 tygodnie temu, ale z nawału wykrytych w nim błędów dopadło mnie chwilowe lenistwo. Dopiero dziś udało mi się wziąć w garść i skończyć zaczętą robotę.

Najwięcej zmian w tej wersji można znaleźć "pod maską", oto najważniejsze z nowości:

  • przepisanie części skryptu na programowanie obiektowe
  • znaczne uproszczenie struktury bazy danych
  • możliwość włączenia komentowania dla osób niezalogowanych
  • możliwość wygenerowania kanału ATOM dla artykułów
  • skórkę dla telefonów komórkowych przywrócono do używalności - wprawdzie była ona w Ironie już od dłuugiego czasu, jednak była dość mocno niedopracowana i od dawna nieaktualizowana. W tej wersji wprowadzono w niej naprawdę sporo zmian.
  • w związku z powyższym nadszedł też czas na zrobienie łatwego przełączania się między motywami
  • pasek dla administratora, na górze strony, zawierający najważniejsze odnośniki
  • więcej zmian w readme…

Pobierz Irona

[Mini] Jakby to było dobrze…

Pierwszy wpis w nowopowstałej kategorii "Mikroblog". Nazwa i prefix wpisu chyba tłumaczą wszystko. Proszę nie spodziewać się zbyt wiele :)

Muszę niektórych rozczarować, to nie będą fantazje erotyczne… To po prostu kilka drobnych myśli, które naszły mnie podczas pisania kolejnej wersji IronCMS-a. Chodzi mi tu o możliwości, które ma wprowadzić HTML5 i PHP6.

Logo HTML 5

Pomyślmy tylko jakby to było pięknie gdyby:

  • zamiast pisać potworki w stylu
    <input onFocus="if (this.value=='Wpisz swój komentarz...') {this.value='';}" onBlur="if (this.value=='') {this.value='Wpisz swój komentarz...'}" [...] />
    
    móc napisać po prostu <input placeholder="Wpisz swój komentarz" ... />
  • praktycznie całą walidację po stronie klienta wykonywać za pomocą takich atrybutów jak required czy pattern (porównywanie tekstu wpisanego z regExem na poziomie HTML-a- marzenie) oraz odpowiednich wartości podanych w type (gdy podamy np. email, to adres zostanie sprawdzony przez browsera)
  • móc nie mieć w PHP takich archaizmów jak safe_mode, register_globals, czy magic_quotes. W większości wypadków są one wyłączone, jednak gdy jest inaczej, to możemy mieć sporo roboty, np. z kasowaniem slashy dodaną przez tego ostatniego "ficzera"
  • nie musieć podawać masy zbędnych atrybutów i tagów takich jak
    • całego długiego doctype w stylu
        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
      
      gdyż od teraz wystarczy nowe <!DOCTYPE html>
    • deklarowanie kodowania poprzez długaśne <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> - w HTML 5 to <meta charset="UTF-8">
    • oczywiste wartości atrybutu type, takie jak text/css dla arkuszy stylów, czy text/javascript dla plików JS
  • mieć semantyczne tagi dla najczęstszych części strony (header, footer, article, section i spółka). Wyszukiwarki pewnie też odetchnęłyby z ulgą
  • w końcu ujednolicona obsługa filmów na stronach poprzez tag video
  • wiele więcej…

Do tego wszystkiego dorzuciłbym jeszcze jedno nierealne życzenie. Żeby przeglądarki działały jak kompilatory. Nie wybaczały nawet najmniejszych błędów :P

Zdaję sobie oczywiście sprawę, że każdy kto interesował się HTML-em 5, nie znajdzie tu wiele nowego, ale po prostu chciałem się podzielić przemyśleniami. Więc proszę nie bić ;)

Jeśli kogoś to zainteresowało i chciałby poczytać conieco o tym co nas czeka, to mogę polecić ten CheatSheet HTML 5.

PS: Obrazki we wpisach. Czyżby nowy trend na sobak.pl?

Przegląd skryptów genialnych #1

Od pewnego czasu zacząłem się interesować CMS-ami (od strony developerskiej). Dlatego też postanowiłem zobaczyć jak wyglądają polskie osiągnięcia na tej scenie. Znalazłem mały spis naszych rodzimych tworów i zacząłem sprawdzać. Dzisiaj przygotowałem dla Was krótki przegląd skryptu znad Wisły o wdzięcznej nazwie CMS Zaba (pamiętajcie

  • nie żaba ;)). Od razu uprzedzam wszelkie (oczywiste) skojarzenia z wymyślną formą promocji mojego "CMS-a". Faktycznie, na przeglądanie innych CMS-ów naszło mnie właśnie przy okazji pisania irona, ale nie zamierzam tym pokazywać jakichś ewentualnych przewag nad innymi skryptami. Zdaję sobie sprawę z tego, że IronCMS to wytwór amatorski i nie może się równać z CMS-ami nieraz tworzonymi przez profesjonalne firmy.

No, ale teraz przechodzimy do rzeczy ;)

  1. Brak instalatora - chociaż to tylko drobna uwaga. Dla większości osób zaimportowanie bazy danych i wypełnienie pliku konfiguracyjnego to chyba nie jest wielki problem (chyba…)
  2. Krótkie znaczniki otwierające (<?) - na nowych konfiguracjach nie zadziała
  3. Brak wielu ikon po zainstalowaniu.
  4. Widać, że z polskiego autor geniuszem nie był. Pozwolę sobie zacytować newsa powitalnego:

    Witam login dla admina to admin haslo admin tak samo jak loguje sie na stronie! Mamy tu klasyczny przykład wiersza białego prozy białej.

  5. Z angielskiego też najlepiej mu nie szło :(. W stopce mamy link o pięknym opisie "Cms Power by Zaba". Dodatkowo przed linkiem nie ma http://, przez co oczywiście przeglądarka traktuje go tak jakby prowadził do katalogu. Na dokładkę mamy też genialną nazwę theme'u domyślnego - defult
  6. Dobrze. Przyszedł czas się zalogować. Dane podane przez autora są poprawne. Co jednak stanie się gdy podamy złe dane? Ano nic - nagłówek "Logowanie", reszta strony pusta. Żadnego komunikatu… Tak samo z resztą jest przy logowaniu poprawnym - jedynym znakiem jest zmiana menu.
  7. Klikam w link "Panel" i oto - ponownie nagłówek "Logowanie"… Wygląda na  to, że z jakichś powodów skrypt nie łapie zmiennych. Pewnie potrzebne włączone register_globals? Zaraz się przekonamy.
  8. W międzyczasie nadszedł czas na przyjrzenie się lekko bazie danych.
    • Brak prefixów tabel
    • Wchodzimy do tabeli "uzytkownicy". Hasła szyfrowane… ale samym md5 bez soli. Słabo.
    • Patrzę na pola w tej tabeli. Mamy tam praktycznie wszystko: logowan, komentarzy, dzwiek, procesor, pamiec, monitor, avart (jak sama nazwa wskazuje, zawiera URL do avatara ;)), lacze, system, myszka, podkladka, potrawa, muzyka, film, aktor, sport etc… Ogólnie wszystko co niezbędne. Szkoda tylko, że nie znalazły się tam tak wyszukane pola jak np. płeć :/
    • Wszystkie powyżej wymienione pola wypełnione ofc danymi autora skryptu.
  9. Tymczasem powracamy do punktu siódmego. "Niespodziewanie" moja diagnoza o konieczności włączenia register_globals przyniosła efekty. Podstrony zaczęły działać, tak samo ew. błędy przy logowaniu.
  10. Czas więc ponownie spróbować wejść do panelu administracyjnego. Klikam więc link "Panel" i znajduję się w… profilu. Okazuje się bowiem, że to co miałem mylnie za panel administratora, okazało się panelem użytkownika. Więc gdzie jest panel administratora? W paczce znajdował się folder "Administracja", dopisałem go do adresu i oto…
  11. …błędy MySQL. Powód? Panel admina posiada osobny plik config.php…
  12. Dobrze, pojawiła się strona logowania. Ale zaraz, jak to? Na stronie jestem zalogowany, a w panelu jeszcze nie, tak? No cóż, za łatwo być nie może :) Powodem tego jest to, że admin, czyli user tworzony domyślnie jest trzymany w dwóch tabelach "uzytkownicy" i "admin". Wprawdzie daje to powalającą możliwość oddzielnego hasła do strony i do panelu, ale… co komu po tym?
  13. Ustawienie stopki przy dłuższych stronach nie zachwyca. Takie rzeczy jak 404 pod jednym linkiem i brak linka do strony też nie….
  14. Zszokował mnie pewien fakt… Otóż po wejściu w zakładkę "Aktualności", okazało się, że… nie da się ich edytować. Jakaś możliwość specjalna?
  15. Postanowiłem dodać kategorię artykułów, lecz zamiast jakiegoś komunikatu/linka zobaczyłem "Artykuly Kategorie - ok0: Update finish". Podobna sytuacja po edycji profilu. Pozostałości po debugu w wersji publicznej? Niedobrze…
  16. Nadszedł czas ustawić kategorię dla mojego artykułu, aby mógł się wyświetlić. Niestety widząc link "[E]", odruchowo założyłem, że edycja dla artykułów jest możliwa. Przeceniłem "Zabę"- pusty link :(
  17. Po interfejsie można by jeździć w nieskończoność, ale przejdźmy do kodu…
  18. Panel admina, sądząc po DTD, jest pisany w xHTML 1.0 Strict. Ambitnie - jednak co z tego skoro mamy 25 błędów?
  19. Kod strony głównej przebija - 35 błędów i to… w HTML 4.01. Widać kto tu rządzi :)
  20. Taki krótki wycinek kodu z panelu administracyjnego:
    <div id="header">
    <ul>
     <li id="current"><a href="index.php">Strona Główna</a></li>
     <li id="current"><a href="index.php?cmd=1">Aktualności</a></li>
     <li id="current"><a href="index.php?cmd=2">Strony Serwisu</a></li>
     <li id="current"><a href="index.php?cmd=10">Artykuly</a></li>
     <li id="current"><a href="index.php?cmd=3">Linki</a></li>
     <li id="current"><a href="index.php?cmd=4">Księga Gości</a></li>
     <li id="current"><a href="index.php?cmd=5">Newsletter</a></li>
     <li id="current"><a href="index.php?cmd=6">Użytkownicy</a></li>
     <li id="current"><a href="index.php?cmd=8">Menu</a></li>
     <li id="current"><a href="index.php?cmd=12">Bannery</a></li>
     <li id="current"><a href="index.php?cmd=11">Pliki</a></li>
     <li id="current"><a href="index.php?cmd=7">Forum</a></li>
     <li id="current"><a href="index.php?cmd=13">Ban</a></li>
     <li id="current"><a href="index.php?cmd=9">Konfiguracja</a></li>
    </ul></div>
    
    Hmm… o ile nie przerobiłem kursu dla idiotów, to ID może być tylko jedno :P. Sam sposób jego nadawania też miażdży.
  21. Reszta strony to tabelki, font w xhtml, tabelki, style inline, zero klasy dla powtarzanych elementów, tabelki, style inline i… czy wspomniałem już o tabelkach?
  22. Jeśli chodzi o nazewnictwo w kodzie. Raz mamy sobie f-cję menu_update(), a za chwilę pokaz_plik(). Totalny mix dwóch języków, z przewagą oczywiście polskiego.
  23. Mógłbym zrobić jeszcze pizdylion^666 punktów, ale mi się nie chce, tak więc pokażę kilka rzeczy na screenie: klik.

Ogólnie można pewnie wytknąć jeszcze masę błędów. Nie oceniałem przecież praktycznie w ogóle kodu PHP. Poza tym jest sporo możliwości samego skryptu których nie testowałem. Forum, download i masę innych… Jeśli komuś jeszcze chciałoby się pośmiać, to skrypt można ściągnąć tutaj. Ja tymczasem z powrotem ustawiam konfigurację PHP na bezpieczną.

PS: Dodam jeszcze króciutkie wyjaśnienie. Moim celem nie było wyśmiewanie autora skryptu. Trzeba docenić to, że zrobił darmowy produkt i udostępnił go ludziom (choć w readme groził, że "Kopiowanie kodu jest surowo karane lub tez kopiowanie plikow….."). Po prostu można potraktować to jako krótką listę błędów których nie należy popełniać.

PS2: Przepraszam za ewidentny bałagan w poście. Był on pisany "na żywo" podczas testów.

PS3: Wynikiem 996 słów uzyskujemy prawdopodobnie najdłuższy dotychczasowy wpis na sobak.pl :)

IronCMS 1.1

Zaledwie osiem dni minęło od premiery pierwszej publicznej wersji mojego CMS-a, a już prezentuję Wam jego kolejną wersję. Nie jest to jednak aż tak wielki powód do dumy jak pozornie mogłoby się wydawać, bo wersja ta spowodowana jest wieloma błędami i spostrzeżeniami do wersji 1.0. W tym miejscu dziękuję wszystkim za konstruktywną krytykę i wszelką pomoc.

W tej wersji skupiłem się głównie na poprawie wytkniętych mi błędów. Tak więc z najważniejszych zmian wymienić można:

  • działające BBCode - szukałem troszkę czegoś odpowiedniego i w sumie oparłem bbcode w Ironie na klasie NBBC. Banalna edycja i dodawanie znaczników, skompresowany kod (pozbawiony wcięć i enterów) zajmuje ok. 2500 linii (64 KB) (w Ironie rozmiar obcięty do 1900 linii). Do tego genialna dokumentacja. Polecam ;)
  • nowe menu w panelu administracyjnym - było na nie wiele narzekań (sam się w nim gubiłem), więc przysiadłem na chwilę i mam nadzieję, że jest łatwiej się w nim połapać.
  • wiele poprawek w systemie komentarzy - możliwość korzystania z bbcode, komentarze adminów nie potrzebują akceptacji (wiem, absurd, przeoczyłem to), tekst domyślny znika po kliknięciu na pole, możliwość dodania komentarzy do artykułów, podniesione zabezpieczenia itd.
  • uporządkowano praktycznie wszystkie formularze w skrypcie - ujednolicono wygląd i poprawiono opisy
  • wszystkie funkcje mysql_* zastąpiono funkcjami własnymi (odniesienie do sugestii Kwpolska) - kto wie? Może kiedyś zobaczymy Irona np. na PostgreSQL? :P
  • dużo, dużo więcej…

Teraz czas na informacje nieco z innej beczki. Otóż w dniu dzisiejszym, grupa tworząca Irona została z powrotem zredukowana do jednoosobowego zespołu szaleńców (czytaj mnie…). M4tx przez cały czas swego udziału włożył do projektu około 20 linii kodu (a po wersji 1.0, która została napisana od nowa ten udział wyniósł równe zero), tak więc stwierdziłem, że nie będę go więcej męczył pytaniem, czy coś zrobi. I został (jak na razie!) wyrzucony z projektu.

Mam nadzieję, że zaprezentowane powyżej zmiany  uważacie za dobre.

IRON CMS 1.1 (*.zip)

A na koniec: Wesołych Świąt Wam życzę :)

Premiera Iron CMS-a!

Z nieukrywaną dumą informuję, że skrypt który zacząłem tworzyć dokładnie 114 dni temu (20.12.10) został w końcu doprowadzony do stanu używalności. Dziś, o godzinie 14:40 nadszedł czas zaprezentować go światu.

Premiera odbyła by się chwilę wcześniej, gdyby nie to, że nie mogłem się dostać do phpMyAdmina na sobak.pl i tym samym zdebugować pewnego zapytania (na localhoście działało, tu nie). Przez około 5 godzin męczyłem się z instalatorem. Dodatkowo ponad godzinę straciłem, czekając aż panel administracyjny 1&1 raczy się załadować., ale, tak, udało się! :) Iron CMS 1.0 jest gotowy!

O tym, że jego przepisywanie od nowa zbliża się do końca informowałem tutaj. Zajęło mi to dokładnie 20 dni (z małymi przerwami). Podczas tego "procesu" skupiłem się głównie na poprawie logiki, wydajności i błędów ze starszych wydań (były 4 wydania prezentowane tylko znajomym).

  • poprawiłem dziesiątki nieoptymalnych miejsc. Trzykrotne łączenie się z bazą w jednym pliku, czy pobieranie tej samej wartości kilkanaście razy pod rząd? Takie rzeczy tylko w starych wersjach Irona (tak, ochrzciłem CMS-a mianem żelazka :D (joke)) :)
  • poprawiłem stare funkcjonalności. Np. f-cja kosza dostępna od wersji 0.3 została rozszerzona o możliwość wyrzucania artykułów. Wcześniej były to tylko podstrony.
  • nowa wersja starego szablonu. Jak już napisałem w zapowiedzi skryptu, użyłem gotowego szablonu. Podczas przepisywania CMS-a na nowo, znalazłem jego nowszą wersję. Został mocno poprawiony HTML i CSS i doszło m. in. górne menu. Dodatkowo dorzuciłem lekką modyfikację szablonu od siebie.
  • możliwość ustawienia oddzielnego theme'u dla panelu administracyjnego
  • zalążek rang użytkowników
  • znaczna poprawa bezpieczeństwa
  • dodany instalator
  • poprawa przejrzystości panelu administracyjnego
  • zmiana wielu rozwiązań pod względem logistycznym
  • setki, naprawdę setki rzeczy o których zapomniałem bądź pisać nie warto…

Skrypt został napisany z użyciem możliwości z PHP5 (wersja czwarta musi odejść do lamusa…) i bazy danych MySQL.

Trochę statystyki

Wielkość skryptu (zdekompresowane)

  • 0.1 - 26.4 kB
  • 0.2 - 2.87 MB
  • 0.3 - 1.48 MB
  • 0.4 - 2.32 MB
  • 1.0 - 344 KB

Skąd tak duża różnica? Od wersji 0.2 w skład skryptu wszedł JS-owy edytor WYSIWYG - TinyMCE. W 0.3 go "lekko" odchudziliśmy (z m4tx'em) - stąd taki spadek rozmiaru. W 0.4 doszło troszkę nowych rzeczy, a IronCMS 1.0 został pozbawiony edytora WYSIWYG, zastąpiono go BBCodem. Jego rozmiar jest podwójnym sukcesem, bo poprzez rozbicie theme'u na theme dla strony i oddzielny dla panelu, ilość obrazków de facto nam się podwoiła.

Dlaczego nie WYSIWYG lecz BBCode? Otóż stwierdziłem, że skryptów idiotoodpornych powstało już mnóstwo. Zdaję sobie sprawę, że to może zawęzić ilość użytkowników Irona (ale spójrzmy obiektywnie - ile ludzi tak czy siak będzie go używać? :P). Poza tym - znajomość BBCode, to nie jest jakaś magiczna sztuka.

Linie kodu (kliknij aby powiększyć)
Statystyki linii w IronCMS

Podziękowania

  • dla Rhina za rozwiązanie niezliczonej ilości moich błędów i przeoczeń
  • dla Pawła1503 i m4tx'a za betatesty
  • dla CapaciousCore'a, za naprawdę fachowe porady dotyczące skryptu.

DOWNLOAD IRON CMS 1.0

[PHP] Pobranie najnowszych wpisów z WordPressa

W tym wpisie przedstawię prosty skrypt pobierający ostatnie wpisy z bloga opartego na WordPressie. Skrypt powinien działać co najmniej na wszystkich WP z gałęzi 3.x

Prezentuję dwie leciutko się różniące wersje pod wyświetlanie dokładnie jednego ostatniego wpisu i wyświetlaniu określonej ilości ostatnich wpisów.

Wersja na jeden wpis

<?php
// Database config
$db['host'] = 'serwer_twojej_bazy';
$db['user'] = 'nazwa_usera';
$db['pass'] = 'haselko';
$db['name'] = 'nazwa_bazy_danych';

@mysql_connect ($db['host'], $db['user'], $db['pass']) or die ('Nie udało się połączyć z bazą danych');
@mysql_select_db ($db['name']) or die('Nie udało się wybrać bazy danych.');

// Get title of newest post
$query = mysql_query ("SELECT `post_title` FROM `wp_posts` WHERE `post_status` = 'publish' AND `post_type`='post' ORDER BY `post_date`  DESC LIMIT 1") or die ('Nie udało się pobrać najnowszego wpisu');

$row = mysql_fetch_array ($query);
$post_title = $row['post_title'];
echo $post_title;
mysql_close();

Wersja na wiele wpisów

<?php
// Database config
$db['host'] = 'serwer_twojej_bazy';
$db['user'] = 'nazwa_usera';
$db['pass'] = 'haselko';
$db['name'] = 'nazwa_bazy_danych';
// Other config
$num_posts  = '5';

@mysql_connect ($db['host'], $db['user'], $db['pass']) or die ('Nie udało się połączyć z bazą danych');
@mysql_select_db ($db['name']) or die('Nie udało się wybrać bazy danych.');

// Get titles of newests posts
$query = mysql_query ("SELECT `post_title` FROM `wp_posts` WHERE `post_status` = 'publish' AND `post_type`='post' ORDER BY `post_date`  DESC LIMIT $num_posts;") or die ('Nie udało się pobrać najnowszego wpisu');

echo '<ul>';
while ($row = mysql_fetch_array ($query)) {
   echo "t<li>";
   echo $row['post_title'];
   echo "</li>n";
}
echo '</ul>';

mysql_close();

Sercem obu tych skryptów jest jedno zapytanie czyli:

SELECT `post_title` FROM `wp_posts` WHERE `post_status` = 'publish' AND `post_type`='post' ORDER BY `post_date`  DESC LIMIT *

różnicą jest jedynie różna wartość ustawienia LIMIT. W pierwszym skrypcie wynosi ona oczywiście jeden, ponieważ pobieramy tylko jeden wpis, a więc tylko jeden rekord. W drugim zaś zależy od ustawienia odpowiedniej zmiennej $num_posts w konfiguracji skryptu.

Oba warianty skryptu różnią się też oczywiście sposobem wyświetlenia pobieranych danych. W pierwszym jest to zwyczajne wywołanie funkcji mysql_fetch_array, w drugim zaś wypadku jest ona użyta w pętli, a wpisy pokazywane są jako lista nieuporządkowana, co można dość łatwo zmodyfikować do swoich potrzeb.

Przedstawione skrypty stanowią tylko swoisty "rdzeń". Musimy oprawić je w ramy dokumentu HTML i ewentualnie możemy ustawić dla nich style CSS.

Zdaję sobie sprawę, że przedstawione skrypty dla wielu osób mogą się wydawać banalne i źle napisane (przecież nie użyłem PDO i miliona wyjątków), ale mam nadzieję, że choć dla jednej początkującej osoby ten prosty skrypt stanie się jakąś bazą do dalszego eksperymentowania z SQL i PHP.

Tak tego nie róbcie…

Krótki wpis zainspirowany moją własną, osobistą głupotą. Znalazłem to przerabiając fragment skryptu pisanego nie tak dawno temu. Dlaczego zrobiłem to w ten sposób? No cóż - głupota i wygoda klawisza ctrl+d w notepadzie++.

Screen jest spory tak więc zamieszczam go pod tym linkiem. Tak się tego nie robi ;) Wszystko wyjaśnione na screenie, więc w tym miejscu kończę wpis.

Tak więc w bulu żałuję błędu i kurczowo trzymam się nadzieji, że w przyszłości będę mądrzejszy :)

PS: Może i Wam zdarzyły się podobne pomyłki?

Poradnik pisania gier MMO via WWW cz. 2

Witam Cię serdecznie w drugiej części mojego poradnika pisania gier MMORPG na przeglądarki internetowe. Jeśli przez cały poprzedni rozdział przebrnąłeś z pozytywnymi odpowiedziami, to teraz przyszedł czas na wybór odpowiedniego silnika do gry.

Osób lekko bardziej zaawansowanych moja odpowiedź na pewno nie zdziwi: stwórz własny engine. Dlaczego?

Czytaj dalej →