Luaコードによる成果物だけをご覧になりたい方は目次に★マークが付いている部分をタップしてください。
すぐにジャンプできますよ!

アナザーエデン関連ページ・サイトマップへ戻る

アナザーエデンのプログラミングを個人サイトで試す

フィーネ・サキ・マユ・ノーナの疾走

アナザーエデンで使われているLuaですが、これを静的Webサイトへ組み込んだうえで動作させることができないか、試してみました。
本来はこのような目的で使うものではないでしょうから、Webサイト制作やITの勉強という意味で考えれば、意義は薄いでしょう。
しかし、私が注目しているのは別のことです。
それは、自作コードによるWebサイトをやっている場合、このように様々なツール等を組み込めばいろんな言語に触れることができるという側面となります。

ここではFengariを用いて、LuaによるUI(ユーザーインターフェース)をJavaScript経由で実装してみたいと思います。

IT知識に関する推奨レベル

ASフィーネステータス画面

冒頭でまずお伝えすると、お勉強する意思がおありであれば、どなたでもチャレンジできます。
それを前提としてお話していきます。

注意して頂きたいのは一番初めの事項です。
「実際にやったことがある」という一文を馴染み深い言葉で言い変えると「HTMLでWebサイトを作ってサーバーにアップロードし、公開に成功したことがある」という意味です。
ホームページ作成サービスやブログ作成等は含みません。
WordPressでギリギリといったところ。
簡単なもので良いので、自らコードを全て記述し、Webサイトの形を構築したことがあるかどうか。
その経験の有無で成功率が変わってくるでしょう。

では、始めます。

Fengariとは何か

天使の唄ASフィーネ

FengariはJavaScriptで実装されたLuaの仮想マシン(VM)で、ブラウザ上でLuaのスクリプトを実行することができます。
これが何を意味するかというと、例えば次のような物語を語れるでしょう。

  1. html・cssは書けるが、JavaScriptは苦手という人がいる。でもLuaは得意。─ なかなか見ないパターンでしょうけど… ─
  2. その人は何かしら凝ったコンテンツを静的Webサイトに実装したいと考えている。
  3. この場合、Fengariを使えばLuaの知見を活かせるため、JavaScriptの学習コストを抑えることができる。

おそらく、Fengariはトランススクリプトではないと思うんですよね。
トランススクリプトはあるプログラミング言語のコードを別の言語に変換するツールのことを指しますが、FengariはLuaコードをそのままJavaScript環境で動作させるためのエンジンと考えたほうが良いと思われます。
これを前提として、続けますね。

改めて、Fengariは上述のようにLuaプログラミング言語をJavaScript環境で実行するためのエンジンです。
LuaのインタープリタをJavaScriptで書き直したもので、ブラウザやNode.jsなどのJavaScript環境でLuaコードを実行できるようにしてくれる仕組みとなっています。

LuaのインタープリタをJavaScriptで書き直す

天使の唄ASフィーネ威力

上述の説明をもうちょっと詳しく書きます。
「LuaのインタープリタをJavaScriptで書き直す」というのは、Luaの実行エンジンをJavaScriptで再実装するという作業になります。
Luaのバイトコードを解釈して実行する仮想マシン(VM)を、JavaScriptで作り直すという意味です。

調べたところでは、LuaコードはLuaインタープリタによって実行されるようです。
このインタープリタはC言語で書かれており、Luaコードをバイトコードにコンパイルし、そのバイトコードを実行します。
FengariはこのプロセスをJavaScriptで再現しているみたい。
つまり、LuaコードをJavaScript環境で直接実行できるようにするために、LuaのインタープリタをJavaScriptで実装しているということになるよね。

ジオ・アンセム

この仕組みを使えば、ブラウザやNode.jsなどのJavaScript環境でLuaスクリプトを実行できるようになると考えました。
例えばWebアプリケーションでLuaを使いたい場合、Fengariを利用することで、特別な設定やコンパイルなしにLuaコードをそのまま動かすことができるのではないかと。

まとめも兼ねて整理すると、Fengariの特徴は次のようになります。

おそらくFengariを使えば、WebアプリケーションやNode.jsアプリケーションにLuaを取り入れることができるでしょう。

