Co nowego na forum?

Dorosłość... Kariera 44 minuty temu
Dobry start. Bazy danych 20 minut temu
Dobry start. Bazy danych 20 minut temu

loza_szydercow dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

44 sekundy temu @karpov: Kolega to widzę chyba jeszcze w żadnej większej organizacji nie uczestniczy...

Xavi17 dodał post w Dobry start.

1 minuta temu I ten właśnie specyficzny przypadek miałem na myśli ;)

loza_szydercow dodał post w Czy posłom powinno się podnieść pensje czy pomniejszyć?

5 minut temu Pensje zlikwidować, dodatki i premie podwyższyć, ustawę kominową zlikwidować, jawnoś...

loza_szydercow dodał komentarz w Dorosłość...

8 minut temu Czy się stoi, czy się leży, dwa tysie się należy - tą prawdę powinien poznać

karpov dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

8 minut temu Niestety, glosuje sie na partie a nie ludzi. A przez to ciezko o specjalistow. Zamia...

grzesiek51114 dodał post w Dobry start.

9 minut temu Właśnie to jest całkiem co innego. Bardziej chciałem przytoczyć tutaj jedną z tych S...

vpiotr dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

10 minut temu Wyborcy powinni się móc grupować w kraje o granicach niezależnych od geografii. Była...

Unilady dodał komentarz w Informatyka na UAM czy WAT

10 minut temu Pisałam na maturze infe, matme i angielski, a fizyi sie od 1,5 roku nie uczyłam, bo...

Patryk27 dodał post w Mało wydajny ajax

11 minut temu Czej, podpiąłeś tę funkcję pod onscroll?

loza_szydercow dodał post w Czy udzielanie się na 4p a poziom danego programisty są skorelo...

11 minut temu WeiXiao napisał(a): co ty ćpiesz loża Zazwyczaj herbatkę, choć czasem kawka też się ...

stivens dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

12 minut temu To co jest niedemokratycznego w evotingu? To co pisalem o emerytach nie bylo na zasa...

vpiotr dodał komentarz w DUŻE WYDARZENIE! Delphi oraz C++Builder w wersji Community Editi...

13 minut temu Tu nie chodzi o dochody z apki tylko w ogóle o dochody. Więc musisz być bezrobotnym...

somekind dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

15 minut temu Ta sama zasada dotyczy wszystkich. Niedemokratycznie by było, gdyby różnych ludzi do...

baant dodał komentarz w Ile zarabiacie?

16 minut temu no przecież mówi, że za mało

Akihito dodał komentarz w Ile zarabiacie?

16 minut temu :D napisz posta wedlug krytreium i poiwem czy jest az tak zle :D

loczek111 dodał post w Mało wydajny ajax

17 minut temu Zwykły menadżer zadań w windowsie pokazuje obciążenie procesora dla przeglądarki a w...

stivens dodał komentarz w Czy posłom powinno się podnieść pensje czy pomniejszyć?

18 minut temu No nie wszystkich bo nie wszyscy moga kandydowac. To jakby wykluczyc ludzi przed 30s...

Xavi17 dodał post w Dobry start.

20 minut temu sprawdzasz mnie ? teoretycznie to samo, ale bezpieczniej używać is null ponieważ w s...

kamila99 dodał post w Informatyka 1st na UŁ

22 minuty temu ja studiowałam informatykę na Politechnice Rzeszowskiej.

pol90 dodał komentarz w Ile zarabiacie?

23 minuty temu A ile zarabiasz ?

Popularne wpisy na mikroblogu

4programmers.net
2018-07-03 20:02Sponsorowane

Rozwiązaniem godnym polecenia szczególnie małym przedsiębiorcom, którzy często są zmuszeni mierzyć się z problemami natury finansowej, jest mikrofaktoring w inviPay.com

Artur, młody przedsiębiorca - freelancer IT przez dwa lata pracował przy projekcie stworzenia platformy carsharingu. Współpraca układała się perfekcyjnie do czasu sprzedania firmy carsharingowej zagranicznemu inwestorowi. Nowy właściciel stwierdził, że jeżeli pracownicy są zatrudnieni na kontrakcie, to wydłuży im terminy płatności za faktury z 14 do 45 dni.
Początkowo ta zmiana przeraziła Artura, ale praca bardzo mu odpowiadała i nie chciał z niej rezygnować. Znajomy zaproponował mu współpracę nad drugim projektem.

