Buat Anda sendiri 3 pertandingan dengan Flixel: Mekanika permainan inti
Indonesian (Bahasa Indonesia) translation by Cuma Hapsah (you can also view the original English article)
Tutorial ini akan memandu Anda melalui semua langkah yang diperlukan untuk menciptakan sebuah permainan Match 3 (seperti Bejeweled) dengan menggunakan Flixel. Kami akan struktur proyek yang menggunakan teknik OOP padat.
Juga tersedia dalam seri ini:
- Buat Anda sendiri 3 pertandingan dengan Flixel: Mekanika permainan inti
- Membuat Anda sendiri 3 pertandingan dengan Flixel: Polandia
Langkah 1: Download file proyek
Setelah men-download file proyek, menempatkan mereka dalam folder "proyek" atau di mana pun Anda merasa nyaman dengan mereka.
Ingat bahwa jika Anda mengubah nama atau path file, Anda juga akan perlu untuk mengubah mereka dalam kode!
Jika Anda melihat di dalamnya Anda akan melihat saya juga dilampirkan mesin Flixel, sehingga Anda tidak perlu men-download itu sendiri. Namun, jika Anda ingin, tersedia di sini.
Langkah 2: Buat proyek
Setelah file kita berada di tempat yang kami memilih mereka untuk menjadi, sekarang saatnya untuk membuat proyek. Dalam tutorial ini saya akan menggunakan FlashDevelop, yang benar-benar gratis (meskipun Windows-only) dan dapat ditemukan di sini. Ini adalah ide yang baik untuk men-download versi stabil terbaru.
Sekarang buka FlashDevelop (atau IDE pilihan Anda) dan menciptakan proyek; untuk melakukan ini di FlashDevelop Anda perlu pergi ke proyek-> proyek baru.



Setelah melakukannya, Anda akan melihat sebuah jendela yang serupa dengan yang di atas, tergantung pada IDE Anda.
Sekarang bahwa proyek dibuat, mari kita periksa beberapa pengaturan. Pertama pergi ke alat-alat-> Program pengaturan atau hanya tekan F10.



Pastikan bahwa Flex SDK lokasi di bawah AS3Context adalah benar menunjuk ke direktori Flex SDK. Jika Anda belum download SDK, pergi di sini, untuk melakukannya.
Setelah memeriksa itu, beralih dari AS3Context ke FlashViewer, dan memeriksa jalan pemutar debug.



