Animowane przejście loga w prostej grze

Animowane przejście loga w prostej grze
D1
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:165
0

Witam. Jestem tu nowy. Uczę się pisząc jakiś program. Czasami jestem w stanie zrobić coś sam, czasami szukam w internecie. Pierwszy raz mi się zdarzyło, że sam nie potrafię sobie poradzić. Jaki mam problem? Zabieram się pewnie za coś co przekracza moje umiejętności, ale nie szkodzi mi spróbować. A więc próbuje napisać małą grę. O ile wszystko mam zaplanowane i już wcześniej testowane różne mechanizmy to teraz chciałbym zacząć pisać wszystko jakby od początku już dodając interfejs. Tak na prawdę na samym początku mam pewien problem. Oczywiście to co chce zrobić nie jest potrzebne, obejdzie się bez tego, ale chciałbym żeby było efektywniej. Ma to wyglądać tak: po włączeniu programu ma być czarny ekran przez 1, 2 sekundy. Później od lewej strony ma wjeżdżać tło. Będąc na środku ma się zatrzymać na chwilę. W tym momencie ma się pojawić logo. Przez 2 sekundy ma tak być, a później wszystko w drugą stronę. Logo ma zniknąć, a tło przejść w prawą stronę. Po zniknięciu ma być czarny ekran przez chwilę po czym ma pojawić się menu.

Próbowałem to zrobić z użyciem zegara, który jest uruchamiany w zdarzeniu onCreate całego programu. Próbowałem też użyć delay(2000). O ile tło wjeżdża prawidłowo i zatrzymuje się to nie wiem co zrobić dalej. W momencie wjechania na odpowiednie miejsce ustawiam clock.enabled na false. Później chciałbym odczekać te dwie sekundy za pomocą delay. Ale wtedy to wgl nie chce się uruchomić. poza tym później, żeby tło wyjechało trzeba uruchomić zegar ponownie, a z tym już mam problem.
Możecie mnie jakoś naproawdzić?
Wielkie dzięki

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:2 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
1

Wszystko możesz wykonać za pomocą jednego Timera - wystarczy chwilę pomyśleć;

Jak rozumiem najpierw ma być czarne tło, następnie logo wjeżdża, zatrzymuje się na dwie sekundy, następnie logo wyjeżdża i znów zatrzymuje się na dwie sekundy; Zrób więc Timer, który będzie miał mały interwał - będzie on określał ilość klatek na sekundę, np. Timer.Interval = 40 da 25 klatek na sekundę, czyli powinno być płynnie; Niech ten Timer korzysta z licznika, czyli zmiennej liczbowej, którą będzie inkrementować w każdym wywołaniu zdarzenia OnTimer; Współrzędne grafiki loga albo trzymaj w jakiejś tablicy, albo obliczaj na bieżąco, na podstawie wartości licznika;

Teraz w zdarzeniu OnTimer przed inkrementacją licznika sprawdzaj w instrukcji Case wartość licznika i wykonuj odpowiednią operację - albo czekaj, albo przesuwaj grafikę w określoną stronę:

Kopiuj
case intCounter of // intCounter to licznik
  0   .. 49:  { wstępne czekanie dwie sekundy na wjazd loga } ;
  50  .. 74:  { przesuwanie grafiki loga z lewej na środek  } ;
  75  .. 124: { oczekiwanie dwie sekundy z logiem na środku } ;
  125 .. 149: { przesuwanie grafiki loga ze środka na prawą } ;
  150 .. 199: { końcowe czekanie dwie sekundy na menu       } ;
  200:        { wyłączenie zegara                           } ;
end;

Inc(intCounter);

Najtrudniejsze będzie przesuwanie loga, ale to zwykła arytmetyka na poziomie podstawówki, więc na pewno sobie poradzisz.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 4x, ostatnio: flowCRANE
_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
1

Aktualny stan animacji możesz zapisać do osobnego pola klasy lub np do clock.Tag wyłączaj zegar dopiero kiedy w całości skończysz animacje, w pozostałych przypadkach jedynie przestawiaj Interval.


Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
D1
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:165
0

Dzięki wielkie, dopiero teraz tak całkiem zrozumiałem działanie zegara. Ja próbowałem to zrobić tak jakby wszystko za jednym "przejściem". Ale zamiast Case użyłem If. Czy to jest jakiś duży błąd czy też może zostać?

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:2 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
1

Ja próbowałem to zrobić tak jakby wszystko za jednym "przejściem".

W ten sposób to nie zadziała jak należy, a nawet jeżeli udałoby Ci się tak zrobić, to Timer byłby zbędny;