ちなみにFengariは、巷でよく語られているところのJavaScriptライブラリではないと思われます。
例えば有名なjQueryは、主にWebページの操作やアニメーションを簡単にするためのライブラリです。
しかし上述のように、FengariはLuaプログラミング言語をJavaScript環境で実行するためのエンジンとなります。

ライブラリとエンジンの違い

ASフィーネ立ち絵

ライブラリとエンジンの違いについて書いておきます。
これは基礎用語に該当するものだから、調べてもらえればたくさん事例が出てきますよ。
「ライブラリ」というのは、特定の機能や処理を簡単に利用できるようにまとめたコードの集まりです。
例えばjQueryはDOM操作やアニメーションを簡単にするためのJavaScriptライブラリです。
開発者が特定のタスクを効率的に行うためのツールキットのようなものと考えれば良いでしょう。
一方「エンジン」は、特定のタスクや一連のタスクを実行するための基盤となるソフトウェアと言えば良いでしょうか。
例えばゲームエンジンと呼ばれているものは、グラフィックス、物理演算、サウンドなどの機能を統合して、ゲームを動作させるための環境を提供します。
エンジンは、より大規模で複雑なシステムを構築するための基盤となるものですね。

まとめると、ライブラリは特定の機能を提供する部品の集まりであり、エンジンはその部品を使って動作するための基盤や環境を提供するものです。

ゲームエンジンについて調べてみる
ASノーナ・フィーネ乾杯

私の分野ではないから細かくは書かないけど、Unity、Unreal Engine、Godot Engine、GameMaker Studio 2、CryEngineといろいろあるようです。
Luaはこれらのゲームエンジンではありませんが、Luaを使用するゲームエンジンを見つけました。
アナザーエデンの関連記事にもあったCocos2d-xですよ。
Cocos2d-xはC++とLuaをサポートしており、モバイルゲームの開発に広く使われているようですね。

このようにして、断片的な情報を繋いでいけます。
加えて、「CRIWARE」はゲームエンジンではなく、ゲーム開発向けのサウンドおよびムービーのミドルウェアのようです。
ゲーム内の音声や映像の処理を効率化し、品質を向上させるためのツールを提供しているみたい。

これらのツールや仕組みを理解した上でプログラミング言語を操ることができれば、アナザーエデンみたいな凄いゲームを作ることができるのでしょう。
これはとっても大変なことだと思いますよ?

fengari-webの使用方法

猫マユ

まず、GitHubのfengari-webリリースページからfengari-web.jsをダウンロードします。
ダウンロードした後は各々のWebサイトにある適切なディレクトリに配置してください。

ここで、GitHubのfengari-webリリースページにある各アセットの概略を書いておきます。

fengari-web.bundle.js
Fengariのすべての機能を1つのファイルにまとめたバンドル版です。
これを使うと、追加の依存関係なしにFengariを利用できます。
fengari-web.bundle.js.map
バンドル版のソースマップファイルです。
デバッグ時に元のソースコードを参照するために使用します。
fengari-web.js
Fengariの標準版です。
必要に応じて他のライブラリと組み合わせて使用することができます。
fengari-web.js.map
標準版のソースマップファイルです。
デバッグ時に元のソースコードを参照するために使用します。
Source code
リポジトリのソースコードをZIP形式またはTAR.GZ形式でダウンロードできます。
これを使ってローカルでビルドやカスタマイズが可能です。
コギトエルゴスム

これらのファイルを使って、Fengariをブラウザ上で実行したり、デバッグしたりするようです。
私もどこまで深入りするかは現段階で未定ですが、あるいは普通にJavaScriptを書くより、Luaを使った方がラクなUIがでてくるかもしれませんね?

ただ…どうやらこれらのツールは2018年から更新がされていない様子。
それで良いものなのか、はたまた他にも実装ルートがあるのかは、今後の調査待ちということに致しましょう。

fengari-web.jsをHTMLに組み込む理由

では、次にダウンロードしてきたfengari-web.jsをHTMLに組み込みます。

fengari-web.jsを組み込むhtmlコード


<script src="/script/fengari-web.js" type="text/javascript"></script>

