Bagaimana Saya Membuat Game Puzzle CSS Murni Intelijen Data PlatoBlockchain. Pencarian Vertikal. Ai.

Bagaimana Saya Membuat Game Puzzle CSS Murni

Baru-baru ini saya menemukan kegembiraan dalam membuat game khusus CSS. Selalu menarik bagaimana HTML dan CSS mampu menangani logika seluruh game online, jadi saya harus mencobanya! Permainan seperti itu biasanya mengandalkan Hack Kotak Centang lama di mana kami menggabungkan status input HTML yang dicentang/tidak dicentang dengan :checked pseudo-kelas di CSS. Kita bisa melakukan banyak keajaiban dengan satu kombinasi itu!

Bahkan, saya menantang diri saya sendiri untuk membangun seluruh permainan tanpa Kotak Centang. Saya tidak yakin apakah itu mungkin, tetapi itu pasti, dan saya akan menunjukkan caranya.

Selain permainan puzzle yang akan kita pelajari di artikel ini, saya telah membuat kumpulan game CSS murni, kebanyakan dari mereka tanpa Hack Kotak Centang. (Mereka juga tersedia di CodePen.)

Ingin bermain sebelum kita mulai?

Saya pribadi lebih suka memainkan game dalam mode layar penuh, tetapi Anda dapat memainkannya di bawah atau buka di sini.

Keren kan? Saya tahu, ini bukan Game Puzzle Terbaik yang Pernah Anda Lihatโ„ข tetapi juga tidak buruk sama sekali untuk sesuatu yang hanya menggunakan CSS dan beberapa baris HTML. Anda dapat dengan mudah menyesuaikan ukuran kisi, mengubah jumlah sel untuk mengontrol tingkat kesulitan, dan menggunakan gambar apa pun yang Anda inginkan!

Kami akan membuat ulang demo itu bersama-sama, lalu menambahkan sedikit kilau ekstra di bagian akhir untuk beberapa tendangan.

Fungsionalitas seret dan lepas

Sementara struktur teka-teki cukup mudah dengan CSS Grid, kemampuan untuk menarik dan melepaskan potongan teka-teki sedikit lebih rumit. Saya harus mengandalkan kombinasi transisi, efek hover, dan pemilih saudara untuk menyelesaikannya.

Jika Anda mengarahkan kursor ke kotak kosong di demo itu, gambar bergerak di dalamnya dan tetap di sana bahkan jika Anda memindahkan kursor keluar dari kotak. Triknya adalah menambahkan durasi dan penundaan transisi yang besar โ€” โ€‹โ€‹begitu besar sehingga gambar membutuhkan banyak waktu untuk kembali ke posisi semula.

img {
  transform: translate(200%);
  transition: 999s 999s; /* very slow move on mouseout */
}
.box:hover img {
  transform: translate(0);
  transition: 0s; /* instant move on hover */
}

Hanya menentukan transition-delay sudah cukup, tetapi menggunakan nilai besar pada penundaan dan durasi mengurangi kemungkinan pemain melihat gambar bergerak mundur. Jika Anda menunggu 999s + 999s โ€” yaitu kurang lebih 30 menit โ€” maka Anda akan melihat gambar bergerak. Tapi Anda tidak akan melakukannya, kan? Maksud saya, tidak ada yang akan mengambil jarak selama itu kecuali mereka meninggalkan permainan. Jadi, saya menganggap ini sebagai trik yang bagus untuk beralih di antara dua status.

Apakah Anda memperhatikan bahwa mengarahkan gambar juga memicu perubahan? Itu karena gambar adalah bagian dari elemen kotak, yang tidak baik untuk kita. Kami dapat memperbaikinya dengan menambahkan pointer-events: none ke gambar tetapi kami tidak akan dapat menyeretnya nanti.

Itu berarti kita harus memperkenalkan elemen lain di dalam .box:

ekstra itu div (kami menggunakan kelas .a) akan mengambil area yang sama dengan gambar (berkat CSS Grid dan grid-area: 1 / 1) dan akan menjadi elemen yang memicu efek hover. Dan di situlah pemilih saudara berperan:

.a {
  grid-area: 1 / 1;
}
img {
  grid-area: 1 / 1;
  transform: translate(200%);
  transition: 999s 999s;
}
.a:hover + img {
  transform: translate(0);
  transition: 0s;
}

Melayang di atas .a elemen memindahkan gambar, dan karena mengambil semua ruang di dalam kotak, itu seperti kita melayang di atas kotak! Melayang gambar tidak lagi menjadi masalah!

Mari drag dan drop gambar kita di dalam kotak dan lihat hasilnya:

Apakah kamu melihat itu? Anda pertama-tama mengambil gambar dan memindahkannya ke kotak, tidak ada yang mewah. Tapi begitu Anda melepaskan gambar, Anda memicu efek hover yang menggerakkan gambar, dan kemudian kami mensimulasikan fitur seret dan lepas. Jika Anda melepaskan mouse di luar kotak, tidak ada yang terjadi.

Hmm, simulasi Anda tidak sempurna karena kami juga dapat mengarahkan kotak dan mendapatkan efek yang sama.

Benar dan kami akan memperbaiki ini. Kita perlu menonaktifkan efek hover dan mengizinkannya hanya jika kita melepaskan gambar di dalam kotak. Kami akan bermain dengan dimensi kami .a elemen untuk mewujudkannya.

Sekarang, mengarahkan kotak tidak melakukan apa-apa. Tetapi jika Anda mulai menyeret gambar, .a elemen muncul, dan setelah dilepaskan di dalam kotak, kita dapat memicu efek hover dan memindahkan gambar.

Mari kita membedah kodenya:

.a {
  width: 0%;
  transition: 0s .2s; /* add a small delay to make sure we catch the hover effect */
}
.box:active .a { /* on :active increase the width */
  width: 100%;
  transition: 0s; /* instant change */
}
img {
  transform: translate(200%);
  transition: 999s 999s;
}
.a:hover + img {
  transform: translate(0);
  transition: 0s;
}

Mengklik gambar akan memicu :active pseudo-class yang membuat .a elemen full-width (awalnya sama dengan 0). Status aktif akan tetap aktif sampai kami merilis gambar. Jika kita melepaskan gambar di dalam kotak, .a elemen kembali ke width: 0, tapi kita akan memicu efek hover sebelum itu terjadi dan gambar akan jatuh ke dalam kotak! Jika Anda melepaskannya di luar kotak, tidak ada yang terjadi.

Ada sedikit kekhasan: mengklik kotak kosong juga memindahkan gambar dan merusak fitur kami. Saat ini, :active ditautkan ke .box elemen, jadi mengkliknya atau anak-anaknya akan mengaktifkannya; dan dengan melakukan ini, kami akhirnya menunjukkan .a elemen dan memicu efek hover.

Kita bisa memperbaikinya dengan bermain dengan pointer-events. Ini memungkinkan kami untuk menonaktifkan interaksi apa pun dengan .box sambil mempertahankan interaksi dengan elemen anak.

.box {
  pointer-events: none;
}
.box * {
  pointer-events: initial;
}

Sekarang fitur drag and drop kami sempurna. Kecuali Anda dapat menemukan cara meretasnya, satu-satunya cara untuk memindahkan gambar adalah dengan menyeretnya dan meletakkannya di dalam kotak.

Membangun kisi teka-teki

Menyatukan puzzle akan terasa mudah dibandingkan dengan apa yang baru saja kita lakukan untuk fitur drag and drop. Kami akan mengandalkan grid CSS dan trik latar belakang untuk membuat teka-teki.

Inilah kisi-kisi kami, yang ditulis dalam Pug untuk kenyamanan:

- let n = 4; /* number of columns/rows */
- let image = "https://picsum.photos/id/1015/800/800";

g(style=`--i:url(${image})`)
  - for(let i = 0; i < n*n; i++)
    z
      a
      b(draggable="true") 