Timer odlicza mniej więcej określoną ilość czasu (ustaloną we właściwości Interval) i każdorazowo po upływie zadanej ilości czasu, wykonuje kod ze zdarzenia OnTimer; Albo używaj Timera do odliczania "klatek", albo zmieniaj mu Interval; Odliczanie ilości klatek można tak łatwo wykonać, jak pokazałem w swoim poprzednim poście; Zmiennym interwałem można zastąpić oczekiwanie tych kilku sekund na wjazd/wyjazd loga i na zatrzymanie loga na środku ekranu; Zrób jak chcesz, byle by działało i nie blokowało interfejsu;

Ale zamiast Case użyłem If. Czy to jest jakiś duży błąd czy też może zostać?

Można, tyle że w zależności od wybranego sposobu może z nich wyjść cała drabinka, którą skrócić można właście instrukcją wyboru (Case);

Jak znajdę chwilę to pokażę implementację sposobu, który opisałem wczesniej.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
D1
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:165
0

Działać działa tak jak chciałem, więc jest wszystko ok. Rozwiązanie było proste, a ja próbowałem na około. Dziękuję raz jeszcze.

Kopiuj
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls;

type

  { TGra }

  TGra = class(TForm)
    ImageLogo: TImage;
    ImageTloStart: TImage;
    PanelWstep: TPanel;
    TimerWejscie: TTimer;
    procedure FormCreate(Sender: TObject);
    procedure TimerWejscieTimer(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
    SzerokoscTla: Integer;
    WysokoscTla: Integer;
    SzerokoscLoga: Integer;
    WysokoscLoga: Integer;
    LicznikTimerWejscie: Integer;
  end;

var
  Gra: TGra;

implementation

{$R *.lfm}

function GetImageSize (const Path: string; Height: boolean = False): integer;
var Image: TImage;
begin
  if ExtractFileExt(Path) <> '' then
    try
      Image := TImage.Create(nil);
      Image.Picture.LoadFromFile(Path);
      if not Height then
        Result := Image.Picture.Width
      else
        Result := Image.Picture.Height;
    finally
      Image.Free;
    end;
end;

procedure WczytajRozmiarTla;
begin
  Gra.SzerokoscTla := GetImageSize('backgrounds/background1full.png');
  Gra.WysokoscTla := GetImageSize('backgrounds/background1full.png', True);
end;

procedure WczytajRozmiarLoga;
begin
  Gra.SzerokoscLoga := GetImageSize('logos/mainlogo.png');
  Gra.WysokoscLoga := GetImageSize('logos/mainlogo.png', True);
end;

{ TGra }

procedure TGra.FormCreate(Sender: TObject);
begin
  WczytajRozmiarTla;
  WczytajRozmiarLoga;

  Gra.Left := 0;
  Gra.Top := 0;
  Gra.Width := screen.Width;
  Gra.Height := screen.Height;

  PanelWstep.Left := 0;
  PanelWstep.Top := 0;
  PanelWstep.Width := screen.Width;
  PanelWstep.Height := screen.Height;
    ImageTloStart.Width := SzerokoscTla;
    ImageTloStart.Height := WysokoscTla;
    ImageTloStart.Left := 0 - SzerokoscTla;
    ImageTloStart.Top := Round((screen.Height - WysokoscTla) / 2);
    ImageTloStart.Picture.LoadFromFile('backgrounds/background1full.png');

    ImageLogo.Width := SzerokoscLoga;
    ImageLogo.Height := WysokoscLoga;
    ImageLogo.Left := Round((screen.Width - SzerokoscLoga) / 2);
    ImageLogo.Top := Round((screen.Height - WysokoscLoga) / 2);
    ImageLogo.Picture.LoadFromFile('logos/mainlogo.png');

    TimerWejscie.Enabled := True;
    LicznikTimerWejscie := 0;
end;

procedure TGra.TimerWejscieTimer(Sender: TObject);
begin
  Inc(LicznikTimerWejscie); 
  if LicznikTimerWejscie = 453 then
    begin
      TimerWejscie.Enabled := False;
      PanelWstep.Visible := False;
      PanelMenuGlowne.Visible := True;
    end
  else
    if LicznikTimerWejscie < 101 then
      ImageTloStart.Visible := True
    else
      if LicznikTimerWejscie < 177 then
        begin
          ImageTloStart.Left := ImageTloStart.Left + Round(((Round((screen.Width - SzerokoscTla) / 2)) + SzerokoscTla) / 76);
          if LicznikTimerWejscie = 176 then
            ImageLogo.Visible := True;
        end
      else
        if LicznikTimerWejscie < 277 then
          begin
            TimerWejscie.Interval := 20;
            if LicznikTimerWejscie = 276 then
              ImageLogo.Visible := False;
          end
        else
          if LicznikTimerWejscie < 353 then
            begin
              TimerWejscie.Interval := 5;
              ImageTloStart.Left := ImageTloStart.Left + Round(((Round((screen.Width - SzerokoscTla) / 2)) + SzerokoscTla) / 76);
            end
          else
            if LicznikTimerWejscie < 453 then
              ImageTloStart.Visible := False;
end;

end.

edytowany 2x, ostatnio: flowCRANE
flowCRANE
Możesz dołączyć do tego posta rozwiązanie? Przyda się tym, którzy z wyszukiwarki trafią do tego wątku w przyszłości - miło by było, gdyby zobaczyli oprócz sugestii także kod :)
D1
No mogę dołączyć kod, ale przede wszystkim nazwy są takie żebym ja wiedział co jest co, chociaż pewnie każdy zrozumie to jak przeanalizuje. Bardziej obawiam się, że nie jest to napisane tak jak być powinno.
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:2 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
1

