Search.....

Tuesday, November 19, 2019

Pemodelan Fuzzy Sugeno dan Tsukamoto

Pemodelan Fuzzy Sugeno dan Tsukamoto

MODEL SUGENO
Dalam penentuan tingkat kepribadian berdasarkan pendidikan, sistem pendukung keputusan kabur digunakan untuk mengubah input yang berupa Pendidikan Nonformal (nonformal) dan Pendidikan Informal (informal) sehingga mendapatkan output berupa tingkat kepribadian. Dalam penentuan tingkat kepribadian digunakan metode Sugeno Orde-Nol, pada tahap pengujian input, pembentukan kombinasi aturan kabur harus disesuaikan dengan data output dengan menyertakan semua variabel dimana pada metode ini anteseden dipresentasikan dengan aturan dalam himpunan kabur, sedangkan konsekuen dipresentasikan dengan sebuah konstanta. 
Selanjutnya dilakukan dengan mencari derajat keanggotaan nilai tiap variabel dari salah satu data. Kemudian mencari Ξ± − predikat untuk setiap aturan kombinasi aturan kabur. Dengan menggunakan rata-rata terbobot (weighted average), hasil Ξ± − predikat yang tidak nol digunakan untuk mencari nilai rata-rata yang juga merupakan penegasan (defuzzifikasi). Berikut adalah beberapa tahap, yaitu: 
1. Pengaburan (fuzzifikasi) pengaburan yaitu proses dimana data inputan nilai yang bersifat tegas (crips input) kedalam input kabur. Pada penelitian ini digunakan beberapa variabel yang digunakan dalam penentuan Tingkat Kepribadian dengan parameter Pendidikan Nonformal (nonformal) dan Pendidikan Informal (informal). Pada Metode Sugeno, baik variabel input maupun variabel output dibagi menjadi satu atau lebih himpunan kabur. Dalam penentuan tingkat kepribadian dengan parameter Pendidikan Nonformal (nonformal) dan Pendidikan Informal (informal), variabel input dibagi menjadi dua yaitu variabel Pendidikan Nonformal dan Pendidikan Informal. Serta satu variabel output, yaitu variabel tingkat kepribadian. Variabel ini dibentuk berdasarkan klasifikasi Pendidikan Nonformal (nonformal) dan Pendidikan Informal (informal).
Tabel 1. Himpunan Kabur
Himpunan kabur beserta fungsi keanggotaan dari variabel Pendidikan Nonformal dan Pendidikan Informal direpresentasikan sebagai berikut: a. Himpunan Kabur Variabel Pendidikan Nonformal (nonformal) Pada variabel nonformal didefinisikan tiga himpunan kabur yaitu rendah, sedang, dan tinggi. Untuk merepresentasikan variabel nonformal digunakan bentuk kurva bahu kiri untuk himpunan kabur rendah, bentuk kurva segitiga untuk himpunan kabur sedang dan bentuk kurva bahu kanan untuk himpunan kabur tinggi. Gambar himpunan kabur untuk variabel nonformal ditunjukkan pada Gambar 1.
Gambar 1. Variable Nonformal
Dimana sumbu vertikal merupakan nilai input dari variabel nonformal, sedangkan sumbu horizontal merupakan tingkat keanggotaan dari nilai input.


b. Himpunan Kabur Variabel Pendidikan Informal (informal) Pada variabel informal didefinisikan tiga himpunan kabur yaitu rendah, sedang, dan tinggi. Untuk merepresentasikan variabel informal digunakan bentuk kurva bahu kiri untuk himpunan kabur rendah, bentuk kurva segitiga untuk himpunan kabur sedang, dan bentuk kurva bahu kanan untuk himpunan kabur tinggi. Gambar himpunan kabur untuk variabel informal ditunjukkan pada Gambar 2.
Gambar 2. Variabel Informal

Dimana sumbu horizontal merupakan nilai input dari variabel informal, sedangkan sumbu vertikal merupakan tingkat keanggotaan dari nilai input. Fungsi keanggotaan diperoleh dengan cara yang sama sebagaimana dalam variabel informal, sehingga menjadi sebagai berikut: 

2. Aplikasi Fungsi Implikasi Berdasarkan kategori dalam penentuan himpunan kabur di atas diperoleh 9 aturan implikasi sebagai berikut:
Tabel 2. Aturan Implikasi
Aturan Implikasi Dalam penentuan tingkat kepribadian ini menggunakan metode Sugeno Orde-Nol, yaitu: 
IF(x1 is A1 ) ∩ (x2 is A2 ) ∩ … ∩ (xN is AN)THEN z = k Keterangan
xn = Variabel input
AN = Kategori 

3. Komposisi Aturan Komposisi aturan menggunakan fungsi Max, yaitu solusi himpunan kabur diperoleh dengan cara mengambil nilai maksimum aturan. Jika semua proposisi telah dievaluasi, maka output akan berisi suatu himpunan kabur yang merefleksikan konstribusi dari tiap-tiap proposisi. Secara umum dapat dituliskan: 
Usf[xi ] = max(Usf[xi ],Ukf[xi ]) 
4. Penegasan (defuzzifikasi) Penegasan yaitu mengkonversi himpunan kabur keluaran ke bentuk bilangan tegas (crips). Dalam metode Sugeno menggunakan metode perhitungan rata-rata terbobot (weight average)

Masing-masing siswa dengan nilai pendidikan nonformal sebesar 12 dan nilai pendidikan informal sebesar 19 ingin mengetahui tingkat kepribadiannya Langkah 
1. Menentukan Himpunan Kabur 
Untuk variabel nonformal didefinisikan pada tiga himpuanan kabur yaitu: RENDAH, SEDANG, dan TINGGI. Setiap himpuanan kabur memiliki interval keanggotaan, yakni seperti terlihat pada g ambar berikut adalah gambar tingkat keanggotaan pada variabel nonformal sebesar 12:
Gambar 3. Variabel Nonformal 

Pendidikan nonformal sebesar 12 termasuk ke dalam himpunan kabur RENDAH dan SEDANG dengan tingkat keanggotaan sesuai fungsi, sehingga diperoleh sebagai berikut:
Sehingga diperoleh
Untuk informal didefinisikan pada tiga himpuanan kabur yaitu: RENDAH, SEDANG, dan TINGGI. Setiap himpuanan kabur memiliki interval keanggotaan, yakni seperti terlihat pada Gambar Berikut adalah gambar tingkat keanggotaan pada variabel informal sebesar 19:
Gambar 4. Variabel Informal
Pendidikan informal sebesar 19 termasuk ke dalam himpunan kabur SEDANG dan TINGGI dengan tingkat keanggotaan sesuai fungsi keanggotaan, sehingga diperoleh sebagai berikut:
Sehingga diperoleh

Langkah 2. Aplikasi Fungsi Implikasi 
Fungsi implikasi yang digunakan dalam proses ini adalah fungsi MIN (minimum), yaitu dengan mengambil tingkat keanggotaan yang minimum dari variabel input sebagai outputnya. Dari dua data kabur input tersebut variabel nonformal: RENDAH (0,375) dan SEDANG (0,625) dan variabel informal: SEDANG (0,375) dan TINGGI (0,625). Berdasarkan 9 𝛼 − π‘π‘Ÿπ‘’π‘‘π‘–π‘˜π‘Žπ‘‘ yang disebutkan pada tabel fungsi implikasi, maka diperoleh hanya 2 𝛼 − π‘π‘Ÿπ‘’π‘‘π‘–π‘˜π‘Žπ‘‘ yang tidak nol, yaitu: 
[R2] JIKA nonformal adalah RENDAH dan informal adalah SEDANG, MAKA tingkat kepribadiannya adalah SEDANG. 
𝛼2 = πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑅𝐸𝑁𝐷𝐴𝐻 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺 
      = π‘šπ‘–π‘›(πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™ _𝑅𝐸𝑁𝐷𝐴𝐻 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺) 
      = π‘šπ‘–π‘›(0,375, 0,375) = 0,375 [R3] 
JIKA nonformal adalah RENDAH dan informal adalah TINGGI, MAKA tingkat kepribadiannya adalah RENDAH. 
𝛼3 = πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑅𝐸𝑁𝐷𝐴𝐻 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑇𝐼𝑁𝐺𝐺𝐼 
      = π‘šπ‘–π‘›(πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™ _𝑅𝐸𝑁𝐷𝐴𝐻 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑇𝐼𝑁𝐺𝐺𝐼) 
      = π‘šπ‘–π‘›(0,375, 0,625) = 0,375 [R5] 