“Pomóż mi napisać moją aplikację, a nie będziesz musiał pracować w obecnej firmie”.

Artur długo się nie zastanawiał i zaczął tworzyć. Po miesiącu kodowania, gdy nasz freelancer miał wystawić fakturę za pracę, okazało się, że nie ma kontaktu ze znajomym, a projekt okazał się oszustwem. Zrozpaczony Artur pozostał z ogromnym problemem.

“Płatność z firmy carsharingowej dopiero za 1,5 miesiąca, a ja straciłem cashflow”.

Zaczął czytać i szukać rozwiązania, aż w końcu doznał olśnienia. Kolega jego ojca, Pan Marek, który prowadzi firmę outsourcującą programistów, wspomniał na swoim blogu o inviPay.com i przyspieszonych płatnościach. Długo nie myśląc Artur zadzwonił do kolegi ojca, wypytał o szczegóły i się ucieszył.

“Artur, zarejestruj się z mojego linka, a ja w zamian dam Ci kontakt do Pani Magdaleny z inviPay.com, która Cię poinstruuje tak, że pojutrze będziesz miał pieniądze na koncie”.

Następnego dnia Artur zadzwonił do Pani Magdy, która pomogła mu w formalnościach.
Tym razem Pan Marek się mylił, ale na korzyść dla Artura. Po potwierdzeniu faktury w firmie carsharingowej pieniądze otrzymał tego samego dnia, poprawiając w ten sposób swoją sytuację. Był tak ucieszony z rozwiązania, że polecił Pani Magdalenie 8 swoich kolegów, którzy również skorzystali finansowania w inviPay.com, a za polecenia koszt faktoringu obniżył się aż o 80%. Artur zapewnił sobie płynność finansową, której potrzebował i pomógł kolegom borykającym się z podobnym problemem.

Bądź jak Artur - polecaj inviPay.com i zarabiaj na tym.

kobuz80

Na szczęście mi staremu kawalerowi,który tylko intercyza+cywilny "ożenek" w ogóle nie grozi :)

jarekr000000
2018-07-17 20:12

Początki w java, a technologiczne zombiaki

Co chwila mamy posty początkujących programistów java, szukających pomocy. I to jest fajne. To jest naprawdę OK język na start. Mogli przecież trafić dużo, dużo gorzej.

Problem natomiast pojawia się z frameworkami. Nie chodzi o moje standardowe utyskiwanie na te wiodące (you know of whom I speak). Są popularne i z tym jakoś żyjemy.

Niestety. znacząca (jak nie większość) część postów nowicjuszy dotyczy problemów mocno już historycznych, a czasem nawet archeologicznych.
My naprawdę nie piszemy już od dawna w XMLu. Mimo to, jakimś cudem, startujący z javą magicznie trafiają na takie kursy i książki. Przyznam, że co któryś post to nawet jak chyba wiem gdzie leży WTF, to nie chce mi się odpisywać, jestem szczęśliwy, że już od lat się w tym nie babram i nie chcę wracać.

Może warto by jakoś umieścić listę ostrzeżen, technologii przestarzałych, których nie warto tykać na starcie? Nazywam je technologiami zombi, bo są martwe, choć nadal się ruszają.
Oczywiście, jest i będzie w nich nadal tony ofert pracy. Tysiące systemow na nich działa i będzie działać, ale po prostu NIE SĄ DOBRE NA START. Bo wyżerają mózgi - jak to zombiaki.

Jak ktoś się już nauczy jako tako programować, to da radę taką technologię też przyswoić, jeśli będzie musiał. Tak jak żołnierz w XXI wieku raczej nie zaczyna szkolenia od szermierki i jazdy konnej, żeby spokojnie dojść do hakownic i muszkietów, tak programista nie musi przechodzić przez wszelkie epoki historycznego rozwoju takiej javy.
Im bardziej nowocześnie się zacznie, tym lepiej. Mózg nie będzie obciążony bzdurami , które dawno już nie są prawdą. (jak np. używanie wszędzie getterówi setterów, bo stare frameworki wymagały, lub nadużywanie interfejsów).

