Isi kandungan:

Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR: 3 Langkah (dengan Gambar)
Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR: 3 Langkah (dengan Gambar)

Video: Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR: 3 Langkah (dengan Gambar)

Video: Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR: 3 Langkah (dengan Gambar)
Video: MEMBUAT GAME SNAKE ARDUINO LED MATRIX 8X8 DIKENDALIKAN DENGAN JOYSTICK || PROGRAM PAKE HAPE ANDROID🐍 2024, Julai
Anonim
Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR
Permainan Platformer yang Dikendalikan Arduino Dengan Joystick dan Penerima IR

Hari ini, kita akan menggunakan mikrokontroler Arduino untuk mengawal permainan platformer berasaskan C # sederhana. Saya menggunakan Arduino untuk mengambil input dari modul joystick, dan menghantar input tersebut ke aplikasi C # yang mendengar dan menyahkod input melalui sambungan Serial. Walaupun anda tidak memerlukan pengalaman sebelumnya dalam membuat permainan video untuk menyelesaikan projek ini, mungkin memerlukan sedikit masa untuk menyerap beberapa perkara yang berlaku dalam "gelung permainan", yang akan kita bincangkan kemudian.

Untuk menyelesaikan projek ini, anda memerlukan:

  • Komuniti Visual Studio
  • Arduino Uno (atau serupa)
  • Modul pengawal kayu bedik
  • Sabar

Sekiranya anda sudah bersedia untuk memulakan, teruskan!

Langkah 1: Sambungkan Joystick dan LED IR

Sambungkan Joystick dan LED IR
Sambungkan Joystick dan LED IR
Sambungkan Joystick dan LED IR
Sambungkan Joystick dan LED IR

Di sini, hubungannya cukup mudah. Saya telah memasukkan gambar rajah yang menunjukkan hanya kayu bedik yang disambungkan, serta persediaan yang saya gunakan, yang merangkumi kayu bedik ditambah LED inframerah untuk mengendalikan permainan dengan alat kawalan jauh, yang disertakan dengan banyak kit Arduino. Ini adalah pilihan, tetapi sepertinya idea hebat untuk dapat melakukan permainan tanpa wayar.

Pin yang digunakan dalam penyediaan adalah:

  • A0 (analog) <- Paksi mendatar atau X
  • A1 (analog) <- Paksi menegak atau Y
  • Pin 2 <- Masukan Joystick Switch
  • Pin 2 <- Input LED inframerah
  • VCC <- 5V
  • Tanah
  • Tanah # 2

Langkah 2: Buat Lakaran Baru

Buat Lakaran Baru
Buat Lakaran Baru

Kami akan bermula dengan membuat fail lakaran Arduino kami. Ini memilih tongkat perubahan untuk perubahan, dan mengirimkan perubahan tersebut ke program C # setiap beberapa milisaat. Dalam permainan video yang sebenarnya, kami akan memeriksa port bersiri dalam gelung permainan untuk mendapatkan input, tetapi saya memulakan permainan sebagai percubaan, jadi framerate sebenarnya berdasarkan jumlah peristiwa di port bersiri. Saya sebenarnya telah memulakan projek dalam projek Arduino sister, Processing, tetapi ternyata jauh lebih lambat dan tidak dapat menangani jumlah kotak di skrin.

Oleh itu, buat dahulu Sketsa baru dalam program penyunting kod Arduino. Saya akan menunjukkan kod saya dan kemudian menerangkan apa yang dilakukannya:

#sertakan "IRremote.h"

