Game 3D di Instagram Javascript, atau jalur penerbangan sosis



Setelah artikel pertama tentang pemrograman game dalam topeng di Instagram, seorang pelanggan meminta saya untuk membuat game di Instagram untuk pizzeria-nya. Game ini rencananya akan digunakan untuk keperluan promosi bisnis. Tentu saja, saya mengerti bahwa, dilihat dari jumlah pandangan artikel pertama, tema Instagram tidak terlalu menarik bagi komunitas Habr. Rupanya, layanan ini masih dianggap sebagai semacam hiburan sembrono untuk pirang, dan sebuah artikel tentang itu hanya cocok sebagai bacaan Jumat untuk koktail malam. Namun, hari ini, baru Jumat. Dapatkan koktail. Dan jangan lupa untuk mengundang pria berambut pirang. Namun, ada kemungkinan bahwa di masa depan teknologi akan mencapai ketinggian seperti itu sehingga kita akan mulai bermain di Instagram di GTA-5. Atau 10.

Artikel ini akan membahas dua game sekaligus. Saya membuat satu untuk memesan, dan kemudian yang kedua untuk diri saya sendiri. Dengan setiap permainan baru, saya dihadapkan dengan tugas-tugas baru, pencarian solusi yang membuat saya berkenalan dengan nuansa baru pembangunan. Mungkin cerita ini akan bermanfaat bagi pengembang lain dari elemen augmented reality. Permainan ini ditulis dalam Javascript murni tanpa menggunakan pustaka tambahan. Untuk menampilkan grafik 3D, alat Instagram bawaan digunakan.

Game 1. Pizza


Jadi, apa esensi dari game pertama. Pizza berputar. Komponen terbang dari permukaannya - potongan sosis, tomat dan sebagainya. Dua pemain harus menangkap mulut mereka. Pemenangnya adalah orang yang, seperti yang Anda duga, akan menangkap lebih banyak. Seiring waktu, kecepatan rotasi meningkat. Hal terlucu dalam game ini bagi saya adalah pemrograman jalur penerbangan elemen yang dapat dimakan ini. Bayangkan memprogram penerbangan sosis. Tidak, tentu saja, saya tidak pernah memiliki pemrograman yang begitu menyenangkan. Saya tertawa bahkan sekarang, menulis artikel ini.

Ketika pelanggan melihat prototipe yang berfungsi, dia mengirimi saya ini: ":))". Ada masalah saat menguji hasil akhir. Itu terdiri dari fakta bahwa subjek tidak bisa memainkan permainan: mereka hanya tertawa terbahak-bahak - itu sangat menyenangkan.

Biarkan saya mengingatkan Anda, pengembangan topeng dan game dibuat di Spark AR Studio. Dan kemudian dari sana Anda dapat mengunggah karya Anda di Instagram untuk dilihat semua orang. Perlu dicatat bahwa teknologi web mengaburkan batas antara sistem operasi untuk pengembang. Anda menulis satu kode, yang kemudian berfungsi di aplikasi Instagram untuk iOS dan Android, tanpa modifikasi atau perubahan apa pun. Tentu saja, pembayaran untuk ini menjadi kecepatan skrip yang pada dasarnya rendah.

Jadwal untuk permainan disediakan oleh pelanggan. Ada beberapa kesulitan dengan model 3D. Khususnya, ketika menggunakan mesin animasi built-in Spark AR Studio, ternyata jika objek bergerak diskalakan, maka koordinatnya salah ditentukan dalam permainan. Tetapi efek menjengkelkan ini tidak diamati jika Anda tidak skala seluruh objek sepenuhnya, tetapi masing-masing jala secara terpisah. Saya harus meninggalkan skala pizza 1: 1, dan meresepkan koefisien tertentu untuk setiap elemen yang membuatnya. Ada juga masalah dengan format FBX di mana Anda perlu mengekspor model untuk game Instagram. Desainer grafis mengirim model dengan tekstur built-in, yang, apalagi, ditempatkan di sepanjang jalur relatif. Editor 3D melihat mereka, tetapi Spark AR tidak. Saya harus mengemas ulang model sehingga file tekstur terletak terpisah dari model dan sepanjang satu jalur dengan mereka.

Dan masalah kecil lain yang saya temui adalah bahwa objek AR Saprk api yang bertanggung jawab untuk menampilkan teks pada layar menolak untuk menerima nilai sebagai nilai - skor permainan, misalnya. Untuk waktu yang lama saya tidak bisa mengerti mengapa tidak ada yang ditampilkan. Apa yang saya lakukan salah? Ternyata Anda harus terlebih dahulu mengonversi angka menjadi string (.toString ()). Ini tidak perlu dikatakan untuk bahasa lain, tetapi agak tidak biasa untuk javascript, yang selalu melakukan ini sendiri.

Animasi sederhana