# Konkret.
Mody programisto/programistko javy. Jeśli się uczysz programowania to omijaj następujące technologie

  1. JSF – nie, nie, nie, po stokroć, naprawdę nie. To wyjątkowo ZŁY framework webowy. Eksperyment nieudany.
  2. EJB – nie warto. Za dużo XMLa i nonsensownych komplikacji.
  3. JavaEE /Servlety i reszta – (przemianowane na Jakarta EE), trochę jak wyżej – po prostu najlepiej olać ten termin (taki Spring w częsci jest zgodny z JavaEE, ale po prostu lepiej uczyć się z podręcznika do Springa, niż z Java EE). Dodatkowo: jak książka/ tutorial używa sformułowania J2EE lub JEE (stare nazwy) to najlepiej dalej nie czytać, bo jest to już naprawdę tak stary zombiak, że inne zombiaki straszą nim swoje dzieci.
  4. GWT – to był bardzo ciekawy eksperyment, ale nie wyszedł. Męczący w codziennej pracy. Olej dla własnego dobra.
  5. Generalnie programowanie w XMLu. Nie nie robimy tego od dawna. Jak materiał zawiera opis jak to świetnie jest oddzielić konfigurację od programowania i pokazuje Ci tony XMLa to przestań czytać/oglądać. To dotyczy Springa w szczególności. Jest już Spring 5 (od września 2017), a wcześniej wiele lat Spring 4. Oba nie wymagają żadnego XMLa. Koniec. Nie trać czasu na nonsensy.
  6. Websphere/Jboss/Glassfishapplication serwery. Naprawde nie. Już tego sobie nie robimy.
    Tak naprawdę do tej listy wkrótce powinien dołączyć Tomcat, ale trzyma się jeszcze ciągle w mainstreamie. I jest mniej szkodliwy od powyższych.
  7. JSP – nie, nie bawimy się w to. JSPki nie są w sumie takie straszne, bo pokazują jak z javy zrobić PHP. Co ma nawet pewne zalety, bo można dokładnie tak samo szybko postawić proste stronki (powinien być konwerter kodu JSP<->PHP). Jakkolwiek, nie po to się bawimy w Javę, żeby robić z niej PHP! Po drugie primo, generowanie kodu HTML po stronie serwera jest passe. Robimy REST serwisy i do tego javascriptiowe single page application (w React,Angularze czy Vue, w zależności co akurat modne w danym tygodniu).
  8. Struts - nie. Nie wiem nawet, jak na to trafiłe(a)ś, ale nie.

Dywagacje dalsze

Nie wiem co tu jeszcze dołączyć? Jest oczywiście wiele przestarzałych technologii- takich jak np. OSGi, ale na szczęście nowi programiści raczej na to nie trafiają.
JavaFX czy Swing? – mam problem. Swing trochę przestarzały, JavaFX za to niszowy, ale uważam, że nie wyżerają mózgów i nawet trochę pomagają na starcie. Po prostu okazało się, że w javie nie robimy desktopów, ale jak ktoś się uprze to można się na takich aplikacjach całkiem dobrze nauczyć programowania.

jarekr000000

Dla uściślenia SOAP i XML przy wymianie danych to nic złego. Ja piłem tylko do programowania w XMLu (Spring 2.X i EJB 2.X - choć oczywiście niektórzy cisną te XMLe do dziś, bo w nowych wersjach nadal działają). Tomcat, mam do niego wąty ale na lipiec 2018 jeszcze nie można go wkładać do trumny, bo za dużo wierzga (aplikujemy pawulon, ale skubaniec twardy).

LukeJL
dziś, 11:26

Pro-tip: jeśli macie problemy z nazwaniem jakiejś klasy, możecie użyć thesaurusa. Wpisujecie słowo, które wam przychodzi do głowy, a które nie do końca pasuje, i patrzycie na podobne. W ten sposób przeszedłem dzisiaj od pomysłu nazywania klasy Recipe do pomysłu, żeby nazwać coś Formula https://www.thesaurus.com/browse/recipe?s=t - to jest fajne, bo można klikać te słowa i przechodzić do kolejnych.

