Alih-alih kata pengantar
Dalam artikel
Lazarus saya baru-baru ini
- menulis komponen untuk animasi sprite, saya menjelaskan proses pembuatan komponen
TImageFragment sederhana yang memungkinkan Anda untuk menampilkan fragmen gambar tertentu.
Melanjutkan topik yang dipilih, dalam artikel ini saya ingin menunjukkan betapa mudahnya membuat animasi sprite di lingkungan pengembangan
Lazarus (
situs resmi ) menggunakan komponen ini.
Dengan pendekatan ini, masing-masing frame animasi dalam proyeksi yang berbeda ditempatkan pada gambar yang sama, dan komponen untuk menampilkan sprite hanya menunjukkan satu fragmen yang dipilih dari gambar ini menggunakan properti
OffsetX dan
OffsetY (offset sudut kiri atas fragmen gambar secara horizontal dan vertikal).
Banyak dari gambar yang sudah jadi ini dapat ditemukan di Web - misalnya, di
sini di situs ini .
Pilih (dan siapkan) gambar
Sebagai contoh saya, saya memilih gambar ini:

- Sangat ekspresif burung Phoenix ini mengepakkan sayapnya.
Seperti yang Anda lihat, setiap baris berisi 4 bingkai untuk masing-masing dari 4 proyeksi. Dengan mengubah hanya
OffsetX , Anda dapat membuat burung mengepakkan sayapnya, dan untuk mengubah proyeksi itu cukup dengan hanya mengganti
OffsetY . Pemisahan bingkai demi baris ini sangat menyederhanakan pemrograman animasi.
Ukuran gambar ini adalah 384x384, dan ukuran setiap frame adalah 96x96. Sayangnya, penggunaan langsung gambar ini membuat kami kesal dengan artefak: beberapa bingkai gambar ditempatkan sehingga tepinya jatuh pada bingkai yang berdekatan, dan selama animasi, goresan kuning berkedip di tepi sprite.
Untuk memperbaiki cacat ini, saya menggunakan editor grafis lintas platform gratis
GIMP (
situs resmi ). Semua yang harus dilakukan adalah menghapus piksel yang menonjol dari gambar di tempat mereka jatuh pada bingkai yang berdekatan.
File yang diperbaiki terlihat seperti ini:

- Dengan mata telanjang, perbedaannya tidak terlihat, tetapi opsi kedua bekerja tanpa artefak.
Buat proyek baru
1. Buat proyek jenis "Aplikasi" baru.
Secara default, IDE membuat proyek yang disebut "project1", yang segera membuat satu modul program yang disebut "unit1", yang menggambarkan kelas yang disebut "" TForm1 "dan mendeklarasikan instance dengan nama" Form1 ".
Secara umum, saat membuat objek baru, IDE memberinya nama yang mirip, terdiri dari nama tipe objek dan nomor seri. Saya menganggap itu gaya yang baik untuk mengubah nama semua objek seperti itu, memberi mereka nama yang bermakna yang mencerminkan peran atau tujuan objek.
Jadi, proyek kami tidak akan disebut "project1", tetapi "Phoenix" - sesuai dengan nama sprite yang dipilih.
2. Simpan proyek baru kami.
Dianjurkan untuk menyimpan setiap proyek dalam direktori terpisah dengan nama yang cocok dengan nama proyek. Selama proses penyimpanan, kami menentukan direktori yang akan disimpan (jika perlu, kami membuatnya di sana), lalu nama file proyek dan nama file modul program. Saya membuat folder "Phoenix" dan menyimpan file proyek di sana ("Phoenix.lpi" alih-alih yang diusulkan "project1.lpi") dan file modul program ("UnitMain.pas" alih-alih yang diusulkan "unit1.pas").
Nuansa case karakterVersi Lazarus untuk Windows mengarahkan nama file modul program ke huruf kecil: "unitmain.pas", tetapi nama program modul mempertahankan huruf asli karakter: "unit UnitMain;". Ini tidak terjadi pada file proyek, nama file mempertahankan huruf asli karakter.
3. Ganti nama formulir dan ubah judulnya.
Formulir yang baru dibuat, disebut "Form1" (properti
Name ), adalah turunan dari kelas "TForm1" dan berisi judul "Form1" (properti
Caption ). Ubah properti
Name dari form menjadi "FormMain", dan nama kelas akan berubah menjadi "TFormMain".
Ubah properti
Caption menjadi "Phoenix" sehingga judul proyek ditampilkan dalam judul jendela.
4. Sebagai hasilnya, saya mendapatkan teks berikut dari modul unitmain.pas:
unit UnitMain; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs; type TFormMain = class(TForm) private public end; var FormMain: TFormMain; implementation {$R *.lfm} end.
5. Kompilasi, jalankan proyek (kunci <F9>):