マユの天アップの瞬間

このようにしてfengari-web.jsをHTMLに組み込む理由は、ブラウザ上でLuaスクリプトを実行するためです。
これを作らないと静的Webサイトに表示できません。
加えて、私が使ってる環境がGoogle CloudのApp Engineなので、そのままではLuaを実行できないのです。
何かしら他のプロダクトを使うか、もしくは今やっているように他のプログラミング言語を経由するような方向にしないと、Webサイト上で形にできないんだよね。

fengari-web.jsをHTMLに組み込むと、次のような状況を自分のWebサイトで作り出すことができます。

Luaの実行環境が提供される
上述しているように、fengari-web.jsはJavaScriptで実装されたLuaの仮想マシン(VM)です。
これをHTMLに組み込むことで、ブラウザ上でLuaコードを実行できる環境が提供されます。
JavaScriptとの相互運用性が出てくる
LuaスクリプトからJavaScriptのオブジェクトや関数にアクセスできます。
LuaとJavaScriptの間でデータをやり取りできます。
ブラウザでデバッグできる
ブラウザの開発者ツールを使ってLuaスクリプトのデバッグができます。
ソースマップファイル(.map)を使うと、元のLuaコードを参照しながらデバッグが可能みたいです。
開発者ツールはともかく、元のLuaの参照まで進むかどうかは今後によりますね。
簡単なセットアップができる
fengari-web.jsをHTMLに組み込むだけで、特別な設定やインストールなしにLuaスクリプトを実行できます。
これが一番大きいでしょう。
手軽にLuaの機能をウェブアプリケーションに追加できるのです。

参考サイト一覧

勉強になりました。ありがとうございます。

無料で「アナデンプログラミング体験」ができます

マユの天255ステータス画面

このあたりまで調べたところで、おそらくやれるだろうと判断しました。
普通はやらないだろうけど、静的WebサイトでLuaの実行はできるのだから、Luaを書く体験ならできるだろうと。

これでフルにJavaScriptを組むよりコードが読みやすいのであれば、Luaの力を借りて簡素なJavaScriptを追加してあげれば、いろんなUIの実装がラクになるのかもしれないと思ったのですよ。

それではいよいよ、Fengariを使ったLuaコードを紹介します。

★アナデンで使われているLuaの正常稼働に成功!

まずは完成形をお見せします。
これはボタンをタップすることで、外部サイトへのメニューが開くようになっています。

Luaは初めて触れる言語ですが、1行1行見ていくと、身構えていたほど難解ではなさそうです。
でもこういうのが何百行何千行と重なっていくと、ものすごい大変になるんだよね…
ここではこういうテストしかやってないから、簡単に見えるだけでしょう。

それではさっそく、htmlを含めて全体のコードを見ていきます。

HTMLにLuaを書く:プルダウンメニュー1


<div class="scoth-dropdown">
   <button onclick="toggleDropdown('menu1')">WFSゲームの公式サイトリスト</button>
   <div class="scoth-dropdown-content" id="menu1"></div>
</div>

 <script>
  const luaCode1 = `
       local items = {
           {name = "アナザーエデン", link = "https://another-eden.jp/"},
           {name = "ヘブンバーンズレッド", link = "https://heaven-burns-red.com/"},
           {name = "WRIGHT FLYER STUDIOS", link = "https://www.wfs.games/"}
       }

       local dropdownHtml = ""
       for _, item in ipairs(items) do
           dropdownHtml = dropdownHtml .. '<a href="' .. item.link .. '">' .. item.name .. '</a>'
       end

       return dropdownHtml
   `;

  const L1 = fengari.load(luaCode1);
  const result1 = L1();

  document.getElementById('menu1').innerHTML = result1;

  function toggleDropdown(menuId) {
   var menu = document.getElementById(menuId);
   if (menu.style.display === "block") {
    menu.style.opacity = "0";
    setTimeout(function () {
     menu.style.display = "none";
    }, 500);
   } else {
    menu.style.display = "block";
    setTimeout(function () {
     menu.style.opacity = "1";
    }, 10);
   }
   event.stopPropagation();
  }

  document.addEventListener("click", function () {
   var menus = document.getElementsByClassName("scoth-dropdown-content");
   for (var i = 0; i < menus.length; i++) {
    if (menus[i].style.display === "block") {
     menus[i].style.opacity = "0";
     setTimeout(function (menu) {
      menu.style.display = "none";
     }, 500, menus[i]);
    }
   }
  });

  var dropdowns = document.getElementsByClassName('scoth-dropdown');
  for (var i = 0; i < dropdowns.length; i++) {
   dropdowns[i].addEventListener("click", function (event) {
    event.stopPropagation();
   });
  }
 </script>