Jalan Player eksternal harus menunjuk ke pemain debug. Jika Anda tidak men-download satu ini belum baik, pergi di sini dan melakukannya, versi yang harus Anda gunakan dengan IDE Anda adalah proyektor konten debugger.
Sekarang bahwa kita memiliki segalanya diatur, kita hanya perlu untuk menguji itu.
package { import flash.display.Sprite; import flash.events.Event; /** * ... * @author You */ public class Main extends Sprite { public function Main():void { trace("It's working!"); if (stage) init(); else addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event = null):void { removeEventListener(Event.ADDED_TO_STAGE, init); // entry point } } }



Paste kode ini ke dalam file Main.as Anda, dan menjalankannya dalam Debug mode. Harus ada tidak ada kesalahan, debug pemain harus bertelur dengan apa-apa tapi jendela kosong dan dalam output Anda harus melihatnya bekerja! -string yang kita dilacak. Jika berhasil, kita dapat pergi ke langkah berikutnya, jika tidak, saya sarankan memeriksa jalan dan memastikan semua adalah mana itu seharusnya. Ingat bahwa jika Anda menggunakan windows XP, Anda perlu memiliki .NET framework diperbarui.
Langkah 3: Melampirkan Flixel ke proyek
Jika semuanya bekerja, kita dapat melampirkan Flixel ke proyek kami dan mengkompilasi aplikasi sederhana.
Mulai dengan pergi ke "Proyek-> Properties" dan kemudian masuk tab yang bernama Classpaths.



Sekarang tekan tombol Tambahkan Classpath, menemukan direktori yang bernama flixel, pilih dan kemudian tekan tombol OK. Anda dapat melihat bahwa sekarang folder yang dipilih telah ditambahkan ke classpaths Anda.



Tekan OK lagi, dan kami sedang finishing dengan mempersiapkan proyek kami. Sekarang kita dapat benar-benar mulai coding!
Hapus semua kode di Main.as hanya menyisakan:
package { }
Jadi kita memiliki sebuah dokumen yang bersih. Sekarang, hal pertama yang perlu kita lakukan adalah impor flixel untuk paket kami, yang kita lakukan dengan:
import org.flixel.*;
Perhatikan bahwa kita tidak menentukan apa yang kita akan menggunakan. Dengan menggunakan * kami Anda termasuk semua kelas dari flixel, bahkan orang-orang yang kita tidak akan menggunakan! Hal itu mungkin membuat SWF file lebih besar, tetapi untuk sekarang kita tidak perlu khawatir tentang itu, kita yang sangat jauh dari menyelesaikan proyek kami. Setelah mengimpor Perpustakaan, kita harus menentukan ukuran dan latar belakang warna untuk SWF kami:
[SWF(width="600", height="450", backgroundColor="#000000")]
Saya mengatur lebar
sampai 600
dan tinggi 450
, jadi itu akan cocok dengan baik di situs, Anda dapat mengubahnya ke apapun yang Anda suka untuk menjadi, yang sama berlaku untuk
. Setelah kami selesai dengan itu, kita harus mendefinisikan objek utama kami:backgroundColor
public class Main extends FlxGame { }
Perhatikan bahwa kelas kami meluas FlxGame
. Itu pada dasarnya berarti bahwa kelas kami, selain memiliki sendiri metode eksklusif dan properti, juga akan berisi semua metode dan properti yang decalred di FlxGame.as. Setelah itu, kita perlu membuat konstruktor:
public function Main() { }
Constructor adalah hanya sebuah metode dengan nama yang sama sebagai objek, dalam kasus ini bernama utama
, yang disebut pada penciptaan objek. Karena kelas utama
kami, akan disebut pada awal permainan kami. Kode saat ini harus seperti ini:
package { import org.flixel.*; [SWF(width="600", height="450", backgroundColor="#000000")] public class Main extends FlxGame { public function Main() { } } }
Kita bisa mencoba untuk menjalankan aplikasi kami sekarang, tekan F5 atau pergi ke proyek-> Test Movie.
col: 19 Error: No default constructor found in base class org.flixel:FlxGame.
Sayangnya, program tidak bisa mengkompilasi. Kesalahan memberitahu kita, bahwa basis kelas - FlxGame, yang merupakan warisan oleh kelas utama kami--tidak memiliki konstruktor default. Konstruktor default adalah konstruktor yang memerlukan tanpa argumen. Itu berarti kita harus feed konstruktor kelas dasar kami beberapa argumen, sehingga kita perlu untuk memanggil constructor yang dari objek utama kami. Untuk melakukan itu, kita menggunakan fungsi super() dari objek utama konstruktor. Semua kita perlu tahu adalah apa jenis argumen kita harus melewati; untuk itu kita dapat langsung ke dokumentasi Flixel atau biarkan kami IDE untuk memberitahu kami bahwa. Dokumentasi dapat ditemukan di sini.
Umum fungsi FlxGame (GameSizeX:uint, GameSizeY:uint, InitialState:Class, Zoom: uint = 2)
Dari flixel docs.
Argumen yang perlu diisi: GameSizeX
, gameSizeY
- yang mengatur lebar dan tinggi permainan kita dalam pixel, berikutnya adalah InitialState
, yang saya akan berbicara tentang dalam detik dan Zoom
, yang jelas. InitialState harus menjadi sebuah kelas yang mewarisi dari FlxState. Itu berarti kita perlu membuat itu, sebelum kita dapat bergerak.
Step 4: Membuat GameState
Untuk membuat sebuah class baru, cukup klik kanan folder yang Anda ingin kelas baru di dan kemudian pergi untuk menambahkan-> kelas baru di tampilan proyek.






Jendela penciptaan kelas AS3 baru akan muncul. Bukan untuk mengisi celah yang hanya nama, saya juga mengatakan IDE untuk mewarisi dari kelas FlxState
dan menciptakan konstruktor nya. Klik OK dan Anda akan melihat dokumen kelas baru bernama GameState.as, jika Anda bernama kelas baru dengan cara yang sama saya lakukan. Anda harus mengganti org.flixel.FlxState impor; dengan org.flixel.* Impor; untuk saat ini. Kode dalam dokumen akan terlihat seperti ini:
package { import org.flixel.*; public class GameState extends FlxState { public function GameState() { super(); } } }
Seperti yang Anda lihat, saat ini kami memiliki konstruktor default dari kelas dasar tersedia. Sekarang mari kita pergi kembali ke Main.as kami dan mari kita mengisi fungsi super() dengan argumen.
package { import org.flixel.*; [SWF(width="600", height="450", backgroundColor="#000000")] public class Main extends FlxGame { public function Main() { super(600, 450, GameState, 1); } } }
Tanpa basa-basi lagi, lakukan kompilasi permainan kami!
Tidak ada yang menarik pada layar, tapi dikompilasi berhasil!
Step 5: Membuat kelas Gem
Mari kita mulai langkah ini membuat kelas dalam cara yang sama, kami menciptakan GameState, tapi kali ini kita akan mewarisi dari FlxSprite.



Permata kelas akan mewakili sebuah permata dalam permainan kami, sekarang mari kita menanamkan grafis untuk itu.
package { import org.flixel.FlxSprite; public class Gem extends FlxSprite { [Embed(source = '../assets/gems.png')] private const ImgGems:Class; public function Gem() { } } }
ImgGems
(gems.png) sekarang akan mewakili citra kita. Mari kita juga membuat update()
akan membuat fungsi, fungsi ini disebut sekali bingkai sehingga kami akan meletakkan hal-hal yang memerlukan perhatian terus-menerus kami di sini, serta hal-hal yang terjadi dari waktu ke waktu.
override public function update():void { super.update(); }
Seperti Anda mungkin telah menyadari, dalam definisi fungsi ini muncul menimpa
. Kami perlu untuk menyatakan bahwa, karena FlxSprite juga memiliki fungsi update() akan membuat sendiri, dan karena kita tidak bisa memiliki dua fungsi dengan nama yang sama dalam satu objek, kita telah ditimpa FlxSprite update() akan membuat fungsi. Karena update() akan membuat FlxSprite yang harus disebut pula (untuk memperbarui animasi dan seterusnya), kita hanya menggunakan super.update(), yang hanya memanggil fungsi ditimpa. Karena kita sekarang dapat menulis kode kita sendiri dalam fungsi ini, ianya seolah-olah kita sedang memperluas update()
-akan membuat dasar. Ini adalah tampilan FlxSprite's
update()
akan membuat fungsi:
override public function update():void { updateMotion(); updateAnimation(); updateFlickering(); }
Seperti yang Anda lihat, itu juga mengabaikan yang konstruktor kelas dasar, tapi ini tidak menyebutnya super.update()
meskipun, karena sejak itu semua dengan basis Warisan kelas 's (FlxObject
) fungsi, itu memanggil mereka sendiri. Itu berarti bahwa kita bisa mengganti kami super.update()
dengan:
updateMotion(); updateAnimation(); updateFlickering();
Dan hasilnya akan sama. Pada kenyataannya, itu akan menjadi sedikit lebih efisien, tetapi karena itu adalah seperti agak kecil, saya akan Luang dua baris kode. :)
Step 6: Membuat animasi untuk kelas Gem
Saatnya untuk memasukkan sesuatu yang berwarna-warni di layar! Mari kita mulai dengan memuat gambar tertanam dan menciptakan animasi di Gem.as.
public function Gem() { loadGraphic(ImgGems, true, false, 32, 32, false); addAnimation("blue", [0]); addAnimation("green", [4]); addAnimation("orange", [8]); addAnimation("aqua", [12]); addAnimation("red", [16]); addAnimation("yellow", [20]); }
Seperti yang Anda lihat, kami melakukan semua ini pada waktu Kapan objek yang dibuat, dalam konstruktor. Pertama kita loadGraphic()
, fungsi ini diperlukan untuk argumen: Gambar, nilai boolean
Apakah animasi sprite, boolean
lain untuk mengetahui apakah atau tidak kita akan menggunakan membalik horisontal (kami akan tidak), lebar frame, ketinggian bingkai dan akhirnya boolean
yang memberitahu fungsi Apakah kita ingin berbagi grafis dengan semua sprite lain menggunakannya atau apakah kita inginkan contoh unik.
Sekarang kita dapat menambahkan animasi. Aku diberi nama mereka setelah mereka akan mewakili warna. Argumen pertama adalah, seperti yang Anda lihat, nama animasi, dan yang kedua adalah array yang berisi indeks dari bingkai pertama dari animasi sesuai.

Permata kami adalah 32px by 32px, itu sebabnya kami menetapkan frameWidth
, frameHeight
untuk 32px masing-masing. ID frame pertama adalah benar-benar 0. Kita menghitung frame dari kiri ke kanan. Seperti yang Anda lihat, bingkai pertama biru, yang kelima hijau, kesembilan jeruk dan seterusnya. Frame kami melewatkan bagian dari sebuah animasi, dan sekarang kita dapat mengabaikan mereka. Animasi kami yang satu frame, dan jika Anda melihat seluruh argumen kita tidak harus mengisi, Anda akan melihat bahwa kita tidak benar-benar Anda menghidupkan apa-apa. Kami hanya mengubah sprite. :)
Langkah 7: Menetapkan animasi
Karena kita memiliki beberapa animasi, kita perlu memberitahu permata animasi yang digunakan. Kita tidak ingin semua permata untuk menggunakan animasi sama, jadi kita perlu menambahkan sebuah variabel baru:
private var type:uint;
Kami ingin memberitahu permata yang animasi harus bermain ketika kita membuat hal itu, jadi kami hanya menambahkan argumen ke konstruktor permata kami:
public function Gem(_type:uint) { loadGraphic(ImgGems, true, false, 32, 32, false); addAnimation("blue", [0]); addAnimation("green", [4]); addAnimation("orange", [8]); addAnimation("aqua", [12]); addAnimation("red", [16]); addAnimation("yellow", [20]); type = _type; }
Kami menyimpan argumen yang diberikan ke variabel kita buat sebelumnya (jenis
). Sekarang mari kita menggunakan tipe
untuk memberitahu permata yang animasi harus bermain:
switch (type) { case 0: play("blue"); break; case 1: play("green"); break; case 2: play("orange"); break; case 3: play("aqua"); break; case 4: play("red"); break; case 5: play("yellow"); break; }
Play()
fungsi menamai animasi sebagai argumen, dan membuat sprite mulai menggunakan animasi dengan nama ini. Seperti yang Anda lihat dalam kode di atas, tergantung jenis
yang nilai, kami menggunakan switch
pernyataan untuk memainkan sebuah animasi yang melekat pada nilai.
Langkah 8: Membuat permata
Kembali ke GameState.as dan di bawah org.flixel.* Impor
; impor feshly kami membuat kelas, permata:
import org.flixel.*; import Gem;
Sekarang kita akan menambahkan baru objek (permata) ke loop permainan kami. Kita melakukan ini dengan menggunakan fungsi berikut:
add(new Gem(0));
Konstruktor kami sekarang harus terlihat seperti ini:
public function GameState() { super(); add(new Gem(0)); }
Add()
mengambil objek sebagai argumen dan menambahkannya ke loop permainan. Kami baru saja membuat objek baru yang kita tidak memiliki referensi, tapi tidak seperti kita perlu ada sekarang. Perhatikan bahwa kami menciptakan sebuah permata yang memberikan 0
sebagai argumen, sehingga akan bermain animasi terikat nomor itu. Mari kita tekan F5 dan melihat apakah kita dapat melihat permata render dengan benar.
Seperti yang diharapkan, kita dapat dengan jelas melihat permata biru di sudut kiri atas! Anda dapat mengganti Gem(0)
Gem(3)
atau angka lainnya, selama itu lebih rendah atau sama dengan 5
.
Langkah 9: Buat Array
Kami masih tidak meninggalkan GameState.as; kali ini Mari kita membuat sebuah array yang dapat berisi semua permata permainan kami. Kita akan menggunakan ini untuk menghasilkan grid permata yang digunakan dalam permainan.
private var gems:Array = new Array(); //this array will contain all of our game's gems
Sekarang mari kita mengisi kami array dengan permata! Kita akan menggunakan untuk loop untuk
itu... tapi persis berapa banyak kita perlu menambahkan? Kita harus menggunakan dua variabel baru. Mari kita sebut mereka baris
dan kolom
. Nama mereka adalah diri cukup jelas, jadi mari kita tidak membuang waktu dan menentukan nasib mereka.
private var columns:uint = 8; private var rows:uint = 8;
Kami menetapkan kolom
dan baris
ke 8
, yang berarti kita akan memiliki 64 permata total. Tanpa basa-basi lagi, mari kita mendorong
banyak permata seperti yang harus ada pada baris
oleh Dewan kolom
.
Langkah 10: Mengisi permata
dengan permata
Mari kita mulai dari menciptakan lingkaran di mana kita akan mendorong semua permata.
for (var i:int = 0; i < columns * rows; ++i) { }
Mari kita gunakan mendorong
untuk menambahkan semua permata ke array
kami:
for (var i:int = 0; i < columns * rows; ++i) { gems.push(new Gem(0)); }
Kita lakukan itu baik-baik saja tapi sekarang tampaknya ada masalah, mereka semua dari jenis
yang sama! Mari kita gunakan fungsi Math.random()
untuk mendapatkan bilangan acak antara 0
dan 5
. Untuk itu tentu saja, kita perlu permainan kami untuk mengetahui berapa banyak jenis yang kita miliki, sehingga kita perlu menambahkan konstan, yang akan mewakili beberapa jenis tersedia untuk permata kami:
private const types = 6; //the number of available gems' types (red, green, blue, etc.)
for (var i:int = 0; i < columns * rows; ++i) { gems.push(new Gem(Math.floor(Math.random() * types))); }
Math.Random()
kembali bilangan real yang lebih besar atau sama dengan 0
dan kurang dari 1
. Kita kalikan dengan jenis
, jadi sekarang nomor acak akan lebih besar atau sama dengan 0
dan kurang dari 6
. Setelah itu kami menggunakan Math.floor()
, sehingga dalam kasus kita akan mendapatkan nomor seperti 5.57648
akan kembali integer terdekat lebih rendah daripada angka itu (5
, dalam hal ini).
Mari kita akhirnya menggunakan fungsi add()
, untuk menambahkan semua permata mendorong ke loop permainan, karena add()
mengembalikan objek yang kami menambahkan, kami hanya membuatnya kembali ke dalam push()
fungsi:
for (var i:int = 0; i < columns * rows; ++i) { gems.push(add(new Gem(Math.floor(Math.random() * types)))); }
Sekarang mari kita tekan F5 dan memeriksa bagaimana permata 64 kami terlihat dalam permainan!