JIKA nonformal adalah SEDANG dan informal adalah SEDANG, MAKA tingkat kepribadiannya adalah TINGGI. 
𝛼5 = πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺 
      = π‘šπ‘–π‘›(πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™ _𝑆𝐸𝐷𝐴𝑁𝐺 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺) 
      = π‘šπ‘–π‘›(0,625, 0,375) = 0,625 [R6] 
JIKA nonformal adalah SEDANG dan informal adalah TINGGI, MAKA tingkat kepribadiannya adalah SEDANG. 
𝛼6 = πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑆𝐸𝐷𝐴𝑁𝐺 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑇𝐼𝑁𝐺𝐺𝐼 
      = π‘šπ‘–π‘›(πœ‡π‘›π‘œπ‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™ _𝑆𝐸𝐷𝐴𝑁𝐺 ∩ πœ‡π‘–π‘›π‘“π‘œπ‘Ÿπ‘šπ‘Žπ‘™_𝑇𝐼𝑁𝐺𝐺𝐼) 
      = π‘šπ‘–π‘›(0,625, 0,625) = 0,625 
Langkah 3. Komposisi Aturan 
Komposisi aturan menggunakan fungsi Max, komposisi aturan merupakan kesimpulan secara keseluruhan dengan mengambil tingkat keanggotaan maksimum dari tiap konsekuen aplikasi fungsi implikasi dan menggabungkan dari semua kesimpulan masing-masing aturan, sehingga diperoleh daerah solusi kabur sebagai berikut: 
π‘ˆπ‘ π‘“[π‘₯𝑖 ] = π‘šπ‘Žπ‘₯(π‘ˆπ‘ π‘“[π‘₯𝑖 ],π‘ˆπ‘˜π‘“[π‘₯𝑖 ]) 
Keterangan: 
π‘ˆπ‘ π‘“[π‘₯𝑖 ] = nilai keanggotan solusi kabur sampai aturan ke-i 
π‘ˆπ‘˜π‘“[π‘₯𝑖 ] = nilai keanggotan solusi kabur sampai aturan ke-i 
Sehingga diperoleh tingkat kepribadian: 
1. RENDAH = π‘šπ‘Žπ‘₯(0,375) = 0,375 
2. SEDANG = π‘šπ‘Žπ‘₯(0,375, 0,625) = 0,625 
3. TINGGI = π‘šπ‘Žπ‘₯(0,625) = 0,625 Langkah 
4. Penegasan (defuzzifikasi) Pada metode Sugeno penegasan menggunakan perhitungan rata-rata terbobot (Weight-Average) : 
Jadi dengan menggunakan Metode Sugeno, masing-masing Siswa dengan pendidikan nonformal sebesar 12 dan pendidikan informal sebesar 19 mempunyai nilai kepribadian 20,7 dengan variabel linguistiknya adalah SEDANG.
MODEL TSUKAMOTO
Teori:
Metode Tsukamoto merupakan perluasan dari penalaran monoton. Pada metode Tsukamoto, Setiap konsekuen pada aturan yang berbentuk IF-THEN harus dipresentasikan dengan suatu himpunan fuzzy dengan fungsi keanggotaan yang monoton. Sebagai hasilnya, output hasil inferensi dari tiap-tiap aturan diberikan secara tegas (crisp) berdasarkan Ξ±-predikat (fire strength). Hasil akhirnya diperoleh dengan menggunakan rata-rata terbobot.
Kasus:
Suatu perusahaan makanan kaleng akan memproduksi makanan jenis ABC. Dari data 1 bulan terakhir, permintaan terbesar mencapai 5000 kemasan/hari, dan permintaan terkecil mencapai 1000 kemasan/hari. Persediaan barang digudang terbanyak mencapai 600 kemasan/hari, dan terkecil pernah mencapai 100 kemasan/hari. Dengan segala keterbatasannya perusahaan sampai saat ini baru mampu memproduksi brang maksimum 7000 kemasan/hari, untuk efisiensi mesin dan SDm tiap hari diharapkan perusahaan memproduksi paling tidak 2000 kemasan. Berapa kemasan makanan jenis ABC yang harus diprosuksi, jika jumlah permintaan sebanyak 4000 kemasan, dan persediaan di gudang masih 300 kemasan, apabilla proses produksi perusahaan tersebut menggunakan 4 aturan fuzzy sebagai berikut:
[R1]   IF permintaan TURUN And Persediaan BANYAK, THEN Produksi Barang BERKURANG;
[R2]   IF permintaan TURUN And Persediaan SEDIKIT, THEN Produksi Barang BERKURANG;
[R3]   IF permintaan NAIK And Persediaan BANYAK, THEN Produksi Barang BERTAMBAH;
[R4]   IF permintaan TURUN And Persediaan SEDIKIT, THEN Produksi Barang BERTAMBAH;
Solusi:
Ada 3 variable fuzzy yang akan dimodelkan, yaitu:
  1. Permintaan terdiri atas 2 himpunan fuzzy, yaitu NAIK dan TURUN1
    Pemintaan (kemasan/hari)
Β΅PmtTURUN [x] = {(1, x ≤ 1000), ((5000-x)/4000, 1000 ≤ x ≤ 5000), (0, x ≥ 5000)}
Β΅PmtNAIK [x]     = {(0, x ≤ 1000), ((x -1000)/4000, 1000 ≤ x ≤ 5000), (1, x ≥ 5000)}
Nilai Keanggotaan :
Β΅PmtTURUN (4000)  = (5000-4000)/4000 = 0.25
Β΅PmtTURUN (4000)  = (4000-1000)/4000 = 0.75
  1. Persediaan,  terdiri atas 2 himpunan fuzzy, yaitu SEDIKIT dan BANYAK
    2
    Persediaan (kemasan/hari)
Nilai keanggotaan:
Β΅PmtSEDIKIT[y]      = {(1, y ≤ 1000), ((600 – y)/500, 100 ≤ y ≤ 600), (0, y ≥ 600)}
Β΅PmtBANYAK [y]     = {(0, y ≤ 1000), ((y-1000)/500, 100≤ y ≤ 600), (1, y ≥ 600)}
Nilai Keanggotaan :
Β΅PmtSEDIKIT(300)  = (600-300)/500 = 0.26
Β΅PmtBANYAK (300)  = (300-100)/500 = 0.4
  1. Produksi barang, terdiri atas 2 himpunan fuzzy, yaitu: BERKURANG dan BERTAMBAH
    3
    Produksi barang (kemasan/hari)
Nilai keanggotaan:
Β΅PmtBERKURANG[z]      = {(1, z ≤ 2000), ((7000 – z)/5000, 2000 ≤ z≤ 7000), (0, z ≥ 7000)}
Β΅PmtBERTAMBAH[z]      = {(0, z ≤ 2000), ((z-2000)/5000, 2000≤ z ≤ 7000), (1, z ≥ 7000)}
Sekarang kita cari nilai z untuk setiap aturan dengan menggunakan fungsi MIN pada aplikasi fungsi implikasinya:
[R1]   IF permintaan TURUN And Persediaan BANYAK THEN Produksi Barang BERKURANG;
Ξ±-predikat1 = Β΅PmtTURUN Β΅PmtBAYAK
Ξ±-predikat1 = min ( Β΅PmtTURUN Β΅PmtBANYAK )
Ξ±-predikat1  = min (0.25; 0,4)
Ξ±-predikat1  = 0.25
lihat himpunan Produksi Barang Berkurang
(7000-z)/5000=0.25 -> z1= 5750
[R2]   IF permintaan TURUN And Persediaan SEDIKIT THEN Produksi Barang BERKURANG;
Ξ±-predikat2 = Β΅PmtTURUN  | Β΅PmtSEDIKIT
Ξ±-predikat2 = min ( Β΅PmtTURUN Β΅PmtSEDIKIT)
Ξ±-predikat2 = min (0.25; 0,6)
Ξ±-predikat2 = 0.25
lihat himpunan Produksi Barang Berkurang
(7000-z)/5000=0.25 -> z2= 5750
[R3]   IF permintaan NAIK And Persediaan BANYAK THEN Produksi Barang BERTAMBAH;
Ξ±-predikat3 = Β΅PmtNAIK Β΅PmtBANYAK
Ξ±-predikat3 = min ( Β΅PmtNAIK Β΅PmtBANYAK)
Ξ±-predikat3 = min (0.75; 0,4)
Ξ±-predikat3 = 0.4
lihat himpunan Produksi Barang Bertambah
(z-2000)/5000=0.4 -> z3= 4000
[R4]   IF permintaan TURUN And Persediaan SEDIKIT THEN Produksi Barang BERTAMBAH;
Ξ±-predikat4  = Β΅PmtTURUN Β΅PmtSEDIKIT
Ξ±-predikat4  = min ( Β΅PmtTURUN  , Β΅PmtSEDIKIT )
Ξ±-predikat4  = min (0.75; 0,6)
Ξ±-predikat4  = 0.6
lihat himpunan Produksi Barang Bertambah
(z-2000)/5000=0.6 -> z4= 5000
Nilai Z dapat dicari dengan cara berikut:
z= Ξ±pred1 * z1 + Ξ±pred2 * z2 + Ξ±pred3 * z3 + Ξ±pred4 * z4/ (Ξ±pred1+ Ξ±pred2+ Ξ±pred3+ Ξ±pred4)
z= 0.25*5750 + 0.25*5750 + 0.4 *4000 + 0.6 * 5000 / (0.25+0.25+0.4+0.6) = 4983
Maka jumlah makanan kaleng jenis ABC yang harus diproduksi sebanyak 4983 kemasan.

