Co nowego na forum?

Roter WIFI Społeczność 21 minut temu
openSSL Hardware/Software dziś, 10:02
Socket TCP PHP dziś, 09:33

miszasty93 dodał wątek Britenet - nowe opinie ?

14 sekund temu Cześć, szukałem informacji na temat Britenet - ostatni wątek z głównie negatywnymi k...

nalik dodał post w Socket TCP

3 minuty temu Nie piszę w PHP, ale widzę, że masz błąd w skrypcie. Dla pojedyńczego połączenia acc...

Shalom dodał post w Dyski SSD do pracolaptopa - faktyczny zysk, czy efekt placebo?

5 minut temu Jest różnica. Szczególnie jak IntelliJ zacznie indeksować jakiś duż projekt ;]

hauleth dodał post w Najprostszy managaer MIkrousług

6 minut temu W takim wypadku ja bym użył Consul + Nomad. Pierwsze jako registry oraz service disc...

WyjmijKija dodał komentarz w Dyski SSD do pracolaptopa - faktyczny zysk, czy efekt placebo?

6 minut temu Fragmentacja jest, tylko nie ma znaczenia

Koziołek dodał komentarz w Spotkanie 4p Wrocław

7 minut temu Weź gości jak ci leżą na wątrobie, już nigdy ich nie spotkasz

Burdzi0 dodał komentarz w Czy trzeba zdać OCA, aby podejść do OCP?

7 minut temu @cerrato: nie ogarnąłem xd

Koziołek dodał post w Java - multithreading

8 minut temu Uwaga co do JCiP. Książka jest aktualna i jedynie nie zawiera informacji o rzeczach...

grzesiek51114 dodał post w Spotkanie 4p Wrocław

10 minut temu W tym tygodniu niestety nie mogę. Mam cały tydzień zajęty gośćmi.

Koziołek dodał komentarz w Java - multithreading

11 minut temu Tru

alagner dodał komentarz w Przekwalifikowanie na DevOpsa

13 minut temu kilkunastoletni system soft-rt sterujący automatyką się na to łapie? ;P

ThisIsHowIRoll dodał komentarz w Java - multithreading

14 minut temu @Koziołek: nie pomyliło Ci się z effective Java 3rd edition, bo odświeżonej JCiP nie...

xxx_xx_x dodał komentarz w Czy to normalne, że nie jem śniadania?

15 minut temu To nieregularność posiłków i głodzenie się może doprowadzić do problemów, nie sam br...

somekind dodał post w c# jak zapisać dane w tabeli?

16 minut temu Pewnie zapisuje tylko bazę danych masz w katalogu debug aplikacji i po ponownej komp...

abrakadaber dodał komentarz w Wykrycie zdalnej kontroli nad programem

16 minut temu a jakie to jest "podejrzane" połączenie?

abrakadaber dodał post w Roter WIFI

21 minut temu czy możesz to już masz napisane w umowie z dostawcą - jeśli się zgodziłeś na taki za...

leonpro778 dodał post w Roter WIFI

21 minut temu Moim zdaniem nie może Ci zabronić korzystania z WiFi. Przeczytaj w umowie czy masz t...

somekind dodał komentarz w CV ze zdjęciem czy bez?

21 minut temu Przez ten teledysk? Nie ściągaj filmów z ruskich torrentów, oni tam często podmienia...

grzesiek51114 dodał post w OpenGL - poczatki sa trudne - nic sie nie rysuje na ekranie

21 minut temu Ale pytanie jak to wszystko spamiętać? Spamiętać to raczej nie spamiętasz. Wydaje mi...

Spine dodał komentarz w Roter WIFI

25 minut temu Hardware...

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 :)

grzesiek51114
wczoraj, 01:04

Ostatnio pisząc projekt w WPF miałem do zebrania dane z około piętnastu, dość dużych kontrolek typu UserControl. W celu zebrania danych, do każdej kontrolki wysyłany jest odpowiedni event za pomocą Prism'a. Kiedy viewmodel takiej kontrolki odbierze event to w odpowiedzi zaczyna propagację innego eventu Prisma, służącego do przesyłu konkretnych danych. Ot komunikacja na zasadzie Request => Response.

Gdzieś te wszystkie eventy z danymi trzeba odebrać
Gdzieś musi być jakiś punkt, w którym zbierze się wszystkie te dane i przetworzy jakoś, np. w celu zapisania ich do bazy danych.

Jest w projekcie taka klasa, która zbiera wszystko razem, subskrybując eventy przesyłające dane z każdej z piętnastu kontrolek.
Tutaj pojawia się problem. Jak wiadomo piętnaście eventów Prism to także piętnaście tokenów subskrypcji, które to trzeba użyć do desubskrybowania eventu.