私はLuaを初めて書くので、いろいろ誤りがあったり冗長であったりするかもしれません。
ただ、正常動作は確認できました。
可能な限り説明を試みます。

コード全体を優しい言葉で説明します

ASフィーネ勝利ポーズ

上記でお見せしたコードは、次のような感じで動作しているのですよ。

簡単に一文で説明

このコードはWebページに「WFSゲームの公式サイトリスト」というボタンを作ります。
ボタンを押すと、ゲームの公式サイトのリンクが表示される仕組みになっています。

少し詳しい説明

HTML部分
Lua部分
JavaScript部分
関数の説明

Luaがどこで使われているかも含めて、ゲームのリンクを簡単に表示したり隠したりできるUIの説明を行いました。
次は個別にコードを見ながら、もうちょっと詳しく説明していこうと思います。

Luaコードの説明

冒頭でお見せした長いコードの中で、Luaの部分は少ないです。
しかし重要な役割を果たしています。
ひとまずLuaの部分だけ書いてみましょう。


const luaCode1 = `
    local items = {
        {name = "アナザーエデン", link = "https://another-eden.jp/"},
        {name = "ヘブンバーンズレッド", link = "https://heaven-burns-red.com/"},
        {name = "WRIGHT FLYER STUDIOS", link = "https://www.wfs.games/"}
    }

    local dropdownHtml = ""
    for _, item in ipairs(items) do
        dropdownHtml = dropdownHtml .. '<a href="' .. item.link .. '">' .. item.name .. '</a>'
    end

    return dropdownHtml
`;

この部分がLuaのコードです。
今の私ではこのレベルが限界ですね…
本来ゲーム開発の現場でLuaはこういう使い方をされていないと思うし、他のセクションで書いている通り、実際はC/C++プログラムに組み込んで使われることが多いようです。

フィーネとマリエル
local items = {...}:
ゲームの名前と公式サイトのリンクを持つテーブルを定義します。
local dropdownHtml = "":
空の文字列変数 dropdownHtml を定義します。
for _, item in ipairs(items) do ... end:
ループを使用して、items テーブル内の各エントリを処理します。
dropdownHtml = dropdownHtml .. '<a href="' .. item.link .. '">' .. item.name .. '</a>':
各アイテムのリンクをHTML形式で文字列に追加します。
return dropdownHtml:
最終的なHTML文字列を返します。

HTMLにLuaを直接組み込んで使うことは珍しいはずですが、このように静的Webサイト内部での表示を通して学習目的として使うのも悪くないのでは?
今回の例のように、JavaScriptとの連携や特定のライブラリを使用してHTML内でLuaを実行することも可能です。
勉強すれば、もっといろんなことができるでしょう。

コードの説明に戻ります。

上記のLuaコードの後、JavaScriptの部分でこのLuaコードを実行し、生成されたHTMLをドロップダウンメニューに挿入する形としました。


const L1 = fengari.load(luaCode1);
const result1 = L1();

document.getElementById('menu1').innerHTML = result1;

この部分が、Luaで生成されたHTMLを「menu1」の内容として設定しています。
Luaの部分は短いものの、ドロップダウンメニューの内容を生成する役割を担っています。
次はJavaScript部分の説明ですね。

JavaScript部分の説明