Salah satu hal baru bagi saya dalam game ini adalah pemrograman animasi objek 3D. (Dalam game Instagram saya sebelumnya "Tic-tac-toe," tidak ada animasi sama sekali.) Mesin animasi di Spark AR Studio sangat spesifik. Dibutuhkan beberapa parameter input, dan kemudian secara reaktif menghubungkan variabel dengan objek di mana Anda ingin mengubah sesuatu. Sebagai contoh, ini akan mengubah koordinat y (startValue, endValue - nilai awal dan akhir) dari beberapa objek 3D dari waktu ke waktu t:

var driverParameters = {
    durationMilliseconds: t,
    loopCount: Infinity,
    mirror: false
};
var driver = Animation.timeDriver(driverParameters);
var sampler = Animation.samplers.linear(startValue, endValue);
sceneObject.transform.y = Animation.animate(driver, sampler);
driver.start();

Untuk memindahkan bahan pizza yang terbang di luar angkasa, saya memutuskan untuk menjalankan tiga animasi seperti itu secara paralel untuk setiap koordinat. Itu cukup untuk menunjukkan koordinat awal (startValue) dan koordinat akhir dihitung dari sudut rotasi pizza (endValue), sehingga itu berada di suatu tempat yang jauh jika pemain tidak menangkap "cangkang" ini dengan mulutnya. Jika tertangkap - maka gerakan berhenti. Acara pembukaan mulut yang sudah saya jelaskan di artikel sebelumnya. Hanya di sini ada permainan untuk dua orang dan, karenanya, akan ada dua wajah dan dua mulut:

FaceTracking.face(0).mouth.openness.monitor().subscribe(function(event) {
    if (event.newValue > 0.2) {
        ...
    };
});

FaceTracking.face(1).mouth.openness.monitor().subscribe(function(event) {
    if (event.newValue > 0.2) {
        ...
    };
});

Titik kunci dalam permainan ini adalah menangkap bahan-bahan terbang dengan mulut Anda, dengan kata lain, menemukan benda terbang di area kecil tertentu di sekitar tengah mulut seseorang. Pada awalnya, perhitungan ini tidak ingin dilakukan dengan benar untuk saya, tetapi solusi untuk masalah itu ditemukan setelah pengenalan benda tersembunyi yang terikat pada koordinat mulut, dan itu berhasil. Untuk beberapa alasan, koordinat langsung mulut tidak kembali. Di sini cameraTransform.applyTo adalah pengurangan koordinat titik wajah ke koordinat di dunia 3D (metode ini diambil dari dokumentasi).

move: function() {
    //   (   )

    //    
    var object = Scene.root.find('pizzafly');
    var olast = {
        x: object.transform.x.pinLastValue(),
        y: object.transform.y.pinLastValue(),
        z: object.transform.z.pinLastValue()
    };

    //   ,       
    var objectHidden = Scene.root.find('nullObject');
    objectHidden.transform.x = FaceTracking.face(face).cameraTransform.applyTo(FaceTracking.face(face).mouth.center).x;
    objectHidden.transform.y = FaceTracking.face(face).cameraTransform.applyTo(FaceTracking.face(face).mouth.center).y;
    objectHidden.transform.z = FaceTracking.face(face).cameraTransform.applyTo(FaceTracking.face(face).mouth.center).z;

    //   
    var mouth = {
        x: objectHidden.transform.x.pinLastValue(),
        y: objectHidden.transform.y.pinLastValue(),
        z: objectHidden.transform.z.pinLastValue()
    };

    //    
    var d = {
        x: Math.abs(olast.x - mouth.x),
        y: Math.abs(olast.y - mouth.y),
        z: Math.abs(olast.z - mouth.z)
    };

    //  
    if ((d.x > 0.03) || (d.y > 0.03) || (d.z > 0.03)) {
        // 
        ...
    } else {
        // 
        ...
    };

},

Selanjutnya, saya menyadari bahwa Anda harus menghapus pemeriksaan kedalaman (koordinat z), karena dalam permainan khusus ini secara visual sulit untuk memperkirakan kedalaman. Artinya, sekarang menjadi mungkin untuk menangkap bahan dengan membuka mulut Anda kapan saja selama penerbangan. Yang utama adalah kombinasi dari x dan y.


Akhirnya, masalah terakhir yang saya temui saat menulis game ini adalah membatasi ukuran build terakhir menjadi 4 MB. Selain itu, sesuai dengan rekomendasi Facebook, agar game dapat ditampilkan pada perangkat seluler sebanyak mungkin, bahkan sesuai dengan 2 MB. Dan 3D-modelers adalah orang-orang kreatif dan ingin membuat model-model berat dengan grid padat dan tekstur besar, sama sekali tidak peduli dengan kita, programmer, atau lebih tepatnya, tentang kinerja akhir dalam game. Saya juga entah bagaimana mengurangi tekstur dalam ukuran dan dikompresi dalam jpg (bukan png), tetapi model pizza itu sendiri harus dikirim untuk direvisi (retopologi). Sebagai hasilnya, bagaimanapun, adalah mungkin untuk masuk ke volume 2MB dengan semua model, tekstur dan skrip. Dan permainan berjalan dengan moderat.