// Pemboleh ubah IR antara penerima = 3; // Pin Isyarat penerima IR IRrecv irrecv (penerima); // buat contoh keputusan 'irrecv' decode_results; // buat contoh 'decode_results' // Joystick / pemboleh ubah permainan int xPos = 507; int yPos = 507; byte joyXPin = A0; byte joyYPin = A1; byte joySwitch = 2; byte clickCounter = -1; int minMoveHigh = 530; int minMoveLow = 490; int currentSpeed = 550; // Default = purata kelajuan int speedIncrement = 25; // Jumlah untuk meningkatkan / menurunkan kelajuan dengan input Y yang tidak bertanda arus panjang = 0; // Memegang cap waktu semasa menunggu = 40; // ms untuk menunggu di antara mesej [Catatan: tunggu lebih rendah = lebih cepat framerate] butang bool tidak menentu Ditekan = salah; // Tolok jika butang ditekan batal penyediaan () {Serial.begin (9600); pinMode (joySwitch, INPUT_PULLUP); attachInterrupt (0, melompat, JATUH); semasa = milis (); // Sediakan masa semasa // Siapkan penerima inframerah: irrecv.enableIRIn (); // Mulakan penerima} // tetapkan gelung void () {int xMovement = analogRead (joyXPin); int yPos = analogRead (joyYPin); // Tangani pergerakan Joystick X tanpa mengira masa: jika (xMovement> minMoveHigh || xMovement current + waiting) {currentSpeed = yPos> minMoveLow && yPos <minMoveHigh // Sekiranya hanya bergerak sedikit …? currentSpeed //… kembalikan kelajuan semasa: getSpeed (yPos); // Hanya menukar yPos jika kayu bedik bergerak dengan ketara // int jarak =; Serial.print ((String) xPos + "," + (String) yPos + ',' + (String) currentSpeed + '\ n'); semasa = milis (); }} // loop int getSpeed (int yPos) {// Nilai negatif menunjukkan Joystick bergerak naik jika (yPos 1023? 1023: currentSpeed + speedIncrement;} lain jika (yPos> minMoveHigh) // Ditafsirkan "Bawah" {// Lindungi dari akan berada di bawah 0 return currentSpeed - speedIncrement <0? 0: currentSpeed - speedIncrement;}} // getSpeed void jump () {buttonPressed = true; // Butang indikasi ditekan.} // lompat // Apabila butang ditekan pada jauh, kendalikan tindak balas yang betul, kosongkanIRIR (keputusan decode_results) // mengambil tindakan berdasarkan kod IR yang diterima {switch (results.value) {case 0xFF18E7: //Serial.println("2 "); currentSpeed + = speedIncrement * 2; break; case 0xFF10EF: //Serial.println("4 "); xPos = -900; break; case 0xFF38C7: //Serial.println("5"); jump (); break; case 0xFF5AA5: // Bersiri. println ("6"); xPos = 900; break; case 0xFF4AB5: //Serial.println("8 "); currentSpeed - = speedIncrement * 2; break; default: //Serial.println (" butang lain "); rehat;} // Tukar akhir} // TAMAT terjemahanIR

Saya cuba membuat kod untuk menjadi lebih jelas, tetapi ada beberapa perkara yang perlu disebutkan. Satu perkara yang saya cuba pertimbangkan adalah seperti berikut:

int minYMoveUp = 520;

int minYMoveDown = 500;

Semasa program dijalankan, input analog dari joystick cenderung melonjak, biasanya berada di sekitar 507. Untuk membetulkannya, input tidak berubah kecuali lebih besar daripada minYMoveUp, atau lebih kecil dari minYMoveDown.

pinMode (joySwitch, INPUT_PULLUP);

attachInterrupt (0, melompat, JATUH);

Kaedah attachInterrupt () memungkinkan kita mengganggu gelung normal pada bila-bila masa, sehingga kita dapat mengambil input, seperti menekan butang ketika tombol joystick diklik. Di sini, kami telah melampirkan gangguan di baris sebelum itu, menggunakan kaedah pinMode (). Catatan penting di sini ialah untuk memasang gangguan pada Arduino Uno, anda mesti menggunakan pin 2 atau 3. Model lain menggunakan pin interrupt yang berbeza, jadi anda mungkin perlu memeriksa pin mana yang digunakan model anda di laman web Arduino. Parameter kedua adalah untuk kaedah panggilan balik, di sini disebut ISR atau "Interrupt Service Routine." Ia tidak boleh mengambil parameter atau mengembalikan apa-apa.