furious programming
wczoraj, 04:46

Platformers coraz bogatszy. W poprzednim wpisie opisałem szczegóły dotyczące ruchu bohatera w pionie i poziomie, więc samo sterowanie miałem już przygotowane. Skupiłem się więc dziś na animowaniu postaci, tak aby przestała być jednokolorowym kwadratem na ekranie.


Pierwszą funkcją animacji bohatera jest chodzenie. Jak już wielokrotnie wspominałem, jednostką pomiaru czasu w silniku tej platformówki są klatki, a więc liczby całkowite – im dłużej ma dana czynność trwać, tym więcej klatek trzeba zliczyć. Tak więc aby móc animować chodzenie bohatera, należy liczyć klatki. Liczyć trzeba od momentu wciśnięcia przycisku ruchu w bok, a zakończyć po puszczeniu tego klawisza lub po spadnięciu z platformy. Ową animacją jest sinsunoidalne zatapianie i wynurzanie się ciała bohatera.

Wygląda to w ten sposób (trzy pierwsze unikalne, reszta dla podglądu, powiększenie trzykrotne):

walking.png

Każdy spajt z powyższej listy wyświetlany jest przez pięć kolejnych klatek, dzięki czemu animacja nie jest ani zbyt szybka, ani zbyt wolna. Aby wiedzieć o ile pikseli przyciąć grafikę, należy obliczyć resztę z dzielenia liczby klatek chodu przez liczbę faz przypadających na pełne zanurzenie i wynurzenie (czyli cztery), a następnie wynik podzielić przez liczbę klatek przypadających na pojedynczą fazę (w której rozmiar grafiki nie zmienia się – czyli pięć):

LWalkPhase := AHero.WalkFrameIndex mod (FRAMES_PER_HERO_WALK * FRAMES_PER_PHASE_HERO_WALK);
LWalkPhase := LWalkPhase div FRAMES_PER_PHASE_HERO_WALK;

W ten sposób uzyskuje się numer fazy chodu – faza pierwsza to brak zanurzenia, druga to zanurzenie o jeden piksel, trzecia o dwa piksele, a czwarta to znów o jeden piksel. Piąta jest równoznaczna z pierwszą – tu następuje zapętlenie animacji. Po obliczeniu rozmiaru przycięcia, wystarczy wyświetlić odpowiedzi fragment. Aby zrobić to prawidłowo, należy wziąć pod uwagę orientację bohatera (kierunek siły przyciągania).


Druga funkcja to rozciąganie bohatera podczas opadania. Tu klatek liczyć nie trzeba, albowiem stopień rozciągnięcia można wyznaczyć na podstawie prędkości wertykalnej – im większa prędkość, tym większe rozciągnięcie. Aby móc namalować rozciągniętego bohatera, należy obliczyć obszar jaki zajmować ma sprajt – a według tego co napisałem zdanie wcześniej, nie jest to trudne:

LArea := AHero.Location.Area;
LArea.Inflate(0, Abs(AHero.VerticalSpeed));

Po kilku minutach zabawy ustaliłem, że najlepiej wygląda bohater, gdy rozciągany jest w pionie wyłącznie wtedy, gdy faktycznie opada. Wznosząc się podczas skoku nie zmienia rozmiaru, po zakończeniu skoku (ale wciąż wznosząc się) też nie – dopiero kiedy osiągnie maksymalną wysokość i prędkość zacznie rosnąć zgodnie z grawitacją. Animacja samego opadania wygląda w ten sposób:

falling.png


Trzecią funkcją jest… mruganie oczkami. ;)

I znów, aby wiedzieć kiedy mrugać a kiedy nie, należy liczyć klatki. Na szczęcie najfajniej jest, gdy klocek mruga bez względu na wykonywaną akcję (stoi, idzie, skacze, spada itd.), więc wystarczy w kółko inkrementować licznik klatek i tak jak przy chodzeniu, obliczać fazę mrugnięcia, aby dało się wybrać odpowiedni sprajt dla animacji.

