【p5js】自分だけのオリジナルパズルを簡単に作成する方法を解説します!

この記事はProcessingで自分だけのオリジナルのパズルの作り方を紹介します!

パズルにはいろいろと種類がありますが、作成するのは「スライディングブロックパズル」の一つで、「15パズル」になります。

一般的には1-15の数字が書かれた15個のコマを利用しますが、ここでは自分で用意した画像を16分割してパズルにしてしまいます。

プログラミング初心者でも楽しめる内容だと思います。

前提の話

何を作れるか?

「15パズル」といっても、ちょっと分かりづらいと思います。

なので、最初に完成イメージを示します。

海中の画像

元の画像

15パズル

一つ目の画像がパズル化したい元画像です。

画像素材をダウンロードできるサイトから持ってきました。


二つ目の動画は実際にパズルを解いている様子です。

元の画像を16分割してランダムに配置した状態から、元の状態に戻るようにタイルを移動していっています。

「15パズル」となっているのは、16枚のタイルとのうち1枚は取り除くからです。

その空いたスペースにタイルを移動することができます。動画では黒塗りになっている部分ですね。

クリックしたタイルが黒塗りの空いたスペースにということです。

何で作るか?

こういった記事の内容だと、普段は「Processing」でコーディングしていますが、今回は「p5js」を使ってみます。

「p5js」はJavaScriptのライブラリで、「Processing」のJavaScript版だと理解していれば良いと思います。

JavaScriptなので、開発環境を作らなくても、通常のブラウザでそのまま実行できます。

p5js公式サイト:https://p5js.org/

p5jsの公式サイト

では、実際に開発していきましょう。

パズルの開発

とりあえずp5jsを動かしてみる

まず、p5jsをブラウザで動かすところから始めます。

公式ページを参考に、CDNのリンクをHTMLで指定するだけでp5jsを利用できるようになります。

作業用のディレクトリを作成して、最低限必要なファイルを設置していきます。

この記事では、表示用のindex.html、処理を記述するsketch.js、パズルにする画像puzzle.jpgの3つに分けることにします。

次に最低限のコードを示します。

index.htmlの6行目でp5jsの読み込み、7行目で処理を記述ファイルを読み込んでいます。

index.htmlはあくまで必要なファイルを読み込んで表示するだけのファイルなので、この後編集はしません。

sketch.jsのsetup()で描画領域の指定、draw()で毎フレームごとに描画領域を黒で塗りつぶすことを指定しています。

このファイルに画像を読み込む処理や、パズルの動きを追記していきます。

Processingを扱ったことがあれば、処理の書き方が良く似ているので、すぐに理解していけるはずです。

index.htmlをブラウザで開いて実行してみましょう。次のようになればOKです。

黒塗りの四角形

ここまででp5jsの動作設定は完了です。

画像の表示

次に画像を表示できるようにします。次のようにsketch.jsを編集します。

9行目で画像の横幅が400になるようにリサイズしています。

高さに0を指定することで、リサイズするときに縦横比が元の画像と変わらないようにしています。

横幅は400で固定、高さは自動調整されます。ちょっとしたテクニックです。

resize()の詳細については、ドキュメントを参照してください。


ここまで書いて気づいたのですが、ローカル環境でindex.htmlを開いても画像は表示されないと思います。

この記事の本題ではないので、エラーの詳細説明については省略しますが、解決策を紹介しますね。

英語になってしまいますが、下記のページに書かれています。

https://github.com/processing/p5.js/wiki/Local-server

この中で、「Web Server for Chrome extension」のところに書かれている方法が最も簡単で、「Web Server for Chrome」というプラグインをインストールするだけです。

注意点としては、ブラウザでchromeを使う必要があるということです。ただ、ほとんどの人がchromeを使っているのではないでしょうか。

もし、Web関連の知識がある人は、別の方法でもローカルサーバを立ち上げて解決できるはずです。

ここでは、「Web Server for Chrome」での実行手順を紹介します。

プラグインをインストール後、アプリを起動すると次のような画面が表示されます。

WebServer for Chromeの画面

「CHOSE FOLDER」をクリックして、index.htmlを格納したディレクトリを指定します。

その状態で「Web Server URL(S)」の下にある「http://〜」のリンクをクリックすると、今度こそ画像が表示されるはずです。

画像を表示するだけなのにちょっと大変でしたね。

こういった問題解決を楽しめるようになると、プログラミングが本当に楽しめるようになると思います。

画像をタイル状に分割する

いよいよパズルの機能を追加していきます。まずは画像を4×4のタイルに分割しましょう。

色々と方法は考えられますが、この記事ではタイルのクラスを作成することにします。

タイルのクラスには、タイルの位置、サイズ、画像の情報、表示機能あたりを持たせておくのが良さそうです。

具体的には次のようにコードを書いてみました。

ポイントを説明します。

13行目のget()で、タイルの領域内の画像を切り抜いて設定しています。

タイルごとに位置情報を持たせているので、対応する領域の画像を簡単に取得できます。

get()の詳細については、ドキュメントを参照してください。

display()では実際にタイルの描画を行います。20行目で取り除かれたタイルか判定して、取り除かれたものであれば、21行目で黒塗りにしています。

47行目で一番右下のタイルを取り除くように設定しています。

sketch.jsを編集して実行すると、次のような画像が表示されるはずです。

16分割された海中の画像

少し分かりづらいかもしれませんが、この時点で画像をタイルごとに分割できています。あとは、タイルを動かす処理を追加するだけです。

いよいよ完成間近です。

タイルを動かせるようにする

具体的な実装に入る前に、タイルを移動(交換)する処理について検討してみましょう。

次の画像のケースを考えます。

画像内のタイルAをクリックした場合、右側に空きの領域(タイルB)があるので、交換されます。

結果として、「タイル交換後」の画像のような配置になります。

では、「タイルの交換」をどのように表現すれば良いでしょうか?

実はタイルAとタイルBに設定している画像を交換するだけで実現できます。具体的には、Tileクラスのプロパティのうち、imgとblankのみを交換します。

blankも交換しないと、交換後のタイルAが黒塗りになってしまい、正しく動作しないので注意しましょう。

上記をまとめると、次のようにシンプルになります。

1.クリックされたタイルが空き領域(黒いタイル)と隣接しているか判定する
2.隣接している場合、Tileクラスのプロパティimgとblankを交換する

この処理をsketch.jsに追加していきましょう。

mousePressed()がクリックされた時に実行されます。タイルがクリックされた場合にmove()が呼ばれて、空き領域が隣接しているか判定します。

隣接していればswap()を呼び出して、2つのタイルのプロパティを交換します。

プログラムを実行して、タイルをクリックしてみましょう。

15パズルのタイルの動きを実現できているはずです。

タイルの初期配置

最後にタイルの初期配置がランダムになるようにしましょう。

この記事では深く考えずに、ランダムにタイルを選択して、空き領域に隣接している場合は移動することにします。

randomize()だけ追加しました。プログラムを実行するたびにタイルの初期配置が変わるはずです。

これで15パズルの基本的な機能は実装できたことになります。

まとめ

今回の記事ではProcessingでオリジナルのパズルを簡単に作成する方法を紹介しました!

画像ファイルを変更すれば、すぐに自分だけの15パズルになります。

色々と試してみてはいかがでしょうか。

コメントを残す

メールアドレスが公開されることはありません。