Można robić to za pomocą prywatnych pól, do których przypinać będziemy odpowiednie eventy, aby później je desubskrybować:

private SubscriptionToken eventToken;
...
// Np. w komendzie bindującej zdarzenie `Loaded` etc...
// Metoda Subscribe zwraca token używany później do desubskrybowania eventu.
eventToken = eventAggregator.GetEvent<PrismEvent>().Subscribe(/* metoda */);
...
// Np. w metodzie desubskrybującej eventy.
eventAggregator.GetEvent<PrismEvent>().Unsubscribe(eventToken);

Jednakże kiedy takich tokenów nazbiera się piętnaście to takie rozwiązanie już nie jest super, bo napisać się trzeba niepotrzebnego kodu co niemiara. Jak wspomniałem, jeden event równa się z zautomatu jednemu tokenowi, za pomocą, którego należy wykonać jedno desubskrybowanie. No, masakra ogólnie.

Wymyśliłem jednak rozwiązanie, które umieściłem a klasie ViewModelBase, po której dziedziczą wszystkie viewmodele w projekcie.

Co wiemy:

  • Wiadomo, że każdy event Prism'a musi dziedziczyć po klasie PubSubEvent lub PubSubEvent<T>, a te z kolei po EventBase Mamy więc wspólnego przodka dla wszystkich typów eventów;
  • Wiadomo także, że każdy token jest typu SubscriptionToken.

A gdyby tak skojarzyć event z tokenem za pomocą słownika w klasie bazowej wszystkich viewmodeli Prism'a?
Co nam to da?

  • Nie musimy deklarować prywatnego pola typu SubscriptionToken w viewmodelu per event;
  • Nie musimy realizować ręcznie desubskrybcji eventu per każdy token;
  • Mamy w słowniku event od razu skojarzony ze swoim tokenem;
  • Dzięki takiemu słownikowi desubskrybowanie wszystkich eventów realizuje tak naprawdę jedna pętla.
    public class ViewModelBase : BindableBase
    {
        protected IDictionary<EventBase, SubscriptionToken> subscriptions;
 
        public ViewModelBase()
        {
            subscriptions = new Dictionary<EventBase, SubscriptionToken>();
        }
 
        public void Unsubscribe()
        {
            foreach (var s in subscriptions)
            {
                s.Key.Unsubscribe(s.Value);
            }
        }
    }

Jak to wygląda w klasie, która będzie dziedziczyć po ViewModelBase? Prosto, starczy dodać do niej tylko taki, przykładowy wpis subskrypcji jakiegoś zdarzenia, np. PrismEvent:

subscriptions.Add(
    eventAggregator.GetEvent<PrismEvent>(),
    eventAggregator.GetEvent<PrismEvent>().Subscribe(/* metoda */));

I już niczego więcej nie trzeba robić, bo w takim viewmodelu wszystko zostanie zrealizowane automatycznie, za pomocą słownika. Naturalnie można to jeszcze bardziej ulepszyć np. w taki sposób żeby metody GetEvent nie wywoływać dwa razy, jednakże jest to w sumie kosmetyka. Najważniejsze jest to, że teraz każdy viewmodel w projekcie Prism posiada automat spinający tokeny z eventami i realizujący ich desubskrybowanie.

Cel został osiągnięty; dopinanie zdarzeń jest szybkie, a viewmodel czysty.

#prism #wpf #pubsubevent

stryku
wczoraj, 12:09

Ostatnio miałem dość napięty harmonogram wszystkiego. Żeby nie wypaść z formy zjadałem tabsy np. magnez.
Któregoś dnia złapałem się na tym, że popijałem wyżej wspomniany magnez kawą.
Myślę, że poczuł się on tak

Madness

Jakby na to nie patrzeć to yerba jest "kuzynem" herbaty.

cerrato

@madness: A obecnie żyjące ptaki są potomkami dinozaurów :P

furious programming
2018-07-21 17:21

W poprzednim wpisie napisałem co nieco na temat wyglądu, zachowania i implementacji ruchu głównego bohatera, natomiast w tym napiszę co nieco na temat świetlików, których zbieractwem poniekąd trudnić się będzie nasz klocek.


Zacznijmy od wymagań. Celem bohatera w mojej demówce będzie przemierzanie wielowarstwowych poziomów. Każdy poziom będzie mniej lub bardziej zagmatwanym labiryntem, posiadającym punkt startowy i co najmniej jeden punkt końcowy. Samo szwędanie się po planszy było by nudne, więc zadaniem pobocznym będzie gromadzenie świetlików, rozrzuconych po całym poziomie. Pewna ich część będzie łatwodostępna (na zachętę), natomiast inne będą poukrywane w taki sposób, aby trzeba było nieco pogłówkować – dostać się do nich poprzez ukryte w ścianie przejście, z poziomu innej warstwy lub za pomocą odwracania grawitacji. Ich wygląd musi przykuwać uwagę – nie mogą to być elementy statyczne, więc trzeba użyć animacji.