Saya yakin Anda dapat melihat mereka semua ada! Sayangnya, setiap satu dari mereka berada di posisi yang sama. Mari kita mengubah itu.
Langkah 11: Posisi permata
Untuk posisi semua permata yang kita perlu tahu seberapa banyak ruang yang kita perlu antara mereka. Mari kita membuat dua konstanta tambahan untuk tujuan ini:
private const spaceX:uint = 32; //the space between columns private const spaceY:uint = 32; //the space between rows
Sekarang mari kita tambahkan ruang ini antara permata:
for (var i:int = 0; i < columns * rows; ++i) { gems.push(add(new Gem(Math.floor(Math.random() * types)))); gems[i].y = Math.floor(i / columns) * spaceY; gems[i].x = (i - (columns * Math.floor(i / columns))) * spaceX; }
Untuk .y permata [i], kita menghitung baris ID (Math.floor(i / columns
)) dan kemudian kalikan dengan lalai sehingga setiap baris
lalai px lebih rendah daripada sebelumnya. Catatan dari di flixel semakin besar nilai y, semakin rendah pada layar objek.
Kedua kita menghitung kolom ID ((-(kolom * Math.floor(i / columns
))) dan kemudian kalikan dengan spaceX
, yang akan menempatkan setiap kolom spaceX
px lebih jauh daripada sebelumnya.
Sekarang Anda dapat mengkompilasi proyek dan melihat hasilnya!

Tidak terlihat indah? Yah, itu bisa lebih baik, misalnya itu bukan pilihan yang baik untuk memulai papan di sudut kiri atas. Ruang di antara permata juga bisa menjadi sedikit lebih besar. Mari kita memperbaiki kedua masalah tersebut dengan membuat beberapa perubahan kecil:
private const spaceX:uint = 42; //the space between gems on X axis private const spaceY:uint = 42; //the space between gems on Y axis private const begX:uint = 140; //the X position component of our board private const begY:uint = 64; //the Y position component of our board public function GameState() { super(); for (var i:int = 0; i < columns * rows; ++i) { gems.push(add(new Gem(Math.floor(Math.random() * types)))); gems[i].y = begY + Math.floor(i / columns) * spaceY; gems[i].x = begX + (i - (columns * Math.floor(i / columns))) * spaceX; } }
Kami hanya menambahkan nilai konstan ke posisi setiap permata, yang harus menghasilkan pergeseran seluruh papan. Mari kita menjalankan permainan kami dan melihat bagaimana tampilannya:
Jauh lebih baik!
Langkah 12: Menunjukkan kursor
Sebelum kita mulai menambahkan fitur baru, kita harus menunjukkan kursor mouse ke pengguna. Mari kita kembali ke Main.as dan menanamkan PNG file dengan kursor mouse kustom kami:
[Embed(source = "../assets/mouseCursor.png")] private var ImgCursor:Class;
Tidak ada yang tak terduga di sini, jadi mari kita hanya pergi straght untuk menampilkan kursor, yang juga merupakan cukup sederhana:
public function Main() { super(600, 450, GameState, 1); FlxG.mouse.show(ImgCursor); }
Kami menggunakan metode FlxG.mouse.show()
untuk membuat kursor terlihat. Jika kita ingin menyembunyikan itu, kita dapat selalu menggunakan FlxG.mouse.hide(),
tetapi diragukan bahwa hal itu akan diperlukan dalam permainan ini. Pemberitahuan yang kami kirimkan ImgCursor
untuk FlxG.mouse.hide()
fungsi, sehingga akan menampilkan kursor dengan grafis kami. Jika kita hanya meninggalkan null
sana, kursor Flash built-in sederhana akan muncul. Ada juga dua argumen lain, yang offsetX
dan offsetY
: ini hanya menggeser gambar kursor sehingga posisinya sebenarnya tidak di sudut kiri atas.
Mari kita membangun dan menjalankan proyek kami untuk melihat jika kursor menampilkan dengan benar:



Itu ada di sana, dan itu semua itu harus dilakukan sekarang!
Langkah 13: Membuat bingkai
Sekarang bahwa kursor mouse kami sudah terlihat, kita dapat mulai menggunakan mouse. Kita akan mulai off dengan memilih sebuah permata, logis bahwa sebelum kita benar-benar melakukan tindakan apapun pada permata pemain seharusnya untuk memilih salah satu permata dari seluruh papan. Hal pertama yang perlu kita pertimbangkan adalah bagaimana akan kita menunjukkan kepada pemain bahwa permata dipilih. Salah satu solusi termudah untuk masalah ini hanya menempatkan perbatasan di sekitar permata dipilih. Perhatikan bahwa frame gambar dalam gems.png, jadi sekarang kita perlu untuk menanamkan untuk GameState
. Mari kita beralih dokumen ke GameState.as, kemudian embed grafis yang diperlukan dan membuat FlxSprite
:
[Embed(source = '../assets/gems.png')] private const ImgGems:Class;
private var frame:FlxSprite = new FlxSprite();
Sekarang mari kita load grafis dan membuat animasi untuk itu, kami dapat melakukan itu semua dalam konstruktor:
frame.loadGraphic(ImgGems, false, false, 32, 32, false);
Sebenarnya, kita membutuhkan hanya satu animasi untuk frame kami. Mari kita melihat gems.png, dan melihat apa yang ID untuk frame animasi kami:

Hal ini tidak baik terlihat pada gambar karena begitu tipis dan ringan, tapi di awal baris ke-7. Ingat kita perlu menghitung ID dari 0
:
frame.addAnimation("frame", [24]);
Tidak ada banyak dilakukan tetapi memeriksa jika itu bekerja dengan baik, tetapi untuk melakukannya pertama kita perlu untuk bermain baru dibuat animasi dan menambahkan bingkai ke loop permainan:
frame.play("frame"); frame.addAnimation("frame", [24]);
Mari kita lihat apakah ia bekerja seperti seharusnya:



Karena kami tidak berubah x
atau y
koordinat, sprite menampilkan di sudut kiri atas layar. Untuk sekarang kita tidak ingin untuk menampilkan di semua, jadi mari kita hanya mengatur properti terlihat
ke palsu
:
frame.visible = false;
Anda dapat menguji proyek sekali lagi untuk memeriksa jika bingkai masih render atau tidak, itu akan benar-benar aneh jika itu terjadi!
Langkah 14: Mempersiapkan untuk seleksi
Sekarang bahwa kita memiliki bingkai kami siap sudah waktunya untuk meletakkannya untuk digunakan, tetapi sebelum itu kita perlu menambahkan sebuah variabel baru yang akan membuat ID dari permata dipilih:
private const types:uint = 6; //the number of available gems' types (red, green, blue, etc.) private const spaceX:uint = 42; //the space between gems on X axis private const spaceY:uint = 42; //the space between gems on Y axis private const begX:uint = 140; //the X position component of our board private const begY:uint = 64; //the Y position component of our board private var gems:Array = new Array(); //this array will contain all of our game's gems private var columns:uint = 8; private var rows:uint = 8; private var selID:int = -1; //selID holds an ID of a selected gem, -1 = no gem selected
Kita set selID
ke-1
, dan akan menunjukkan, bahwa tidak ada permata dipilih (kita menghitung dari 0
, jadi jika selID sama dengan 0
, maka itu berarti permata pertama yang dipilih). Jadi, ketika kita harus memilih sebuah permata? Waktu yang tepat untuk itu adalah ketika tombol mouse ditekan atau dirilis. Sekarang mari kita membuat fungsi update()
akan membuat kami dan beberapa variabel baru sementara kita berada di itu:
override function update():void { var pressed:Boolean = FlxG.mouse.justPressed(); var released:Boolean = FlxG.mouse.justReleased(); var mouseX:Number = FlxG.mouse.x; var mouseY:Number = FlxG.mouse.y; }
Variabel-variabel yang kita buat hanya lebih mudah digunakan daripada beberapa lama bernama fungsi (Flx.mouse.justPressed();
), dan itu semata-mata mereka. Mengetik metode tersebut, kami akan dapat hanya menggunakan variabel-variabel yang kami hanya menyatakan.
Langkah 15: Pilih sebuah permata
Sekarang kita perlu menempatkan beberapa kondisi sebelum kita benar-benar memilih sebuah permata, dan ini adalah:
if (released && mouseX > begX && mouseX < begX + columns * spaceX && mouseY > begY && mouseY < begY + rows * spaceY) { }
Kondisi pertama memastikan bahwa tombol mouse (ingat bahwa di Flash kami benar-benar dapat menggunakan hanya tombol kiri mouse) dirilis dalam kerangka ini permainan. Kedua, ketiga, maju dan kelima memastikan bahwa mouse berada di Dewan daerah kedua pada X
dan sumbu Y
, jika tidak maka seharusnya tidak mungkin untuk membuat pilihan. Jika pemutar mengklik di luar batas itu, itu harus berarti ia ingin melakukan sesuatu yang lain.
Sekarang bahwa kita memiliki kondisi kita, sudah waktunya untuk menambah bahkan lebih variabel yang akan membantu kita dalam menjelajahi Dewan permata!
if (pressed && mouseX > begX && mouseX < begX + columns * spaceX && mouseY > begY && mouseY < begY + rows * spaceY) { var rowID:uint = Math.floor((mouseY - begY) / spaceY); var columnID:uint = Math.floor((mouseX - begX) / spaceX); var id:uint = rowID * columns + columnID; }
Seperti yang Anda bisa menebak, rowID
dan columnID
melakukan hal yang sama itu selama posisi permata kami, tapi sekarang itu memegang baris dan kolom dari batu permata di bawah kursor. Kami menghitung ini dengan Math.floor ((mouseY-begY) / lalai)
untuk gem's baris, dan oleh Math.floor ((mouseX-begX) / spaceX)
untuk gem's kolom. Kemudian kami hanya menggunakan dua variabel tersebut untuk memberitahu id
tepatnya apa yang ID adalah di bawah kursor.
Sekarang untuk memilih permata kami kita hanya perlu memberitahu selID
bahwa beberapa jenis id
mendapat dipilih, kemudian membuat frame terlihat dan memindahkannya ke posisi permata itu:
selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y;
Menetapkan posisi mudah, kita tahu posisi yang tepat dari setiap permata, selama kita memiliki ID nya. Kita juga diberitahu selID
yang sekarang dipilih gem's ID sama dengan id
.
Mari kita mencoba dan melihat apakah ia bekerja baik:
Dengan pengujian, Anda dapat melihat bahwa tidak ada yang aneh tentang memilih, ia bekerja dengan cara yang seharusnya. Karena itu kita dapat melanjutkan ke langkah berikutnya.
Langkah 16: Konsep menukar dua permata
Mari kita merencanakan bagaimana menerapkan menukar dua permata. Ide pertama yang akan mungkin pop di kepala Anda adalah untuk membuat salinan mendalam permata yang pertama, menggantikan permata pertama dengan kedua, dan akhirnya menggantikan salinan mendalam yang kami buat sebelumnya dengan permata kedua, dengan cara ini kita akan bertukar easly cantik permata. Tentu saja itu bukan cara yang paling efisien melakukan hal itu, setelah semua dengan menukar saja kita membuat empat salinan. Untuk melakukan hal ini lebih efisien, kita hanya harus swap permata yang jenis dan mengubah animasi mereka sedang dimainkan. Cara ini kita akan menyelamatkan diri sendiri kesulitan menyalin. Hal lain adalah, bahwa kita seharusnya tidak hanya swap permata yang posisi segera, karena itu tidak akan terlihat sangat cantik. Kita perlu membuat transisi yang lancar dari posisi permata pertama, yang kedua, untuk kedua permata tentu. Saya telah diambil sketsa sederhana untuk membantu Anda memvisualisasikan apa akan terjadi kedua, pada layar dan dalam permainan:



Seperti yang Anda lihat, kami hanya memindahkan permata posisi permata lain, dan pada akhir kita hanya beralih mereka kembali ke posisi awal mereka, dengan jenis berubah. Cara kedua melakukan yang akan hanya reverse itu - kita akan swap permata posisi dan jenis di awal, dan kemudian membuat transistion untuk posisi awal mereka, tapi karena aku tidak ingin membuat Anda bahkan lebih bingung, kita akan tetap ke versi pada sketsa.
Hal pertama yang harus kita lakukan adalah untuk membuat sebuah fungsi yang akan memindahkan permata dari satu posisi ke yang lain, maka setelah mencapai posisi itu bergeser kembali, dan akhirnya mengubah jenis. Yang cukup banyak, tetapi kita dapat melakukan tugas-tugas ini satu per satu. Pertama mari kita pergi ke Gem.as dan mari kita membuat sebuah fungsi baru dalam Gem
kelas permata kami. Mari kita menyebutnya hanya move()
:
public function move(_x:Number, _y:Number, _type:int):void { }
Kita perlu menambahkan beberapa argumen, tetapi fungsi itu sendiri tidak akan terlalu rumit, sebagian besar bergerak akan benar-benar terjadi di update()
akan membuat. Dalam fungsi ini kita akan hanya menyimpan variabel, sehingga permata akan ingat mana seharusnya bergerak (_x, _y
), dimana seharusnya pergeseran setelah mencapai tujuan, dan apa jenis permata harus itu berubah menjadi, setelah pindah kembali ke asli posisi (_type
). Kita juga perlu untuk mengetahui apakah permata yang bergerak atau tidak. Mari kita mendeklarasikan variabel-variabel:
private var startX:int; //the x value that the gem will shift to after finishing moving private var startY:int; //the y value that the gem will shift to after finishing moving private var destX:int; //the x value that the gem moves to private var destY:int; //the y value that the gem moves to private var destType:uint; //the type that the gem will change into after finishing moving private var moving:Boolean = false; //is the gem moving?
Mari kita mengisi fungsi move()
kita sekarang:
public function move(_x:Number, _y:Number, _type:int):void { startX = x; startY = y; destX = _x; destY = _y; destType = _type; moving = true; }
Itu saja, hal berikutnya yang perlu kita lakukan adalah untuk menangani data ini di update()
akan membuat.
Langkah 17: Menangani Gem's gerakan
Saatnya untuk melihat fungsi update() akan membuat kami di kelas permata. Mari kita hanya mulai dengan menyatakan bahwa sesuatu harus terjadi ketika bergerak diatur ke true:
override public function update():void { super.update(); if (moving) { } }
Sekarang mari kita mengurus sebenarnya posisi berubah; untuk itu kami, jelas, perlu untuk mengetahui seberapa cepat permata harus bergerak. Mari kita menyatakan konstan baru:
private const speed:int = 450; //speed of the moving gem, pixels/second
Baik-baik saja sekarang bahwa selesai, mari kita pergi kembali ke update()-akan membuat kami. Kita tahu bahwa permata dapat bergerak dalam empat arah (kami tidak mendukung gerakan diagonal, tetapi bisa easly ditambahkan kemudian permainan selesai), itu juga perlu bergerak sampai mencapai tujuan akhir (destX, destY):
if (moving) { if (Math.abs(destX - x) < speed*FlxG.elapsed) x = destX; if (Math.abs(destY - y) < speed*FlxG.elapsed) y = destY; if (destX > x) x += speed*FlxG.elapsed; else if (destX < x) x -= speed*FlxG.elapsed; if (destY > y) y += speed*FlxG.elapsed; else if (destY < y) y -= speed*FlxG.elapsed; }
Karena kita tahu destX
dan destY
, itu mudah untuk mengubah posisi gem's. Kita hanya bergerak ke arah tujuan sampai x
sama dengan destX
, dan kami reapeat yang y
properti. Tentu saja itu tidak dapat benar-benar sama tapi perubahan posisi harus kurang dari satu langkah. Perhatikan bahwa kita menggunakan FlxG.elapsed
, dan kami multyplying dengan kecepatan kami. terus
berlalu nilai berapa banyak detik berlalu sejak frame terakhir. Jika kita multyplying kecepatan kami oleh itu, itu berarti bahwa kecepatan kami sekarang tidak 450px setiap bingkai, tapi 450px per detik, membuat bingkai-independen. Karena kita tidak mengimpor semua kelas flixel ke permata
, sekarang kita perlu mengimpor FlxG
, yang kita gunakan:
import org.flixel.FlxSprite; import org.flixel.FlxG;
Jadi sekarang kita hanya perlu berhenti, pergeseran permata untuk posisi awal, dan mengubah jenis.
Langkah 18: Menyelesaikan Gem's gerakan
Pertama, mari kita benar-benar memindahkan batu permata hanya jika x
dan y
tidak sama dengan destX
dan destY
, ada gunanya dalam bergerak jika kita sudah di tujuan kami:
if (destX != x || destY != y) { if (moving) { if (Math.abs(destX - x) < speed) x = destX; if (Math.abs(destY - y) < speed) y = destY; if (destX > x) x += speed; else if (destX < x) x -= speed; if (destY > y) y += speed; else if (destY < y) y -= speed; } } else if (moving) { }
Jika kami adalah tujuan kami, tetapi bergerak
masih set ke true
artinya kami hanya tiba di sana, dan sekarang adalah waktu untuk melakukan semua pergeseran dan mengubah tipe. Kita juga perlu mengubah pindah
ke palsu
:
else if (moving) { x = destX = startX; y = destY = startY; moving = false; type = destType; }
Baiklah, sekarang kita akan perlu mengubah animasi dengan cara yang sama kita lakukan di contructor. Tidak membuat kode kami lebih besar dari perlu, mari kita hanya membuat sebuah fungsi yang melakukan itu:
public function InitType():void { switch (type) { case 0: play("blue"); break; case 1: play("green"); break; case 2: play("orange"); break; case 3: play("aqua"); break; case 4: play("red"); break; case 5: play("yellow"); break; } }
Sekarang kita dapat hanya mengganti bagian yang sama dari kode dari konstruktor kami dengan panggilan sederhana untuk fungsi baru kami:
type = _type; InitType();
Dan akhirnya Mari kita tambahkan mana itu dibutuhkan di tempat pertama:
else if (moving) { x = destX = startX; y = destY = startY; moving = false; type = destType; InitType(); }
Langkah 19: Swap permata
Karena kita tampaknya dilakukan dengan bergerak, kita hanya perlu untuk mencobanya dan melihat apakah ia bekerja. Mari kita pergi ke GameState.as dan perubahan fungsi update kami sedikit:
for (var i:int = 0; i < gems.length; ++i) gems[i].update();
Pertama, kita perlu untuk memperbarui permata kami jika kita ingin melihat salah satu gerakan mereka. Sekarang bahwa kita telah diambil dari perawatan yang, mari kita pergi lebih dalam ke dalam fungsi update()
akan membuat kami. Jika setiap permata dipilih, mari kita membuat klik akan swap permata diklik dengan yang dipilih, dan secara otomatis menghapus pilihan:
if (selID == -1) { selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y; } else { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); selID = -1; frame.visible = false; }
Hal ini sangat mudah untuk memeriksa apakah permata apapun yang dipilih, sejak maka selID
berbeda dengan -1
. Jika selID
sama dengan-1
, kemudian kami sedang memilih sebuah permata yang diklik. Jika kita memiliki setiap permata yang dipilih sudah, kami menggunakan fungsi kami baru saja dibuat untuk swap permata yang posisi. Anda dapat melihat bahwa kita sedang menukar permata itu ID adalah selID - itu permata dipilih, dan kami akan bertukar dengan permata yang memiliki ID yang sama dengan id - yang merupakan permata yang diklik dalam kerangka ini. Sejak kami pindah permata dipilih, kita perlu bergerak yang lain juga, jadi itu bergerak ke posisi dipilih permata dan mendapat jenis
itu. Akhirnya kita set selID
ke-1
, mencatat bahwa ada tidak ada pilihan dan membuat pilihan bingkai tidak terlihat (karena tidak ada permata itu bisa mengarah ke). Mari kita menguji proyek kami dan melihat apakah ia bekerja:
gems[selID].move(gems[id].x, gems[id].y, gems[id].type);
Ketika kita mencoba untuk swap permata, jendela output akan menunjukkan kesalahan yang pada dasarnya menjelaskan mengapa melakukan istirahat kode kami. Hal ini terjadi, karena GameState tidak dapat mengakses jenis properti di kelas permata. Itulah sebabnya begitu karena kita menyatakan jenis sebagai variabel pribadi, dan itu berarti kita benar-benar tidak dapat mengaksesnya di luar kelas kita dinyatakan dalam. Kita bisa melakukan dua hal tentang hal ini, baik mengubahnya dari pribadi untuk umum atau untuk menyediakan fungsi umum yang hanya akan kembali jenis permata. Umumnya pilihan kedua bijaksana untuk menggunakan, tetapi karena kita satu-satunya yang bekerja pada proyek ini, benar-benar tidak peduli banyak, kita hanya dapat mengubah pribadi ke publik di Gem.as kami:
public var type:uint;
Sekarang mari kita coba lagi dan periksa apakah itu bekerja:
Ya itu tidak, dan itu tidak cukup baik. Jika Anda berpikir kecepatan harus berbeda, Anda dapat selalu mengatur yang terus-menerus kita menyatakan dalam Gem.as apa pun yang Anda suka. Perhatikan bahwa untuk sekarang kita tidak membuat batasan dan Anda dapat swap permata yang Anda inginkan.
Langkah 20: Konsep membersihkan permata
Sekarang saatnya untuk menghapus beberapa permata dari papan kami. Untuk sekarang kita akan pergi mencari setiap pertandingan untuk nanti, dan akan berkonsentrasi pada membersihkan permata kita inginkan, itu akan mudah untuk membersihkan pertandingan kemudian jika kita melakukan ini sekarang. Tentu saja kita tidak melakukan apa-apa seperti menghapus permata dari array, tidak, ini tidak akan terlalu efisien dan akan mengacaukan kami array yang cukup banyak. Sekali lagi aku punya beberapa sketsa disiapkan, mereka akan membantu Anda memahami gagasan untuk melaksanakan fungsi kliring, meskipun saat ini tidak benar-benar sesuatu yang rumit:






Kami hanya skala ke permata yang kita ingin jelas. Kami akan berangkat permata yang tak terlihat di papan untuk sekarang. Setelah membersihkan mereka akan perlu dipindahkan sebelum permata di atas mereka akan jatuh, tapi kami akan melakukannya ketika kita akan menciptakan fungsi fall()
kita, sekarang mari kita berkonsentrasi pada tugas kita saat ini.
Langkah 21: Skala ke permata
Mari kita buka Gem.as dan menyatakan dua variabel yang baru di sana. Kita harus tahu kapan untuk skala turun dan berapa lama scaling turun harus dilakukan:
private const speed:int = 450; //speed of the moving gem, pixels/second private const dieTime:Number = 0.5; //time taking to scale down from 1.0 to 0.0 in seconds public var type:uint; private var startX:int; //the x value that the gem will shift to after finishing moving private var startY:int; //the y value that the gem will shift to after finishing moving private var destX:int; //the x value that the gem moves to private var destY:int; //the y value that the gem moves to private var destType:uint; //the type that the gem will change into after finishing moving private var moving:Boolean = false; //is the gem moving? private var dying:Boolean = false; //is the gem scaling down?
Aku memanggil mereka dua baru dieTime
variabel dan mati
. dieTime
memegang waktu scaling permata turun dan mati
akan menunjukkan kepada kita Apakah kita sedang scaling turun atau tidak. Sekarang mari kita menciptakan metode baru, yang hanya akan mengubah scaling turun pada:
public function die():void { dying = true; }
Sekarang kami harus menangani scaling permata turun.
Langkah 22: Menangani Scaling turun
Pergi ke fungsi update()
akan membuat kami di Gem.as, dan mari kita menambahkan pernyataan bersyarat yang baru:
else if (moving) { x = destX = startX; y = destX = startY; moving = false; type = destType; InitType(); } else if (dying) { }
Sekarang mari kita hanya skala permata, secara vertikal dan horizontal. Jika skala lebih rendah dari atau sama dengan 0
, mari kita berhenti scaling itu:
else if (dying) { if (scale.x > 0) { scale.x -= FlxG.elapsed/dieTime; scale.y -= FlxG.elapsed/dieTime; } else { scale.x = 0; scale.y = 0; dying = false; } }
Dan itu akan untuk gem's tindakan. Sekarang sisa pekerjaan terletak pada permainan logika.
Langkah 23: Kosongkan permata
Baiklah, saatnya untuk menguji fungsi clear()
. Pertama, mari kita komentar kami memilih dan mari kita membuatnya clear()
permata kursor menunjuk ke sebaliknya:
if (selID == -1) { gems[id].die(); /* selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y;*/ }
Jika Anda menjalankan permainan sekarang Anda akan melihat bahwa tidak ada yang terjadi berdasarkan klik. Setelah menempatkan beberapa breakpoints, mereka menunjukkan kita kepada penyebab ini, dan akar yang ada di sini:
if (destX != x || destY != y) { if (moving) { if (Math.abs(destX - x) < speed*FlxG.elapsed) x = destX; if (Math.abs(destY - y) < speed*FlxG.elapsed) y = destY; if (destX > x) x += speed*FlxG.elapsed; else if (destX < x) x -= speed*FlxG.elapsed; if (destY > y) y += speed*FlxG.elapsed; else if (destY < y) y -= speed*FlxG.elapsed; } }
Karena kami awalnya tidak menetapkan destX
dan destY
untuk x
dan y
, kita sudah masa lalu melalui kondisi pertama, tetapi kami tidak berhasil melewati kedua. Mari kita menambahkan beberapa kode untuk memperbaiki itu, begitu destX
dan destY
akan sama dengan x
dan y
, ketika permata tidak bergerak:
if (destX != x || destY != y) { if (moving) { if (Math.abs(destX - x) < speed*FlxG.elapsed) x = destX; if (Math.abs(destY - y) < speed*FlxG.elapsed) y = destY; if (destX > x) x += speed*FlxG.elapsed; else if (destX < x) x -= speed*FlxG.elapsed; if (destY > y) y += speed*FlxG.elapsed; else if (destY < y) y -= speed*FlxG.elapsed; } else { destX = x; destY = y; } }
Sekarang karena kita tidak akan pergi melalui kondisi pertama, kami lain
sebelum jika (mati)
tidak akan mengacaukan sesuatu. Mari kita coba untuk menjalankan proyek sekali lagi dan melihat apakah ia bekerja:
Kliring bekerja dengan baik, ingatlah bahwa Anda dapat mengubah saat scaling dengan mengubah dieTime
di Gem.as.
Langkah 24: Konsep pemijahan permata baru
Saatnya untuk berpikir bagaimana kita akan melaksanakan pemijahan permata baru. Hal pertama yang kita harus lakukan adalah untuk beralih permata dibersihkan di atas papan, mengacak jenis mereka dan membiarkan semua permata jatuh jarak yang dibersihkan. Tentu saja, setelah semua jatuh ke bawah kami akan memindahkan mereka ke posisi mereka awal dengan mengubah jenis, dengan cara yang sama kita lakukan saat kita telah menukar permata! Berikut adalah beberapa sketsa yang menunjukkan konsep ini:












Saya berharap hal ini jelas, pastikan Anda memahami semua itu karena sekarang kita akan menulis sebuah metode yang akan melakukan semua ini bagi kita.
Langkah 25: Mempersiapkan permata jatuh
Sebelum kita mulai menulis fungsi fall()
kami, mari kita pergi ke Gem.as dan mari kita pertama membuat fungsi di sini. Kita akan menyebutnya recreate()
, itu hanya akan mengubah jenis permata untuk satu acak dan bermain animasi yang melekat pada tipe
:
public function recreate(types:int):void { moving = dying = false; type = Math.floor(Math.random() * types); InitType(); }
Kami juga mengatur bergerak
dan mati
untuk nilai-nilai awal mereka. Anda harus juga telah memperhatikan bahwa pada sketsa tidak semua permata bisa kembali ke posisi sebelumnya, misalnya dibersihkan permata tidak boleh kembali di atas papan, tapi untuk posisi awal mereka. Kita harus membuat fungsi lain yang akan biarkan kami memutuskan mana permata harus bergeser, setelah itu succefully pindah ke tujuan. Mari kita menyatakan fungsi kami untuk tujuan itu:
public function moveToShift(_x:Number, _y:Number, shiftX:Number, shiftY:Number, _type:int):void { startX = shiftX; startY = shiftY; destX = _x; destY = _y; destType = _type; moving = true; }
Seperti yang Anda lihat, kami hanya menambahkan dua argumen: shiftX
, licik, dan kami mengatur startX, startY
ke nilai bukan untuk x, y. sejak sambil menangani gerakan kemudian kita beralih permata kami ke startX, startY,
jika kita menggunakan fungsi ini, permata akan bergeser ke shiftX
, licik isntead. Saya berharap hal ini tidak membingungkan Anda, itu sebenarnya cukup sederhana jika Anda masih ingat gerakan penanganan kode.
Langkah 26: Pergeseran permata dibersihkan
Mari kita kembali ke GameState.as kami dan di sini juga, membuat sebuah fungsi baru:
/* * fall function will let blocks fall if there is "no block" underneath * them * * * columnID - in which column does the falling occur * * rowID - in which row is the LAST (the lowest one) block * * blockCount - how many blocks (vertically) were destroyed * * */ public function fall(columnID:uint, rowID:uint, gemCount:uint):void { }
Kami akan mengambil columnID, rowID
blok terakhir dalam pertandingan (yang terendah) sebagai argumen, dan tentu saja kita perlu tahu berapa banyak permata yang ada di pertandingan, yang adalah apa gemCount
untuk. Mari kita mulai dari pengaturan permata dibersihkan lagi:
var last:int = columns * rowID + columnID; //setting all cleared blocks and making them into new ones for (var i:int = 0; i < gemCount; ++i) { gems[last - i * columns].y = begY - (i+1) * offsetY; gems[last - i * columns].scale = new FlxPoint(1.0, 1.0); gems[last - i * columns].recreate(types); }
Tidak banyak yang menjelaskan di sini, seperti yang Anda lihat kami menghitung ID dari permata terakhir (satu di baris terendah) dan menyimpannya dalam variabel terakhir
. Setelah itu, kami pergeseran dibersihkan permata di atas papan, skala mereka kembali ke ukuran penuh dan menggunakan fungsi baru dibuat recreate
() kita untuk mengubah jenis dibersihkan permata. Sekarang mari kita benar-benar memindahkan permata ke posisi mereka ditakdirkan:
Langkah 27: Biarkan permata jatuh
Mari kita mulai dari loop. Loop kami menggunakan dihitung mulai dari permata dibersihkan terakhir sampai satu di baris 0
. Jika kita jelas permata di satu kolom, permata akan jatuh hanya dalam kolom:
for (var n:int = last; n >= 0 ; n -= columns) { }
Sekarang kita dapat pergi dan bergerak permata. Kita hanya bergerak permata saat ini kami sedang memproses (n
) turun jarak sama dengan jumlah dibersihkan permata (gemCount
), dikalikan dengan lalai, yang membuat mereka pada dasarnya menggantikan gem gemCount
baris di bawah ini. Jika Anda masih tidak bisa membayangkan itu kemudian menggunakan contoh, jika kita sedang membersihkan pertandingan tiga permata, setiap permata di atas orang permata yang cocok akan harus memindahkan 3 baris di bawah baris sendiri. Ingat bahwa kita beralih permata kembali kemudian jadi permata harus mengubah jenis
jenis
permata yang akan menggantikannya. Permata harus mengubah jenis
jenis
baris gemCount
permata di atasnya. Dalam contoh, jika kita cocok tiga permata, batu permata akan perlu untuk mengubah jenis yang baris tiga permata di atasnya. Berikut adalah semua yang penjelasan dimasukkan ke dalam kode:
for (var n:int = last; n >= 0 ; n -= columns) { gems[n].move(gems[n].x, gems[n].y + gemCount * offsetY, gems[n - gemCount * columns].type); }
Langkah 28: Menangani kasus-kasus khusus
Tapi itu hanya puncak gunung es. Kita perlu untuk menutup kasus-kasus lain, karena dalam beberapa solusi ini tidak akan bekerja. Misalnya permata dibersihkan, dalam hal ini mereka harus bergeser tidak di atas papan, yang adalah posisi mereka saat ini sekarang, tapi untuk posisi mereka mantan. Kami menciptakan fungsi untuk membantu kami melakukan itu sebelumnya, sekarang kita hanya perlu menggunakannya. Jadi, pertama-tama, kita perlu membedakan permata dibersihkan dari yang lain. Itu cukup sederhana, kita tahu ID dari permata dibersihkan terakhir, jadi kita juga tahu bahwa setiap permata hingga gemCount
baris - 1
di atas itu, juga dihapus:
for (var n:int = last; n >= 0 ; n -= columns) { if (n >= last - (gemCount - 1) * columns) { gems[n].moveShift(gems[n].x, gems[n].y + gemCount * spaceY, gems[n].x,begY + Math.floor(n / columns) * spaceY, gems[n - gemCount * columns].type); { else { gems[n].move(gems[n].x, gems[n].y + gemCount * spaceY, gems[n - gemCount * columns].type); } }
Sekarang perhatikan, bahwa kita tidak bisa hanya mengubah jenis semua permata kami seperti itu. Itu karena beberapa permata... memiliki ada permata di atas mereka! Dan aku tidak berbicara tentang permata yang dihapus dan posisi mereka adalah yang tertinggi. Aku berbicara tentang permata yang berada di baris atas Dewan. Sebagai contoh, sebuah permata dari baris 0
tidak beralih jenis
yang permata dalam baris -1,
karena seperti permata yang tidak ada! Permata tertinggi yang perlu untuk mendapatkan jenis
baru mereka dari permata yang dibersihkan, dan id permata yang dibersihkan yang sebenarnya cukup jauh dari mereka. Jadi sekarang kita perlu membedakan permata yang bisa mendapatkan ID baru mereka cara langsung antara orang-orang yang tidak bisa. Hal ini cukup sederhana karena orang-orang yang tidak bisa selalu id terendah. ID mereka harus lebih rendah daripada gemCount * kolom:
for (var n:int = last; n >= 0 ; n -= columns) { if (n >= gemCount * columns) { if (n >= last - (gemCount - 1) * columns) { gems[n].moveShift(gems[n].x, gems[n].y + gemCount * spaceY, gems[n].x,begY + Math.floor(n / columns) * spaceY, gems[n - gemCount * columns].type); { else { gems[n].move(gems[n].x, gems[n].y + gemCount * spaceY, gems[n - gemCount * columns].type); } else { } }
Langkah 29: Menangani kasus-kasus lebih khusus
Kami hampir di sana! Perhatikan bahwa permata di baris tertinggi juga dapat dihapus, itu berarti kita akan membutuhkan struktur yang sama seperti yang di atas:
for (var n:int = last; n >= 0 ; n -= columns) { if (n >= gemCount * columns) { if (n >= last - (gemCount - 1) * columns) { gems[n].moveShift(gems[n].x, gems[n].y + gemCount * spaceY, gems[n].x,begY + Math.floor(n / columns) * spaceY, gems[n - gemCount * columns].type); { else { gems[n].move(gems[n].x, gems[n].y + gemCount * spaceY, gems[n - gemCount * columns].type); } else { if (n >= last - (gemCount - 1) * columns) { } else { } } }
Sekarang Anda dapat melihat bahwa kita perlu variabel penolong lain yang akan membantu kita menghitung permata dari terakhir ke atas. Mari kita menyatakan karena ini akan membantu kami iterate dapat nama satu huruf, misalnya h
. Jadi, kami akan menggunakannya untuk membantu kita menghitung gem yang (yang bisa mendapatkan jenis
baru dari permata apapun di atas) harus mendapatkan jenis
dari permata yang dibersihkan. It's pretty mudah untuk membayangkan, permata tertinggi harus mendapatkan jenis
dari permata dibersihkan tertinggi, dan permata terakhir (dari mereka yang tidak bisa mendapatkan jenis dari atas!) harus akhirnya mendapatkan jenis
dari permata terakhir yang dibersihkan. Sketsa kecil di sini:



Penjelasan cukup, mari kita kode itu:
var h:int = 0; for (var n:int = last; n >= 0 ; n -= columns) { if (n >= gemCount * columns) { if (n >= last - (gemCount - 1) * columns) { gems[n].moveShift(gems[n].x, gems[n].y + gemCount * spaceY, gems[n].x,begY + Math.floor(n / columns) * spaceY, gems[n - gemCount * columns].type); { else { gems[n].move(gems[n].x, gems[n].y + gemCount * spaceY, gems[n - gemCount * columns].type); } else { if (n >= last - (gemCount - 1) * columns) { gems[n].moveToShift(gems[n].x, gems[n].y + gemCount * spaceY, gems[n].x, begY + Math.floor(n / columns) * spaceY, gems[last - h * columns].type); } else { gems[n].move(gems[n].x, gems[n].y + gemCount * spaceY, gems[last - h * columns].type); } ++h; } }
Kami, tentu saja, harus meningkatkan nilai h
sehingga ia akan menunjuk ke permata yang lebih tinggi dan lebih tinggi di atas (yang memiliki ID lebih rendah dan lebih rendah!) dengan setiap langkah loop. Kita sudah selesai!
Langkah 30: Tes jatuh
Mari kita gunakan trik yang sama kita gunakan untuk memeriksa kliring. Mari kita pergi ke update()
akan membuat fungsi GameState.as kami, dan mari kita membunuh, mengatakan, tiga permata dan segera setelah itu memanggil fungsi fall()
kami. Perhatikan bahwa karena kita tidak benar-benar memberikan setiap saat untuk scaling turun animasi, permata yang akan segera respawned. Tidak akan terlihat baik, tetapi untuk tujuan pengujian, sangat baik untuk melakukannya!
if (selID == -1) { gems[id].die(); gems[id - columns].die(); gems[id - columns * 2].die(); fall(columnID, rowID, 3); /* selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y;*/ }
Kami sedang membersihkan permata kita diklik pada dan juga dua permata di atasnya. Itu berarti kita tidak bisa benar-benar klik pada setiap permata dari baris pertama atau kedua, karena kemudian kami akan mencoba untuk membunuh permata yang tidak ada. Mari kita cepat menambahkan kondisi untuk mencegah kesalahan dalam kasus kita klik terlalu tinggi pula:
if (selID == -1) { if (rowID >= 2) { gems[id].die(); gems[id - columns].die(); gems[id - columns * 2].die(); fall(columnID, rowID, 3); } /* selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y;*/ }
Sekarang seharusnya tidak ada masalah, jika Anda secara tidak sengaja mengklik terlalu tinggi, tidak ada yang buruk akan terjadi. Itu adalah semua tentang! Kita dapat menguji permainan sekarang:
Ia bekerja!
Step 31: Membuat cek untuk metode pertandingan
Sekarang saatnya untuk menulis fungsi yang akan mengenali pertandingan. Ini tidak akan menjadi rumit sebagai fungsi fall()
kami, sehingga Anda dapat yakin. Fungsi ini akan menghitung berapa banyak permata dari jenis
yang sama yang ada di atas batu permata kami bertukar, di bawah ini, dan untuk kedua sisi itu. Mari kita mulai dengan menyatakan fungsi dalam GameState.as:
public function preCheck(clears:Array, id:uint, type:uint, skipID:uint):Boolean { }
membersihkan
akan digunakan sebagai referensi untuk sebuah array yang akan memegang variabel yang kita ingin mengubah ke dalam angka permata dari jenis yang sama sebagai permata kami ke sisi itu. Sebagai contoh jika kita mendeklarasikan array baru dan menyebutnya someArray
, dan jika kita melewati array sebagai argumen ke fungsi ini, fungsi akan mengubah nilai-nilai someArray [0], someArray [1], someArray [2] someArray [3]
dengan nomor permata dengan jenis yang sama sebagai permata kami diperiksa untuk memang benar, kiri, bawah dan atas masing-masing.
membersihkan [0]
akan mengadakan berapa banyak permata dari jenis yang sama di sisi kanan permata diperiksa, membersihkan [1]
di sisi kiri, membersihkan [2]
di bawah permata memeriksa dan membersihkan [3]
di atasnya. Saya berharap hal ini tidak membingungkan Anda, itu sebenarnya lebih mudah untuk mendapatkan ini dengan hanya menggunakan fungsi dan menonton apa yang terjadi!
Argumen berikutnya yang id
, yang pada dasarnya adalah ID dari permata kami diperiksa, jenis
yang pada dasarnya adalah jenis permata kami diperiksa
(Perhatikan bahwa karena kita harus check()
untuk pertandingan sebelum kita swap permata, kita perlu menggunakan jenis permata kita swap dengan) , dan akhirnya skipID
yang menceritakan yang ID harus kami melewatkan saat memeriksa apakah permata berikutnya adalah dari jenis yang sama atau tidak (yang juga karena kita perlu check()
untuk pertandingan sebelum kita benar-benar swap permata, karena kita sedang memeriksa jenis
permata kita swap dengan , kami tidak dapat menyertakan permata itu sebagai permata dari jenis yang sama, karena jenis
itu akan berubah di akhir swap! Itu bisa bekerja hanya jika keduanya swap permata adalah dari jenis
yang sama, tetapi menukar mereka tidak masuk akal tidak? Hal ini tentu saja tidak bisa menghasilkan pertandingan baru!).
Perhatikan bahwa kami juga sedang kembali nilai Boolean
dalam fungsi ini. Kami akan mengembalikan true
jika ada pertandingan, dan false
jika tidak ada. Oh, dan ingat bahwa kami harus menggunakan array, karena jika kita menggunakan tipe sederhana seperti int, uint, nomor,
kemudian ia tidak akan dilewatkan ke ini berfungsi sebagai referensi, tetapi sebagai salinan.
Langkah 32: Periksa permata di sebelah kanan
Sekarang karena semuanya dijelaskan kita bisa menulis. Pertama kita harus menetapkan variabel semuanya jelas
ke 0, sehingga kita tidak sengaja mendapatkan dalam kesulitan apapun:
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0;
Kedua, mari kita periksa permata yang ada di sisi kanan kami, ingat bahwa karena kita sedang memeriksa ID dari permata, kita juga perlu memastikan bahwa kita tidak pergi ke baris berikutnya! Jika kita ingat bahwa, maka sisanya sederhana, kami sedang memeriksa apakah permata di sebelah kanan adalah dari jenis
yang kita sedang mencari. Jika itu benar, maka kita kenaikan kami membersihkan [0]
variabel dan memeriksa permata berikutnya, jika itu lagi dari jenis yang sama, kami kenaikan membersihkan [0]
lagi-lagi, dan begitu, dan sebagainya. Tentu saja jika kita tersandung pada ID kita perlu melewatkan maka kita hanya istirahat
loop:
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0; //going right, checking if we are in the same row for (var i:int = 1; Math.floor((id + i)/columns) == Math.floor((id)/columns); ++i) { if (gems[id + i].type == type && id + i != skipID) ++clears[0]; else break; }
Kondisi terus loop kami adalah baris permata dengan ID kita memeriksa ((id + saya)
) sama dengan permata kami diperiksa ID (id
). Hal ini cukup sederhana.
Langkah 33: Periksa selama sisa arah
Sekarang saatnya untuk memeriksa sisa arah. Untuk sebelah kiri kode hampir identik, tapi sekarang karena kita akan pergi kiri, kita akan perlu untuk mengurangi id
, alih-alih meningkatkan dengan permata dicentang masing-masing:
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0; //going right, checking if we are in the same row for (var i:int = 1; Math.floor((id + i)/columns) == Math.floor((id)/columns); ++i) { if (gems[id + i].type == type && id + i != skipID) ++clears[0]; else break; } //nearly the same loop, but we will go left this time for (var j:int = 1; Math.floor((id - j)/columns) == Math.floor((id)/columns); ++j) { if (gems[id - j].type == type && id - j != skipID) ++clears[1]; else break; }
Setelah itu, kita akan turun, jadi kita akan perlu untuk mengubah baris. Jika hal ini terjadi, kita perlu berhati-hati untuk tidak melangkah keluar dari batas-batas Dewan!
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0; //going right, checking if we are in the same row for (var i:int = 1; Math.floor((id + i)/columns) == Math.floor((id)/columns); ++i) { if (gems[id + i].type == type && id + i != skipID) ++clears[0]; else break; } //nearly the same loop, but we will go left this time for (var j:int = 1; Math.floor((id - j)/columns) == Math.floor((id)/columns); ++j) { if (gems[id - j].type == type && id - j != skipID) ++clears[1]; else break; } //now we're going down, we need to check whether we are not going out of lower bounds for (var z:int = columns; id + z < gems.length; z += columns) { if (gems[id + z].type == type && id + z != skipID) ++clears[2]; else break; }
Akhirnya Mari kita periksa permata di atas. Kita masih perlu berhati-hati untuk tidak melangkah keluar dari batas-batas papan kami:
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0; //going right, checking if we are in the same row for (var i:int = 1; Math.floor((id + i)/columns) == Math.floor((id)/columns); ++i) { if (gems[id + i].type == type && id + i != skipID) ++clears[0]; else break; } //nearly the same loop, but we will go left this time for (var j:int = 1; Math.floor((id - j)/columns) == Math.floor((id)/columns); ++j) { if (gems[id - j].type == type && id - j != skipID) ++clears[1]; else break; } //now we're going down, we need to check whether we are not going out of lower bounds for (var z:int = columns; id + z < gems.length; z += columns) { if (gems[id + z].type == type && id + z != skipID) ++clears[2]; else break; } //and finally up, this time we just check for upper bound for (var m:int = columns; id - m >= 0; m += columns) { if (gems[id - m].type == type && id - m != skipID) ++clears[3]; else break; }
That's it! Sekarang kita tahu berapa banyak permata di setiap arah kami permata (tidak termasuk orang-orang diagonal).
Langkah 34: Periksa untuk pertandingan
Sekarang kita perlu untuk mengembalikan true
atau false
, tergantung apakah ada pertandingan setidaknya tiga permata di baris atau kolom:
//return true if there is a streak of 3 or more gems along any axis if (clears[3] + clears[2] >= 2 || clears[1] + clears[0] >= 2) return true; else return false;
Dan kita sudah selesai! Atau kita akan menjadi, jika tidak satu sedikit detail yang akan keluar untuk siang cepat atau lambat... untuk melihat hal itu, mari kita pertimbangkan kasus khusus seperti:



Seperti yang Anda lihat, dengan fungsi kita semua empat permata akan dianggap cocok! Fungsi akan kembali benar
, dan membersihkan [0]
akan memiliki nilai 1
, dan kemudian kita akan jelas bahwa permata tambahan, sayangnya. Untuk memperbaiki bahwa kita hanya harus menetapkan variabel kembali ke 0
jika ada tidak cocok pada sumbu mereka:
//if there are fewer than 3 gems in a row on either of the axes, we don't care about them if (clears[3] + clears[2] <= 1) { clears[3] = 0; clears[2] = 0; } if (clears[1] + clears[0] <= 1) { clears[1] = 0; clears[0] = 0; } //return true if there is a streak of 3 or more gems at any axis if (clears[3] + clears[2] >= 2 || clears[1] + clears[0] >= 2) return true; else return false;
Saat ini kita benar-benar selesai! Mari kita lihat pada fungsi akhir kami:
public function check(clears:Array, id:uint, type:uint, skipID:uint):Boolean { /* * 0 - RIGHT * 1 - LEFT * 2 - DOWN * 3 - UP */ clears[3] = clears[2] = clears[1] = clears[0] = 0; //going right, checking if we are in the same row for (var i:int = 1; Math.floor((id + i)/columns) == Math.floor((id)/columns); ++i) { if (gems[id + i].type == type && id + i != skipID) ++clears[0]; else break; } //nearly the same loop, but we will go left this time for (var j:int = 1; Math.floor((id - j)/columns) == Math.floor((id)/columns); ++j) { if (gems[id - j].type == type && id - j != skipID) ++clears[1]; else break; } //now we're going down, we need to check whether we are not going out of lower bounds for (var z:int = columns; id + z < gems.length; z += columns) { if (gems[id + z].type == type && id + z != skipID) ++clears[2]; else break; } //and finally up, this time we just check for upper bound for (var m:int = columns; id - m >= 0; m += columns) { if (gems[id - m].type == type && id - m != skipID) ++clears[3]; else break; } //if there's less than 3 gems in a row on either of the axes, we don't care about them if (clears[3] + clears[2] <= 1) { clears[3] = 0; clears[2] = 0; } if (clears[1] + clears[0] <= 1) { clears[1] = 0; clears[0] = 0; } //return true if there is a streak of 3 or more gems at any axis if (clears[3] + clears[2] >= 2 || clears[1] + clears[0] >= 2) return true; else return false; }
Langkah 35: Periksa, Swap, jelas & jatuh Bagian 1
Ini adalah waktu untuk mengumpulkan semua fungsi yang kami bekerja pada, dan menggunakannya untuk membuat permainan dimainkan. Hal pertama yang harus kita lakukan adalah pergi ke fungsi update()
akan membuat kami di GameState.as, dan kembali ke keadaan sebelumnya, yakni menukar permata setelah mengklik pada mereka:
if (selID == -1) { selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y; } else { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); selID = -1; frame.visible = false; }
Sekarang mari kita tambahkan beberapa pembatasan untuk bertukar, pemain harus mampu swap hanya tetangga permata. Permata dipilih ID dapat:
- Tinggi oleh
1
, tapi permata harus tetap berada di baris yang sama - Menurunkan dengan
1
, tapi sekali lagi, permata harus tetap berada di baris yang sama - Lebih tinggi oleh
kolom
- Lebih rendah oleh
kolom
if (selID == -1) { selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y; } else if (((selID == id - 1 || selID == id + 1) && rowID == Math.floor(selID / columns)) || selID == id + columns || selID == id - columns) { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); selID = -1; frame.visible = false; }
Akhirnya, kita juga harus Hapus permata jika pemain tidak klik pada salah satu permata tetangga:
if (selID == -1) { selID = id; frame.visible = true; frame.x = gems[selID].x; frame.y = gems[selID].y; } else if (((selID == id - 1 || selID == id + 1) && rowID == Math.floor(selID / columns)) || selID == id + columns || selID == id - columns) { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); selID = -1; frame.visible = false; } else { border.visible = false; selID = -1; }
Dan kami selesai dengan menciptakan pembatasan. Mari kita menjalankan permainan dan melihat jika kita pasti bisa bertukar hanya permata tetangga:
That's right, semuanya berjalan seperti yang direncanakan.
Langkah 36: Periksa, Swap, jelas & jatuh Bagian 2
Sekarang bahwa kita tahu pemain diklik permata yang dapat ditukar (itu adalah langsung berikutnya ke, diatas atau dibawah itu), kita perlu memeriksa jika permata ini setelah menjadi bertukar akan membuat pertandingan. Kita akan menggunakan fungsi check()
kita untuk itu. Sekarang mari kita ciptakan array dua yang akan terus membersihkan [3], membersihkan [2], membersihkan [1], membersihkan [0]
dan Boolean dua yang akan memegang nilai kembali fungsi check()
, untuk setiap swap permata:
private var stCheck:Boolean = false;//boolean that holds the value returned by check() for the first swapped gem private var ndCheck:Boolean = false;//boolean that holds the value returned by check() for the second swapped gem private var st:Array = new Array(); //array that will hold numbers of cleared gems to the sides of the first swapped gem private var nd:Array = new Array(); //array that will hold numbers of cleared gems to the sides of the second swapped gem
Mari kita juga mendorong empat uints
ke mereka dalam konstruktor kami:
frame.visible = false; for (var j:int = 0; j < 4; ++j) { st.push(0); nd.push(0); } }
Langkah 37: Periksa, Swap, jelas & jatuh bagian 3
Mari kita pergi kembali ke update()
akan membuat dan memeriksa untuk pertandingan sebelum kita swap permata. Kita juga perlu untuk mencegah selID
kami mengubah dengan-1
segera (jika kita menemukan kecocokan), karena kita masih akan membutuhkannya:
else if (((selID == id - 1 || selID == id + 1) && rowID == Math.floor(selID / columns)) || selID == id + columns || selID == id - columns) { stCheck = check(st, selID, gems[id].type, id); ndCheck = check(nd, id, gems[selID].type, selID); if (stCheck || ndCheck) { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); } else selID = -1; frame.visible = false; }
Untuk membuat hal-hal yang lebih elegan, kami menetapkan nilai kembali dari check()
untuk variabel-variabel yang kita buat untuk tujuan ini. Kemudian hanya sebelum menukar permata kami memeriksa apakah kita akan mendapatkan setiap pertandingan setelah menukar. Jika kita lakukan, maka kita akan membiarkan permata yang bergerak, jika tidak, kita tidak melakukan apa pun tetapi Hapus permata.
Langkah 38: Periksa, Swap, jelas & jatuh Bagian 4
Sekarang kita akan memiliki untuk menghapus permata setelah menukar mereka, tapi kami tidak bisa benar-benar melakukannya segera. Kita perlu timer yang marilah kita akan menangani kliring sedikit kemudian daripada segera, dan untuk bahwa kita juga perlu beberapa variabel tambahan. Beberapa di antaranya akan menunjukkan bahwa kita sedang menunggu sampai kami dapat menangani misalnya kliring permata dan beberapa di antaranya akan konstanta yang akan terus waktu kita perlu menunggu sampai kami dapat melakukan tindakan tertentu. Mari kita menambahkan mereka ke puncak GameState.as kami:
private const swapTime:Number = 1.0; //time needed for swapping the gems to finish private const clearTime:Number = 1.0; //time needed for clearing the gems to finish private const fallTime:Number = 1.0; //time needed for falling gems to finish
private var swapping:Boolean = false; //are the gems swapping? private var clearing:Boolean = false; //are the gems being cleared? private var falling:Boolean = false; //are the gems falling? private var timer:Number = 0.0; //all prupose timer
Langkah 39: Periksa, Swap, jelas & jatuh Bagian 5
Sekali lagi, mari kita kembali ke fungsi update()
akan membuat kami di GameState.as, dan ketika kami bergerak permata, mari kita menetapkan swapping
untuk benar:
if (stCheck || ndCheck) { gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); swapping = true; }
Sekarang bahwa permainan kami tahu bahwa kami sedang menukar permata, mari kita menangani hal itu secara terpisah:
if (swapping) { timer += FlxG.elapsed; if (timer >= swapTime) { swapping = false; timer = 0.0; } }
Ketika menukar selesai, kita juga harus mulai membersihkan permata yang cocok. Kita tidak boleh meletakkan kode terlalu banyak dalam fungsi update()
akan membuat kita karena itu akan tumbuh rumit, jadi mari kita menyatakan fungsi baru bernama clear()
, yang kita akan menggunakan di sini nanti.
Langkah 39: Periksa, Swap, jelas & jatuh Bagian 6
Mari kita mulai menciptakan fungsi kita. Langkah pertama akan menjadi menyatakan itu, mari kita mengatakan, di atas fungsi update()
akan membuat (we're masih dalam GameState.as):
public function clear():void { }
Ada tiga kasus yang kita harus menyadari: yang pertama adalah, bahwa kedua swap permata tampaknya dalam pertandingan setelah swap, dan kita perlu menghapus pertandingan kedua; yang kedua adalah, hanya permata pertama menemukan sebuah pertandingan; dan final ketiga kasus itu hanya permata kedua telah menemukan sebuah pertandingan:
public function clear():void { if (stCheck && ndCheck) { } else if (stCheck) { } else { } }
Sekarang kami hanya tugas adalah untuk membuat semua permata dalam pertandingan untuk die()
. Itulah nama menyeramkan salah satu fungsi sekarang yang saya pikir dari itu... Toh, mari kita mulai dari kasus yang paling sulit, yang pertama. Untuk kesederhanaan, mari kita membuat variabel baru bahwa kita akan mampu menggunakan bukan st [0], st [1]
dan sebagainya, karena itu akan menjadi tidak nyaman:
public function clear():void { if (stCheck && ndCheck) { var clearRight:uint = st[0]; var clearLeft:uint = st[1]; var clearDown:uint = st[2]; var clearUp:uint = st[3]; } else if (stCheck) { } else { } }
Sekarang kita dapat menggunakan clearRight, clearLeft, clearDown, clearUp
, yang merupakan cukup sedikit lebih mudah. Hal pertama yang perlu kita lakukan, adalah untuk mengetahui apakah kita harus membersihkan permata di sumbu horisontal, vertikal yang, atau mungkin di kedua. Kita melakukan itu dengan cara yang sama kami memeriksa apakah ada setiap pertandingan atau tidak:
public function clear():void { if (stCheck && ndCheck) { var clearRight = st[0]; var clearLeft = st[1]; var clearDown = st[2]; var clearUp = st[3]; if (clearLeft + clearRight >= 2 && clearUp + clearDown >= 2) { } else if (clearUp + clearDown >= 2) { } else { } } else if (stCheck) { } else { } }
Di sini lagi, mari kita mulai dari kasus pertama. Jadi pada dasarnya, kita perlu untuk menghapus semua permata dari atas ke bawah dan dari kiri ke kanan, tetapi kita perlu ingat bahwa kita tidak bisa (atau lebih tepatnya seharusnya tidak, karena tidak ada hal buruk akan benar-benar terjadi di sini...) membuat die()
permata setiap dua kali. Itulah mengapa sambil pergi dari atas ke bawah, kita hanya akan melewatkan permata kami memeriksa sebelumnya:
public function clear():void { if (stCheck && ndCheck) { var clearRight = st[0]; var clearLeft = st[1]; var clearDown = st[2]; var clearUp = st[3]; if (clearLeft + clearRight >= 2 && clearUp + clearDown >= 2) { for (var i:int = selGem - clearUp*columns; i <= selGem + clearDown*columns; i += columns) { if (i != selGem) gems[i].die(); } for (var j:int = selGem - clearLeft; j <= selGem + clearRight; ++j) gems[j].die(); } else if (clearUp + clearDown >= 2) { } else { } } else if (stCheck) { } else { } }
Dan itu akan melakukannya. Sekarang kita tidak perlu berhati-hati tentang membuat kami die()
permata dua kali ketika pertandingan hanya horizontal atau vertikal hanya, jadi kita cukup copy dan paste loop dari kasus pertama (tentu saja kita perlu mengubah vertikal loop sedikit) untuk kasus-kasus lain :
public function clear():void { if (stCheck && ndCheck) { var clearRight = st[0]; var clearLeft = st[1]; var clearDown = st[2]; var clearUp = st[3]; if (clearLeft + clearRight >= 2 && clearUp + clearDown >= 2) { for (var i:int = selGem - clearUp*columns; i <= selGem + clearDown*columns; i += columns) { if (i != selGem) gems[i].die(); } for (var j:int = selGem - clearLeft; j <= selGem + clearRight; ++j) gems[j].die(); } else if (clearUp + clearDown >= 2) { for (var n:int = selGem - clearUp*columns; n <= selGem + clearDown*columns; n += columns) gems[n].die(); } else { for (var m:int = id - clearLeft; m <= id + clearRight; ++m) gems[m].die(); } } else if (stCheck) { } else { } }
Selesai!
Langkah 40: Periksa, Swap, jelas & jatuh bagian 7
Perhatikan bahwa kita melakukan pembersihan hanya untuk permata pertama (yang ID selGem
). Kita perlu melakukan hal yang sama untuk kedua, dan dalam dua kasus lain kita harus copy dan paste mereka secara terpisah juga. Karena itu akan menghasilkan kode terlalu banyak, mari kita membungkus apa yang kita menulis saat ini menjadi salah satu fungsi cantik tunggal:
public function kill(first:Boolean):void { var clearRight:uint; var clearLeft:uint; var clearDown:uint; var clearUp:uint; var id:uint; if (first) { id = selID; clearRight = st[0]; clearLeft = st[1]; clearDown = st[2]; clearUp = st[3]; } else { id = swapID; clearRight = nd[0]; clearLeft = nd[1]; clearDown = nd[2]; clearUp = nd[3]; } if (clearLeft + clearRight >= 2 && clearUp + clearDown >= 2) { for (var i:int = id - clearUp*columns; i <= id + clearDown*columns; i += columns) { if (i != id) gems[i].die(); } for (var j:int = id - clearLeft; j <= id + clearRight; ++j) gems[j].die(); } else if (clearUp + clearDown >= 2) { for (var n:int = id - clearUp*columns; n <= id + clearDown*columns; n += columns) gems[n].die(); } else if (clearLeft + clearRight >= 2) { for (var m:int = id - clearLeft; m <= id + clearRight; ++m) gems[m].die(); } }
Aku bernama kill()
fungsi karena kami membuat die()
permata setelah semua. Argumen hanya adalah, apakah kita sedang membersihkan pertandingan pertama permata, atau untuk yang kedua. Jika argumen (dulu
) diatur ke true
, maka yang cocok untuk permata pertama dibersihkan, jika itu diatur ke false
kemudian yang cocok untuk kedua. Mendasarkan pada itu, kami membuat clearLeft, clearRight, clearUp, clearDown
mengambil nilai-nilai mereka baik dari st
atau nd
array. Kami juga mengubah id
dari permata kita sedang memeriksa yang cocok untuk. Satu masalah kecil muncul, seperti yang Anda lihat, kita memiliki ID untuk permata yang pertama (yang selID
), tapi kami tidak menyimpan id dari permata kedua! Sementara aku menamakannya swapID (tidak ada bahkan seperti variabel belum), dan kita akan melaporkannya sekarang! Dan sementara kita berada di itu, kita harus pergi kembali ke update()
akan membuat dan menyimpan id
swap permata ke variabel ini:
private var selID:int = -1; //selID holds an ID of a selected gem, -1 = no gem selected private var swapID:int = -1;//id of the gem that got swapped with selID
if (stCheck || ndCheck) { swapID = id; gems[selID].move(gems[id].x, gems[id].y, gems[id].type); gems[id].move(gems[selID].x, gems[selID].y, gems[selID].type); swapping = true; }
Dan kami selesai dengan ini!
Langkah 41: Periksa, Swap, jelas & jatuh bagian 8
Kembali ke fungsi clear()
, dan mari kita mengisi ruang hilang dengan fungsi baru dibuat kill()
kami:
public function clear():void { if (stCheck && ndCheck) { kill(true); kill(false); } else if (stCheck) { kill(true); } else { kill(false); } }
Dan jangan lupa untuk menunjukkan bahwa kita berada sekarang di tengah kliring, sehingga animasi (scaling turun) dengan aman dapat mengeksekusi itu sendiri:
public function clear():void { if (stCheck && ndCheck) { kill(true); kill(false); } else if (stCheck) { kill(true); } else { kill(false); } clearing = true; }
Langkah 42: Periksa, Swap, jelas & jatuh Bagian 9
Akhirnya, mari kita menempatkan fungsi clear()
ke penanganan swap, sehingga kita dapat melihat apakah fungsi kita bekerja keras bekerja dengan benar:
if (swapping) { timer += FlxG.elapsed; if (timer >= swapTime) { swapping = false; clear(); timer = 0.0; selID = -1; } } else if (released && mouseX > begX && mouseX < begX + columns * spaceX && mouseY > begY && mouseY < begY + rows * spaceY)
Kita perlu set selID
ke-1
, sejak setelah kliring harus ada permata tidak dipilih. Kita juga harus melarang pemain dari memilih permata sementara kita sedang menangani kliring, itu sebabnya kami menambahkan lain
sebelum kondisi untuk menangani input pengguna. Mari kita menjalankan permainan kami dan melihat jika permata mendapatkan dihapus dengan benar setelah menukar:
Merasa lebih dan lebih seperti sebuah permainan yang sebenarnya! Meskipun permata yang baru tidak jatuh Namun, kita dapat melihat fungsi check()
kita dalam tindakan. Bukti bahwa itu bekerja dengan baik, adalah bekerja tepat fungsi clear()
. :)
Kesimpulan
Membersihkan permata setelah menemukan kecocokan selesai bagian pertama dari tutorial ini.
Kami mulai keluar sementara memiliki apa-apa di bawah tangan kami, tapi sekarang kita memiliki banyak fungsi yang digunakan untuk menyelesaikan permainan. Kami mulai dengan render Dewan permata pada layar, kemudian kita perlahan-lahan membuat permainan lebih dapat dimainkan dengan menambahkan kemungkinan menukar permata, kemudian untuk membersihkan mereka dari papan dan bertelur yang baru. Akhirnya kami menciptakan fungsi untuk dapat memeriksa apakah permata dalam pertandingan, dan kita menggunakannya dalam permainan sehingga kita dapat benar-benar jelas seluruh pertandingan bukan acak permata.
Tapi semua itu hanya setengah dari pekerjaan yang diperlukan untuk menciptakan sebuah permainan yang dimainkan! Saya mendorong Anda untuk datang kembali dan menyelesaikan proyek ini dengan bagian kedua. Terima kasih untuk membaca!