Dan setelah beberapa waktu dia kembali dengan kata-kata bahwa "efeknya mengandung terlalu banyak teks statis." Saya harus menghapus angka hitung mundur dan alih-alih mengatur animasi ke panah di stopwatch, yang sekarang mulai menghitung waktu alih-alih. Setelah itu, game disetujui.

Game 2. Tentang kupu-kupu (ButterFlap)



Sekarang saya akan berbicara tentang membuat game kedua. Saya tidak dapat membantu membuat game, ini adalah hobi saya. Beberapa hari sebelum 8 Maret, saya memutuskan untuk membuat game Instagram untuk liburan ini. Sesuatu tentang bunga, kupu-kupu, dan permen. Tapi saya tidak bisa memikirkan apa esensi dari game itu. Pikiran itu berputar di kepala saya. Mungkin kupu-kupu akan mengumpulkan permen dan menaruhnya di keranjang? Atau mungkin kupu-kupu akan mengambil permen di udara dan melemparkannya, dan pemain perlu menangkapnya dengan mulutnya? Secara umum, saya scammed selama beberapa hari dan, setelah tidak menemukan solusi, saya menyadari bahwa pada 8 Maret, permainan saya masih tidak punya waktu untuk melewati moderasi, karena yang terakhir membutuhkan 3-4 hari. Aku sudah ingin meninggalkan usaha ini, ketika tiba-tiba idenya datang dengan sendirinya, tiba-tiba. Saya tidak lagi mengikat permainan ke Hari Perempuan, sekarang itu hanya permainan.

Scroller. Dari kiri ke kanan, lansekap dan berbagai rintangan bergerak. Pemain harus mengendalikan kupu-kupu yang dapat bergerak bebas di dalam layar dan mengumpulkan berlian yang tergantung di udara. Juga, dari kanan ke kiri sedikit lebih cepat dari sisa gambar, awan bergerak, dari mana hujan turun. Anda harus bersembunyi dari hujan di bawah bunga. Jika seekor kupu-kupu jatuh di bawah air, maka sayapnya menjadi basah dan jatuh, ini adalah akhir dari permainan. Saya menyebut permainan itu secara sederhana: ButterFlap.

Ya, semua ini terdengar bagus. Saya, langsung, ingin bermain sendiri. Tetapi saya ingat bahwa saya bukan seorang seniman sama sekali. Namun, saya dapat membuat model 3D, dan ini lebih mudah daripada menggambar. Jadi, diputuskan, biarlah ada penggulung 3D.

Seni grafis


Saya menemukan model online bebas royalti yang harus saya perbaiki. Dia menarik tekstur ke yang tanpa tekstur, setelah sebelumnya menempatkan yang terakhir dalam atlas tekstur: artefak dalam bentuk "tangga" terlihat pada model non-tekstur, dan smoothing dapat diatur untuk tekstur dalam permainan, yang membuat penampilan objek lebih rapi dan tidak begitu datar. Model-model yang mengandung tekstur juga memiliki kekurangannya yang harus diperbaiki. Pertama, ukuran tekstur bukan kelipatan dua dalam kekuasaan. Artinya, misalnya, bisa sama dengan 1200x1200. Saya harus mengompres ke 1024x1024. Pemroses video dapat mengubah skala atau mengisi tekstur yang tidak sesuai dengan ruang kosong, yaitu yang tidak 1024x1024, 512x512, 256x256, dll. Bagaimanapun, tindakan tersebut adalah beban tambahan selama kerja gim dan konsumsi memori yang tidak berarti,oleh karena itu, lebih baik menyiapkan gambar yang benar terlebih dahulu secara manual. Situasi ini juga diselamatkan oleh fakta bahwa saya mendistribusikan semua tekstur dengan atlas tekstur, jadi jika, misalnya, tekstur aslinya berukuran 400x200 piksel, maka saya bisa memasukkannya ke dalam atlas 1024x1024, di samping yang serupa lainnya. Setelah ini, secara alami perlu untuk mengukur pemindaian UV juga, tetapi ini dilakukan dalam beberapa detik. Masih menemukan varian model di mana untuk beberapa alasan tekstur diikat di sepanjang jalur absolut seperti "C: \ Work \ Vasya \ Map.jpg". Ya, tidak ada folder seperti itu di komputer saya! Saya harus menentukan jalur ke tekstur secara manual ... Tapi mengapa Anda mendapat ide bahwa saya harus menyimpan semua proyek saya di drive "C:"!? Oh, pemodel ini, seniman bebas ... Ngomong-ngomong, dengan nama folder di jalur acak yang ditinggalkan, Anda dapat secara tidak sengaja mempelajari lebih lanjut tentang identitas pemodel,misalnya namanya. Senang bertemu denganmu!