Mrugnięcie też składa się z czterech faz – pierwsza to otwarte oczy, druga to przymrużone, trzecia to zamknięte, a czwarta to znów przymrużone. Piąta jest taka sama jak pierwsza – animacja zapętla się. Duszki wyglądają tak (trzy pierwsze są unikalne – dalsze tylko dla podglądu):

winking.png

Obliczenie fazy mrugnięcia jest identyczne jak w przypadku liczenia fazy chodu, natomiast odstępy pomiędzy mrugnięciami nie są stałe, bo wyglądało by to tandetnie… Dlatego liczba klatek pomiędzy mrugnięciami jest losowana. Aby klocek mrugał raz częściej, a raz rzadziej, zamiast po prostu losować liczbę klatek z zadanego przedziału, losuję wartość od 4 do 8 i na jej podstawie przesuwam bitowo wartość 1:

FWinkWaitFrames := 1 shl RandomRange(4, 9);

To daje wartości 16, 32, 64, 128 lub 256, a więc bohater czasem mignie kolejny raz po 266ms, a czasem dopiero po kilku sekundach. Rozwiązanie trywialne, a finalny efekt bardzo ładny, bo nieprzewidywalny.


Czwartą i ostatnią funkcją jest mała modyfikacja wcześniej opracowanego efektu rozciągania podczas opadania. W trybie debugowania można w dowolnym momencie odwrócić kierunek grawitacji, natomiast w trybie standardowym, tylko jeśli bohater znajduje się na bramce i trzyma odpowiedni klawisz. Bramki mogą być również w powietrzu, więc możliwe jest odwrócenie siły przyciągania podczas opadania, a więc wtedy, gdy bohater ma rozciągnięte ciało. Aby animacja rozciągania wyglądała dobrze, trzeba było dodać również animację kurczenia.

To nieco utrudniło sprawę, bo bohater musiał być rozciągany nie tylko podczas opadania, ale także podczas wznoszenia, co było zablokowane ze względu na dwie pierwsze fazy skoku, w których rozmiar ciała bohatera miał być stały. Dlatego też trzeba było dodać nowy parametr (wartość logiczną), w którym zapisywana jest informacja o tym, czy klocek wznosi się po skoku. Jeśli po skoku to nie zmienia się długości jego ciała, a jeśli nie – zmienia się.


Animacji tyle, a teraz czas na malowanie grafik. Pomimo tylu różnych funkcji, bohatera opisują zaledwie trzy sprajty, a konkretniej te z fazami mrugania – pierwsza z otwartymi oczami, druga z przymrużonymi, a trzecia z zamkniętymi. Rozciąganie jego ciała to nic innego jak namalowanie rozciągniętej grafiki.

Pewnie się zastanawiacie, co z kierunkiem ruchu i orientacją według grawitacji. A no nic – grafikę można flipnąć w poziomie dla ruchu w lewo, a w pionie dla przyciągania w górę. Do tego celu napisałem dwie proste procedurki, dzięki którym nie muszę tworzyć kolejnych duszków:

type
  TRGBTriple = packed record
    B, G, R: UInt8;
  end;
 
type
  PRGBTripleArr = ^TRGBTripleArr;
  TRGBTripleArr = packed array [0 .. MaxInt div SizeOf(TRGBTriple) - 1] of TRGBTriple;
 
procedure FlipBufferHorizontal(ABuffer: TBitmap);
var
  LLine: PRGBTripleArr;
  LLineIndex, LPixelIndexLeft, LPixelIndexRight: Integer;
var
  LPixel: TRGBTriple;
begin
  ABuffer.BeginUpdate();
 
  for LLineIndex := 0 to ABuffer.Height - 1 do
  begin
    LLine := ABuffer.ScanLine[LLineIndex];
 
    LPixelIndexLeft := 0;
    LPixelIndexRight := ABuffer.Width - 1;
 
    while LPixelIndexLeft < LPixelIndexRight do
    begin
      LPixel := LLine^[LPixelIndexLeft];
      LLine^[LPixelIndexLeft] := LLine^[LPixelIndexRight];
      LLine^[LPixelIndexRight] := LPixel;
 
      LPixelIndexLeft += 1;
      LPixelIndexRight -= 1;
    end;
  end;
 
  ABuffer.EndUpdate();