1. Langkah Pertama Input Permintaan
langkah pertama input permintaan
2. Langkah Kedua Input Persediaan
langkh kedua input persediaan
3. Langkah Ketiga Input Produksi
langkah ketiga input produksi
4. Langkah Keempat Input Permintaan Real dan Persediaan Real
langkah ke empat input permintaan real dan persediaan real
Result:
Maka makanan jenis ABC yang harus diprosuksi sebanyak
result

Sunday, October 20, 2019

Sistem Pakar Diagnosis Penyakit Gigi Menggunakan Kepastian Metode Faktor

Perkembangan teknologi berkembang pesat dengan meningkatnya kebutuhan manusia khususnya dalam teknologi seluler dimana teknologi yang sering digunakan adalah android. Keberadaan android ini memudahkan pengguna dalam mengakses informasi. Android ini bisa digunakan untuk kebutuhan sehat, misalnya mendeteksi penyakit gigi. Salah satu cabang ilmu komputer yang dapat membantu masyarakat dalam mendeteksi penyakit gigi adalah sistem pakar. Dalam penelitian ini, membuat sistem pakar untuk diagnosis penyakit gigi dengan menggunakan metode Certainty Factor. Dental aplikasi diagnosis penyakit dapat mendiagnosis pasien berdasarkan cengkeraman pasien penyakit gigi sehingga bisa didapat penyakit kemungkinan dari pasien itu sendiri. Aplikasi ini aplikasi sistem pakar yang beroperasi pada platform android. Selanjutnya dalam akurasi pengukuran tes sistem yang dilakukan oleh 20 pasien, ada 19 kasus sesuai dan 1 kasing yang tidak pas. Jadi, dari pengujian sistem dilakukan oleh 20 pasien menghasilkan tingkat akurasi 95%.

1. Latar Belakang
         Perkembangan waktu yang semakin maju seperti saat ini membuat kebutuhan manusia menjadi banyak dan semakin didukung dengan semakin banyak teknologi informasi terutama dalam teknologi mobile dimana teknologi itu yang sering digunakan adalah android. Hampir semua jenis smartphone android memiliki yang terjangkau harga yang memungkinkan masyarakat untuk memiliki smartphone ini. Sistem operasi ini bisadigunakan dalam proses implementasi aplikasi sistem pakar untuk android adalah platform terbuka bagi pengembang untuk membuat aplikasi mereka sendiri yang dapat digunakan oleh berbagai perangkat seluler. 
         Sebagai bagian penting dari sistem pencernaan, gigi digunakan untuk mengunyah makanan sebelum pergi turun ke sistem pencernaan jadi jika gigi mendapat kesulitan dalam mengunyah makanan, pencernaan proses akan mendapat masalah juga. Gigi sangat rentan terhadap kuman, meski giginya kecil Terkadang mendapat perhatian kurang berpengaruh terhadap kesehatan manusia karena masalah gigi dapat menyebabkan penyakit lain yang memiliki tingkat bahaya lebih tinggi. 
         Sistem pakar adalah sistem berbasis komputer yang menggunakan pengetahuan, fakta dan alasan teknik dalam memecahkan masalah biasanya dapat diselesaikan oleh seorang ahli khususnya bidang. Ini adalah bagian dari perangkat lunak khusus tingkat tinggi atau pemrograman tingkat tinggi bahasa, yang sedang mencoba untuk menduplikasi fungsi dari seorang ahli pada khususnya bidang keahlian. Tujuan dari sistem pakar bukan untuk menggantikan peran manusia, tetapi untuk mempresentasikan pengetahuan manusia dalam bentuk suatu sistem, sehingga dapat digunakan oleh banyak orang. Sistem pakar dibuat dalam bidang pengetahuan untuk keahlian tertentu mendekati kemampuan manusia dalam satu bidang spesifik. 
         Masalah yang ditangani seorang ahli tidak hanya masalah yang mengandalkan algoritma saja namun terkadang juga masalah yang sulit untuk dipahami. Karena itu ahlinya algoritma berbasis sistem yang dibangun belum dibangun berdasarkan pengetahuan dan aturan. Metode statistik didasarkan pada asumsi bahwa ketidakpastian adalah probabilitas dari suatu insiden / fakta benar atau salah. Dalam kepastian teori, serta logika fuzzy, ketidakpastian diwakili dengan tingkat kepercayaan. Ada dua langkah dalam penggunaannya dari setiap metode non-probabilitas. Pertama, keharusan untuk dapat mengekspresikan derajat kepercayaan. Kedua, perlunya memanipulasi (menggabungkan) tingkat kepercayaan saat menggunakan sistem berbasis pengetahuan. Teori kepastian yang mendasari penggunaan Certainty Factor (CF). CF mengungkapkan kepercayaan diri pada insiden (atau fakta atau hipotesis) berdasarkan kejadian (atau berdasarkan penilaian ahli).

2. Metode Penyelesaian
         Konsep faktor kepastian diusulkan untuk mengakomodasi ketidakpastian suatu ahli yang sering berpikir untuk menganalisis informasi dengan frasa seperti "Mungkin", "Sepertinya", "hampir pasti" dan seterusnya. Metode faktor kepastian seleksi adalah cocok untuk sistem pakar dalam penelitian ini, karena pada dasarnya metode CF diasumsikan sebagai tingkat kepercayaan ahli untuk data yang digunakan. Certainty Factor memperkenalkan konsep kepercayaan dan ketidakpercayaan. Metode ini cocok untuk mendiagnosis sesuatu tidak pasti. Metode certainty factor hanya dapat memproses dua bobot dalam satu perhitungan. Untuk bobot lebih dari 2 banyak, untuk melakukan perhitungan agar terhindar dari masalah saat bobot dihitung secara acak berarti bahwa tidak ada aturan untuk menggabungkan berat karena kombinasi dari hasil seperti itu akan tetap sama. Penelitian sebelumnya menjelaskan hasil pencarian sistem pakar menunjukkan bahwa gejala apa pun yang dipilih oleh pengguna akan menjadi mencari semua jenis penyakit yang memenuhi gejala. Jika ditemukan kongruensi, antara gejala-gejala penyakit, maka sistem akan menghitung nilai CF kombinasi sesuai dengan aturan yang ada dengan basis pengetahuan dan nilai CF dimasukkan oleh pengguna.

Certainty Factor (CF) menunjukkan ukuran kepastian terhadap fakta atau aturan. Umum rumus metode faktor kepastian sebagai berikut:
CF[h,e] = MB[h,e] – MD[h,e] 
CF [h, e] = faktor kepastian
MB [h, e] = ukuran tingkat keyakinan / kepastian hipotesis h, jika diberikan / sedang bukti yang dipengaruhi e (antara 0 dan 1)
MD [h, e] = ukuran tingkat ketidakpercayaan / ketidakpastian hipotesis h, jika diberikan bukti yang dipengaruhi e (antara 0 dan 1)

