Pertama kali saya menulis Tetris lebih dari setahun yang lalu, dan saya baru mempelajari js belum lama ini.
Untuk memperkuat pemahaman saya tentang js dan menambah kecintaan saya pada game, saya menulis Tetris berbasis kanvas menggunakan kode js paling dasar tanpa mengacu pada ide dan kode orang lain.
Selama liburan musim panas tahun pertama saya, saya menggunakan sintaks es6 untuk memperbaikinya, termasuk gula sintaksis kelas, fungsi panah, dll., untuk lebih meningkatkan pemahaman saya tentang es6. Kode ini memiliki 400+ baris.
Jika Anda ingin membuat game kecil ini, Anda harus terlebih dahulu memahami kanvas H5, pemrosesan array js, pemantauan dan pemrosesan event keyboard, penggunaan timer, dll. Selebihnya adalah pemrosesan logika dasar.
Aturan mainnya adalah inti dan prioritas utama kode kami
Logika inti di sini adalah untuk menentukan apakah blok tersebut bertabrakan (blok yang sedang bergerak bertabrakan dengan blok yang sudah diposisikan sehingga blok yang sedang bergerak tidak dapat bergerak ke bawah, karena blok kita secara default bergerak ke bawah. Jika tidak dapat bergerak ke bawah, dianggap Berjalan ke bawah. sebagai blok yang telah diposisikan, kemudian dihasilkan blok baru dan terus bergerak ke bawah dari posisi awal).
Dan tumbukan ini juga perlu diterapkan ketika balok tersebut mengalami deformasi. Demikian pula, jika balok tersebut bertabrakan dengan balok lain yang berada diposisi yang sama selama proses deformasi, kita harus mencegah agar balok tersebut tidak berhasil mengalami deformasi.
Kode terlampir, diskusi dan koreksi dipersilakan.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <title>es6-Rekonstruksi Tetris (berdasarkan kanvas)</title> <style type=text/css> #tetris{ margin: 10px 250px;} </style></head><body> <lebar kanvas=700 tinggi=525 id=tetris></canvas> <div id=text style='color: red;font-size: 30px;'>Skor saat ini: 0</div> <script type=text/javascript> /** * [Desain kelas Tetris lengkap oleh magic_xiang] * @param {number} side [panjang setiap sisi persegi (px), default 35] * @param {number} lebar [jumlah kotak dalam satu baris (number), default 20] * @param {number} tinggi [Jumlah blok yang disertakan dalam kolom (default 15)] * @param {number} speed [Blok kecepatan gerakan jatuh (ms), default 400] */ class tetris{ konstruktor(sisi=35, lebar=20, tinggi=15 , speed=400){ this.side = side // Panjang sisi tiap balok this.width = width // Banyaknya balok dalam satu baris this.height = height // Banyaknya balok dalam kolom this .kecepatan = kecepatan // Penurunan kecepatan pergerakan blok this.num_blcok // Variabel numerik dari blok saat ini bertipe this.type_color // Variabel string dengan tipe warna saat ini this.ident // Pengidentifikasi setInterval this.direction = 1 // The arah blok, diinisialisasi ke 1, default Status this.grade = 0 // Digunakan untuk menghitung skor this.over = false // Apakah permainan sudah selesai this.arr_bX = [] // Menyimpan koordinat X dari blok saat ini ini.arr_bY = [] // Simpan koordinat Y dari blok saat ini this.arr_store_X = [] // Simpan koordinat X dari semua blok yang telah mencapai bagian bawah this.arr_store_Y = [] // Simpan koordinat Y dari semua blok yang telah mencapai bagian bawah ini. arr_store_color = [] // Simpan semua blok yang telah mencapai bagian bawah Warna persegi this.paints = document.getElementById('tetris').getContext('2d') //Dapatkan kuasnya sendiri = ini } // Enkapsulasi metode paints untuk membuat kode lebih ringkas paintfr(x, y, scale=1){ this.paints.fillRect(x*this.side, y*this.side, scale*this.side, scale*this.side ) } // Permainan dimulai gameStart(){ this.init() this.run() } // Inisialisasi pekerjaan init(){ this.initBackground() this.initBlock() } // Blok secara otomatis jatuh run(){ this.ident = setInterval(self.down_speed_up(), this.speed) } // Inisialisasi peta initBackground(){ this.paints.beginPath() this.paints.fillStyle='#000000 ' / /Warna isian peta adalah hitam for(let i = 0; i < this.height; i++){ for(let j = 0; j < this.width; j++){ this.paintfr(j, i) } } this.paints.closePath() } // Inisialisasi posisi dan warna blok initBlock(){ this.paints.beginPath() this.createRandom('rColor') // Buat string warna, this.paints.fillStyle = this.type_color this.createRandom('rBlock') //Buat nomor tipe blok this.arr_bX.forEach((item, indeks) => { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() } // Gunakan array untuk menggambar Blok drawBlock(warna){ this.paints.beginPath() this.paints.fillStyle = warna this.arr_bX.forEach((item, indeks) => { this.paintfr(item, this.arr_bY[index], 0.9) }) this.paints.closePath() } // Gambarlah blok yang sudah diposisikan drawStaticBlock( ){ this.arr_store_X.forEach((item, indeks) => { this.paints.beginPath() this.paints.fillStyle = this.arr_store_color[index] this.paintfr(item, this.arr_store_Y[index], 0.9) this.paints.closePath() }) } // Buat nomor acak dan kembalikan jenis atau warna blok ketik createRandom( ketik){ biarkan temp = this.width/2-1 if (ketik == 'rBlock'){ //Jika berupa blok, ketik this.num_blcok = Math.round(Math.random()*4+1) switch(this.num_blcok){ case 1: this.arr_bX.push(temp,temp-1,temp, temp+ 1) this.arr_bY.push(0,1,1,1) pecahkan kasus 2: this.arr_bX.push(temp,temp-1,temp-1,temp+1) this.arr_bY.push(1,0,1,1) pecahkan kasus 3: this.arr_bX.push(temp,temp-1,temp+1,temp+2) this.arr_bY.push(0,0,0, 0) pecahkan kasus 4: this.arr_bX.push(temp,temp-1,temp,temp+1) this.arr_bY.push(0,0,1,1) pecahkan kasus 5: this.arr_bX.push(temp,temp+1,temp,temp+1) this.arr_bY.push(0,0,1,1) break } } if (ketik == 'rColor'){ //if Ini adalah tipe warna let num_color = Math.round(Math.random()*8+1) switch(num_color){ case 1: this.type_color='#3EF72A' break case 2: this.type_color='kuning' kasus kerusakan 3: this.type_color='#2FE0BF' kasus kerusakan 4: this.type_color='red' kasus kerusakan 5: this.type_color='abu-abu' kasus kerusakan 6: this.type_color ='#C932C6' kasus kerusakan 7: this.type_color= '#FC751B' kasus kerusakan 8: this.type_color= '#6E6EDD' break case 9: this.type_color= '#F4E9E1' break } } } // Tentukan apakah balok-balok tersebut bertumbukan (lebih rendah), dan apakah balok melintasi batas bawah selama deformasi judgeCollision_down(){ for(let i = 0 ; saya < ini.arr_bX.panjang; i++){ if (ini.arr_bY[i] + 1 == ini.tinggi){ //Apakah batas bawah dilintasi selama deformasi return false } if (this.arr_store_X.length != 0) { //Tentukan apakah balok-balok tersebut bertumbukan (bawah) for(let j = 0; j < this.arr_store_X.length; j++ ){ if (ini.arr_bX[i] == ini.arr_store_X[j]) { if (ini.arr_bY[i] + 1 == this.arr_store_Y[j]) { return false } } } } } return true } //Menilai apakah balok-balok tersebut bertumbukan (kiri dan kanan), dan apakah balok melintasi batas kiri dan kanan selama deformasi judgeCollision_other(num){ for(let i = 0; i < this.arr_bX.length; i++){ if (num == 1) { //Apakah batas kanan dilintasi selama deformasi if (this.arr_bX[i] == this.width - 1) return false } if (num == -1) { //Apakah batas kiri dilintasi selama deformasi if (this.arr_bX[i] == 0) return false } if (this.arr_store_X.length != 0) { / /Tentukan apakah balok-balok tersebut bertumbukan (kiri dan kanan) for(misalkan j = 0; j < this.arr_store_X.length; j++){ if (this.arr_bY[i] == this.arr_store_Y[j]) { if (this.arr_bX[i] + num == this.arr_store_X[j]) { return false } } } } } mengembalikan true; //Fungsi akselerasi down_speed_up( ){ biarkan flag_all_down = benar flag_all_down = this.judgeCollision_down() jika (flag_all_down) { this.initBackground() for(misalkan i = 0; i < this.arr_bY.length; i++){ this.arr_bY[i] = this.arr_bY[i] + 1 } } else{ for(misalkan i=0; i < ini.arr_bX.panjang; i++){ ini.arr_store_X.push(ini.arr_bX[i]) this.arr_store_Y.push(this.arr_bY[i]) this.arr_store_color.push(this.type_color) } this.arr_bX.splice(0,this.arr_bX.length) this.arr_bY.splice(0,this.arr_bY. panjang) ini.initBlock() } ini.clearUnderBlock() this.drawBlock(this.type_color) this.drawStaticBlock() this.gameover() } //Tombol arah adalah fungsi gerakan kiri move(dir_temp){ this.initBackground() if (dir_temp == 1) { //Kanan biarkan flag_all_right = true flag_all_right = this.judgeCollision_other(1) if (flag_all_right) { untuk(biarkan i = 0; i < this.arr_bY.length; i++){ this.arr_bX[i] = this.arr_bX[i]+1 } } } else{ biarkan flag_all_left = true flag_all_left = this.judgeCollision_other(-1) if (flag_all_left) { untuk(biarkan i=0; saya < ini.arr_bY.panjang; i++){ ini.arr_bX[i] = this.arr_bX[i]-1 } } } this.drawBlock(this.type_color) this.drawStaticBlock() } //Kunci arah adalah fungsi arah transformasi ruang up_change_direction(num_blcok){ if (num_blcok == 5) { return } let arr_tempX = [] let arr_tempY = [] //Karena saya tidak tahu apakah transformasinya bisa berhasil, saya simpan dulu for(let i = 0;i < this.arr_bX.length; i++){ arr_tempX.push(this.arr_bX[i]) arr_tempY.push(this.arr_bY[i]) } this.direction++ //Ekstrak koordinat pusat dan ubah bentuknya dengan The pusat saat ini yang akan menang biarkan ax_temp = this.arr_bX[0] biarkan ay_temp = this.arr_bY[0] this.arr_bX.splice(0, this.arr_bX.length) //Hapus array this.arr_bY.splice(0, this.arr_bY.length) if (num_blcok == 1) { switch(this.direction%4){ kasus 1: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+1,ay_temp+1,ay_temp+1) pecahkan kasus 2: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp, ay_temp-1,ay_temp+1) pecahkan kasus 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp) pecahkan kasus 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp, kapak_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp) break } } if (num_blcok == 2) { switch(this.direction%4){ kasus 1: this.arr_bX.push(ax_temp,ax_temp -1,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp-1,ay_temp) pecahkan kasus 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp-1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+ 1 ,ay_temp+1) pecahkan kasus 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp+1) pecahkan kasus 0: this.arr_bX.push(ax_temp,ax_temp, ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp-1) break } } if (num_blcok == 3) { switch(this.direction%4){ kasus 1: this.arr_bX.push(ax_temp ,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) pecahkan kasus 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp,ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+ 2 ) pecahkan kasus 3: this.arr_bX.push(ax_temp,ax_temp-1,ax_temp+1,ax_temp+2) this.arr_bY.push(ay_temp,ay_temp,ay_temp,ay_temp) pecahkan kasus 0: this.arr_bX.push(ax_temp,ax_temp,ax_temp, ax_temp) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp+1,ay_temp+2) break } } if (num_blcok == 4) { switch(this.direction%4){ kasus 1: this.arr_bX.push(ax_temp ,ax_temp-1,ax_temp,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp,ay_temp+1,ay_temp+1) pecahkan kasus 2: this.arr_bX.push(ax_temp,ax_temp,ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp+ 1 ,ay_temp,ay_temp-1) pecahkan kasus 3: this.arr_bX.push(ax_temp,ax_temp,ax_temp-1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp-1) pecahkan kasus 0: this.arr_bX.push(ax_temp,ax_temp, ax_temp+1,ax_temp+1) this.arr_bY.push(ay_temp,ay_temp-1,ay_temp,ay_temp+1) break } } if (! (this.judgeCollision_other(-1) && this.judgeCollision_down() && this.judgeCollision_other(1) )) {// Jika transformasi tidak berhasil, jalankan kode berikut this.arr_bX.splice(0, this.arr_bX.length) this.arr_bY.splice(0, this.arr_bY.length) for(biarkan i=0; i< arr_tempX.length; i++){ this.arr_bX.push(arr_tempX[i]) this.arr_bY.push(arr_tempY[i ]) } } this.drawStaticBlock() } //Ketika satu baris penuh, kosongkan blok-bloknya, dan koordinat Y dari blok atas adalah +1 clearUnderBlock(){ //Hapus blok tingkat rendah let arr_row=[] let line_num if (this.arr_store_X.length != 0) { for(let j = this.height-1; j >= 0; j--) { untuk (misalkan i = 0; i < this.arr_store_color.length; i++){ if (this.arr_store_Y[i] == j) { arr_row.push(i) } } if (arr_row.length == this.width) { line_num = j break }else{ arr_row.splice(0, arr_row.length) } } } if (arr_row.length == this.width ) { //Hitung nilai nilai this.grade++ document.getElementById('text').innerHTML = 'Nilai saat ini:'+this.grade untuk(misalkan i = 0; i < arr_row.length; i++){ this.arr_store_X.splice(arr_row[i]-i, 1) this.arr_store_Y.splice(arr_row[i]-i, 1) this.arr_store_color. splice(arr_row[i]-i, 1) } //Biarkan blok atas turun satu spasi untuk(misalkan i = 0; i < this.arr_store_color.length; i++){ if (this.arr_store_Y[i] < line_num) { this.arr_store_Y[i] = this.arr_store_Y[i]+1 } } } //Menilai akhir permainan gameover() { untuk (misalkan i=0; i < this.arr_store_X.length; i++){ if (this.arr_store_Y[i] == 0) { clearInterval(this.ident) this.over = true } } } } let tetrisObj = new tetris() tetrisObj.gameStart() // Fungsi tombol arah document.onkeydown = (e) => { if (tetrisObj.over) return switch(e.keyCode){ case 40: // Arahnya ke bawah tetrisObj.down_speed_up() break case 32: // Spasi untuk mengubah arah tetrisObj.initBackground() // Gambar ulang peta tetrisObj.up_change_direction(tetrisObj.num_blcok) tetrisObj.drawBlock(tetrisObj.type_color) break case 37: // Arahnya ke kiri tetrisObj.initBackground() tetrisObj .pindah (-1) tetrisObj.drawBlock(tetrisObj.type_color) break case 39: // Arahnya benar tetrisObj.initBackground() tetrisObj.move(1) tetrisObj.drawBlock(tetrisObj.type_color) break } } </script></body></ html>
Di atas adalah keseluruhan isi artikel ini, saya harap dapat bermanfaat untuk pembelajaran semua orang. Saya juga berharap semua orang mendukung VeVb Wulin Network.