end;
 
procedure FlipBufferVertical(ABuffer: TBitmap);
var
  LLineTop, LLineBottom: PRGBTripleArr;
  LLineIndexTop, LLineIndexBottom, LPixelIndex: Integer;
var
  LPixel: TRGBTriple;
begin
  ABuffer.BeginUpdate();
 
  LLineIndexTop := 0;
  LLineIndexBottom := ABuffer.Height - 1;
 
  while LLineIndexTop < LLineIndexBottom do
  begin
    LLineTop := ABuffer.ScanLine[LLineIndexTop];
    LLineBottom := ABuffer.ScanLine[LLineIndexBottom];
 
    for LPixelIndex := 0 to ABuffer.Width - 1 do
    begin
      LPixel := LLineTop^[LPixelIndex];
      LLineTop^[LPixelIndex] := LLineBottom^[LPixelIndex];
      LLineBottom^[LPixelIndex] := LPixel;
    end;
 
    LLineIndexTop += 1;
    LLineIndexBottom -= 1;
  end;
 
  ABuffer.EndUpdate();
end;

To wszystko – z finalnego efektu jestem bardzo zadowolony. Wisienką na torcie była zmiana sposobu malowania tła poziomu w kolorze – zamiast wypełniać je jednym kolorem, teraz wypełniane jest subtelnym, wertykalnym gradientem (ostatni załącznik).

Następne w kolejce do animowania są świetliki, czym zajmę się jutro. Póki co jeszcze nie wiem dokładnie jak mają wyglądać, ale na pewno też będą mrugać swoimi świecącymi zadkami, tak samo nieregularnie jak bohater mruga oczami. Na szczęście pomysłów nie brakuje. Do następnego. ;)

#free-pascal #lazarus #platformer #retro

furious programming

Odwrócenie kierunku siły przyciągania to zmiana wartości jej określającej (liczba ta znajduje się w klasie poziomu) oraz zmiana orientacji bohatera (enum w klasie bohatera). Z logiki to tyle – za wygląd klocka na ekranie odpowiada jego renderer (o tym niżej).

Bohatera opisują trzy sprajty o takim samym rozmiarze, różniące się wyłącznie wyglądem oczu (patrz: trzy pierwsze sprajty w trzecim załączniku) – tak więc faza mrugnięcia jest kluczowa. Sprajty posiadają bohatera odwróconego w prawo, ”nogami” do dołu. Namalowanie bohatera na ekranie realizowane jest w kilku krokach:

Obliczenie obszaru bohatera

Pobiera się obszar hitboxu bohatera (zawsze o rozmiarze 14x16 pikseli, tyle samo ile rozmiar sprajtów), następnie sprawdza się czy bohater idzie i jeśli tak, oblicza się fazę chodu i odpowiednio skraca się obszar w pionie, na podstawie jego orientacji pionowej, a jeśli spada to na podstawie prędkości wertykalnej rozciąga się obszar w pionie. W innych przypadkach (np. gdy stoi, wznosi się itd.), rozmiar obszaru jest zgodny z hitboxem.

Przeliczenie pozycji obszaru

Z absolutnego (globalnego, według pozycji na planszy) na relatywny, według pozycji kamery. Wynikiem są współrzędne zgodne z buforem ramki (gdzie lewy górny róg to punkt 0,0).

Wybranie sprajtu

To realizuje się na podstawie fazy mrugnięcia. Jeśli bohater nie mruga to bierze się sprajt, na którym klocek ma otwarte oczy.

Przycięcie sprajtu

Jeśli bohater idzie to obliczana jest faza chodu, następnie obliczana jest liczba pikseli przycięcia, a na koniec sama grafika zostaje przycięta z dołu. Na tym etapie duszek nadal stoi nogami do dołu, więc zawsze przycina się mu umowne nogi.

Określenie kierunku w poziomie