Kodenya mungkin terlihat aneh tetapi dikompilasi menjadi HTML biasa:

<g style="--i: url(https://picsum.photos/id/1015/800/800)">
 <z>
   <a></a>
   <b draggable="true"></b>
 </z>
 <z>
   <a></a>
   <b draggable="true"></b>
 </z>
 <z>
   <a></a>
   <b draggable="true"></b>
 </z>
  <!-- etc. -->
</g>

Saya yakin Anda bertanya-tanya ada apa dengan tag itu. Tak satu pun dari elemen ini memiliki arti khusus โ€” saya hanya menemukan bahwa kodenya jauh lebih mudah untuk ditulis menggunakan <z> daripada sekelompok <div class="z"> atau terserah.

Inilah cara saya memetakannya:

  • <g> adalah wadah grid kami yang berisi N*N <z> elemen.
  • <z> mewakili item grid kami. Ia berperan sebagai .box elemen yang kita lihat di bagian sebelumnya.
  • <a> memicu efek hover.
  • <b> mewakili sebagian dari gambar kita. Kami menerapkan draggable atribut di atasnya karena tidak dapat diseret secara default.

Baiklah, mari kita daftarkan wadah grid kita di <g>. Ini di Sass, bukan CSS:

$n : 4; /* number of columns/rows */

g {
  --s: 300px; /* size of the puzzle */

  display: grid;
  max-width: var(--s);
  border: 1px solid;
  margin: auto;
  grid-template-columns: repeat($n, 1fr);
}

Kami sebenarnya akan membuat anak-anak grid kami โ€” the <z> elemen โ€” kisi juga dan memiliki keduanya <a> dan <b> dalam area grid yang sama:

z {
  aspect-ratio: 1;
  display: grid;
  outline: 1px dashed;
}
a {
  grid-area: 1/1;
}
b {
  grid-area: 1/1;
}

Seperti yang Anda lihat, tidak ada yang mewah โ€” kami membuat kisi dengan ukuran tertentu. Sisa CSS yang kita butuhkan adalah untuk fitur drag and drop, yang mengharuskan kita untuk menempatkan potongan secara acak di sekitar papan. Saya akan beralih ke Sass untuk ini, sekali lagi untuk kenyamanan untuk dapat mengulang dan menata semua potongan puzzle dengan fungsi:

b {
  background: var(--i) 0/var(--s) var(--s);
}

@for $i from 1 to ($n * $n + 1) {
  $r: (random(180));
  $x: (($i - 1)%$n);
  $y: floor(($i - 0.001) / $n);
  z:nth-of-type(#{$i}) b{
    background-position: ($x / ($n - 1)) * 100% ($y / ($n - 1)) * 100%;
    transform: 
      translate((($n - 1) / 2 - $x) * 100%, (($n - 1)/2 - $y) * 100%) 
      rotate($r * 1deg) 
      translate((random(100)*1% + ($n - 1) * 100%)) 
      rotate((random(20) - 10 - $r) * 1deg)
   }
}

Anda mungkin telah memperhatikan bahwa saya menggunakan Sass random() fungsi. Begitulah cara kita mendapatkan posisi acak untuk potongan puzzle. Ingatlah bahwa kita akan menonaktifkan posisi itu ketika melayang di atas <a> elemen setelah menyeret dan menjatuhkan yang sesuai <b> elemen di dalam sel grid.

z a:hover ~ b {
  transform: translate(0);
  transition: 0s;
}

Dalam lingkaran yang sama, saya juga mendefinisikan konfigurasi latar belakang untuk setiap potongan teka-teki. Semuanya secara logis akan berbagi gambar yang sama dengan latar belakang, dan ukurannya harus sama dengan ukuran keseluruhan kisi (didefinisikan dengan --s variabel). Menggunakan yang sama background-image dan beberapa matematika, kami memperbarui background-position untuk menampilkan hanya sebagian dari gambar.

Itu dia! Game puzzle khusus CSS kami telah selesai secara teknis!