fengari-web.jsを使うことでLuaコードが実行できるよう環境設定していますが、その後の長いJavaScriptはユーザーがボタンをクリックしたときにメニューを表示・非表示にする動作や、メニュー外をクリックしたときにメニューを閉じる動作を実現しています。
これらの部分はユーザーインターフェースの動作を制御するために書いたのですが、どうだろう…
全部Luaで制御することもできると思うんだけど、ちょっと今の私には厳しい…


 const L1 = fengari.load(luaCode1);
 const result1 = L1();

 document.getElementById('menu1').innerHTML = result1;

 function toggleDropdown(menuId) {
  var menu = document.getElementById(menuId);
  if (menu.style.display === "block") {
   menu.style.opacity = "0";
   setTimeout(function () {
    menu.style.display = "none";
   }, 500);
  } else {
   menu.style.display = "block";
   setTimeout(function () {
    menu.style.opacity = "1";
   }, 10);
  }
  event.stopPropagation();
 }

 document.addEventListener("click", function () {
  var menus = document.getElementsByClassName("scoth-dropdown-content");
  for (var i = 0; i < menus.length; i++) {
   if (menus[i].style.display === "block") {
    menus[i].style.opacity = "0";
    setTimeout(function (menu) {
     menu.style.display = "none";
    }, 500, menus[i]);
   }
  }
 });

 var dropdowns = document.getElementsByClassName('scoth-dropdown');
 for (var i = 0; i < dropdowns.length; i++) {
  dropdowns[i].addEventListener("click", function (event) {
   event.stopPropagation();
  });
 }
</script>

const L1 = fengari.load(luaCode1);:
fengari.load関数を使って、luaCode1に書かれたLuaコードをJavaScriptで実行できる形に変換します。
この結果がL1に保存されます。
const result1 = L1();:
L1を呼び出してLuaコードを実行し、その結果をresult1に保存します。
この結果は、Luaコードが生成したHTML文字列です。
document.getElementById('menu1').innerHTML = result1;:
menu1というIDを持つHTML要素を取得し、その中身をresult1の内容に置き換えます。
この段階を踏むことで、生成されたHTMLがドロップダウンメニューとして表示されます。
アップフィーネ
function toggleDropdown(menuId) { ... }:
toggleDropdownという関数を定義しています。
この関数は、渡されたID (menuId) を持つメニューの表示・非表示を切り替えます。
var menu =
document.
getElementById(menuId);:
menuIdで指定されたIDを持つHTML要素を取得します。
if (menu.style.display === "block") { ... } else { ... }:
メニューが表示されているかどうかをチェックします。
表示されている場合は非表示にし、表示されていない場合は表示するように切り替えます。
menu.style.opacity = "0";:
メニューの透明度を0に設定して非表示にします。
setTimeout(function () { menu.style.display = "none"; }, 500);:
500ミリ秒(0.5秒)後にメニューの表示スタイルをnoneに設定して、完全に非表示にします。
menu.style.display = "block";:
メニューの表示スタイルをblockに設定して表示します。
setTimeout(function () { menu.style.opacity = "1"; }, 10);:
10ミリ秒後にメニューの透明度を1に設定して表示します。
event.stopPropagation();:
クリックイベントが親要素に伝播するのを防ぎます。
document.addEventListener("click", function () { ... });:
ページ全体にクリックイベントリスナーを追加します。
このリスナーは、メニュー外のどこかがクリックされたときにメニューを非表示にします。
var menus = document.getElementsByClassName("scoth-dropdown-content");:
scoth-dropdown-contentというクラス名を持つすべてのHTML要素を取得します。
for (var i = 0; i < menus.length; i++) { ... }:
すべてのメニュー要素に対して、以下の処理を繰り返します。
if (menus[i].style.display === "block") { ... }:
メニューが表示されている場合、以下の処理を行います。
menus[i].style.opacity = "0";:
メニューの透明度を0に設定して非表示にします。
setTimeout(function (menu) { menu.style.display = "none"; }, 500, menus[i]);:
500ミリ秒後にメニューの表示スタイルをnoneに設定して、完全に非表示にします。
var dropdowns = document.getElementsByClassName('scoth-dropdown');:
scoth-dropdownというクラス名を持つすべてのHTML要素を取得します。
for (var i = 0; i < dropdowns.length; i++) { ... }:
すべてのドロップダウン要素に対して、以下の処理を繰り返します。
dropdowns[i].addEventListener("click", function (event) { event.stopPropagation(); });:
ドロップダウン要素内のクリックイベントでイベントの伝播を停止し、メニュー内のクリックがメニュー外のクリックと誤認されないようにします。
天使の唄フィーネ直前