No mogę dołączyć kod, ale przede wszystkim nazwy są takie żebym ja wiedział co jest co, chociaż pewnie każdy zrozumie to jak przeanalizuje.

Tym się nie przejmuj - nazewnictwo jest mniej ważne niż choćby formatowanie kodu;

Bardziej obawiam się, że nie jest to napisane tak jak być powinno.

No to czemu nie pytasz dalej? Trzeba było od razu pokazać kod i poprosić o sprawdzenie;


Przede wszystkim zamień tę drabinkę **If**ów na instrukcję wyboru (czyli Case) - zobaczysz jak kod się skróci i jak zwiększy się jego czytelność; Możesz przecież korzystać z zakresów - podałem Ci wcześniej przykład takiej instrukcji;

Nie wiem też po co wyłączasz i włączasz Timer - wszystko może przebiegać na ciągłej pracy zegara; Dodatkowo, w tych etapach, w których ma być stały czarny ekran oraz kiedy logo ma stać bez ruchu na środku ekranu, nie musisz liczyć klatek; Wystarczy zmienić Interval od razu na liczbę np. 2000 (czyli dwie sekundy), dzięki czemu program będzie czekał faktyczne dwie sekundy, a zmienną LicznikTimerWejście inkrementujesz tylko raz; Czyli podsumowując - możesz inkrementować licznik tylko podczas jednej z dwóch animacji ruchu loga;

To w sumie tyle - dobrze by było, gdybyś dodał do załączników posta źródła Twojego projektu, aby można było przetestować kod u siebie; Łatwiej by było pokazywać co można zmienić i wymieniać się plikami.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
D1
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:165
0

W sumie nie chcę żeby ktoś jakoś za bardzo ingerował w ten kod. Chce to zrobić sam a jedynie się pytać o coś tylko jeśli sobie nie potrafię poradzić.

flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:2 minuty
  • Lokalizacja:Tuchów
  • Postów:12164
0

Nie musisz podawać właściwego kodu Twojego projektu - chodzi o jakikolwiek projekt, który implementuje funkcję animowanego loga; Może to być np. aplikacja testowa, która prócz animacji loga nic innego nie robi;

Łatwiej doradzić coś, jeśli ma się kod do dyspozycji, można go skompilować i przetestować; Tobie też będzie lepiej zobaczyć poprawiony kod i poczytać do niego wskazówki - szybciej zapamiętasz dobre techniki pisania kodu; Ale zmuszać Cię nie będę;

Jeżeli więc dalej masz jakiekolwiek problemy z tą animacją to pytaj.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 1x, ostatnio: flowCRANE
D1
  • Rejestracja:ponad 10 lat
  • Ostatnio:ponad 8 lat
  • Postów:165
0

Nie nie. Już problemów żadnych nie mam. Wszystko działa tak jak miało być. A instrukcję if ostatecznie zamieniłem na case. Jest czytelniej, zajmuje mniej miejsca.

A jeśli będę miał jeszcze jakiś problem to następnym razem będę wstawiał załączniki.

_13th_Dragon
  • Rejestracja:ponad 19 lat
  • Ostatnio:2 miesiące
2
dani17 napisał(a):
Kopiuj
  Gra.Left := 0;
  Gra.Top := 0;
  Gra.Width := screen.Width;
  Gra.Height := screen.Height;

Można zamienić na:

Kopiuj
  Gra.BoundsRect:=Bounds(0,0,screen.Width.screen.Height);

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)