Yang paling sulit adalah menemukan model kupu-kupu yang cocok dengan animasi. Spark AR menggunakan animasi yang dapat diekspor dari editor 3D apa pun ke format FBX. Sayap sepasang model kupu-kupu yang saya unduh entah bagaimana dicerminkan secara aneh - satu sayap dimodelkan, dan yang kedua tercermin dalam beberapa hal yang tidak saya mengerti, dan, dengan demikian, dua di antaranya ternyata. Dengan pendekatan pemodelan ini, pada akhirnya, dalam permainan, salah satu sayap (disalin) tidak ingin menerima cahaya dari sumbernya dan selalu tetap redup. Saya tidak mengambil risiko mengubah model secara drastis, karena animasi akan terbang. Dan dalam animasi saya bukan noob yang lebih besar dari pada pemodelan 3D. Mungkin masalahnya adalah sesuatu yang lain: Saya mencoba, misalnya, untuk memperluas normals, tetapi itu tidak membantu. Singkatnya, model 3D gratis sangat merepotkan. Akibatnya, setelah mandi sepanjang malam,dengan coba-coba, saya menemukan model yang cocok, yang setelah beberapa fine-tuning dengan file mulai terlihat memuaskan. Sesuatu yang saya tidak suka tentang itu, tetapi itu adalah hal-hal kecil: Saya mereduksi tekstur, mengubah geometri di beberapa tempat, dan menyesuaikan parameter material. Akhirnya, kupu-kupu itu lepas landas. Hore. Tapi sekarang aku kelelahan. Jadi saya memutuskan untuk pergi tidur dan melanjutkan keesokan harinya. Ya, saya menghabiskan 7-8 hari untuk membuat game. Tetapi itu adalah pekerjaan yang agak santai di malam hari, membaca dokumentasi, artikel dan menemukan jawaban atas pertanyaan.Jadi saya memutuskan untuk pergi tidur dan melanjutkan keesokan harinya. Ya, saya menghabiskan 7-8 hari untuk membuat game. Tetapi itu adalah pekerjaan yang agak santai di malam hari, membaca dokumentasi, artikel dan menemukan jawaban atas pertanyaan.Jadi saya memutuskan untuk pergi tidur dan melanjutkan keesokan harinya. Ya, saya menghabiskan 7-8 hari untuk membuat game. Tetapi itu adalah pekerjaan yang agak santai di malam hari, membaca dokumentasi, artikel dan menemukan jawaban atas pertanyaan.


Sepanjang malam keesokan harinya saya mengerjakan grafik. Kekhasan topeng permainan untuk Instagram, seperti yang telah saya sebutkan, adalah bahwa disarankan untuk tidak melampaui volume 2MB untuk seluruh permainan (maksimum 4 MB). Saya tidak khawatir tentang skrip: ukurannya tidak akan melebihi 50 Kb. Tetapi lebih dari model 3D tanaman harus cukup disulap. Sebagai contoh, bagian dari bunga matahari di mana benih berada dibuat secara geometri. Ratusan poligon ... Ganti dengan sepotong bola beberapa lusin segitiga dan rentangkan tekstur yang diunduh, pada kenyataannya, dari bagian ini. Jumlah daun juga bisa dikurangi. Kami membuat rumput di bagian bawah layar dengan bidang dua segitiga dengan tekstur overlay dengan saluran alfa. Kami mencapai volume dengan bayangan dan menyalin fragmen gambar di dalam tekstur itu sendiri.

Secara umum, diinginkan untuk meminimalkan jumlah tekstur, serta ukurannya dalam byte. Teksturlah yang menciptakan sebagian besar permainan. Saya terbiasa dengan tekstur di mana transparansi diperlukan, ditempatkan dalam satu atlas tekstur - dalam png 32 bit, dan tekstur yang tidak menggunakan saluran alfa, kemas dalam atlas lain, menyimpannya dalam jpg. Jpg bisa menyusut lebih kuat dari png. Elemen rumput dan UI yang membutuhkan transparansi telah pergi ke atlas png, dan segala sesuatu yang lain untuk jpg.

Total volume. Secara total, saya mendapatkan 4 jenis tanaman, batu, kupu-kupu, yang akan dikendalikan pemain, dan awan. Tekstur semua model ini dalam bentuk terkompresi mengambil 2 atlas 1024x1024 jpg dan png dengan volume total 500 Kb. Modelnya sendiri membutuhkan sekitar 200 Kb. Ditambah skrip. Suara - 31 Kb. Total: sekitar 1 Mb. Dalam warna hijau, ukuran build baru saja ditampilkan (ini yang pas dengan 2 MB).


Tiba-tiba saya mengalami masalah yang sama sekali tidak terduga. Saya menghapus beberapa model yang tidak digunakan, tetapi tidak melalui Spark AR Studio, tetapi dari sistem file. Selanjutnya, ketika merakit bangunan, saya menemukan bahwa mereka menghilang dari adegan Spark AR Studio, tetapi masih masuk ke perakitan. Dan untuk menghapus proyek dari sumber daya yang tidak digunakan tidak mungkin. Tautan ke mereka dari "Ringkasan Aset" tidak mengarah ke mana pun. Rupanya, ini adalah cacat di Spark AR Studio. Saya harus membuat ulang proyek lagi, menambahkan semua sumber daya yang diperlukan di sana sejak awal.

Tempat kejadian