Cetakan bersiri (…)

Ini adalah garis yang akan menghantar data kami ke permainan C #. Di sini, kami menghantar bacaan paksi-X, bacaan paksi-Y, dan pemboleh ubah kelajuan ke permainan. Pembacaan ini dapat dikembangkan untuk memasukkan input dan bacaan lain untuk menjadikan permainan lebih menarik, tetapi di sini, kami hanya akan menggunakan pasangan.

Sekiranya anda sudah bersedia untuk menguji kod anda, muat naik ke Arduino, dan tekan [Shift] + [Ctrl] + [M] untuk membuka monitor bersiri dan melihat apakah anda mendapat output. Sekiranya anda menerima data dari Arduino, kami siap untuk bergerak ke bahagian C # kod…

Langkah 3: Buat Projek C #

Untuk memaparkan grafik kami, pada mulanya saya memulakan projek dalam Pemprosesan, tetapi kemudian memutuskan akan terlalu lambat untuk menunjukkan semua objek yang perlu kami paparkan. Oleh itu, saya memilih untuk menggunakan C #, yang ternyata jauh lebih lancar dan lebih responsif ketika menangani input kami.

Untuk bahagian C # projek, yang terbaik adalah hanya memuat turun fail.zip dan mengekstraknya ke foldernya sendiri, kemudian mengubahnya. Terdapat dua folder dalam fail zip. Untuk membuka projek di Visual Studio, masukkan folder RunnerGame_CSharp di Windows Explorer. Di sini, klik dua kali fail.sln (penyelesaian), dan VS akan memuatkan projek.

Terdapat beberapa kelas yang berbeza yang saya buat untuk permainan ini. Saya tidak akan membahas semua butiran mengenai setiap kelas, tetapi saya akan memberikan gambaran keseluruhan mengenai kelas utama.

Kelas Kotak

Saya membuat kelas kotak untuk membolehkan anda membuat objek segi empat tepat yang boleh dilukis di skrin dalam bentuk tingkap. Ideanya adalah untuk membuat kelas yang dapat diperluas menggunakan kelas lain yang mungkin ingin melukis semacam grafik. Kata kunci "maya" digunakan supaya kelas lain dapat menggantikannya (menggunakan kata kunci "ganti"). Dengan cara itu, kita boleh mendapatkan tingkah laku yang sama untuk kelas Pemain dan kelas Platform apabila kita perlu, dan juga mengubah objek yang kita perlukan.

Jangan terlalu risau tentang semua harta tanah dan membuat panggilan. Saya menulis kelas ini supaya saya dapat memperluasnya untuk permainan atau program grafik yang mungkin ingin saya buat pada masa akan datang. Sekiranya anda hanya perlu melukis segi empat tepat, anda tidak perlu menulis kelas besar seperti ini. Dokumentasi C # mempunyai contoh yang baik tentang bagaimana melakukan ini.

Walau bagaimanapun, saya akan memaparkan beberapa logik kelas "Kotak" saya:

bool maya awam IsCollidedX (Box otherObject) {…}

Di sini kita memeriksa perlanggaran dengan objek dalam arah X, kerana pemain hanya perlu memeriksa perlanggaran dalam arah Y (atas dan bawah) jika dia berbaris dengannya di layar.

bool maya awam IsCollidedY (Box otherObject) {…}

Apabila kita berada di atas atau di bawah objek permainan lain, kita memeriksa perlanggaran Y.

bool maya awam IsCollided (Box otherObject) {…}

Ini menggabungkan perlanggaran X dan Y, mengembalikan sama ada objek berlanggar dengan objek ini.

kekosongan maya awam OnPaint (Grafik grafik) {…}