Ada tiga hal yang mungkin terjadi: 
1) Beberapa bukti digabungkan untuk menentukan CF dari suatu hipotesis Jika e1 dan e2 adalah observasi, maka:

2) CF dihitung dari kombinasi beberapa hipotesis 
Jika h1 dan h2 adalah hipotesis, maka: 
MB [h1 ∧ h2, e] = min (MB [h1, e], MB [h2, e]) MB [h1 ˅ h2, e] = maks (MB [h1, e], MB [h2, e]) MD [h1 ∧ h2, e] = min (MD [h1, e], MD [h2, e]) MD [h1 ˅ h2, e] = maks (MD [h1, e], MD [h2, e]) 

3) Beberapa aturan saling terkait, ketidakpastian aturan menjadi masukan bagi aturan lain, lalu:
MB [h, s] = MB ’[h, s] * maks (0, CF [s, e]) 
MB '[h, s] = ukuran kepercayaan h berdasarkan kepercayaan penuh pada validitas s

3. Hasil dan Diskusi
         Berdasarkan wawancara dengan seorang ahli tentang gejala yang mengarah pada munculnya penyakit gigi dan diperoleh 28 gejala penyakit gigi dan 10 penyakit gigi. Basis pengetahuan dimasukkan ke dalam program komputer sehingga komputer bertindak sebagai ahli mampu mengidentifikasi gejala penyakit gigi. Berikut adalah tabel data gejala yang dapat dilihat pada Tabel 1 dan tabel data penyakit ditunjukkan pada Tabel 2.

Table 1. Data Symptoms
Table 2. Data Disease 
         Selanjutnya akan dilakukan aturan dasar. Basis aturan adalah aturan yang dibuat untuk menghubungkan gejala dengan penyakit. Aturan dasar dapat ditulis ke struktur IF (id_symacteria) LALU (id_disease) CF (x). Berikut tabel dasar aturan yang diperoleh dari wawancara dengan dokter gigi dengan nilai faktor kepastian pada Tabel 3.
Table 3. Tabel Aturan Dasar

         Tahap pengujian aplikasi dilakukan untuk menguji aplikasi diagnosa dengan hasil yang telah dihitung secara manual menggunakan faktor kepastian. Jika seorang pasien memilih sulit untuk mengunyah gejala, demam, pembengkakan rahang, Pembengkakan Biji Lymph dan sakit gigi atau berdenyut dalam Tabel 4.
Tabel 4. Input pengguna berdasarkan gejala yang dialami dan nilai CF

Sehingga perhitungan manual sebagai berikut:
a. Nilai CF untuk Abses Periodontal

b. Nilai CF untuk Abses Periapical 

c. CF vslue of Bruxism

d. Nilai CF Gula Purulent

         Dari perhitungan manual di atas hasil diperoleh nilai Faktor Kepastian untuk masing-masing penyakit: Abses Periodontal (0,363), Abses Periapical (1), Bruxism (0,239), Gusi Purulent (0,272). Dapat disimpulkan bahwa pasien menderita penyakit abses periapical dengan persentase 1 x 100% = 100%. Saat dihitung menggunakan aplikasi itu akan menghasilkan seperti yang ditunjukkan pada Gambar 1.
Gambar 1. Aplikasi Hasil Perhitungan
         Diagnosis sistem pakar uji penyakit gigi dilakukan dengan membandingkan keakuratan hasil akhir dari kemungkinan jenis penyakit gigi yang ditimbulkan oleh sistem kepada mereka diproduksi oleh para ahli. Eksperimen sistem pakar mendiagnosis penyakit gigi dilakukan dengan membandingkan Hasilnya akurat jenis penyakit gigi yang diproduksi oleh sistem dan pakar. Berikut ini adalah tabel hasil pengujian keakuratan sistem yang ditunjukkan pada Tabel 5.
Tabel 5. Hasil Pengujian Sistem Akurasi
         Pengujian dilakukan terhadap 20 responden. Dalam semua kasus ada 19 kasus sesuai dan 1 kasing yang tidak pas. Untuk menentukan tingkat akurasi sistem, maka perhitungannya adalah sebagai berikut:
Jadi, dapat disimpulkan bahwa tingkat akurasi sistem dengan seorang pakar sebesar 95%.

4. Kesimpulan
         Pengembangan sistem pakar diagnosis penyakit gigi dilakukan melalui beberapa tahapan perancangan sistem dengan tujuan untuk memberikan gambaran umum tentang gigi penyakit. Setiap gejala dinilai bobot untuk menghitung nilai CF dari suatu penyakit. Aplikasi diagnosa sistem pakar penyakit gigi dibangun menggunakan JAVA bahasa pemrograman dengan bantuan perangkat lunak Eclipse Mars. Untuk mengadopsi keahlian seorang dokter, bobot setiap data input gejala menggunakan sistem berbasis web menggunakan bahasa pemrograman PHP dengan framework Code Igniter dan MySQL sebagai database. Selanjutnya, dalam pengukuran akurasi uji sistem dilakukan oleh 20 pasien, ada 19 kasus yang sesuai dan 1 kasus yang tidak sesuai. Jadi, dari pengujian sistem yang dilakukan oleh 20 pasien menghasilkan tingkat akurasi 95%. Untuk saran tentang penelitian lebih lanjut untuk mengadopsi keahlian yang dimasukkan dokter melalui Android yang memungkinkan dokter memantau aplikasi ini.

Saturday, December 22, 2018

Tutorial Game Mario dengan Processing

Tutorial Game Mario dengan Processing


HI SOBAT.. KALI INI ANE AKAN POSTING MELANJUTKAN TUTORIAL MEMBUAT GAME MARIO DIMANA PART 1 DAN 2 NYA BISA DILIHAT DI SINI :

SHINY, PICKUP MENGKILAP

Di perpustakaan permainan, harta adalah bentuk "pikap". Pickup adalah hal-hal yang bisa diambil oleh pemain atau NPC (karakter non-pemain) dengan berjalan ke dalamnya, dan ketika mereka melakukannya, "sesuatu" dapat terjadi. Tentu saja, kita memegang kendali, jadi yang terjadi tergantung pada kita. Sangat berguna.

Jika Anda pernah memainkan permainan mario, Anda mungkin tahu bahwa mario suka mengumpulkan koin, dari semua ukuran dan warna. Dalam permainan kami, kami akan memberinya dua jenis koin berbeda untuk diambil: koin normal, dan koin naga misterius:

Untuk membuat pickup koin, kita mulai dengan membuat master "Mario pickup", yang dapat kita gunakan sebagai superclass untuk setiap pickup yang akan kita buat dalam permainan kita:

Meskipun kode ini tidak banyak membantu, kami akan mengelompokkan hal-hal sebagai "Mario Pickup", dan itu akan berguna jika kami pernah memperkenalkan kelas pickup yang bukan untuk Mario. 
Jadi, mari kita tulis koin pikap kami. Mereka cukup lugas, jadi begini :