Saya telah lama berpikir tentang bagaimana menerapkan pengguliran semua objek di layar. Dari alat untuk ini, hanya ada javascript dan mesin animasi built-in paling sederhana di Spark AR Studio, yang dapat dengan mudah mengubah koordinat objek dari nilai awal ke final dalam waktu tertentu.

Ya, dilema masih muncul sebelum ini: apakah akan membuat seluruh level permainan, adegan dalam editor 3D, dengan menduplikasi tanaman berulang sebanyak yang diperlukan dan menempatkannya di posisi yang tepat, untuk menggulir seluruh adegan dalam permainan, atau memuat hanya satu salinan dari setiap 3D objek dan gantikan mereka ke arah pemain di luar layar. Jawabannya jelas. Pilihan kita adalah pilihan kedua. Kalau tidak, pasti tidak mungkin masuk ke dalam 2 MB: kemungkinan besar, pemandangan sesuai dengan opsi pertama akan berat. Tapi kemudian Anda membutuhkan tata letak objek. Dan saya, tanpa ragu-ragu, memutuskan untuk menggunakan editor 3D sebagai editor level. Ya, ternyata saya melakukan keduanya. Tanaman untuk permainan, saya menyimpan masing-masing dalam satu salinan. Dan dari editor saya hanya perlu koordinat. Setelah menyelesaikan pekerjaan,Saya menulis koordinat semua objek dan membuat array dengan data untuk game.

lv:[
    {n:'flower1', x:8.0, y:-6.5},
    {n:'cloud', x:10.0, y:0.1},
    {n:'rain', x:10.0, y:6.6},
    {n:'flower1', x:14, y:-2.5},
    {n:'diamond_red', x:20, y:2.0},
	...
],

Namun - array asosiatif yang terpisah, sesuai dengan jenis objek, di mana ukuran colliders dan perpindahannya relatif terhadap pusat objek 3D disimpan, serta bendera (col) yang menentukan apakah objek tersebut merupakan hambatan (jika tidak, pemain melewatinya). Untuk beberapa jenis objek, bendera (hancurkan) diatur, yang menentukan apakah objek harus disembunyikan setelah interaksi, serta (v) parameter, yang menentukan tingkat interaksi tertentu, misalnya, jumlah poin yang didapat atau hilang pemain.

colld:{
    'flower1': {dx:0, dy:5, w:2.3, h:1.4, col:true},
    'diamond_green': {dx:0, dy:0, w:1, h:1, col:false, v:1, destroy:true},
    'diamond_red':{dx:0, dy:0, w:1, h:1, col:false, v:-2},

    ...
},

Nuansa sedikit. Rumput di bagian bawah adegan harus bergulir terus menerus. Jadi, Anda harus menggunakan dua salinan objek ini dan menggantikannya satu per satu saat Anda bergerak. Bunga akan muncul di satu layar tidak lebih dari satu salinan masing-masing.

Mengingat masalah skala yang saya temui ketika mengembangkan game pertama, saya mengatur ulang skala semua model di editor 3D. Dengan demikian, dalam model AR Saprk segera dimuat dalam ukuran normal. Memang benar, dalam naskah, itu tidak dapat dilakukan tanpa "angka ajaib", koefisien global, kode universal, yang mengandung esensi alam semesta. Alam semesta virtual, tentu saja. Dan saya siap untuk mengungkapkan nomor ini kepada Anda. Gunakan itu, orang-orang! Tidak masalah! Jumlah ini adalah 0,023423. Singkatnya, meskipun pengaturan ulang semua skala, satu meter di editor 3D ternyata sama dengan angka ini di Spark AR Studio. Kemungkinan besar, saya, bagaimanapun, tidak sepenuhnya memahami semua seluk-beluk bekerja dengan grafis 3D, karenanya koefisien. Koordinat (tetapi bukan ukuran) dari semua objek yang diekspor dari editor dikalikan dengan itu, Anda dapat menebaknya.Di mana untuk menyesuaikan skala adegan di Spark AR, saya tidak menemukan.

Masalah berikutnya yang saya temui adalah hilangnya urutan objek ketika mengekspor dari editor 3D. Benda-benda kompleks yang terdiri dari beberapa jerat dapat muncul secara tak terduga pada adegan dalam permainan sedemikian rupa sehingga, misalnya, jerat yang berada di belakang yang lain tiba-tiba melompat ke depan. Dan, jika Anda melihat urutan objek setelah mengekspor ke Spark AR Studio, maka itu benar-benar menunjukkan bahwa mesh ini karena beberapa alasan lebih tinggi dalam daftar, meskipun lebih rendah di editor. Saya memecahkan masalah ini dengan membagi adegan menjadi beberapa lapisan dan menyimpannya ke file yang berbeda.

Animasi yang kompleks