あれ?
ていうか、結局JavaScriptを使ってないか?
Luaでやり切れるのか調べてみたけど、まぁそもそもこうやって実装するもんじゃないしねー
私がこうして静的Webサイトをホスティングしているから環境を作れるというだけで、本来であれば、アナザーエデンみたいなアプリを作るための言語なんでしょう。
まぁ、ちょっとしたWeb開発系のジョークだよね😆ww

JavaScriptのイベントリスナーとは

イベントリスナーは、JavaScriptの中で特定のイベントが発生したときに実行される関数のことを指します。
イベントには、ユーザーがボタンをクリックする、マウスを動かす、キーを押す、ページが読み込まれるなど、さまざまな種類があります。
イベントリスナーを使うことで、JavaScriptはこれらのイベントに反応して特定の動作を実行することができます。
例えば、ユーザーがボタンをクリックしたときに、何かの処理を行いたい場合にイベントリスナーを使います。
簡単な例を見てみましょう。

イベントリスナーの例:html


<button id="myButton">クリックしてね!</button>

イベントリスナーの例:JavaScript


// ボタン要素を取得
var button = document.getElementById("myButton");

// イベントリスナーを追加
button.addEventListener("click", function() {
alert("ボタンがクリックされました!");
});

この例にあるJavaScriptは、次のような流れで動作しています。

ボタン要素を取得
document.getElementById("myButton") を使って、HTML内のボタン要素を取得します。
イベントリスナーを追加
button.addEventListener("click", function() {...}) を使って、ボタンに「クリック」イベントリスナーを追加します。
イベントが発生したときの処理
ボタンがクリックされたときに、指定された関数(この場合は、アラートを表示する処理)が実行されます。
フィーネCC直前1

こういうのがイベントリスナーの基本的な仕組みです。
イベントリスナーを使用することで、ユーザーの操作に応じて動的に反応するWebページを作成することができます。
JavaScriptがホームページの動作を制御するとよく言われるのは、こういった部分から来ています。

CSSの説明

ASねここの壁紙

ちょっと長すぎるなーと思ってCSSは省略していたのですが…
せっかくだから解説を付けましょうか!
CSSは必須ではないんだけど、書けるのと書けないのとでは、やっぱりデザインの幅が違います。
プルダウンメニューが滑らかに表示されるアニメーションだってcssで制御しているのですよ。
思い付く限りで書いてみますね。

デザインの制御
ウェブページの見た目(色、レイアウト、フォントなど)を細かく制御できない。
レスポンシブデザイン
画面サイズに応じてレイアウトを変更するレスポンシブデザインが難しい。
ユーザー体験の向上
ユーザーが快適に利用できるインターフェースを作成するのが困難になる。
スタイルの統一
複数のページで一貫したデザインを保つのが難しい。
維持と管理
大規模なサイトでのデザイン変更が手間になる。

いろんな意見があるのですが、特に「複数のページで一貫したデザインを保つ」というのが重要な側面かと思います。
これはhtmlだけでもできないことはないのですが、cssを使うと簡単になります。
どこかでまとめて指定しておけば、他も全て同じになるんだよね。

さっそくコードを見てみましょう。

LuaによるプルダウンメニューをサポートするCSS


/* lua.css */
/* ドロップダウンメニューのスタイルを定義 */
.scoth-dropdown {
 position: relative; /* 親要素に対する位置を相対的に設定 */
 display: inline-block; /* インラインブロック要素として表示(要素が並んで表示される) */
}

/* ドロップダウンメニューのコンテンツのスタイル */
.scoth-dropdown-content {
 display: none; /* デフォルトでは非表示にする */
 position: absolute; /* 親要素に対して絶対位置を設定 */
 background-color: #f9f9f9; /* 背景色を薄いグレーに設定 */
 box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); /* ボックスシャドウを設定し、浮き上がるように見せる */
 z-index: 1; /* 重なり順序を設定(他の要素より前面に表示) */
 white-space: nowrap; /* テキストを折り返さずに表示 */
 opacity: 0; /* 透明度を0に設定(表示されない状態) */
 transition: opacity 0.5s; /* 透明度の変化を0.5秒間でアニメーションさせる */
}