Domyślnie sprajt zawiera klocka patrzącego w prawo, więc jeśli bohater pzesuwa się w lewo, to grafikę odbija się horyzontalnie za pomocą procedury FlipBufferHorizontal, której kod umieściłem we wpisie.

Określenie kierunku w pionie

Jak wyżej, tyle że sprawdza się czy bohater przyciągany jest w górę i jeśli tak, za pomocą procedury FlipBufferVertical odbija się grafikę w pionie. Kod procedury pod koniec wpisu.

Namalowanie sprajtu na buforze ramki

Mamy obliczony obszar, mamy też wybraną grafikę, teraz wystarczy Canvas.StrechDraw i gotowe. Ta metoda jest kluczowa, bo pozwala na namalowanie rozciągniętej grafiki, a to konieczne w przypadku, gdy bohater opada z większą prędkością (wtedy obliczony obszar ma większą wysokość niż 16px).

To wszystko, jeśli chodzi o namalowanie bohatera znajdującego się na planszy. Wygląda jakby było to skomplikowane, jednak kodu wcale nie jest dużo. Natomiast jeśli trzeba by wyświetlić bohatera nie na planszy, a w konkretnym, stałym miejscu (np. w lewym górnym rogu ekranu, z liczbą żyć) to wystarczy pobrać obszar, pobrać sprajt i go namalować – niczego nie trzeba obliczać.

Kod metod renderera wrzucam na pastebin – zobacz sobie.


Teraz warstwy poziomu. Obraz poziomu składa się z kilku elementów:

  1. Jednokolorowe tło (na zrzucie: niebieskie),
  2. Warstwa najdalsza – dużo większy fragment, zeskalowany, 33% ciemniejsza od koloru tła,
  3. Warstwa środkowa – nieco większy fragment, zeskalowany, 66% ciemniejsza od koloru tła,
  4. Warstwa najbliższa – fragment o rozmiarze obszaru kamery, 100% ciemniejsza od koloru tła (czyli zawsze czarna).

Podczas animacji zmiany warstwy, malowane są cztery warstwy zamiast trzech.

Jeśli przełączamy się do warstwy wgłąb, najbliższa (czarna) skalowana jest w górę (coraz większy zoom), aż do zniknięcia, cały czas w kolorze czarnym, a warstwa która widoczna nie była, stopniowo wyłania się z tła, płynnie zwiększając przyciemnienie od 0% do 33%.

Jeśli przełączamy się do warstwy bliższej, ta o jeden bliższa od obecnie najbliższej skalowana jest w dół (coraz mniejszy zoom), cały czas będąc czarną, a ta najdalsza powoli zanika, zmniejszając płynnie przyciemnienie od 33% do 0%. Animacja przełączania warstwy trwa 15 klatek, a więc 250ms.

Tłem jest „subtelny gradient”, w którym kolor u góry jest zgodny z bazowym kolorem tła, a dolny jest nieco ciemniejszy od bazowego. Różnica jasności u góry i u dołu jest bardzo mała, dlatego na pierwszy rzut oka niewidoczna. Skopiuj sobie ten obraz np. do Painta i spróbuj wypełnić najjaśniejsze obszary – nie wypełnisz całych obszarów, a tylko wąskie pasy.

Gradient nie może być dużo ciemniejszy na dole, bo podczas przełączania warstwy, ta wizualnie najdalsza pojawia się ”znikąd”, zwiększając przyciemnienie względem bazowego koloru tła od 0% do 33%. W takim przypadku pojawiająca się warstwa, na dole ekranu (a więc na ciemniejszej części gradientu) była by jaśniejsza od tła, powodując bardzo brzydko wyglądające mignięcia. A wszystkie warstwy muszą być ciemniejsze od koloru tła – takie jest założenie.


Taki opis wystarczy, czy jeszcze coś chcesz wiedzieć? ;)

furious programming

@cerrato: w razie czego tutaj masz nagranie z ruchu kamery po planszy, łącznie z pokazaniem efektu zmiany warstwy na bliższą lub dalszą. Więcej informacji na temat tego nagrania oraz renderowania poziomów znajdziesz we wcześniejszym wpisie.