Tapi kita selalu bisa melakukan yang lebih baik, bukan? Saya menunjukkan kepada Anda cara membuat kisi-kisi bentuk potongan puzzle di artikel lain. Mari kita ambil ide yang sama dan terapkan di sini, ya?

Bentuk potongan puzzle

Inilah permainan puzzle baru kami. Fungsionalitas yang sama tetapi dengan bentuk yang lebih realistis!

Ini adalah ilustrasi bentuk pada grid:

Bagaimana Saya Membuat Game Puzzle CSS Murni

Jika Anda perhatikan lebih dekat, Anda akan melihat bahwa kami memiliki sembilan bentuk potongan puzzle yang berbeda: the empat sudut, yang empat tepi, dan satu untuk yang lainnya.

Kisi-kisi potongan puzzle yang saya buat di artikel lain yang saya rujuk sedikit lebih mudah:

Kita dapat menggunakan teknik yang sama yang menggabungkan topeng CSS dan gradien untuk membuat bentuk yang berbeda. Jika Anda tidak terbiasa dengan mask dan gradien, saya sangat menyarankan untuk memeriksa kasus yang disederhanakan itu untuk lebih memahami teknik sebelum pindah ke bagian selanjutnya.

Pertama, kita perlu menggunakan penyeleksi khusus untuk menargetkan setiap kelompok elemen yang memiliki bentuk yang sama. Kami memiliki sembilan grup, jadi kami akan menggunakan delapan pemilih, ditambah pemilih default yang memilih semuanya.

z  /* 0 */

z:first-child  /* 1 */

z:nth-child(-n + 4):not(:first-child) /* 2 */

z:nth-child(5) /* 3 */

z:nth-child(5n + 1):not(:first-child):not(:nth-last-child(5)) /* 4 */

z:nth-last-child(5)  /* 5 */

z:nth-child(5n):not(:nth-child(5)):not(:last-child) /* 6 */

z:last-child /* 7 */

z:nth-last-child(-n + 4):not(:last-child) /* 8 */

Berikut adalah gambar yang menunjukkan bagaimana peta itu ke grid kita:

Bagaimana Saya Membuat Game Puzzle CSS Murni Intelijen Data PlatoBlockchain. Pencarian Vertikal. Ai.
Bagaimana Saya Membuat Game Puzzle CSS Murni

Sekarang mari kita tangani bentuknya. Mari fokus mempelajari satu atau dua bentuk saja karena semuanya menggunakan teknik yang sama โ€” dan dengan begitu, Anda memiliki beberapa pekerjaan rumah untuk terus dipelajari!

Untuk potongan puzzle di tengah grid, 0:

mask: 
  radial-gradient(var(--r) at calc(50% - var(--r) / 2) 0, #0000 98%, #000) var(--r)  
    0 / 100% var(--r) no-repeat,
  radial-gradient(var(--r) at calc(100% - var(--r)) calc(50% - var(--r) / 2), #0000 98%, #000) 
    var(--r) 50% / 100% calc(100% - 2 * var(--r)) no-repeat,
  radial-gradient(var(--r) at var(--r) calc(50% - var(--r) / 2), #000 98%, #0000),
  radial-gradient(var(--r) at calc(50% + var(--r) / 2) calc(100% - var(--r)), #000 98%, #0000);

Kodenya mungkin terlihat rumit, tetapi mari kita fokus pada satu gradien pada satu waktu untuk melihat apa yang terjadi:

Dua gradien membuat dua lingkaran (ditandai hijau dan ungu dalam demo), dan dua gradien lainnya membuat slot yang terhubung dengan potongan lain (yang bertanda biru mengisi sebagian besar bentuk sementara yang bertanda merah mengisi bagian atas). Sebuah variabel CSS, --r, mengatur jari-jari bentuk lingkaran.

Bagaimana Saya Membuat Game Puzzle CSS Murni Intelijen Data PlatoBlockchain. Pencarian Vertikal. Ai.
Bagaimana Saya Membuat Game Puzzle CSS Murni

Bentuk potongan puzzle di tengah (ditandai 0 dalam ilustrasi) adalah yang paling sulit dibuat karena menggunakan empat gradien dan memiliki empat lengkungan. Semua potongan lainnya menyulap lebih sedikit gradien.

Misalnya, potongan puzzle di sepanjang tepi atas puzzle (ditandai 2 dalam ilustrasi) menggunakan tiga gradien, bukan empat:

mask: 
  radial-gradient(var(--r) at calc(100% - var(--r)) calc(50% + var(--r) / 2), #0000 98%, #000) var(--r) calc(-1 * var(--r)) no-repeat,
  radial-gradient(var(--r) at var(--r) calc(50% - var(--r) / 2), #000 98%, #0000),
  radial-gradient(var(--r) at calc(50% + var(--r) / 2) calc(100% - var(--r)), #000 98%, #0000);

Kami menghapus gradien pertama (atas) dan menyesuaikan nilai gradien kedua sehingga menutupi ruang yang tertinggal. Anda tidak akan melihat perbedaan besar dalam kode jika Anda membandingkan dua contoh. Perlu dicatat bahwa kita dapat menemukan konfigurasi latar belakang yang berbeda untuk membuat bentuk yang sama. Jika Anda mulai bermain dengan gradien, Anda pasti akan menemukan sesuatu yang berbeda dari yang saya lakukan. Anda bahkan dapat menulis sesuatu yang lebih ringkas โ€” jika demikian, bagikan di komentar!

Selain membuat bentuk, Anda juga akan menemukan bahwa saya menambah lebar dan/atau tinggi elemen seperti di bawah ini:

height: calc(100% + var(--r));
width: calc(100% + var(--r));

Potongan-potongan teka-teki perlu meluap sel grid mereka untuk terhubung.

Bagaimana Saya Membuat Game Puzzle CSS Murni Intelijen Data PlatoBlockchain. Pencarian Vertikal. Ai.
Bagaimana Saya Membuat Game Puzzle CSS Murni

Demo terakhir

Ini demo lengkapnya lagi. Jika Anda membandingkannya dengan versi pertama, Anda akan melihat struktur kode yang sama untuk membuat grid dan fitur drag-and-drop, ditambah kode untuk membuat bentuk.

Kemungkinan peningkatan

Artikel berakhir di sini, tetapi kami dapat terus menyempurnakan teka-teki kami dengan lebih banyak fitur! Bagaimana dengan timer? Atau mungkin semacam ucapan selamat ketika pemain menyelesaikan teka-teki?

Saya dapat mempertimbangkan semua fitur ini di versi mendatang, jadi awasi repo GitHub saya.

Membungkus

Dan CSS bukan bahasa pemrograman, mereka bilang. Ha!

Saya tidak mencoba untuk memicu #HotDrama dengan itu. Saya mengatakannya karena kami melakukan beberapa hal logika yang sangat rumit dan mencakup banyak properti dan teknik CSS di sepanjang jalan. Kami bermain dengan CSS Grid, transisi, masking, gradien, penyeleksi, dan properti latar belakang. Belum lagi beberapa trik Sass yang kami gunakan untuk membuat kode kami mudah disesuaikan.

Tujuannya bukan untuk membangun game, tetapi untuk menjelajahi CSS dan menemukan properti dan trik baru yang dapat Anda gunakan di proyek lain. Membuat game online dalam CSS adalah tantangan yang mendorong Anda untuk menjelajahi fitur CSS dengan sangat detail dan mempelajari cara menggunakannya. Plus, itu sangat menyenangkan bahwa kita mendapatkan sesuatu untuk dimainkan ketika semua dikatakan dan dilakukan.

Apakah CSS adalah bahasa pemrograman atau tidak, tidak mengubah fakta bahwa kita selalu belajar dengan membangun dan menciptakan hal-hal yang inovatif.

Stempel Waktu:

Lebih dari Trik CSS