Selama tiga malam lagi, saya mengutak-atik pemrograman. Jika saya menggunakan mesin Spark AR Studio standar untuk menggerakkan sayap kupu-kupu, tugas untuk memindahkan latar belakang tidak begitu sederhana. Saya masih tidak mengerti bagaimana cara melampirkan tidak hanya satu parameter variabel untuk iterasi siklus gerak, tetapi fungsi callback penuh. Bagaimanapun, saya tidak bisa melakukannya, parameter animasi saat ini tidak ingin ditransfer ke sana. Dan fungsi seperti itu hanya perlu, karena jika di game pertama (dengan pizza) saya memeriksa tabrakan dengan membuka mulut dengan berlangganan, maka tidak ada acara seperti itu di sini. Dan itu hanya perlu untuk memeriksa tabrakan dengan objek lingkungan saat karakter bergerak, sesuai dengan koordinatnya saat ini. Dan untuk ini, koordinat harus dibandingkan pada setiap iterasi. Dan kemudian saya berpikir. Lagipula, saya sudah menulis game dalam javascript.Dan mengapa tidak menggunakan mesin animasi Anda yang saya tulis sebelumnya untuk game-game itu? Prinsip operasinya kira-kira sama: dalam waktu tertentu, parameter (atau parameter) berubah antara nilai awal dan akhir yang diberikan. Dan nilai saat ini dilewatkan sebagai parameter - Anda tidak akan percaya itu - dalam fungsi callback yang diberikan, di mana, misalnya, Anda dapat mengatur objek 3D pada adegan di koordinat yang sama dengan nilai saat ini, atau memeriksa tabrakan pada mereka. Terima kasih, Cap. Saya harus sedikit menyesuaikan mesin saya dengan "ekosistem" lokal: menghapus referensi ke objek jendela dari sana, karena tidak ada di sini, dan hal-hal kecil lainnya.Dan nilai saat ini dilewatkan sebagai parameter - Anda tidak akan percaya itu - dalam fungsi callback yang diberikan, di mana, misalnya, Anda dapat mengatur objek 3D pada adegan di koordinat yang sama dengan nilai saat ini, atau memeriksa tabrakan pada mereka. Terima kasih, Cap. Saya harus sedikit menyesuaikan mesin saya dengan "ekosistem" lokal: menghapus referensi ke objek jendela dari sana, karena tidak ada di sini, dan hal-hal kecil lainnya.Dan nilai saat ini dilewatkan sebagai parameter - Anda tidak akan percaya itu - dalam fungsi callback yang diberikan, di mana, misalnya, Anda dapat mengatur objek 3D pada adegan di koordinat yang sama dengan nilai saat ini, atau memeriksa tabrakan pada mereka. Terima kasih, Cap. Saya harus sedikit menyesuaikan mesin saya dengan "ekosistem" lokal: menghapus referensi ke objek jendela dari sana, karena tidak ada di sini, dan hal-hal kecil lainnya.

Ya, namun - tentang menggulir lanskap dan objek lingkungan. Saya memutuskan untuk menempatkan seluruh dunia dalam satu NullObject, yaitu, dalam objek 3D kosong, wadah, dan memindahkannya hanya menggunakan satu parameter untuk animasi - koordinat x-nya. Di dalam wadah, semua model memiliki koordinat yang sama seolah-olah mereka berada di luar, hanya sekarang bagi mereka sistem referensi terkait dengan objek kosong ini. Batuan dan bunga akan diulangi (apalagi, pada ketinggian yang berbeda dari tanah, sesuai dengan diagram level), sehingga Anda dapat menggunakan kembali benda-benda ini saat Anda bergerak, mengaturnya posisi horizontal dan vertikal yang diinginkan di dalam "wadah". Saya menulis sebuah sistem pencarian untuk objek-objek yang jatuh ke dalam frame (pada offset kontainer saat ini), yang mengatur objek yang meninggalkan frame ke posisi baru lebih jauh jika harus muncul di sana. Anda bisa melihat,cara kerjanya pada contoh tiga objek. (Akan ada lebih banyak dari mereka dalam permainan, sehingga di sana Anda tidak akan lagi melihat efek "penataan ulang" objek lingkungan seperti itu.)



Fungsi untuk memperbarui koordinat objek terlihat seperti ini:

oCoordSet: function(v) {
    //  :    
    //   
    var camx = -ap.oWorld.transform.x.pinLastValue();
    //  
    var x1 = camx - ap.game.scro.w2;
    var x2 = camx + ap.game.scro.w2;
    //   
    for (var i = 0; i < ap.d.lv.length; i++) {
        //    
        if ((ap.d.lv[i].x >= x1) & (ap.d.lv[i].x <= x2)) {
            //   
            ap.d.lv[i].o = Scene.root.find(ap.d.lv[i].n);
            //  -  
            ap.d.lv[i].o.transform.y = ap.d.lv[i].y;
            if ((ap.d.lv[i].n == 'cloud') || (ap.d.lv[i].n == 'rain')) {
                //    ,
                //  
                //   2.3,
                //     
                ap.d.lv[i].o.transform.x = ap.d.lv[i].x - (x2 - ap.d.lv[i].x) * 2.3 + 0.2;
            } else {
                //    ,
                //      
                ap.d.lv[i].o.transform.x = ap.d.lv[i].x;
            };
        };
    };
    //        
    //     
    if (camx > ap.game.grassPosLast) {
        ap.game.grassPosLast += ap.game.grassd;
        ap.game.grassi = 1 - ap.game.grassi;
        ap[ap.game.grassNm[ap.game.grassi]].transform.x = ap.game.grassPosLast;
    };
},