Letakkan sprite di formulir
Dengan asumsi bahwa Anda telah menginstal komponen
TImageFragment yang dijelaskan dalam artikel
Lazarus saya sebelumnya
- kami menulis komponen untuk animasi sprite , pilih tab "Game" pada palet komponen dan tambahkan komponen "TImageFragment" ke formulir.
Menggunakan properti
Picture , memuat gambar (versi tetap burung Phoenix) ke dalam komponen. Selain itu, kami juga mengubah properti objek baru berikut:
- atur properti Tinggi dan Lebar ke 96
- atur properti Kiri dan Atas ke 0 (nyaman untuk mencocokkan dengan tangkapan layar saya)
- Properti nama diubah dari "ImageFragment1" yang tidak nyaman menjadi "Sprite" yang sederhana dan dapat dimengerti.
Jika semuanya dilakukan dengan benar, komponen akan menampilkan bingkai pertama dari gambar:

Teks modul
UnitMain akan
mengalami perubahan kecil:
- modul
ImageFragment ditambahkan ke bagian
penggunaan uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ImageFragment;
- objek baru akan muncul di deklarasi kelas
TFormMain = class(TForm) Sprite: TImageFragment; private public end;
Tambahkan animasi - sayap sayap
1. Tambahkan komponen baru dari kelas
TTimer ke
formulir .
Komponen ini terletak pada tab "Sistem" pada palet komponen. Anda dapat menempatkannya di tempat yang nyaman di formulir, karena tidak ditampilkan di aplikasi yang sedang berjalan.
2. Ganti nama objek yang ditambahkan.
Objek baru secara otomatis mendapatkan nama "Timer1", tetapi kami menamainya menjadi "TimerLive". Sering kali lebih mudah untuk memberi nama benda seperti itu, terdiri dari dua bagian: yang pertama mencerminkan kelas objek, dan yang kedua mencerminkan tujuannya.
3. Ubah properti
Interval dari 1000 menjadi 100.
Biarkan bingkai animasi ini saling menggantikan setiap 100 milidetik, yaitu 10 kali per detik. Di masa depan, properti ini dapat diubah untuk memperlambat atau mempercepat rentang sayap - sesuai kebijakan programmer.
4. Tambahkan pengendali acara OnTimer.
Cara termudah untuk melakukan ini adalah klik dua kali pada ikon objek
TimerLive baru. Sebagai hasil dari tindakan ini, IDE itu sendiri akan menambahkan prosedur baru ke deklarasi kelas bentuk, tautan ke prosedur ini ke properti objek, dan badan prosedur baru akan ditambahkan ke bagian
implementasi (dan kursor akan ditempatkan di dalam prosedur baru ini, antara
kata kunci mulai dan
akhir ).
5. Tambahkan satu baris kode ke prosedur baru.
Sprite.OffsetX := (Sprite.OffsetX + 96) mod 384;
Sebagai hasil dari tindakan ini, deklarasi kelas akan terlihat seperti ini:
TFormMain = class(TForm) Sprite: TImageFragment; TimerLive: TTimer; procedure TimerLiveTimer(Sender: TObject); private public end;
Dan prosedur baru - event
handler OnTimer akan terlihat seperti ini:
procedure TFormMain.TimerLiveTimer(Sender: TObject); begin Sprite.OffsetX := (Sprite.OffsetX + 96) mod 384; end;
Setelah menyusun dan menjalankan aplikasi, Anda dapat menyaksikan burung Phoenix mengepakkan sayapnya.
Ini terjadi karena pengendali peristiwa waktu setiap 100 milidetik mengubah siklus offset fragmen yang ditampilkan, dan frame yang dipilih digeser secara horizontal, secara berurutan menampilkan 4 frame dari garis atas gambar yang dimuat. Operasi
mod - mendapatkan sisa divisi - mencegah offset melampaui ukuran gambar, dan sebagai hasilnya, frame ke-4 kembali diikuti oleh frame ke-1.
Tambahkan gerakan sprite di sekitar jendela
1. Tambahkan modul
Matematika ke bagian
penggunaan uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, ImageFragment, Math;
2. Tambahkan variabel baru dan konstan ke deklarasi kelas.
Untuk menyimpan vektor memindahkan sprite di sekitar jendela, tambahkan variabel tipe
TPoint private FVector: TPoint;
Di tempat yang sama, kami mendeklarasikan konstanta untuk mendefinisikan modul kecepatan
const Speed = 10;
3. Tambahkan komponen lain dari kelas
TTimer ke
formulir .
Saya mengingatkan Anda: komponen ini terletak di tab "Sistem" pada palet komponen.
Objek baru lagi secara otomatis mendapatkan nama "Timer1", dan kami menamainya - kali ini menjadi "TimerMove". Tujuan dari pengatur waktu kedua adalah untuk mengontrol pergerakan sprite. Saya tidak mengikat kedua proses (animasi dan gerakan) ke timer yang sama sehingga masing-masing timer dapat diatur secara terpisah - misalnya, untuk memperlambat frekuensi ayunan sayap tanpa memperlambat gerakan, dan sebagainya.
4. Ubah properti
Interval dari 1000 menjadi 100.
Biarkan timer ini juga menyala setiap 100 milidetik, yaitu 10 kali per detik. Di masa depan, properti ini juga dapat diubah untuk memperlambat atau mempercepat frekuensi rendering fakta sprite move.
5. Tambahkan
pengendali acara
OnTimer .
Untuk perubahan, kali ini saya mengusulkan untuk melakukan ini dengan mengklik dua kali berlawanan dengan peristiwa
OnTimer pada tab "Acara" pada objek
TimerMove yang baru. Seperti terakhir kali, sebagai hasil dari tindakan ini, IDE itu sendiri akan menambahkan prosedur baru ke deklarasi kelas bentuk, tautan ke prosedur ini ke properti objek, dan badan prosedur baru akan ditambahkan ke bagian
implementasi (dan kursor akan ditempatkan di dalam prosedur baru ini, di antara kunci kata
- kata
mulai dan
berakhir ).
6. Tambahkan dua baris kode ke prosedur baru.
Sprite.Left := Max(0, Min(Width - Sprite.Width, Sprite.Left + FVector.x)); Sprite.Top := Max(0, Min(Height - Sprite.Height, Sprite.Top + FVector.y));
Menggunakan fungsi Max () dan Min () mencegah sprite keluar dari form (jendela aplikasi utama).
Untuk menggunakan fungsi-fungsi ini kami menghubungkan modul
Matematika ke bagian
penggunaan .
7. Tambahkan
pengendali event
OnKeyPress .
Pilih formulir (klik pada persegi panjang abu-abu dari tata letak jendela di luar semua komponen yang ditambahkan) dan pada tab Acara kita menemukan acara
OnKeyPress . Dengan mengklik dua kali pada nilai kosong event handler, kami membuat dan menetapkan prosedur baru - event handler.
8. Tambahkan beberapa baris kode ke prosedur baru.
if Key = 'a' then FVector := TPoint.Create(-Speed, 0) else if Key = 'd' then FVector := TPoint.Create(Speed, 0) else if Key = 'w' then FVector := TPoint.Create(0, -Speed) else if Key = 's' then FVector := TPoint.Create(0, Speed) else if Key = ' ' then FVector := TPoint.Create(0, 0);
Sebagai hasil dari tindakan ini, deklarasi kelas akan terlihat seperti ini:
TFormMain = class(TForm) Sprite: TImageFragment; TimerMove: TTimer; TimerLive: TTimer; procedure FormKeyPress(Sender: TObject; var Key: char); procedure TimerLiveTimer(Sender: TObject); procedure TimerMoveTimer(Sender: TObject); private FVector: TPoint; const Speed = 10; public end;
Dan prosedur baru - Penangan event
OnTimer dan
OnKeyPress akan terlihat seperti ini:
procedure TFormMain.TimerMoveTimer(Sender: TObject); begin Sprite.Left := Max(0, Min(Width - Sprite.Width, Sprite.Left + FVector.x)); Sprite.Top := Max(0, Min(Height - Sprite.Height, Sprite.Top + FVector.y)); end; procedure TFormMain.FormKeyPress(Sender: TObject; var Key: char); begin if Key = 'a' then FVector := TPoint.Create(-Speed, 0) else if Key = 'd' then FVector := TPoint.Create(Speed, 0) else if Key = 'w' then FVector := TPoint.Create(0, -Speed) else if Key = 's' then FVector := TPoint.Create(0, Speed) else if Key = ' ' then FVector := TPoint.Create(0, 0); end;
Setelah mengkompilasi dan memulai aplikasi, Anda dapat memindahkan burung Phoenix di layar menggunakan tombol "a", "w", "s", "d" dan hentikan dengan spasi.
Kami menggunakan proyeksi sprite yang berbeda
Tambahkan kode berikut ke akhir prosedur
TFormMain.FormKeyPress if FVector.x < 0 then Sprite.OffsetY := 96 else if FVector.x > 0 then Sprite.OffsetY := 192 else if FVector.y < 0 then Sprite.OffsetY := 288 else Sprite.OffsetY := 0;
Mengubah properti
OffsetY tergantung pada vektor perpindahan menyebabkan gambar berputar ke arah gerakan.
Semua Teks Modul UnitMain unit UnitMain; {$mode objfpc}{$H+} interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, ImageFragment, Math; type TFormMain = class(TForm) Sprite: TImageFragment; TimerMove: TTimer; TimerLive: TTimer; procedure FormKeyPress(Sender: TObject; var Key: char); procedure TimerLiveTimer(Sender: TObject); procedure TimerMoveTimer(Sender: TObject); private FVector: TPoint; const Speed = 10; public end; var FormMain: TFormMain; implementation {$R *.lfm} procedure TFormMain.TimerLiveTimer(Sender: TObject); begin Sprite.OffsetX := (Sprite.OffsetX + 96) mod 384; end; procedure TFormMain.TimerMoveTimer(Sender: TObject); begin Sprite.Left := Max(0, Min(Width - Sprite.Width, Sprite.Left + FVector.x)); Sprite.Top := Max(0, Min(Height - Sprite.Height, Sprite.Top + FVector.y)); end; procedure TFormMain.FormKeyPress(Sender: TObject; var Key: char); begin if Key = 'a' then FVector := TPoint.Create(-Speed, 0) else if Key = 'd' then FVector := TPoint.Create(Speed, 0) else if Key = 'w' then FVector := TPoint.Create(0, -Speed) else if Key = 's' then FVector := TPoint.Create(0, Speed) else if Key = ' ' then FVector := TPoint.Create(0, 0); if FVector.x < 0 then Sprite.OffsetY := 96 else if FVector.x > 0 then Sprite.OffsetY := 192 else if FVector.y < 0 then Sprite.OffsetY := 288 else Sprite.OffsetY := 0; end; end.
Alih-alih kata penutup
Contoh sederhana ini tidak mengklaim peringkat tinggi untuk kecepatan atau kegunaan. Jika seseorang, seperti dalam
artikel sebelumnya , ingin memberi tahu dalam komentar bahwa animasi perlu dilakukan salah - selamat datang, tulis artikel Anda. Dan topik artikel ini adalah bagaimana membuat animasi dalam beberapa baris kode, tanpa menggunakan perpustakaan khusus, praktis βon the kneeβ. Metode ini telah diuji dalam praktiknya, itu benar-benar berhasil, jadi sebelum mengkritik dan "minus", baca kembali artikel ini tentang apa dan mengapa.