Talentu artystycznego raczej nie mam, więc postanowiłem, że świetlik będzie po prostu kulką ”światła”. Aby przykuwał uwagę, światełko powinno co jakiś czas migać. Świecić, gasnąć, świecić, gasnąć – różne interwały, różne jasności, co wybrać… Przetestowałem różne animacje i wyszło na to, że najlepiej świetlik wygląda wtedy, gdy cały czas świeci pełną jasnością, a co jakiś czas na chwilkę przygasa.

W rezultacie powstały trzy sprajty, opisujące wygląd światełka (powiększenie czterokrotne):

firefly sprites.png

Jak wspomniałem wyżej, aby stworzyć złudzenie przygasania światełka, przez większą część animacji wyświetlany jest ostatni sprajt, ten z dużą, białą kulką. Pozostałe dwa malowane są tylko przez kilka klatek samego mrugnięcia:

firefly animation.png

Przypomina Wam to coś? W ten sam sposób obsługiwana jest animacja mrugania bohatera – w niej zwykle wyśwetlany jest klocek z otwartymi oczami, a raz na jakiś czas wyświetla się dwa pozostałe sprajty w odpowiedniej kolejności, poczas faktycznego mrugania.


Miganie światełek gotowe, ale to wciąż mało – świetliki zwykle nie lewitują w stałym miejscu, dlatego też przyda się subtelny ruch. Niewielki, o małej prędkości, aby nie denerwował oka. Biorąc pod uwagę to, że świetlik fizycznie powinien znajdować się wewnątrz obszaru danej kafli poziomu, wybrałem kilka prostych ścieżek ruchu:

  • wyłącznie w osi pionowej – lekko wznosi się, następnie opada, znów znosi się i znów opada,
  • ruch po ścieżce okrąkłej lub owalnej,
  • ruch po ścieżce w kształcie ósemki lub symbolu nieskończoności.

Wyszło mi, że najfajniej świetlik wygląda, jeśli przesuwa się po ścieżce okrągłej. Teraz implementacja.


Pozycją bazową świetlika są współrzędne określające środkowy piksel danej kafli poziomu (pseudośrodkowy, bo kafle są rozmiaru 16x16 pikseli). Bazowa pozycja nigdy się nie zmienia – ona będzie wykorzystywana do sprawdzania kolizji z bohaterem. Bieżący sprajt świetlika wyświetlany jest w zadanej odległości od punktu bazowego, dzięki czemu:

  • nie muszę tworzyć wielu sprajtów z różnym odchyleniem od punktu centralnego,
  • krótki kod logiki wyliczającej offset mogę przenieść do renderera (to samo zrobiłem w przypadku animacji zatapiania i wynurzania bohatera podczas jego chodzenia po platformie),
  • mogę kalibrować prędkość ruchu oraz promień ścieżki modyfikując kilka stałych (szybko i wygodnie),
  • w dowolnym momencie mogę zmienić kształt ścieżki, bez konieczności modyfikowania kolekcji sprajtów.

Wynikiem powyższego są wyłącznie trzy sprajty, różniące się ”jasnością” (w konsekwencji czego: wielkością kulki), kilka linijek kodu wyliczania kąta i offsetu umieściłem wewnątrz klasy renderera świetlików oraz zadeklarowałem kilka stałych z parametrami animacji. Aby nieco urozmaicić animację, dodałem jeszcze jeden parametr – kierunek ruchu. Świetlik może krążyć zgodnie lub przeciwnie z ruchem wskazówek zegara, albo nie krążyć wcale (to na potrzeby licznika świetlików, który wyświetlany będzie w lewym górnym rogu ekranu).


Kalibracja ruchu po okręgu znów pochłonęła trochę czasu – nie mogłem się zdecydować. Ostatecznie ustaliłem, że animacja uwzględniać będzie 30 różnych kątów odchylenia od kąta , pod każdym z tych trzydziestu kątów świetlik wyświetlany będzie prez 8 klatek (co daje pełne okrążenie w 240 klatek, czyli w cztery sekundy), natomiast promień wynosić będzie 2 piksele.

Jeśli o animację świecenia i przygasania chodzi, to postąpiłem pobodnie jak w przypadku mrugania – liczba klatek pełnego świecenia jest losowana i przeliczana na wartości 16, 32, 64, 128 lub 256, natomiast czas wyświetlania każdego sprajtu to 4 klatki. Czas trwania samej animacji przygaścięnia to 12 klatek, czyli 200ms.