/* ドロップダウンメニュー内のリンクのスタイル */
.scoth-dropdown-content a {
 color: #0078D4; /* リンクの文字色を青に設定 */
 padding: 12px 16px; /* リンクの内側に余白を設定 */
 text-decoration: none; /* リンクの下線を消す */
 display: block; /* ブロック要素として表示(縦に並ぶ) */
}

/* リンクにホバーしたときのスタイル */
.scoth-dropdown-content a:hover {
 background-color: #f1f1f1; /* 背景色を薄いグレーに変更 */
}

/* ドロップダウンメニューを開くボタンのスタイル */
.scoth-dropdown button {
 background-color: rgba(85, 139, 47, 0.5); /* ボタンの背景色を半透明の緑に設定 */
 color: #000000; /* 文字色を黒に設定 */
 padding: 8px 15px; /* ボタン内の余白を設定 */
 border: 2px solid #558b2f; /* ボタンの外枠を設定 */
 border-radius: 5px; /* ボタンの角を丸くする */
 cursor: pointer; /* マウスポインタを指示棒に変更 */
 font-size: 14px; /* 文字のサイズを設定 */
 transition: background-color 0.3s, box-shadow 0.3s; /* 背景色とボックスシャドウの変化を0.3秒間でアニメーションさせる */
}

/* ボタンにホバーしたときのスタイル */
.scoth-dropdown button:hover {
 background-color: rgba(107, 142, 35, 0.7); /* 背景色を少し濃い緑に変更 */
 box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); /* ボックスシャドウを設定し、浮き上がるように見せる */
}

/* ボタンにフォーカスが当たったときのスタイル */
.scoth-dropdown button:focus {
 outline: none; /* ボタンのデフォルトのフォーカス枠を消す */
 box-shadow: 0 0 0 3px rgba(85, 139, 47, 0.5); /* 緑の枠を表示し、フォーカスされていることを示す */
}

Luaはさすがに特別な事例ですが、html・css・JavaScriptの3つは基本の部分なんですよね。
でも基本と言いつつ、深みに行くと非常に難しくなります。
そこそこレベルでいいからこの3つを書ければ、自分でプラットフォームを作ることができるってこと。

★最高難易度コンテンツ:アナデン開発に使われているLuaコードを書く!

これはさっきのゲーム公式リンク集と同じコードですよ。
同一Webページ内に2つ以上のリストを置くから、IDをmenu1とmenu2に分けているというだけです。

Luaの公式サイト、オシャレですね!
加えて、ここで表示している「World Wide Web Consortium」と「開発者向けのウェブ技術」というWebサイトは、Web制作をしている人たちにとって馴染み深いものとなっています。
特にWorld Wide Web Consortium、略してW3Cはいろんな教科書に掲載されている団体ですよ?

Luaの実行環境を実装できたことになる

星5フィーネキャライラストヘッダー

これにて、当WebサイトにLuaの実行環境が実装されました。
今後はいろんなページで使用可能です。
せっかく良い感じのプルダウンメニューができたので、必要なポイントで導入していくと良さそう。
公式リンクというのはやたらと宣伝するようなものではありませんし、こうやって控えめに、でもユーザーがそれと分かるようなUIで添付していくつもり。

HTMLにLuaを書く:プルダウンメニュー2


<div class="scoth-dropdown">
   <button onclick="toggleDropdown('menu2')">フロントエンド技術とLuaの公式サイトリスト</button>
   <div class="scoth-dropdown-content" id="menu2"></div>
</div>