Karakter utama


Karakter utama dalam permainan adalah kupu-kupu yang tidak dapat tenggelam, yang dengan berani terbang ke depan, mengatasi rintangan. Saya memutuskan untuk melakukan manajemen dengan menetapkan penanda, atau kursor (titik cahaya), dengan memutar dan memiringkan kepala. Dan ke arah titik ini seekor kupu-kupu akan terbang perlahan (pada kenyataannya, itu bukan pejuang, juga tidak bisa berteleportasi). Misalnya, jika Anda berlangganan acara head tilt, maka Anda dapat menerapkan kontrol vertikal seperti ini:

FaceTracking.face(0).cameraTransform.rotationX.monitor().subscribe(function(event) {
    var v = event.newValue;
    //  
    var scrH2 = ap.game.scr.h2;
    //
    var p = -v * 0.5;
    if (p < -scrH2) {
        p = -scrH2;
    } else if (p > scrH2) {
        p = scrH2;
    };
    //  
    var d = 0.006;
    //  
    var cur = ap.oPers.transform.y.pinLastValue();
    if (p < cur) {
        cur -= d;
        if (cur < p) {cur = p;};
    } else {
        cur += d;
        if (cur > p) {cur = p;};
    };
    //    ()
    ap.oPointer1.transform.y = p;
    //   ,
    // ,    
    ap.game.pers.dy + = cur - ap.game.pers.y;
});

Begitu pula untuk horizontal. Hanya di sana perlu untuk berlangganan ke acara bukan dari kemiringan, tetapi dari rotasi kepala (rotasiY), dan bukannya ketinggian layar, pertimbangkan lebarnya.

Colliders


Semua ini luar biasa, dunia bergerak, dan karakter permainan dapat dengan bebas bergerak di sekitar layar. Tetapi sekarang Anda membutuhkan penangan benturan, jika tidak, tidak ada permainan yang akan berhasil. Ada tiga peristiwa dalam permainan, yang menurutnya posisi karakter dapat berubah. Ini adalah rotasi dan kemiringan kepala, serta pergerakan dunia, di mana koordinat horizontal pemain (x) secara otomatis meningkat.

Karena saya tidak tahu bagaimana iterasi dari face handler bekerja di Spark AR - apakah mereka dipanggil dengan frekuensi tertentu atau diatur ke frekuensi jam maksimum yang dimungkinkan, dan di mesin animasi saya, saya dapat mengontrol parameter ini, saya memutuskan untuk menentukan tabrakan di fungsi saya. pergerakan dunia, yang disebut pada frekuensi yang saya setel (60 frame per detik). Dalam acara pemrosesan wajah, kami hanya akan "menumpuk" gerakan.

Prinsipnya akan seperti itu. Dalam peristiwa memiringkan kepala dan memutar kepala, offset sepanjang sumbu x dan y diakumulasikan. Selanjutnya, dalam fungsi menggulir dunia, perpindahan horisontal juga ditambahkan ke "celengan". Dan kemudian diperiksa, jika perpindahan akumulasi ditambahkan ke koordinat asli, maka akan ada tabrakan dengan salah satu benda di dunia. Jika tidak, maka koordinat asli pemain plus offset dilakukan oleh koordinat saat ini. Dan kemudian kami memperbarui yang sumber ke yang saat ini (reset) dan mengatur ulang offset. Jika demikian, maka gulung kembali koordinat ke aslinya. Selain itu, kita perlu menentukan sumbu tabrakan mana, karena kedua koordinat tidak dapat diputar kembali. Kalau tidak, pemain hanya "menempel" ke satu titik di ruang dan tidak bisa lagi bergerak ke mana pun. Adalah perlu untuk memberinya kebebasan bergerak di sepanjang poros sepanjang tabrakan itu tidak terjadi.Jadi Anda bisa memberinya kesempatan untuk terbang di sekitar rintangan.

setPersPos: function(camx, camdx) {
    //   
    //       (camx,camdx)

    //     
    var persx = ap.game.pers.x;
    var persy = ap.game.pers.y;
    var dx = ap.game.pers.dx;
    var dy = ap.game.pers.dy;

    // ,     
    var col = ap.collisionDetect(
        {x: persx, y: persy, dx: dx, dy: dy},
        {x: camx, dx: camdx, y: 0}
    );

    if (col.f == true) {
        // 

        if (col.colx == true) {
            //   
            //    ,
            //   
            //(    ,    )
            ap.game.pers.x = col.x;
        } else {
            //    ,
            //   
            ap.game.pers.x = persx + dx;
        };

        if (col.coly == true) {
            // -  
            ap.game.pers.y = col.y;
        } else {
            ap.game.pers.y = persy + dy;
        };

    } else {
        //  ,   
        ap.game.pers.x = persx + dx;
        ap.game.pers.y = persy + dy;
    };

    // 
    ap.game.pers.dx = 0;
    ap.game.pers.dy = 0;

    //     
    ap.oPers.transform.x = ap.game.pers.x;
    ap.oPers.transform.y = ap.game.pers.y;
},