Gotowy efekt fruwania i migania świetlików oraz mrugania bohatera tutaj – fireflies.webm


Mniej istotnym, ale mimo wszystko ważnym nowym ficzerem jest implementacja martwego pola kamery. Poruszanie się bohatera w obrębie tego pola nie powoduje przesuwania kamery, dzięki czemu rozgrywka wygląda jakoś ładniej. Ogólnie dead zone nie może być zbyt duży, bo gdyby tak było, to kamera przesuwałaby się tylko wtedy, gdy bohater podejdzie blisko bocznej krawędzi lub gdy mocno zbliży się do górnej/dolnej. To skutecznie utrudniłoby rozgrywkę, dlatego że na ekranie wyświetlany byłby tylko niewielki obszar poziomu, przez co nie wiadomo by było czy np. daną przepaść da się przeskoczyć, lub czy można spaść z platformy i w przepaść nie wpaść (masło maślane).

Niektóre stare platformówki niestety ale tak działały i przesuwały kamerę po znacznym zliżeniu się do krawędzi ekranu – np. Earthworm Jim na SNES-a. Niektóre gdy robiły to inaczej – kamera była ustawiana według kierunku ruchu w poziomie. Tak było to zrealizowane w grze Pitfall: The Mayan Adventure, na tę samą platformę. Uważam, jest to bardzo dobre rozwiązanie.

Możliwych funkcji kamery jest znacznie więcej – można bohatera centrować w kamerze, ale dać możliwość rozglądania się (czyli przesuwania samej kamery we wszystkich kierunkach), można też dynamicznie zwiększać/zmniejszać offset kamery od bohatera podczas trwania ciągłego ruchu (np. im dłużej bohater idzie, tym bardziej dosuwa się go do przeciwnej krawędzi ekranu). Ten pierwszy efekt był w niektórych grach wykorzystywany – np. w grze Aaahh!!! Real Monsters można było użyć grubasa do wystrzelenia jego oka w dowolnym kierunku, co skutkowało przykuciem kamery do niego (oka) i zobaczeniem co jest dużo dalej od bohatera, a za pomocą strzałek dodatkowo umożliwić odsunięcie kamery od oka. Śmieszne rozwiązanie, ale cholernie pomocne podczas eksploracji poziomów i szukania zaułków ze specjalnymi przedmiotami.

Sam jednak ograniczę się do niewielkiego martwego pola, bo już czas na deadline.


Animowanie i wyświetlanie różnych obiektów jest gotowe, sterowanie i klawiszologia także. Teraz pozostaje dodać wykrywanie kolizji bohatera ze świetlikami i aktualizowanie liczników. Po tym będzie już można stworzyć menu i outro, a następnie zabrać się w końcu za tworzenie konkretnych poziomów gry, co będzie ostatnim krokiem na drodze do wydania tej demówki. ;)

#free-pascal #lazarus #platformer #retro

Shizzer
2018-07-21 17:21

Na moim blogu znów zawitał kolejny post z serii rozwiązywania zadań w kategorii Reverse Engineering.

Pochodzi ono z tego mini CTFa - https://pwning2017.p4.team/. Rozwiązałem je już wcześniej, ale dopiero teraz mam czas żeby pouzupełniać wpisy na blogu. Ogólnie postarałem się opisać problem jak najkrócej, ale w kierunku tych mniej doświadczonych pasjonatów więc otarłem się również o wytłumaczenie niektórych instrukcji z języka Assembly. Jeśli ktoś byłby ciekawy to oto link - https://shizz3r.blogspot.com/[...]uber-keygen-reverse.html#more

Niedługo na blogu powinna pojawić się postów stricte programistyczna, natomiast będzie to opis mojej drogi od początku do końca projektu, a nie eksperckie wywody. Projekt, który będę realizował to interpreter języka Brainfuck - będzie on jednak pisany w języku C w oparciu o Linked Listy i samodzielnie zaimplementowany stos. Z tym, że będzie to mój pierwszy "większy" program napisany w oparciu o wskaźniki.

Na blogu pojawią się również rozwiązania trzech zadań z tego linku - https://hack.cert.pl/challenges. Dwa zadania rozwiązałem w czasie konkursu, jedno już po ogłoszeniu wyników. (przedział wiekowy Junior) Mogę zdradzić, że kategorie tych zadań to: RE, Web i pwn.

Zapraszam więc do czytania, przy czym zaznaczam, że nie piszę bloga "okiem eksperta". Piszę bloga jako uczeń dlatego jeśli zauważycie, że coś robię nie tak jak powinienem to byłbym wdzięczny za każdą konstruktywną krytykę. :)