<script>
   // 技術サイトの名前とリンクのリストをLuaコードとして用意します
   const luaCode2 = `
        local items = {
            {name = "World Wide Web Consortium", link = "https://www.w3.org/"},
            {name = "開発者向けのウェブ技術(JavaScript)", link = "https://developer.mozilla.org/ja/docs/Web/JavaScript"},
            {name = "Lua", link = "https://www.lua.org/"}
        }

        local dropdownHtml = ""
        for _, item in ipairs(items) do
            dropdownHtml = dropdownHtml .. '<a href="' .. item.link .. '">' .. item.name .. '</a>'
        end

        return dropdownHtml
    `;

   // LuaのコードをJavaScriptで実行して、結果を取得します
   const L2 = fengari.load(luaCode2);
   const result2 = L2();

   // 取得した結果をHTMLのmenu2というIDの箱に表示します
   document.getElementById('menu2').innerHTML = result2;

   // ボタンをクリックすると、表示するか隠すかを切り替える関数です
   function toggleDropdown(menuId) {
    var menu = document.getElementById(menuId);
    if (menu.style.display === "block") {
     // 表示されている場合は、透明にして隠します
     menu.style.opacity = "0";
     setTimeout(function () {
      menu.style.display = "none";
     }, 500);
    } else {
     // 表示されていない場合は、透明から見えるようにします
     menu.style.display = "block";
     setTimeout(function () {
      menu.style.opacity = "1";
     }, 10);
    }
    event.stopPropagation();
   }

   // ページのどこかをクリックしたときに、リストを自動で隠す機能です
   document.addEventListener("click", function () {
    var menus = document.getElementsByClassName("scoth-dropdown-content");
    for (var i = 0; i < menus.length; i++) {
     if (menus[i].style.display === "block") {
      menus[i].style.opacity = "0";
      setTimeout(function (menu) {
       menu.style.display = "none";
      }, 500, menus[i]);
     }
    }
   });

   // ドロップダウンをクリックしてもイベントが伝播しないようにします
   var dropdowns = document.getElementsByClassName("scoth-dropdown");
   for (var i = 0; i < dropdowns.length; i++) {
    dropdowns[i].addEventListener("click", function (event) {
     event.stopPropagation();
    });
   }
</script>

Luaコードを試した感想

ASフィーネ僥倖

いくらWeb制作に慣れているとは言え、このクラスまで来るとちょっと息苦しいですね😵‍💫
特にLuaなんてアナザーエデンをプレイしていなければ出逢えなかった言語でしょうし、初めて触りました。
でも何とか…こうした簡素なプルダウンメニューくらいなら実装できたということになります。
とても良い勉強になりましたよ。
これだけでもアナザーエデンと出逢えた価値があるというもの。
JavaScriptのエンジンを経由して、本来であればフロントエンド技術とはならない言語を静的Webサイトで動作させる試み。
これは今後の私のWeb制作活動にとって、極めて大きなコード資産となります。
有益な形が残る学びの機会が与えられたこと、深く感謝申し上げます。

次回予告…

アニメフィーネ

まだ明確には決めてないんですけどね。
このLuaについて調べている過程でいろんな知見を得ました。
もしくは思い出しました。
アナザーエデンとてLuaだけで書かれているわけではありませんし、今後もいろんな言語ネタをやってみるのもおもしろいですよね。
もしくはLuaでもっといろいろ実装してみるか。
Luaのほうが簡単ないしは手間がかからないかな?

まぁまぁ🎵
少なくとも、すでにLuaの実行環境は構築したわけですから。
今後も手持ち資料の発掘状況次第で、いろーんな個人サイトネタを書いていきましょう!


サイトマップ

アナザーエデン関連ページ・サイトマップ

アナザーエデンの強敵戦やストーリーコンテンツのリスト、お勧めバッジなどを掲載したコーナーです。
期間限定のない普通のRPGですので、初心者でも安心して続けていけるゲームとなっています。
もっとも重要なグラスタについては、場所別に網羅した表があります。

個人サイトのホスティングとコンテンツ作成

個人でウェブサイトを作るにはどうすればいいか。
HTML・CSS・JavaScriptの書き方はもちろん、無料かつ広告なしでホームページを作る方法を掲載したコーナーです。
Webデザインやレイアウトについても書いてあります。

魚釣りなどアウトドアのエリア

ゲームとパソコンだけじゃなく、アウトドアも趣味なんです。
このコーナーでは魚釣りの記録とか、魚料理のレシピ、はたまたサイクリングなどなど。
アウトドアに関連するコンテンツが詰め込まれています。