Fungsi deteksi tabrakan itu sendiri:

collisionDetect: function(opers, ow) {
    // , opers -   , ow -  

    var res = {f: false, colx: false, coly: false, x: 0, y: 0};

    var ocoll, x, y, w, h, persx, persy, persx0, persy0, od, colx1, coly1, colx2, coly2;
    var collw = false, collh = false;

    //  
    //(  ,  "" )
    persx0 = opers.x + ow.x - ow.dx;
    persy0 = opers.y + ow.y;

    //       
    persx = persx0 + opers.dx;
    persy = persy0 + opers.dy;

    //  
    for (var i = 0; i < ap.d.lv.length; i++) {
        od = ap.d.lv[i]; //obj data

        //    (   ),
        //     
        //        
        if (typeof ap.d.colld[od.n] !== "undefined") {

            //       
            ocoll = ap.d.colld[od.n];
            colx1 = od.x + ocoll.x1;
            colx2 = od.x + ocoll.x2;
            coly1 = od.y + ocoll.y1;
            coly2 = od.y + ocoll.y2;

            if ((persx < colx1) || (persx > colx2) || (persy < coly1) || (persy > coly2)) {} else {
                //   
                res.f = true;

                //        ,
                //,    
                if ((persx0 < colx1) || (persx0 > colx2)) {
                    collw = true;
                };
                //        ,
                //,    
                if ((persy0 < coly1) || (persy0 > coly2)) {
                    collh = true;
                };

            };
        };

    };

    //   

    //  ,     ,
    //  
    if (collw == true) {
        res.colx = true;
        res.x = persx0 - ow.x;
    } else {
        res.x = opers.x;
    };

    // -  
    if (collh == true) {
        res.coly = true;
        res.y = persy0 + ow.y;
    } else {
        res.y = opers.y;
    };

    return res;
},

Hujan


Saya menggunakan mesin partikel standar Spark AR Studio untuk menghidupkan hujan. Tidak ada yang istimewa di sini. Kami menambahkan objek Emtter ke adegan, tidak lupa untuk menanyakannya Emitter -> Space -> Local (bukan Dunia). Ini untuk memastikan bahwa tetesan tidak secara dinamis tertinggal di belakang awan selama pergerakan, tetapi selalu jatuh secara langsung. Metode ini lebih nyaman untuk penentuan lebih mudah saat kupu-kupu jatuh dalam hujan - tidak perlu melakukan koreksi ketinggian. Untuk tetesnya sendiri, saya menyiapkan tekstur yang sesuai. Nah dan, tentu saja, objek hujan akan bergerak bersama dengan objek cloud. Kemudian saya menambahkan kondisi cloud hit ke kode penanganan tabrakan. Dan, jika tidak ada halangan di atas pemain pada saat ini, maka kupu-kupu jatuh dan permainan berakhir.

Moderasi


Untuk moderasi yang berhasil, video wajib dari game tidak boleh mengandung teks statis yang tidak terikat ke objek. Jika tidak, robot langsung menghentikan moderasi. Namun, setelah itu, seseorang memeriksa permainan selama beberapa hari. Dan dia tidak menyukai banyaknya teks sebelum pertandingan, dan juga pada akhirnya. Saya harus mengurangi jumlah teks. Setelah itu, game disetujui.

Ringkasan


Bukan berarti permainan saya sangat menarik. Dia mungkin tidak memiliki dinamika dan mekanika tambahan. Saya akan merilis pembaruan. Tapi saya menyadari bahwa membuat game di Instagram itu menarik. Ini semacam tantangan. Saya sangat menikmati proses pemrograman dan menyelesaikan semua jenis tugas di bawah minimalis dalam hal alat dan jumlah memori yang dialokasikan. Saya ingat seseorang mengatakan bahwa 640 Kb sudah cukup untuk semua orang. Sekarang coba pas game 3D 2 MB. Saya, mungkin, tidak akan berdebat bahwa mereka cukup untuk semua orang ... Tetapi cobalah!


Sebagai penutup, saya ingin menyatukan semua daftar saat-saat tidak jelas yang saya temui. Mungkin ini berguna bagi seseorang sebagai lembar contekan saat membuat game untuk Instagram.

  • Skala. Sesuaikan skala semua model 3D di editor 3D sehingga ia segera 1: 1 di atas panggung dalam permainan.
  • . . , .
  • . FBX, . -. , .
  • . JPG , , , -, JPG, PNG.
  • . , , . Spark AR , . , , , 3D-.
  • 3D , : , . . .
  • , , . javascript .
  • Dalam konteks Spark AR, tidak ada objek jendela dan semua jenis objek browser spesifik seperti webkitRequestAnimationFrame, mozRequestAnimationFrame, dan sebagainya. Ini adalah takdir ketika pemrograman dalam animasi javascript.

All Articles