『Replicube』実況:Luaのコードでボクセル立体を描くパズルを18問解く
ゲーミングボーイ『Replicube』は、指定された3Dオブジェクトを再現するステージクリア型のパズルゲームだ。ボクセルを手で置くのではなく、プログラムを書いて配置する。この動画では、実況者が最初のチュートリアル問題集11問と、次に届く追加問題集7問を解いていく。全問クリアを目指すのではなく、2つの問題集を終えたところで区切るという方針だ。実況者は全体を通して、スコアを詰めることよりも読みやすいコードを書くことを優先している。
ゲームの仕組み:座標を受け取って色を返す
チュートリアルによると、このゲームはマインクラフトのようなボクセル空間に、全16色のボクセルを配置していく。ボクセルとは「体積のある画素」という意味の造語である。配置にはコードを使い、常に白を返すコードを書けば空間全体が白で埋まり、紫を返せば紫、青を返せば青になる。つまり各ボクセルの座標を受け取り、そこに置く色の値を返すコードを書く、という形式だ。実況者は「早くも頭が痛くなって参りました」と言いつつ、最近は戦うゲームばかりだったので、たまにはこういう平和なゲームもいいと話している。
ゲーム内ではCubenetという場所の管理人からメールが届き、そこに添付された基礎問題集を解く流れになっている。画面の上に正解の形状、下に現在のコードが描く形状が表示される。採点にはコード量や実行速度も含まれるようだが、実況者は最適化を「後のデザート」に回し、まずは読みやすさを重視すると決める。理由として「コードなんて基本、人間用に書くもの」と述べている。
1-1〜1-3:色の書き換えと条件分岐
1問目は、すでにあるコードのコメントを読めば、返している色が少し違うだけだと分かる。PURPLEをREDに書き換えてクリアした。
2問目では、位置に応じて2色に塗り分ける。座標を表す変数x、y、zが与えられているので、yが1以上ならDARKBLUE、そうでなければORANGEを返すif文を書いて解いた。
3問目のテーマは比較演算子である。実況者は、この言語では不等価を「~=」で書くことに注目し、近いうちに使うことになりそうだと予想している。問題自体は2問目とほぼ同じパターンで、「yが○○以上」という条件で解ける。比較演算子を使わない別解として return GREEN - (y + 4) // 3 * 2 のような書き方もできると挙げたが、この種のコードは読み手を困らせやすいとして採用しなかった。
1-4・1-5:透明にする方法
4問目から、y座標に加えてx座標とz座標も使い始める。初期コードには虹色の配色がすでにできている。y座標の値をそのまま色コードとして流用しているため、1段上がるごとに次の色に変わる仕組みだ。ただし、この問題で必要なのはオブジェクトの一部を透明にすることだけである。コメントによると、何も返さないか、0またはEMPTYを返せば透明になる。初期コードの「xとzが2以上のとき」という条件を「0以上のとき」に変えてクリアした。
5問目もほぼ同じ構造で、「x、y、zがすべて1以上のとき」という条件を書いて解いた。
1-6:絶対値で線対称な形を描く
6問目ではabs関数が登場する。コメントには、絶対値を返す関数で、線対称なオブジェクトの描画に重宝すると書かれている。今回の目標形状はどの軸についても線対称になっている。
実況者はまずz軸に注目し、zの絶対値が2以上なら無を返すようにして厚みを決めた。「2以上または-2以下」と書くこともできるが、絶対値の概念を使ったほうが理解しやすいコードになると実況者は考えている。残りの井桁状の形も絶対値を使って縦棒と横棒を作り、論理和のorでつないで完成させた。線対称な構造は今後も頻出しそうなので、絶対値を使う場面は多そうだと実況者は見込んでいる。
1-7:エラーメッセージを読んで直す
7問目は最初からエラーが出ている。実況者はまずエラーメッセージを読む。「LUA_ERRSYNTAX」という表示から、この言語がLuaであると推測した。10行目のifを閉じるendが期待されているのに、13行目にifが書かれている。つまりendの書き忘れである。
これを直しても完成ではなく、赤であるべき箱がGREYになっている箇所が残っていたので、そこも書き換えてクリアした。実況者はここで、ゼロからコードを書く機会は実は少なく、実際には他人のコードを読む力のほうが重要になることが多いと話している。
1-8:自由課題「sushi?」をチェス盤距離とテーブルで解く
ところが8問目は、ゼロから書かせる問題だった。問題名は「sushi?」で、実況者は「とんでもない感性」を感じている。形状を自由に作ってよさそうなので、中央からの距離に応じて赤・白・緑に塗り分ける方針を立てた。
ここで使う距離はチェス盤距離と呼ばれるものだ。8方向に動ける駒が何歩でたどり着けるか、という距離であり、実況者は『風来のシレン』などのローグライクでもたまに世話になる概念だと紹介している。この距離はmax関数があれば求めやすいため、Documentationタブを開いて調べた。ドキュメントは4章構成で、1章が概要、2章が描画の詳細、3章に求めていた情報がありそうだという。そこで、変数を定義できること、+や-などの演算子が使えること、そしてmax関数があることを確認した。
赤・白・緑への変換について、実況者は便利な機能がなければif文で愚直に分岐するつもりだった。「面白実装」の案としては、7・1・11を16進数で並べた0xb17を距離に応じて右シフトする方法も挙げている。
ここで実況者は余談として、普段の動画収録に使っているOBSのプラグインはLuaでも書けると話す。YouTubeのタイムスタンプを自動生成する簡単なプラグインを書いたことがあり、Luaに触れたのは人生でそのときだけかもしれないという。
実装では、まずxの絶対値とyの絶対値の最大値をとって、原点からのチェス盤距離を求めた。今回は0、1、2のいずれかになるので、これを0→7(赤)、1→1(白)、2→11(緑)に変換する仕組みが必要になる。ドキュメントに「table」という文字がちらっと見えたので、配列のような構造が使えると推測した。多くの言語で使える角括弧の配列リテラルを書いたところ、Luaでは使えなかった。そこで「Table」という名称から中括弧型だろうと考えて書き換えると、ほぼうまくいった。ただし色が1つずれており、Luaの添字が1から始まることが判明した。これに合わせて直し、寿司が完成した。
使った要素は小難しかったが、コードを眺めると意外と簡潔に見えると実況者は言う。ただし、そう思っているのはたいてい書いた本人だけだ、と自分で付け加えている。
1-9・1-10:「塗らない場所」と入れ子のif
9問目は、マウスで視点を動かして形状をよく確認しよう、という操作のチュートリアルに近い問題だ。上の開いた箱の形で、xかzが±3のとき、またはyが-3のときにBROWNを返せばよい。yが+3の場合を除くことで、上の蓋を開けた形になる。ここでも絶対値を使った。コメントは「どこを塗るか」ではなく「どこを塗らないか」で表現させたがっているようだったが、実況者はどちらでもよいと判断している。前の寿司に力を入れすぎたため、やや拍子抜けだったという。
10問目は、実況者いわくGoogle Chromeのような配色だが、色の並びに特徴的な規則性は見当たらない。コメントも入れ子のifを期待しているようなので、素直に条件分岐を書いた。yが1以上のときは、xが1以上ならGREEN、そうでなければORANGEを返す。yが1以上でないときは、zが1以上ならBLUE、そうでなければREDを返す。実況者は軸が見やすいように視点を回転させながら書き進めた。
1-11:二重の綴りミスとX字の仕組み
チュートリアル最後の11問目も、最初から不具合を抱えている。エラーメッセージによると、31行目で「colo」という未知の変数を扱っている。これは「color」の入力ミスだと推測して修正した。しかしそれだけでは階段が一部しか描かれない。さらにコードを読むと、イギリス英語の綴りの「colour」になっている箇所があり、これを直して完成した。
このコードがX字を描ける理由について、実況者は x==y や x==-y という式を使っているからだと読み解いた。一次関数を等式として使うとこういう形が描ける、ということだ。実況者はここで「まあ私にはきっと無縁の知識でしょう」と言っている。
2-1〜2-3:等式で斜めの線を描く
チュートリアルを終えると、コミュニティから歓迎のメールと全7問の追加問題集が届く。
追加問題集の1問目では、さっき「無縁」と言ったばかりの一次関数の問題がさっそく出てきた。y = -x の直線なので、Luaでは x == -y と書ける。==による比較はtrueかfalseを返すが、Replicubeではこれが白と無として描画されるため、比較結果をそのまま返すだけでクリアできた。
2問目も斜めの直線だが、z座標でさらに絞り込む必要がある。まず x == y で平面を描き、論理積andで x == z の条件をつないで形を完成させた。返り値をtrue/falseではなくGREENか無にするため、末尾に and GREEN を付け、短絡評価を利用している。
3問目は2問目を線対称にした形なので、式を絶対値版に変えるだけで解けた。abs(x)を2回計算しているのはやや無駄だが、遅い処理ではないので気にしないことにしている。
2-4〜2-6:剰余と加算で模様を作る
4問目では、割り算の余りを返す%演算子が導入される。初期コードはyを3で割った余りで、0・1・2に順番に振り分けている。正解の形状を見ると、xの値を0か1に変換しているように見えたので、2で割った余りを使えばよいと推測した。1マス分ずれていたため、xから1を引いて調整してクリアした。
5問目はチェッカーボードだ。まず平面にするために0でなければ無を返す処理を書こうとして、最初はzで条件を書いてしまい、yに直した。RGBの矢印がXYZに対応しているが、ときどき忘れてこんがらがるという。模様については、2問目の初期コードにあった return x+y で加算すると斜めの縞模様になるのを「こっそりチラ見」していた。これを%で丸めればチェッカーボードになる。最初はピンクになったので、黒を返すように直してクリアした。条件分岐を避けたい場合は、余りの0と1を白黒の1と3に変換する式でも実現できると示したが、色への変換が非常に分かりづらくなると実況者は評している。
6問目は斜めの虹色の模様である。加算で斜めの縞を描けることを使い、まずxとyを足した。これでおおむね似た見た目になった。ただ、実況者のコードでは原点が0を返すのに対し、正解ではLIGHTGREENになっていたので、LIGHTGREENを足して合わせた。最後にzが0以外のときに無を返して厚みを調整し、完成させた。
2-7:四つ脚のテーブルと関数による整理
最終問題は典型的な四つ脚のテーブルで、素材はすべてBROWNだ。形状だけ考えればよいので、実況者は現実の組み立て工程にならい、天板と脚を分けて処理した。-- でコメントが書けると分かったので、コメントも付けている。天板はyが1のときにBROWNを返すだけの平面である。脚は、まず描画範囲をyが0以下に制限して高さを決めた。位置は線対称なので、いつもどおり絶対値を使い、xとzの絶対値がともに2のときだけ描画する。これらの条件をandでつなぎ、すべて満たすときにBROWNを返して完成させた。
ただ、実況者は少し名残惜しく、もう少し手を加えることにした。ドキュメントによれば自前の関数を定義できたはずなので、それを使ってみたかったという。今のコードは素材が全部BROWNなのに return BROWN を2回書いており、「やっぱりWHITEに変えてくれない?」と言われたら二度手間になる。そこで形状だけを扱う関数を作り、色は1か所で決める形に書き直した。
具体的には、その座標が天板かどうかを返すisTopPlate関数と、脚かどうかを返すisLeg関数を定義し、「天板または脚であればBROWNを返す」と書いた。Luaの関数名はたぶんsnake_caseが一般的だが、今回は画面幅が極端に狭いので念のためcamelCaseにしたという。関数呼び出しには一定のコストがかかるものの、静止物体の描画ではそれほど性能を求められないので問題ないと実況者は判断している。一方、本作ではアニメーションも作れるようなので、そういう場面では多少気を払ったほうがいいかもしれないとも述べている。
実況者の評価
2つの問題集を終えて、実況者は『Replicube』を次のように評価している。最初は取っ付きにくい印象があったが、UIも導入も非常に丁寧で、遊んでみるととても楽しい。いろいろな観点や解法があるパズルゲームとして優秀で、プログラミングに興味を持つきっかけとしても楽しめる。数学的な分野とのつながりもあり、多方面で楽しめる作品だと感じた、と締めくくっている。
今日やっていくのは、ボクセル状の3D空間でたのしくお絵描きしていくゲーム『Replicube』。指定された3Dオブジェクトをつくるステージクリア型のパズルゲームということで、まずはチュートリアルを読み進めていきます。
どうやらマイクラのようなボクセル空間上に、全16色のボクセルを配置していくたのしいパズルゲームの模様です。『ボクセル』というのは体積のある画素という意味の造語ですが、このゲームではそのボクセルをプログラムを書いて配置していくようです。
何を言うとるんやという感じですが、常に白を返すコードを書けば、全体が白で埋まり、紫なら紫、青なら青といったように、色の値を返すようなコードを書けばいいみたいです。早くも頭が痛くなって参りました。
最近は何かと戦ってばかりだったので、たまにはこういう平和なゲームもいいものです。という訳で、導入部分は概ね読了。完全に理解したところで、早速本編に入っていきましょう。
まずはメールをチェック。Cubenetというところの管理人さんから、ようこそReplicubeへというあたたかいメールが届いていました。このメールに基礎問題が添付されていたので、まずはこの問題集を解いていくことにします。
まずは1問目。下が現状で、上が正解の模様です。最初からある程度コードが書かれており、コメントの解説を真面目に読んでいけば、返している色がちょっと違うみたいだから、そこを書き換えればいいということがわかります。という訳で、PURPLEをREDに変更。無事1問目クリアとなりました。
どうやらコード量や速度も評価点となるようですが、最適化の余地は後のデザートとして残しておいて、とりあえずは読みやすさ重視で進めていきましょう。コードなんて基本、人間用に書くものですからね。
という訳で、2問目へと移動。1問目は全面1色に塗るだけの問題でしたが、今回は位置に応じて2色に塗り分けるみたいです。座標を示すx、y、zの変数が与えられているので、この値に応じて、返す色を変えればいいみたい。
今回はY座標の値に応じて色を切り替えたいので、yが1以上であればDARKBLUEを返して、そうでなければORANGEを返す。OK。2問目、撃破です。この調子でどんどん行きましょう。
3問目。今回は2つの値の間で比較を行う比較演算子をテーマとした問題のようです。この言語では不等価には「~=」を使う模様。この知識は近い将来使うことになる気がします。
さて、問題自体は前回とほぼ同じパターンなので、前回と同じく「yが◯◯以上」が使えそうです。比較演算子を使わずに書くとすれば、return GREEN - (y + 4) // 3 * 2なども使えそうですが、この手のコードは読み手を特に困らせがちなので、やはり今回は分かりやすさ重視で進めていきます。ということで、3問目も撃破。ifや比較演算子の復習に丁度良い問題でした。
4問目。これまではY座標だけ使っていましたが、ここからはX座標やZ座標も使っていくようです。最初から完成済みのこのレインボーな配色は、Y座標の値を色のコードとして流用することで、1段ごとに次の色に変わるという便利な仕組みを実現しているみたいです。
今回はその部分はどうでもよくて、オブジェクトの一部を透明にするだけでOKです。コメントを読むと、何も返さないか、0やEMPTYを返せば透明化するようなので、これを使って目的の箇所を透明化していきます。最初から「xとzが2以上のとき」というコードが書かれていたので、これを「0以上のとき」に変えればOKのはず。
よーし。4問目、撃破です。どんどんいきましょう。この動画でどこまでやるのかって話なんですが、パズルゲームで全問解いちゃっても仕方ないので、今回はこの最初の問題集と、それから次の問題集を一通りやって、そこで一区切り付けようと考えています。
という訳で5問目に挑戦。これはさっきの問題と大体同じで、「x、y、zが全て1以上のとき」と書けると良さそうです。OK。5問目、撃破です。
6問目。今回は新たにabsという関数が登場。コメントを読んでみた限りでは、絶対値を返してくれるもののようです。線対称なオブジェクトを描画するのに特に重宝すると書いてあります。与えられているコードでも、確かに線対称な形状になってますね。
今回描画したいオブジェクトを眺めてみると、確かに、どの軸についても線対称になっており、絶対値が便利に使えそうな形状をしています。まずは、Z軸に着目して、絶対値が2以上なら無を返すように実装してみます。これでZ軸、いわば厚さの部分に関してはOK。「2以上または-2以下」と書く事もできますが、この辺りは絶対値の概念を持ち込むほうが理解しやすいコードになっている気がします。
あとは井桁状の形状をつくればOK。これも絶対値を使うのがお手軽。縦棒と横棒とをorの論理和で繋げば完成です。線対称な構造は頻出しそうなので、今後も絶対値を使う機会は多そうです。
さて、7問目ですが、なんかエラーが出てるみたい。こういう時はまずエラーメッセージを読みましょう。LUA_ERRSYNTAX。これはLuaという言語なのかな。その構文が間違ってるようで、10行目のifを閉じるendが期待されてるのに、13行目にはifと書かれている。ということで、endを書き忘れていたようです。
これで万事が解決かと思いきや、よく見てみると、一部間違った箇所がある模様。REDの箱がGREYになっているみたいなので、そこを探して書き換えてあげると良さそうです。OK。7問目、撃破です。
0からコードを書き始める機会って実は稀なので、他人のコードを読む力の方が実際には重要になってくる事が多いですよね。
さて、8問目。そんな事を話していたら、0から書かせてくれる問題が登場しました。「sushi?」と書かれており、とんでもない感性を感じます。この問題では好き放題して良さそうなので、中央からの距離に応じて赤・白・緑に塗り分ける作戦でいこうと思います。
この手の距離はチェス盤距離とも呼ばれており、風来のシレンなんかのローグライクでも稀にお世話になる概念だったりします。要するに、8方向に動ける駒が何歩で辿り着ける場所か?という距離です。この距離はmax関数があると求めやすいので、Documentationというタブを開いてみて、そういう関数があるのか調べてみています。
4章構成のドキュメントみたいで、1章はざっくりとした概要、2章は描画の詳細。そして3章に求めていた話が載っていそうです。まずは、変数の定義が可能という情報をGET。これでコードが少し読みやすくなりそうです。あとは、+や-などの利用可能な演算子の話。これもどこかで使う機会がありそうな気がします。
あったあった。求めていたmax関数も使えるそうです。あとは、赤・白・緑を表現するための便利な機能があると良さそうですが、無ければ愚直にif文で分岐するか。面白実装でいくなら16進数で7、1、11を表して、0xb17を距離に応じて右シフトするとかですかね。
普段、動画を録るのには『OBS』という大人気のアプリを使っているんですが、OBSの簡単なプラグインはLuaでも書けるので、YouTubeのタイムスタンプを自動生成するという簡単なプラグインを書いたことがあります。人生でLuaに触れたのはその一度だけかも…。
という訳でReplicubeのドキュメントを大体読了。欲しかった情報も吸い終わったところで、たのしいコーディングタイムに入っていきます。
まずはチェス盤距離の計算。xまたはyの絶対値の最大値を取ることで、原点からのチェス盤距離を求められます。今回だと、0、1、2のいずれかの値になります。0の場合は赤、1なら白、2なら緑を返したいので、0を7に、1を1に、2を11に変換するという何らかの仕組みを用意する必要があるのですが、ドキュメント内でtableという文字がちらっと見えた気がしたので、なんか配列的な構造が使えるのだろうと推測し、適当に配列を用意して使ってみることにします。
多くの言語では角括弧で配列リテラルを使えますが、どうやらLuaでは使えないみたいです。『Table』という名称から察するに、あくまで配列風に使えるだけの機能かもしれず、その場合は中括弧を使うタイプの言語が多いので、書き換えてみたところ、ほぼ上手くいきました。色が1個ずれているという事で、Luaの添字は1で始まるという事が判明。これに対応し、ようやくお寿司が完成しました。
実装に使った要素こそ小難しかったものの、こうしてコードを眺めてみると、意外と簡潔に見えるような気がしてます。そういう時って大体、書いた人だけがそう思ってる事がほとんどです。さて、次の問題に行きましょう。
9問目。今回はどちらかと言うと操作方法のチュートリアルのようです。マウスでぐりぐりと動かせるので、形状をよく確認してねという事ですね。実装自体は簡単で、xかzが±3のときか、あるいはyが-3のときにBROWNを返せばOK。yが+3のときを除くことで、上の蓋をあけているという事ですね。
これもまた線対称な構造が多いので、以前も使った絶対値を活用していきます。コメントの誘導的には「どこを塗るか」ではなく「どこを塗らないか」を表現してほしそうですが、この際どっちでもいいでしょう。OK。9問目、撃破です。前回の寿司に力を入れすぎたせいで、やや拍子抜けの雰囲気になってしまいました。
さて10問目。Google Chromeみたいな配色ですが、Replicube上ではこれらの配色にあまり特徴的な規則性は見当たりません。コメントを見る限りでも、入れ子状のifの利用が期待されているようなので、素直に愚直な条件分岐を書いていこうと思います。
まずはyが1以上のときに、xが1以上であればGREENを返して、そうでなければORANGEを返す。これで上部は完成。あとは下部でも同じことをやっていくだけです。軸が見やすい位置に回転させてから、yが1以上ではなかった場合、zが1以上であればBLUEを返せば良くて、そうでなければ、REDを返す。
よーし。10問目、撃破です。次がチュートリアルの最後の問題。
11問目。今回もまた最初からバグり散らかしている問題のようです。エラーメッセージを読んでみると、31行目で「colo」という知らない変数に働きかけているとの事で、「color」の入力ミスがあるという事がなんとなく推測できます。という訳で、ここを修正すれば全てが解決、という訳にもいかず、階段が一部しか描画されていないように見えます。更にコードを読んでみると「colour」というイギリス英語の綴りになっている箇所があり、これを修正することで無事完成となりました。
どういう原理でX字が描画できているのかですが、x == yやx == -yというコードを利用している模様。要するに、一次関数を等式として使えば、なんかこういうのが描けるみたいです。私にはきっと無縁の知識でしょう。という訳で、チュートリアルを全てクリア。おっと、メールだ。
ようこそコミュニティへ。新しいプレイヤーが参加してくれて嬉しいです! チュートリアルを修了したという事で、新たなパズルを用意してみました! という訳で、追加の問題集が送られてきました。全7問とさっきよりは短めなので、今回の動画ではこの7問までをやっていきましょう。
ということで1問目。さきほど私には無縁の知識と言っていましたが、早速、一次関数を利用する問題が現れました。これはy = -xで描画される直線のはずなので、Luaにおける適当な等式に読み替えると、x == -yとして表現できそうな気がします。==で比較するとtrueかfalseが返りますが、Replicubeでは白と無を描画してくれる値なので、この結果を直接返すだけでOKのようです。という訳で、1問目を難なく撃破。
2問目に移ります。今回も斜めの直線を描画するという問題。前回はZ軸を無視した平面でしたが、今回は更にZ座標の値で絞り込んで、直線を描画していくようです。まずは前回同様、x == yで平面を描画します。更にこれをxとzの関係性で絞り込もうと考え、論理積のandでx == zの条件を繋ぎます。
これで形状は完成。あとは、返す値をtrueかfalseかではなく、GREENか無相当かに変換したいので、適当にand GREENを使って短絡評価で対処。2問目、撃破です。
3問目。さっきの問題を線対称にしただけっぽいので、線対称ということで、絶対値を使うと良さそうです。という訳で、さっきのをabs版に変えるだけでOK。abs(x)が2回計算されてるのがやや無駄ですが、遅い処理でもないし、いいでしょう。3問目、撃破です。
4問目。新たに割り算の余りを返す%という演算子を導入するようです。既存コードでは、yを3で割った余りを使い、0、1、2のいずれかの値に順番に振り分けるという使い方をしている模様。続いて、上側の正解の形状を見てみると、xの値を0か1に変換しているように見えます。という訳で、恐らく2で割った余りを使えばOK。1マス分だけズレているみたいなので、適当にxから1でも引いて調整しておきます。これで4問目も撃破。残り3問となり、終わりが見えてきました。
5問目。今回はチェッカーボードを描いていくようです。とりあえずは平面にしたいので、0でなければ無を返すという処理を書いていきます。あ、zじゃなくてyか。RGBの矢印がXYZに対応しているという事ですが、たまにその辺を忘れてこんがらがる事があります。
さて、チェッカーボードの実装ですが、2問目の初期コードにreturn x+yというのが書かれており、加算で斜めの縞模様になるのをこっそりとチラ見できていたので、それを%で丸めればチェッカーボードの完成です。あとはピンク色になっちゃっているのを、黒色を返すように修正してあげるだけでOK。5問目、撃破となりました。
もし後半で条件分岐を避けたいなら、余りの0と1を、1と3の白黒に変換すればいいので、こんな感じにすれば実現できますが、やはり色への変換は非常に分かりづらい事になりますね。
さて、6問目。残り2問となりました。さっきも言ったように、加算を使えば斜めの縞模様を描けるので、ここはxとyとをひとまず足し合わせてみます。
これで大体似た感じの表情になりました。私のコードだと原点の部分が0を返す一方で、正解ではLIGHTGREENを返しているようなので、LIGHTGREENを足せば具合が良くなりそうです。あとは厚みを調整するだけで良さそうなので、zが0以外のときに無を返すようにすれば完成です。OK。6問目、撃破です。
7問目。最後の問題となりました。典型的な四つ脚のテーブルが課題のようです。素材の色はすべてがBROWN。形状に着目するだけで良い課題のようなので、ここはひとつ、現実の組立工程に即しながら、天板と脚とを分けて処理していきましょう。
--でコメントが書けるみたいなので、とりあえず天板から対処していきます。天板は非常に単純な平面形で、yが1のときにBROWNを返すだけでOK。これでひとまず天板が完成しました。
続いては4本の脚を用意していきます。しっかりとコメントも書いておきましょう。まずは脚の高さを決定。描画範囲をyが0以下の部分に制限します。続いて、脚の位置についてですが、今回は線対称な形状とも見て取れるので、いつもの絶対値を利用できそうです。具体的にはxとzの絶対値が2になるときだけ描画すればOK。この辺の条件を全部andで繋いで、すべてが一致するときだけBROWNを返すようにすれば完成です。
やりました。最終問題、撃破です。とはいえ、ちょっと名残惜しい気がするので、もう少しだけ手を加えてから終わろうと思います。というのも、確かドキュメントによると、自前の関数を定義することもできた気がするので、この機能をちょっと使ってみたかったんです。
今回、素材全体がBROWNであるのに「return BROWN」を2回も書いていますし、「やっぱりWHITEに変えてくれない?」とか言われると二度手間になりそうなので、形状だけを扱う関数を定義したりしながら、色は1箇所で決めるようにしていこうと思います。
という訳で、まずは「その座標が天板かどうかを返す関数」を用意。続いて「脚かどうかを返す関数」も用意します。Luaの関数名は多分snake_caseが一般的ですが、今回は極端に画面幅が狭いので、念のためcamelCaseで命名しておきます。という訳でisTopPlate関数とisLeg関数が爆誕。あとは定義した関数を利用して、「天板または脚であればBROWNを返す」というコードを書いていきましょう。
関数の呼び出しには一定のコストが掛かりますが、今回は静止した物体を描画するだけなので、そこまで高い性能を要求されないし、いいんじゃないかなと思っています。本作ではアニメーションも実装できるようなので、そういう領域を扱うときには、幾らか気を払った方がいいのかもしれません。という訳で、無事に書き換えが完了。最終問題もクリアし、GGとなりました。
ボクセル状の3D空間でたのしくお絵描きしていくゲーム『Replicube』。最初こそ取っ付きづらい印象があったものの、UIや導入も非常に丁寧で、遊んでみると非常にたのしい作品でした。いろんな観点や解法のあるパズルゲームとしてもたいへん優秀。プログラミングに興味を持つための取っ掛かりとしても楽しいですし、数学的な分野との繋がりもあり、多方面で楽しめる作品だと感じました。
それじゃ、今回はここまでにしようかな。いいねやチャンネル登録していただけると嬉しいです。ではでは、またね。
記事公開 · 更新