Itu saja, hanya itu yang harus kita definisikan. Sekarang jika kita ingin menggunakannya dalam permainan kita, kita cukup membuat new Coin(...,...) atau new DragonCoin(...,...) dan kemudian menambahkannya ke daftar pickup kami, untuk pemain hanya: 
class MarioLayer extends LevelLayer {  [...]  MarioLayer(Level owner) {    [...]
    // add coints above the horizontal platforms    addCoins(928,height-236,96);    addCoins(912,height-140,128);    addCoins(1442,height-140,128);
    // add a dragon coin at the start    addForPlayerOnly(new DragonCoin(352,height-164));  }
  // a handy function for placing lots of coins  void addCoins(float x, float y, float w) {    float step = 16, i = 0, last = w/step;    for(i=0; i<last; i++) {      addForPlayerOnly(new Coin(x+8+i*step,y));    }  }}  
Fungsi addCoins adalah fungsi yang nyaman yang memungkinkan kita menambahkan string koin mulai dari posisi x/y dan mencakup lebar w . Kami menggunakan nilai stepuntuk menghemat koin kami, menggunakan 16 piksel sebagai jarak dari satu pusat koin ke pusat koin berikutnya, dan kemudian kami mulai menambahkan koin "untuk pemain saja", seperti yang jelas dari addForPlayerOnly(...) nama fungsi. Hasil? Mengapa, mari kita mainkan game terbaru kami dan lihat sendiri:


Seperti yang Anda lihat, kita dapat mengambil koin dengan berlari ke dalamnya. Jika kita mau, kita dapat membuat skor Mario naik setiap kali dia mengambil koin, tetapi kita akan melakukannya nanti karena itu membutuhkan bekerja dengan sesuatu yang disebut "HUD", yang merupakan informasi yang Anda dapatkan tentang permainan Anda seperti skor, kesehatan, sisa waktu, peralatan saat ini, dan semua hal semacam itu. 

MUSUH!

Ya, saatnya menambah musuh ke permainan kami.Berlari saja mengumpulkan koin akan jauh lebih menantang jika Anda mencoba untuk tidak menyerang musuh pada saat yang bersamaan. Jadi mari tambahkan favorit Mario lama: Koopa Trooper.

Pasukan Koopa sangat mirip Mario: Mereka memiliki negara dan perlu beralih di antara mereka ketika mereka melakukan sesuatu, jadi mungkin tidak mengherankan, mendefinisikan seorang polisi Koopa sangat mirip dengan mendefinisikan Mario. Kecuali kita tidak perlu khawatir tentang memasukkan penanganan input, karena kita tidak akan mengontrol.
class Koopa extends Interactor {  // we construct a Koopa trooper pretty much the same way we did Mario:  Koopa(float x, float y) {    super("Koopa Trooper");    setStates();    setForces(-0.25, DOWN_FORCE);        setImpulseCoefficients(DAMPENING, DAMPENING);    setPosition(x,y);  }
  // And we use states.  void setStates() {    // walking state    State walking = new State("idle", "graphics/enemies/Red-koopa-walking.gif", 1, 2);    walking.setAnimationSpeed(0.12);    addState(walking);  }}
Lalu kami menambahkannya seperti kami menambahkan yang lain: 


class MarioLayer extends LevelLayer {  [...]  MarioLayer(Level owner) {    [...]      Koopa koopa = new Koopa(264, height-178);    addInteractor(koopa);  }}
Itu lumayan bagus, tapi agak tidak lengkap. Mari kita coba mainkan:

Kami tidak terluka! Musuh ini tidak berbahaya! Dan dia agak bodoh, setelah berjalan ke dinding di sebelah kiri, dia hanya memilih untuk terus berjalan ke kiri. Jadi jelas, kita perlu mengajarkannya beberapa hal lagi. Pertama, mari kita perbaiki masalah "Saya tidak tahu apa itu tembok". Ketika aktor (pemain atau NPC) memukul sesuatu, fungsi khusus disebutgotBlockeddisebut oleh perpustakaan game. Biasanya, fungsi ini tidak "tidak ada", jadi ketika Anda menabrak dinding, tidak ada yang benar-benar terjadi, selain itu Anda berhenti. Tapi, untuk pasukan Koopa kami, kami ingin menyadari bahwa itu tidak bisa berjalan lebih jauh, dan harus berbalik. Tidak masalah:


class Koopa extends Interactor {  [...]    void gotBlocked(Boundary b, float[] intersection) {    // is the boundary vertical?    if (b.x == b.xw) {      // yes it is. Reverse direction!      fx = -fx;      setHorizontalFlip(fx > 0);    }  }}
Di sana, bagus dan sederhana. The if (bx == b.xw)kode memeriksa apakah batas vertikal atau tidak: untuk garis vertikal, yang xawal dan akhir koordinat nilai yang sama, dengan hanya ketinggian di awal dan akhir menjadi berbeda, jadi kami hanya memeriksa "adalah mulai x nilai ( bx) yang sama dengan nilai x akhir b.xw)? Jika demikian, arah sebaliknya ". Dan kami membalik arah dengan mengubah kekuatan seragam yang bertindak pada pasukan Koopa kami. Untuk membuatnya terdorong ke kiri, kita gunakan -0,25 sebagai gaya horizontal, sehingga untuk membuat pasukan Koopa 'terdorong' ke kanan, kita dapat mengembalikannya menjadi 0,25, dan membalik sprite Koopa trooper. Pekerjaan selesai!

Dan sekarang, mari kita membuat musuh kita menjadi berbahaya. Ini membutuhkan penambahan dalam interaksi antara Mario dan pasukan Koopa: Mario harus bisa menekan mereka, dan pasukan Koopa harus mampu mengalahkan Mario. Jadi kita akan mengubah kedua kelas.

MEMBUAT PASUKAN KOOPA BERBAHAYA UNTUK MARIO

Untuk membuat pasukan Koopa berbahaya bagi Mario, kita perlu memastikan "sesuatu" harus terjadi ketika Mario dan seorang Koopa menyentuh polisi. Untungnya, perpustakaan game sudah memiliki fungsi untuk itu, kita hanya perlu mengisinya.
class Mario extends Player {  [...]
  void setupStates() {    [...]
    State dead = new State("dead", "graphics/mario/small/Dead-mario.gif", 1, 2);    dead.setAnimationSpeed(0.25);    dead.setDuration(15);    addState(dead);        [...]  }
  // what happens when we touch another player or NPC?  void overlapOccurredWith(Actor other, float[] direction) {    // for the moment, we only care about what happens    // when we touch Koopa troopers    if (other instanceof Koopa) {      // if we touch a koopa trooper, we die! O_O      die();    }  }
  void die() {    // switch to dead state    setCurrentState("dead");    // turn off interaction, so we don't flag more touching koopas or pickups or walls, etc.    setInteracting(false);    // make up jump up in an "oh no!" fashion    addImpulse(0,-30);    // and turn up gravity so we fall down quicker than usual.    setForces(0,3);  }}
Ini adalah awal dari perubahan yang harus kita buat, tetapi yang bagus: jika kita menyentuh seorang polisi Koopa, kita mati. 

Memastikan kami memulai ulang game

Tentu saja sementara pasukan Koopa sekarat dan meninggalkan permainan bukan masalah besar, jika kita mati kita ingin memulai kembali permainan. Saat ini, itu tidak terjadi, jadi kita perlu menambahkan satu kode lagi untuk membuat semuanya berjalan sesuai keinginan kita:
[...]void reset() {  clearScreens();  addScreen("level", new MarioLevel(4*width, height));}[...]class Mario extends Player {  [...]  void handleStateFinished(State which) {    if(which.name == "dead") {      removeActor();      reset();    } else {      setCurrentState("idle");    }  }  [...]}
Kami memperkenalkan fungsi global baru ("dapat dipanggil dari mana saja dalam kode") yang disebut reset(), yang pada dasarnya menyeka segalanya, dan kemudian membangun kembali level kami, dengan mario baru, koopa trooper, koin, dan semua yang kami katakan harus dibangun saat kami membuat MarioLevel kami.

Jadi sekarang jika kita menyentuh pasukan Koopa, kita akan kalah, dan kemudian permainan dimulai lagi. Mari tingkatkan arena permainan!

Membuat Mario berbahaya bagi pasukan Koopa
Dalam game Mario klasik, sebagian besar musuh dapat dikalahkan dengan melompat di atas mereka. Jadi ini membutuhkan dua perubahan: Mario harus tahu dari arah mana dia memukul pasukan Koopa, dan pasukan Koopa harus dapat diperas. Mari kita memecahkannya:
class Mario extends Player {  [...]  void overlapOccurredWith(Actor other, float[] direction) {    if (other instanceof Koopa) {      // get a reference to this Koopa trooper      Koopa koopa = (Koopa) other;    // get the angle at which we've impacted with this koopa trooper      float angle = direction[2];
  // Now to find out whether we bopped a koopa on the head!      float tolerance = radians(75);if (PI/2 - tolerance &lt;= angle &amp;&amp; angle &lt;= PI/2 + tolerance) {        // we hit it from above!        // 1) squish the koopa trooper        koopa.squish();    // Stop moving in whichever direction we were moving in        stop(0,0);        // instead, jump up!        setImpulse(0, -30);        setCurrentState("jumping");      }
      // if we didn't hit it at the correct angle, we still die =(      else { die(); }    }  }
  [...]}
Di sini kita melihat beberapa matematika. Alih-alih hanya memberi tahu kami mana dari empat arah kiri, kanan, atas, atau bawah yang kami pukul, perpustakaan permainan memberi kami sudut pandang yang sebenarnya saat kami memukul aktor lain. Itu benar-benar berguna, tetapi juga membuatnya sedikit sulit untuk mengetahui apa arah "nyata" yang akan kita masuki. Jika Anda tidak mengerti apa yang terjadi di kode di atas, tidak apa-apa. Saya akan coba menjelaskannya di sini:

Untuk kebanyakan hal, sudut tidak berubah dari nol derajat ke 360 ​​derajat, seperti yang mungkin Anda terbiasa, tetapi mereka menggunakan "radian". Menggunakan derajat, ada 360 derajat ke lingkaran penuh. Menggunakan Radian, ada 2 × Ο€ "derajat". Ο€ sebenarnya adalah angka, tetapi tidak mungkin untuk menulis tanpa menggunakan satu juta milyar angka desimal, jadi kami menggunakan huruf untuk itu sebagai gantinya. Nilainya kira-kira 3,14, dan adalah nilai yang Anda dapatkan jika Anda menggambar lingkaran dengan diameter setengah. (satu setengah meter, satu setengah kaki, tidak terlalu penting). Jika Anda mengukur berapa lama lingkaran sebenarnya, jawabannya adalah Ο€. Untuk pengukuran sudut, kita sebenarnya menggunakan lingkaran khusus yang disebut "lingkaran unit", yang memiliki diameter dua. (lagi, dua meter atau dua kaki, atau dua inci, tidak masalah). Lingkaran ini memiliki diameter dua kali Ο€.

Jika kita melihat lingkaran unit ini, dan menandai nilai di sekitar garis lingkaran, lalu di ujung kanan, nilainya adalah 0. Bergerak searah jarum jam sepanjang lingkaran, nilai paling bawah adalah setengah Ο€, paling kiri adalah Ο€ , bagian atas adalah satu setengah Ο€, dan kemudian ketika kita kembali ke tempat kita mulai, kita mendapatkan dua Ο€, yang sama dengan nol. Ini mungkin terdengar aneh, tetapi anggap itu sama dengan jam. Setelah kita melakukan perjalanan sepanjang angka jam, kita berakhir di awal dan angka "reset". Itu juga terjadi di sini.
Jadi, jika kita ingin melompat dari "puncak", diekspresikan dalam gagasan radian ini, kita ingin datang dengan sudut antara Ο€ dan dua Ο€ (di suatu tempat antara "kiri" dan "kanan"). Itulah yang dilakukan kode di atas.
class Koopa extends Interactor {  [...]
  void setStates() {    // walking state  State walking = new State("idle", "graphics/enemies/Red-koopa-walking.gif", 1, 2);    walking.setAnimationSpeed(0.12);    addState(walking);
    // if we get squished, we first lose our shell.State noshell = new State("noshell", "graphics/enemies/Naked-koopa-walking.gif", 1, 2);    noshell.setAnimationSpeed(0.12);    addState(noshell);
    setCurrentState("idle");  }
  [...]
  void squish() {    // do we have our shell? Then we only get half-squished.    if (active.name != "noshell") {      setCurrentState("noshell");      return;    }    // no shell... this koopa is toast.    removeActor();  }}
Mendapatkan squished akan melakukan dua hal. Pertama, jika kita adalah pasukan Koopa yang normal, cangkang kita melindungi kita. Alih-alih dikotori mati, kita hanya kehilangan cangkang kita. Tidak ada masalah besar.Tapi, jika Mario mempermainkan kita lagi, kita bersulang. Jadi kode melakukan ini juga:

if (active.name != "noshell") periksa apakah kita sudah kehilangan cangkang kita atau tidak. The !=berarti "tidak", jadi jika keadaan aktif kami bukanlah "tidak shell" negara, kita set sederhana negara saat ini untuk "tidak shell", dan keluar fungsi squish. Kami tidak perlu melakukan lebih banyak.
Namun, jika kita berada dalam keadaan "tidak ada cangkang", kita mati. Sebagai aktor dalam game, itu berarti kita harus dikeluarkan dari permainan, jadi itulah removeActor()fungsi yang dilakukan oleh kita. Setiap aktor (pemain, NPC, pickup, dll) yang memanggil fungsi ini akan dikeluarkan dari permainan, dan untuk semua maksud dan tujuan tidak ada lagi. Itu yang saya sebut mati!


Sejauh ini kita begitu terperangkap dalam menambahkan hal-hal keren yang benar-benar kita lupakan bahwa tujuan dari sebuah permainan adalah untuk memenangkannya. Jadi bagaimana kita menang di game Mario ini? Permainan Mario yang berbeda memiliki cara yang berbeda untuk menang atau keluar dari level, jadi mari gunakan solusi sekolah lama: pos sasaran yang harus kita jalankan, dengan tali garis gawang yang naik dan turun.
Untuk mewujudkan hal ini, kami akan menggabungkan beberapa hal yang sudah kami miliki untuk membuat game kami:

1. pos sasaran "dekat dengan layar",
2. sebuah posting tujuan "di kejauhan", dan
3. tali yang naik dan turun di antara mereka.

Kami akan menggunakan tiga gambar untuk ini:


Seperti yang Anda tebak, kami akan menambahkan pos tujuan kembali ke daftar banyak gambar latar belakang yang sudah kami gunakan, dan mudah-mudahan dapat diprediksi, kami dapat menambahkan posting frong ke daftar gambar "latar depan":
class MarioLayer extends LevelLayer {  [...]  MarioLayer(Level owner) {    [...]    // and let's add the thing that makes us win!    addGoal(1920, height-48);  }  void addGoal(float xpos, float hpos) {    // add the back post to the background images    Sprite back_post = new Sprite("graphics/assorted/Goal-back.gif");    back_post.align(CENTER, BOTTOM);    back_post.setPosition(xpos, hpos);    addBackgroundSprite(back_post);    // and add the front post ot the foreground images    Sprite front_post = new Sprite("graphics/assorted/Goal-front.gif");    front_post.align(CENTER, BOTTOM);    front_post.setPosition(xpos+32, hpos);    addForegroundSprite(front_post);    // the finish line rope    addForPlayerOnly(new Rope(xpos, hpos-16));  }}
Sejauh ini bagus, kecuali untuk baris terakhir itu. Ia mengatakan kami menambahkan Ropeke daftar hal-hal yang hanya untuk pemain ... apakah itu Pickup? Nah, jika Anda ingat deskripsi pickup, mereka adalah hal-hal yang pemain bisa masuk ke, untuk membuat "sesuatu" terjadi, dan itulah yang kami inginkan! Ketika Mario berlari ke tali, kami ingin dia memenangkan pertandingan, jadi kami akan membuat pickup baru yang terlihat seperti tali kami:
class Rope extends MarioPickup {  Rope(float x, float y) {    // use the right picture for our rope    super("Finish line", "graphics/assorted/Goal-slider.gif", 1, 1, x, y, true);
    // now, set up the "up and down" animation for this pickup    Sprite rope_sprite = getState("Finish line").sprite;    rope_sprite.align(LEFT, TOP);
    // there are two paths: up, and down. First, up: we move 116 pixels up, over 50 frames    rope_sprite.addPathLine(0, 0,      1,1,0,   0, -116,   1,1,0,    50);
    // and then down: we move the same 116 pixels down, over 50 frames    rope_sprite.addPathLine(0, -116,   1,1,0,   0, 0,      1,1,0,    50);
    // then, make sure that we keep "playing" this    // animation, and make sure we don't try to     // "drive along the path", because that would    // look really weird.    rope_sprite.setNoRotation(true);    rope_sprite.setLooping(true);  }}
Anda mungkin telah memperhatikan bahwa ini adalah pekerjaan yang sedikit lebih banyak daripada pickup lainnya, karena kami ingin tali ini bergerak naik dan turun. Kami melakukan ini dengan memberikan "jalur jalur" sprite yang dapat dilewati. Kode di atas menunjukkan cara membuatnya bergerak naik dan turun, tetapi kami juga dapat mengukur dan memutar di atas jalur. "1,1,0" itu, yang Anda lihat empat kali (dua kali untuk naik, dan dua kali ke bawah) berarti "skala secara horizontal sebesar 1,0, skala vertikal sebesar 1,0, dan putar sebesar 0 derajat", sehingga sprite kami akan terlihat sama di awal jalurnya seperti di ujung jalurnya, untuk jalur naik dan turun.

Jadi bagian terakhir dari teka-teki ini adalah: apa yang terjadi ketika Mario mengambil tali ini? Yah ... dia harus memenangkan pertandingan! Jadi, mari tambahkan sedikit terakhir ke kode Mario dan lihat seperti apa permainan kami sekarang sehingga kami bisa menang:
class Mario extends Player {  [...]
  void setupStates() {    [...]
    // add a winning state for Mario. We'll make his victory last 15 frames.    State won = new State("won", "graphics/mario/small/Standing-mario.gif");    won.setDuration(15);    addState(won);
    setCurrentState("idle");      }
  void handleStateFinished(State which) {    // we reset the game not just if Mario dies, but    // also if he's won and his winning state is "done":    if(which.name == "dead" || which.name == "won") {      removeActor();      reset();    } else {      setCurrentState("idle");    }  }
  [...]
  void pickedUp(Pickup pickup) {    // when we pick up a rope, win!    if (pickup.name=="Finish line") {      setCurrentState("won");    }  }
  [...]}
Cukup lurus ke depan pada saat ini, bukan? Tambahkan status kemenangan, pastikan bahwa kami menyetel ulang gim agar kami dapat bermain lagi ketika kami selesai dengan status kemenangan kami, dan pastikan untuk mengubah status kemenangan kami jika kami mengambil alih talinya.

Menyelesaikan permainan kami

Pada titik ini kita memiliki semua elemen utama di tempat. Kami memiliki pahlawan, kami memiliki orang jahat, kami memiliki harta, kami bisa mati atau kami bisa menang. Ini semua sangat penting untuk permainan yang menyenangkan untuk dimainkan. Namun, masih ada beberapa pekerjaan yang harus dilakukan.

LEBIH BANYAK MUSUH
Pertama, kita butuh lebih banyak musuh. Jika kita melompati polisi Koopa itu, atau menghimpitnya, sisa levelnya bebas dari bahaya. Itu tidak terlalu menarik atau menggairahkan, jadi mari kita mulai menempatkan pasukan Koopa lagi ke level kita.

Kami hanya dapat menambahkan lebih banyak Koopas dengan cara yang sama seperti yang kami lakukan sebelumnya, tetapi ini adalah saat yang tepat untuk berbicara tentang "pemicu". Bayangkan berjalan melalui tingkat, dan tidak ada pasukan Koopa sama sekali. Namun, ketika Anda berjalan di atas tanah tertentu, seorang polisi Koopa ditambahkan di luar layar. Untuk pemain, seolah-olah levelnya diisi dengan pasukan Koopa, tetapi di belakang layar, kami hanya menjatuhkan mereka pada saat-saat terakhir.

Kenapa kita melakukan ini? Mengapa tidak menambahkan semuanya di awal? Nah, jika kita melakukan itu, mereka juga akan berjalan di sekitar level dari detik pertama. Itu membuatnya sangat sulit untuk mengontrol apa yang dilihat oleh Mario ketika mereka muncul, karena kita perlu memperhitungkan setiap saat bahwa Mario tidak melihatnya. Jika kita menjatuhkan mereka pada saat-saat terakhir sebelum Mario "harus" melihat mereka, kita bisa lebih mengontrol di mana mereka ketika mereka muncul.

Ini juga berarti kita dapat menambahkan musuh yang tampaknya lebih dari biasanya. Jika kita menambahkan pasukan Koopa seratus di awal, dan Mario hanya melihat tiga atau empat sekaligus, kita akan membuang-buang banyak waktu komputer membuatnya menghitung di mana untuk menempatkan orang-orang 96 atau 97 pasukan Koopa lainnya karena mereka jalan-jalan. Untuk sebagian besar dari mereka, itu akan menjadi detik atau bahkan beberapa menit sebelum mereka muncul ... mengapa membuang waktu komputer ketika kita dapat menjatuhkan musuh pada saat-saat terakhir, bukan?

Pemicu
Untuk membuat "pemicu koopa trooper", kita dapat menggunakan perpustakaan permainan yang dibangun di "Trigger", dan sama seperti sebelumnya ketika kita membuat aktor atau pickup, memperluas dari kelas Trigger ini: 
class KoopaTrigger extends Trigger {  // these values will let us position a new Koopa trooper when triggered   float koopa_x, koopa_y;    // our constructor is pretty straight forward. The first four values  // are where the trigger is in the left, the last two where a new koopa  // should be made, relative to trigger.  KoopaTrigger(float x, float y, float w, float h, float _kx, float _ky) {    super("koopa", x, y, w, h);    koopa_x = _kx;    koopa_y = _ky;  }
  // when Mario runs through the trigger, this function is automatically  // called by the game engine, and the instructions in it are run.  void run(LevelLayer layer, Actor actor, float[] intersection) {    // make a new Koopa trooper, relative to the trigger's position    Koopa k = new Koopa(x+koopa_x, koopa_y);    // add this Koopa trooper to the list of enemies for the layer the trigger is in    layer.addInteractor(k);    // and remove this trigger so that it's not repeated. Unless we want infinite Koopas!    removeTrigger();  }}
Jadi pemicu khusus ini relatif sederhana: ia menempati beberapa ruang persegi panjang di lapisan tingkat, dan ketika seorang aktor berjalan melaluinya, kode dalam run(...,...,...)fungsi dijalankan. Dalam hal ini, buat koopa, tambahkan ke layer, dan kemudian mematikan pemicu sehingga tidak memicu waktu kedua (atau ketiga, keempat, dll.).

Tentu saja, kita masih perlu menambahkan pemicu ini ke permainan kami, jadi mari lakukan:
class MarioLayer extends LevelLayer {  [...]
  MarioLayer(Level owner) {    [...]
    addTrigger(new KoopaTrigger(412,0, 5,height, 350, height-64));    addTrigger(new KoopaTrigger(562,0, 5,height, 350, height-64));    addTrigger(new KoopaTrigger(916,0, 5,height, 350, height-64));
    // temporarily show triggers in our game:    showTriggers = true;  }}
Kami menempatkan tiga pemicu untuk koopas, semuanya tinggi di seluruh layar, yang pertama di 412 piksel dari kiri tingkat, yang kedua di 562 dan yang ketiga pada 916 piksel dari kiri tingkat. Pemicu ini memiliki lebar 5 piksel, dan semuanya akan memunculkan polisi Koopa baru ke tingkat 350 piksel di sebelah kanan tempat pemicu berada, pada ketinggian lapisan tanah tingkat itu, 64 piksel di atas bagian bawah layar.

Biasanya, pemicu tidak terlihat, tetapi karena kami sedang membuat game kami saat ini, dan kami ingin melihat di mana mereka berada, kami dapat menunjukkan di mana mereka dengan secara eksplisit menyalakan gambar untuk memicu, menggunakan showTriggers = true.


Sekarang game ini sedikit lebih menantang. Tetapi kita bisa melakukan lebih baik

BAHKAN MEMBUAT LEVEL ITU SENDIRI TANTANGAN!

Mari kita buat dunia sedikit lebih berbahaya dengan memperkenalkan kutukan dari banyak pemain Mario: muncher! Di dalam lubang!

Munchers adalah tanaman kecil yang mengganggu yang mencoba mengunyah Anda ketika Anda menyentuh mereka:

Apa yang membuat tanaman ini sangat berbahaya adalah bahwa tidak ada arah aman dari mana kita bisa mendekati mereka. Jika kita menyentuh mereka, kita mati. Untuk membuat segalanya lebih mudah, mari kita masukkan ke dalam lubang, sehingga jika kita melompati pit, kita aman dari muncher, dan jika kita jatuh ke dalam lubang, maka apakah kita memiliki muncher atau tidak, kita akan mati juga. Dengan cara itu, muncher terlihat sangat menakutkan bagi orang-orang yang memainkan permainan kami, tetapi mereka sebenarnya tidak lebih atau kurang berbahaya daripada pit mereka.

Kita dapat membuat lubang dengan memutar tanah dari satu hamparan terus menerus ke dua peregangan, dengan celah di antaranya:
class MarioLayer extends LevelLayer {  [...]
  MarioLayer(Level owner) {    [...]
    mario = new Mario(32, height-64);    addPlayer(mario);
    // add one half of the ground, rather than all of it in one go:    addGround("ground", -32,height-48, -32 + 17*32,height);
    // make sure there's a boundary on the "exposed" side!    addBoundary(new Boundary(-32 + 17*32,height-48,-32 + 17*32,height));
    // and then add the second half, so that there's a gap in between    addGround("ground", -32 + 19*32,height-48, width+32,height);
    // make sure there's a boundary on the "exposed" side here, too!    addBoundary(new Boundary(-32 + 19*32,height,-32 + 19*32,height-48));
    [...]  }
  [...]}
Dan kemudian mari kita isi lubang itu dengan muncher!
class Muncher extends Interactor {  // constructing a Muncher is the same as Mario or Koopas  Muncher(float x, float y) {    super("Muncher");    setPosition(x,y);    setupStates();  }
  void setupStates() {    // Munchers only do one thing... munch!    State munch = new State("munch","graphics/enemies/Muncher.gif", 1, 2);    munch.setAnimationSpeed(0.20);    addState(munch);  }
  void overlapOccurredWith(Actor other, float[] overlap) {    // If someone runs into us... and that someone is Mario... he dies! O_O    if (other instanceof Mario) {      ((Mario)other).die();    }  }}
Disin kami membuat Muncher yang bertanggung jawab untuk membuat Mario mati. Jika dia bertemu dengan seorang Muncher, hal-hal buruk akan terjadi. Tapi, perpustakaan game tidak tahu tentang "Mario", hanya tahu tentang Aktor, jadi kita harus memeriksa dulu apakah Mario terlibat, dan jika demikian, kita perlu memberi tahu perpustakaan permainan bahwa kita akan memanggil fungsi yang hanya ada untuk Aktor dari "Mario" jenis, itulah yang ((Mario)other).die()tentang. The (Mario)other namun mengatakan perpustakaan untuk mempertimbangkan 'lain' semacam Mario, dan (...).die()berarti "memanggil fungsi die () pada apa pun di dalam mereka kurung". 

Jadi sekarang yang tersisa adalah menambahkan tanaman Muncher kami yang lucu, sedikit, mengerikan, dan menghebohkan ke dalam lubang keputusasaan kami ~~!
class MarioLayer extends LevelLayer {  [...]
  MarioLayer(Level owner) {    [...]
    addGround("ground", -32,height-48, -32 + 17*32,height);    addBoundary(new Boundary(-32 + 17*32,height-48,-32 + 17*32,height));
    addInteractor(new Muncher(521, height-8));    addInteractor(new Muncher(536, height-8));    addInteractor(new Muncher(552, height-8));    addInteractor(new Muncher(567, height-8));
    addBoundary(new Boundary(-32 + 19*32,height,-32 + 19*32,height-48));    addGround("ground", -32 + 19*32,height-48, width+32,height);
    [...]  }   [...]}
Keputusasaan selesai! Mari matikan pemicu dan gambar batas, dan mainkan permainan baru kami yang lebih menantang!

Kami sudah cukup jauh, tetapi ada sesuatu yang masih hilang. Sesuatu yang besar. Suara!

MENAMBAHKAN MUSIK DAN EFEK SUARA KE PERMAINAN KAMI

Hingga saat ini, kami bermain tanpa suara. Namun, saya tidak tahu permainan apa pun yang tidak memiliki setidaknya trek musik latar belakang, atau efek suara untuk hal-hal tertentu. Dan permainan kami kehilangan hal-hal itu! Karena kita hampir selesai, saya pikir sudah waktunya kita menambahkan itu, karena itu agak konyol untuk bermain dengan suara dimatikan, bukan?

The SoundManager: memuat, memutar, dan berhenti
Perpustakaan permainan menawarkan kita satu objek untuk menangani semua kebutuhan audio kita, SoundManagerobjek. Objek ini dapat memuat, memutar, menjeda, dan menghentikan file audio untuk kami, selama kami dapat mengikat file-file itu ke berbagai hal. Jadi mari kita lihat bagaimana kita dapat menggunakan SoundManager untuk memainkan musik latar belakang. Biasanya Anda ingin mengaitkan satu trek musik latar dengan setiap level, jadi mari kita berikan beberapa musik MarioLevel kami:
class MainLevel extends Level {  MainLevel(float levelWidth, float levelHeight) {    super(levelWidth, levelHeight);    addLevelLayer("background layer", new MainBackgroundLayer(this));    addLevelLayer("main layer", new MainLevelLayer(this));    setViewBox(0,0,screenWidth,screenHeight);    // Add some background music!    SoundManager.load(this, "audio/bg/Overworld.mp3");    SoundManager.play(this);  }}
Semuanya masih sama seperti sebelumnya kecuali untuk SoundManagerkode: Pertama kita memuat file, dan pastikan untuk "mengikat" ke level itu sendiri (ingat thiskata kunci dari tutorial terakhir?). Kemudian, kami segera mulai memainkannya.
Di mana saja, idenya hampir sama: kita mengaitkan file suara dengan "hal", menggunakan SoundManager.load(thing, "path to sound file"), dan kemudian ketika kita perlu memainkannya, kita sebut SoundManager.play(thing). Jadi, misalnya, mari berikan Mario semua efek suaranya:
class Mario extends Player {  [...]
  void setStates() {    [...]
    State dead = new State("dead", "graphics/mario/small/Dead-mario.gif", 1, 2);    dead.setAnimationSpeed(0.25);    dead.setDuration(100);    addState(dead);       // sound effect associated with this state:    SoundManager.load(dead, "audio/Dead mario.mp3");
    State jumping = new State("jumping", "graphics/mario/small/Jumping-mario.gif");    jumping.setDuration(15);    addState(jumping);    // sound effect associated with this state:    SoundManager.load(jumping, "audio/Jump.mp3");
    [...]  }
  void handleInput() {    [...]
    if(isKeyDown('W') &amp;&amp; active.name!="jumping" &amp;&amp; boundaries.size()&gt;0) {      addImpulse(0,-35);      setCurrentState("jumping");      // play our jump sound when we jump:      SoundManager.play(active);    }
    [...]  }
  [...]
  void die() {    setCurrentState("dead");    setInteracting(false);    addImpulse(0,-30);    setForces(0,3);    // when we die, stop the background music    SoundManager.stop(getLevelLayer().getLevel());    // and then play the sad music =(    SoundManager.play(active);  }
  [...]}
Perhatikan bahwa kami mengubah durasi untuk keadaan "mati" Mario menjadi 100 bingkai, bukan 15, sekarang. Itu karena musik yang dimainkan membutuhkan 100 frame untuk dimainkan.

Pasukan Koopa dimodifikasi dengan cara yang sama:
class Koopa extends Interactor {  [...]
  void setStates() {    State walking = new State("idle", "graphics/enemies/Red-koopa-walking.gif", 1, 2);    walking.setAnimationSpeed(0.12);    // the only sound koopas can make while walking is the "getting squished" sound    SoundManager.load(walking, "audio/Squish.mp3");    addState(walking);
    State noshell = new State("no shell", "graphics/enemies/Naked-koopa-walking.gif", 1, 2);    noshell.setAnimationSpeed(0.12);    // we make the same sound when we're squished a second time.    SoundManager.load(noshell, "audio/Squish.mp3");    addState(noshell);
    setCurrentState("idle");  }
  [...]
  void squish() {    // play the squish sound, regardless of whether we lose our shell, or die    SoundManager.play(active);
    [...]  }}
Untuk pickup, kita memuat file di konstruktor, dan memutarnya ketika kita dijemput:
class Coin extends MarioPickup {  Coin(float x, float y) {    super("Regular coin", "graphics/assorted/Regular-coin.gif", 1, 4, x, y, true);    // set up the clip to play when we get picked up    SoundManager.load(this, "audio/Coin.mp3");  }  void pickedUp() {    // play our "picked up" sound clip    SoundManager.play(this);  }}
Jadi jika kita semua efek suara di mana pun kita menginginkannya, akhirnya kita mendapatkan permainan yang terasa seperti permainan nyata.


Dan di sana kita memilikinya, permainan penuh. Dan dalam waktu kurang dari sehari!
Jika Anda ingin melihat kode lengkap kami akhirnya menulis sebagai satu file besar, klik disini ini akan terlihat sangat dekat dengan apa yang Anda miliki di Processing jika Anda sudah memprogram!