Dengan menggunakan kaedah di atas, kami memasukkan semua objek grafik dan menggunakannya semasa program sedang berjalan. Kami membuat segi empat tepat yang mungkin perlu dilukis. Ini dapat digunakan untuk berbagai animasi. Untuk tujuan kami, segi empat tepat akan baik untuk platform dan pemain.

Kelas Perwatakan

Kelas Character meluaskan kelas Box saya, jadi kami mempunyai fizik tertentu di luar kotak. Saya membuat kaedah "CheckForCollisions" untuk memeriksa dengan cepat semua platform yang telah kami buat untuk perlanggaran. Kaedah "Jump" menetapkan kelajuan ke atas pemain ke pemboleh ubah JumpSpeed, yang kemudian diubah bingkai demi bingkai di kelas MainWindow.

Perlanggaran ditangani sedikit berbeza di sini daripada di kelas Box. Saya memutuskan dalam permainan ini bahawa jika melompat ke atas, kita dapat melompat melalui platform, tetapi ia akan menangkap pemain kita dalam perjalanan ke bawah jika bertembung dengannya.

Kelas Platform

Dalam permainan ini, saya hanya menggunakan konstruktor kelas ini yang mengambil koordinat X sebagai input, mengira semua lokasi X platform di kelas MainWindow. Setiap platform disediakan pada koordinat Y rawak dari 1/2 skrin hingga 3/4 dari ketinggian skrin. Ketinggian, lebar, dan warna juga dihasilkan secara rawak.

Kelas MainWindow

Di sinilah kita meletakkan semua logik untuk digunakan semasa permainan sedang berjalan. Pertama, dalam konstruktor, kami mencetak semua port COM yang tersedia untuk program ini.

foreach (port rentetan dalam SerialPort. GetPortNames ())

Console. WriteLine ("PELABUHAN TERSEDIA:" + port);

Kami memilih mana yang akan kami terima komunikasi, sesuai dengan port mana yang sudah digunakan oleh Arduino anda:

SerialPort = SerialPort baru (SerialPort. GetPortNames () [2], 9600, Parity. None, 8, StopBits. One);

Perhatikan arahan: SerialPort. GetPortNames () [2]. [2] menandakan port bersiri mana yang akan digunakan. Sebagai contoh, jika program mencetak "COM1, COM2, COM3", kita akan mendengar COM3 kerana penomboran bermula pada 0 dalam array.

Juga dalam konstruktor, kami membuat semua platform dengan jarak separa rawak dan penempatan dalam arah Y di skrin. Semua platform ditambahkan ke objek List, yang di C # hanyalah cara yang sangat user-friendly dan efisien untuk mengatur struktur data seperti array. Kami kemudian membuat Pemain, yang merupakan objek Karakter kami, menetapkan skor menjadi 0 dan menetapkan GameOver ke false.

kekosongan statik peribadi DataReceived (pengirim objek, SerialDataReceivedEventArgs e)

Ini adalah kaedah yang dipanggil semasa data diterima di port Serial. Di sinilah kita menerapkan semua fizik kita, memutuskan apakah akan menampilkan permainan, memindahkan platform, dll. Sekiranya anda pernah membina permainan, anda biasanya mempunyai apa yang disebut "gelung permainan", yang disebut setiap kali bingkai menyegarkan. Dalam permainan ini, kaedah DataReceived bertindak sebagai gelung permainan, hanya memanipulasi fizik kerana data diterima dari pengawal. Mungkin berfungsi lebih baik untuk menyiapkan Pemasa di tetingkap utama, dan menyegarkan objek berdasarkan data yang diterima, tetapi kerana ini adalah projek Arduino, saya ingin membuat permainan yang benar-benar berjalan berdasarkan data yang berasal darinya.

Kesimpulannya, penyediaan ini memberi asas yang baik untuk mengembangkan permainan menjadi sesuatu yang dapat digunakan. Walaupun fiziknya tidak sempurna, ia berfungsi dengan baik untuk tujuan kita, iaitu menggunakan Arduino untuk sesuatu yang disukai semua orang: bermain permainan!

Disyorkan: