ESKEES スクリプト言語 — リファレンス
アルファ版のため、予告なく変わる可能性があります。操作の手順は はじめてガイド、全体の仕組みは ESKEES の仕組み を参照してください。
.eskx(と旧形式の .emg)に、「クリックしたら表情が変わる」「夜になったら服が替わる」といった演出から、テトリスや パタパタ のような小さなゲームまでを記述するための言語です。Lua に似た構文で、ブロックは end で閉じます。
| 項目 | 内容 |
|---|
| 編集する場所 | ESKEES の上部バー「ロジック」(ブロック / テキスト / 図。どれも同じ構文木を編集します)。テキストのシンタックスハイライトと補完もこの言語に対応しています |
| 実行する場所 | Player・showcase・Screen(壁紙)・ESKEES のテストプレイ(同じ再生エンジン。違いは §14) |
従来の書き方(repeat 3 … end・!=・+= など)と Lua の書き方(repeat … until・~=・for … do など)の両方を解析できます。
1. 字句
コメント
-- 行末までがコメント(Lua と同じ)
--[[ … ]] の複数行コメントはありません。
名前
パーツ名・フレーム名・クリック領域の名前・サウンドの名前はアセット内の名前そのもので、日本語や空白も使えます。
| 書き方 | 用途 |
|---|
顔 score ミノ | 空白と記号(" ' , ( ) = < > + - * / % [ ] { } # ~ ;)を含まなければ、そのまま書けます |
"ロゼ のコピー" '赤' | 含む場合は " か ' で囲みます |
board.cells | 名前の中の . はテーブルのフィールド(§8) |
self.x | 実行中のアクターの値(§4) |
self:flap() enemy:hit(1) | 名前の中の : はメソッド呼び出し(§7.12) |
preset 表情:笑顔 | コマンドの後の名前は、: を含んでもそのまま扱います(ステートの 軸:ステート) |
文字列
"…" か '…' で書きます。エスケープできるのは \" \' \\ だけです。改行は含められません[[ … ]] の長い文字列はありません
数値
3 0.5 -2。指数表記(1e3)と 16 進数(0xff)はありません。true / false は 1 / 0 の別名です。
文の区切り
- 改行で区切ります(1 行に 1 文)。空行はいくつでも置けます。インデントは自由です
- 文の区切りとしての
; はありません(テーブル内の区切り {1; 2} にだけ使えます) - 括弧・テーブル・引数の中では改行できます
予約語
文の先頭に来る語(関数名には使えません): wait break scene if switch local return function loop while repeat frame cycle move turn size place ui say sound music tween spawn destroy for toggle show hide preset play stop poke reset var save on class end camera stage
文の中で意味を持つ語: then elseif else do in until case each at to by times forever nowait on self ease wait then destroy volume stop show hide click pairs ipairs and or not nil true false count touching in scene from save follow shake power off
予約済みの名前(同じ名前の変数を作っても、こちらが優先されます): screen camera world
2. スクリプトの構成
スクリプトの最上位に書けるのは次の 5 つだけです(それ以外を書くと「var か save か on か function か class が必要です」というエラーになります)。
var score = 0 to 999999 save -- 画面に表示でき、保存もできる数値の変数(§5.1)
save 記録 = { best = 0 } -- セーブデータの構造(§5.2)
function add(a, b) -- 関数(§5.3)
return a + b
end
class 鳥 -- アクターのクラス(§5.4)
vy = 0
function update(dt)
self.y += self.vy * dt
end
end
on press 顔 -- トリガー(§6)
score = add(score, 1)
end
- 並び順は自由です(シリアライズすると
var → save → function → class → on の順になります) function は最上位にだけ書けます(トリガーの中には書けません)
3. 値と型
| 型 | 例 | 備考 |
|---|
| 数値 | 3 0.5 | 64 bit 浮動小数点数。文字列にすると、整数は小数点なし、それ以外は小数 6 桁まで |
| 文字列 | "夜" | .. で連結します |
| テーブル | {} {1, 2} {x = 1} | 配列と辞書を兼ねます。配列の添字は 1 から。nil を代入すると削除されます |
| nil | nil | 値がないことを表します。未定義の名前・テーブルに存在しないキー |
真偽値
| 値 | 真偽 |
|---|
| 数値 | 0 だけが偽(Lua とは異なります。従来のルールを変えないため) |
| 文字列 | 空文字列 "" だけが偽 |
| nil | 偽 |
| テーブル | 常に真 |
比較(== / ~=)
- 型が同じなら値で比較します。型が異なれば数値に変換して比較します(
"3" == 3 は真) - テーブルは同じテーブルかどうかで比較します(内容では比較しません)
nil == nil は真、nil == 0 も真です(未定義の変数は 0 というルールのため)< <= > >= は、両方が文字列なら辞書順、それ以外は数値に変換して比較します
数値への変換
算術演算(+ - * / %)と数値の入力欄では、文字列を数値として解釈します("3" → 3、解釈できなければ 0)。nil とテーブルは 0 です。
4. 変数とスコープ
名前を参照すると、次の順で探します(最初に見つかったものを使います)。
local 変数と関数の引数(現在のブロックと、その外側のブロック。呼び出した関数の中からは見えません)var で宣言した変数(数値のみ)- スクリプト内のグローバル変数(
var なしで代入したもの。任意の値を持てます) - 組み込みの名前(
math dt time screen data。§9) - どれにも該当しなければ 0
「中断データ」は、Player を閉じても続きから再開するために自動で保存されるデータです(セーブデータとは別のものです)。
| 種類 | 作り方 | 持てる値 | 画面に表示 | 中断データ(Player) | セーブ |
|---|
| 宣言した変数 | var n = 0 | 数値のみ(テーブルは拒否) | される | 保存される | save を付ければ端末に保存 |
| グローバル変数 | board = {}(var なし) | 任意 | されない | 保存されない | — |
| ローカル変数 | local x = 1 / 引数 | 任意 | されない | — | — |
| セーブ | save 記録 = { … } | テーブル(JSON にできるもの) | されない | — | 端末に保存(§5.2) |
| アクターの値 | self.hp = 3 | 数値のみ(self.frame は文字列) | されない | 保存される | — |
self
- 実行中のアクターを指します。
spawn の直後・for each の中・on tap クラス の中・クラスのメソッドの中で決まります self.名前 で読み書きします(アクターがいない場合、読むと 0、書くと警告を出します)self に別名を付けることはできません(local me = self とは書けません)
5. 宣言
5.1 var — 宣言した変数
var 名前 [= 初期値] [to 上限] [save] [from 割り当て元]
| 書き方 | 意味 |
|---|
var n | 初期値 0、上限・下限なし |
var n = 3 | 初期値 3(数値リテラルのみ。式は書けません) |
var n = 0 to 8 | 初期値 0 が下限を兼ね、上限は 8。代入した値は必ずこの範囲に収まります |
var n = 0 to 8 save | 値を保存します(何日もかけて増やす値など。この変数をリセットするときは確認が表示されます) |
var h from clock.hour | 1 秒に 1 回、外部から値が割り当てられます(§11) |
- 数値しか持てません。 文字列は数値に変換し、テーブルは拒否します(警告を出します)
- 値が変わると
on change 名前 が発火します(スクリプトで変更した場合も、外部から割り当てられた場合も) - ESKEES の画面で作成した変数(
interact.json の variables)と同じものです。両方にある場合は画面で作成したものが優先されます
5.2 save — セーブデータ
save 記録 = { best = 0, stages = {}, options = { se = 1, bgm = 1 } }
- 初期値(テーブル)がデータ構造の宣言を兼ねます。スクリプトからは通常のテーブルとして読み書きします(
記録.best = score) - フレームの終わりに、変更があれば端末に保存します(まとめて 1 回。変更がなければ保存しません)
- 次回起動時は初期値とマージして復元します。保存されていた値のうち、初期値にあるキーで、同じ型のものだけを復元します。追加された項目は初期値、削除された項目は破棄します。配列(初期値が空のテーブルか、1 から連続するテーブル)は丸ごと復元します
- 保存先: Player・showcase・Screen はブラウザ(端末)です(キーはファイル名。エクスポートし直しても残ります)。テストプレイでは保存されません(「最初から」をまたいでは残ります。「セーブデータを表示」「セーブデータを削除して最初から」があります)
- ESKEES では、ロジックのワークスペースの「セーブデータの構造」で、項目・型(数値 / 文字列 / 配列 / テーブル)・初期値を表形式で編集できます
- JSON にできるもの(数値・文字列・テーブル)だけを保存できます。1 つあたり 100 万文字までです。循環参照のテーブルは保存できません(警告を出します)
5.3 function — 関数
function 名前(引数1, 引数2)
…
return 値
end
| 項目 | ルール |
|---|
| 書ける場所 | スクリプトの最上位のみ |
| 名前 | 組み込み関数(math.floor など)・コマンド名(move size …)と同じ名前は付けられません。同じ名前の関数を 2 つ定義することもできません |
| 引数 | 任意の値を渡せます。足りない引数は nil、余分な引数は無視します |
| 戻り値 | return 値(1 つだけ)。return だけ、または最後まで実行した場合は nil |
| 文として呼ぶ | f(1, 2) — 中で wait できます(呼び出したスクリプトごと待機します) |
| 式から呼ぶ | n = f(1) + 1 — その場で最後まで実行します。中で wait に到達したら処理を打ち切り、nil を返します(警告を出します) |
| 呼び出しの深さ | 200 段まで(無限再帰になると停止して警告を出します) |
break | 関数の外側のループは抜けません |
5.4 class — アクターのクラス
class 鳥
vy = 0 -- 初期値(生成したときに self.vy に設定される)
function init() -- 生成した直後に 1 回
end
function update(dt) -- 毎フレーム、アクターごとに
end
function tap() -- そのアクターがクリックされたとき
end
function flap() -- 独自に名前を付けたメソッド
self.vy = -300
end
end
| 項目 | ルール |
|---|
| クラス名 | パーツ名(spawn 鳥 の 鳥)か、コンポーネント名(§5.5) |
| 中に書けるもの | 名前 = 式(初期値)と function(メソッド)だけ。文は書けません |
| 初期値 | 生成したときに式を評価して設定します。数値のみ(それ以外は 0 にして警告を出します) |
| 予約されたメソッド | init()(生成直後)/ update(dt)(毎フレーム)/ tap()(クリックされたとき)。実行環境が自動で呼び出します |
| その他のメソッド | self:名前(引数)、またはアクターを持つ変数から enemy:hit(1) |
メソッド内の wait | 使えません(毎フレーム呼ばれるため、待機すると次のフレームと重なります。警告を出して打ち切ります) |
| Lua の書き方 | function 鳥:flap() … end とも書けます。解析すると class 鳥 の中に入り、シリアライズすると class の形になります |
5.5 コンポーネントのロジック
ESKEES のコンポーネント(複数のアセットのレイヤーとテキストを組み合わせたもの)と同じ名前の class を書くと、キャンバスに配置したそのコンポーネントのインスタンスがすべて、再生開始時にアクターになります(ライブラリのコンポーネントの「…」→「ロジックを作成」)。
- 最初のフレームで
on start より前に、配置したパーツを非表示にして同じ位置にクラスのアクターを生成し、初期値と init() を適用します - アクターはクラス(コンポーネント名)と画像(そのインスタンスのパーツ)を別に持ちます。
spawn クラス は最初のインスタンスの画像で生成します - エクスポート時は
game.json の adopt に保存します。スクリプトからクラスを削除すると、配置したものは静止した画像に戻ります
6. トリガー
on トリガー [対象]
文…
end
| 書き方 | 発火するタイミング | self | 発火する環境 |
|---|
on start | 開いたときに 1 回(中断データから再開したときは発火しない) | — | すべて |
on frame | 毎フレーム。1 フレームの秒数は dt | — | すべて |
on every 秒 | その間隔ごと(数値リテラルのみ)。画面が隠れていた間の分は取り戻さない | — | すべて |
on change 変数 | 宣言した変数が変わったとき | — | すべて |
on scene シーン | そのシーンに入ったとき(§12) | — | すべて |
on press 領域 | 押した瞬間。any なら画面のどこを押しても(何もない場所でも) | — | すべて |
on click 領域 | クリック(press と同じ 1 回の操作で続けて発火) | — | すべて |
on down 領域 | 押し下げ | — | すべて |
on up 領域 | 離した(押した領域に対して発火) | — | すべて |
on drag 領域A to 領域B | A をドラッグして B の上で離した | — | すべて |
on enter 領域 / on leave 領域 | カーソルが乗った / 外れた(押していないとき) | — | Player・showcase(Screen は発火しない) |
on tap クラス | アクターをクリックした | クリックされたアクター | すべて |
on key キー | キーを押した瞬間(押し続けても繰り返さない)。any ならどのキーでも | — | Player・showcase(Screen は発火しない) |
on keyup キー | キーを離した | — | 同上 |
- 「領域」は
interact.json の shapes(ESKEES の「クリック領域」)の ID、旧形式の hit.json の領域の ID、UI のボタンの ID です on press / click / down / up / key / keyup の対象に any を使えます- 同じトリガーのスクリプトが実行中の場合、新しく発火しても破棄します(§12)
7. 文
7.1 制御
| 書き方 | 意味 | 待機 |
|---|
if 式 then … elseif 式 then … else … end | 条件分岐 | — |
switch 式 / case 値, 値 then … / else … / end | 値による分岐(== と同じ比較)。case が 1 つもなければ構文エラー | — |
loop … end | 無限ループ。中に wait がないと、1 フレームあたり 10,000 文で打ち切られます | — |
while 式 [do] … end | 式が真の間 | — |
repeat 回数 … end | 指定回数(回数は式) | — |
repeat … until 式 | 式が真になるまで(後判定。repeat の直後が改行ならこちら) | — |
for i = 開始, 終了[, ステップ] [do] … end | 数値の範囲でループ。i はループ内だけの変数 | — |
for k, v in pairs(テーブル) [do] … end | テーブルの要素を 1 つずつ(配列部分が先、その他は追加した順。ループ開始時点のコピー) | — |
for i, v in ipairs(テーブル) [do] … end | 配列(1 から、要素が途切れるところまで) | — |
for each in クラス … end | そのクラスのアクターを 1 体ずつ(self)。ループ開始時点のアクターが対象。ループを抜けると元の self に戻る | — |
break | 最も内側のループを抜ける(関数の外には出ない) | — |
return [式] | 関数から戻る。トリガーの中なら、そこで終了する | — |
wait 秒 | 指定秒数後に続きから再開する(式。0 以下なら待たない) | 待機 |
wait click 名前 | それがクリックされるまで停止する。名前はクリック領域・アクターのクラス・UI のボタン。any なら何をクリックしても | 待機 |
7.2 代入
| 書き方 | 意味 |
|---|
名前 = 式 / += / -= | 変数への代入(local → var → グローバルの順に探して代入)。+= は数値の加算 |
local a = 式 / local a, b = 1, 2 | ローカル変数を作成(値を書かなければ nil) |
t[キー] = 式 / t.名前 = 式 / += / -= | テーブルへの代入(nil を代入すると削除)。テーブル以外には代入できません(警告を出します) |
self.名前 = 式 / += / -= | 実行中のアクターの値(数値) |
self.frame = "赤" | 表示するフレーム(switch パーツ)。nil か "" で既定のフレーム |
a, b = b, a のような多重代入はありません(local だけで使えます)。
7.3 パーツ(アセットのパーツ)
| 書き方 | 意味 |
|---|
frame パーツ = フレーム | フレームを切り替える(switch パーツ) |
cycle パーツ | フレームを 1 つ進める(最後の次は先頭) |
show パーツ / hide パーツ | 表示 / 非表示(何回実行しても同じ) |
toggle パーツ | 表示を反転する(2 回実行すると元に戻る) |
preset プリセット | プリセットを適用する。ステートは 軸:ステート の名前で指定 |
move パーツ to x, y / move パーツ by dx, dy | 位置をずらす(アセットの位置からのオフセット。数値リテラルのみ) |
turn パーツ 角度 | 回転(度。数値のみ) |
size パーツ 倍率 | スケール(1 が等倍。数値のみ) |
place パーツ | move / turn / size をリセットする |
poke メッシュのキー | メッシュを揺らす(存在しなければ何もしない) |
7.4 アニメーション(タイムライン)
| 書き方 | 意味 | 待機 |
|---|
play アニメーション | 1 回再生する | 終了まで待つ |
play アニメーション times 式 | 指定回数再生する | 終了まで待つ |
play アニメーション nowait / play アニメーション times 3 nowait | 再生して次へ進む | 待たない |
play アニメーション forever | ループ再生する | 待たない |
play アニメーション on self | 実行中のアクターに適用する(そのクラスのパーツを対象とするアニメーションを、アクターの位置を原点に 1 回再生。終了すると元の見た目に戻る) | 長さの分だけ待つ(nowait で待たない・forever でループ) |
stop アニメーション | 停止して先頭に戻す | — |
「アニメーション」は actions[] の ID、なければ sprites[] の ID です。既定のクリップは名前で指定できません(自動で再生されているため)。
7.5 サウンド
| 書き方 | 意味 | 待機 |
|---|
sound 名前 | 効果音を再生する(重ねて再生できる) | — |
sound 名前 volume 0.5 | 音量を掛ける(0..1。数値のみ) | — |
sound 名前 wait | 再生が終わるまで待つ | 待機 |
music 名前 | BGM を切り替える(前の曲は 0.5 秒でフェードアウト。同じ曲なら何もしない) | — |
music stop | BGM を停止する | — |
- 名前は ESKEES のライブラリの「サウンド」の名前です(
game.json の sounds) - 最初のクリック・キー入力までは再生されません(ブラウザの自動再生の制限)。それより前の
music は記録しておき、そのときに再生します。効果音は破棄します - 一時停止中は停止します。Screen(壁紙)では、トレイの「音を鳴らす」がオンのときだけ再生します
7.6 画面のテキスト(UI)
| 書き方 | 意味 |
|---|
ui パネル show / ui パネル hide | ESKEES の「UI」で作成したパネルを表示 / 非表示にする |
say テキスト要素 = テキスト | テキストを書き換える。{変数名} や {clock.time} は描画時に値に置き換わる(§11) |
7.7 アクター
| 書き方 | 意味 |
|---|
spawn クラス at x, y | アクターを 1 体生成する(x, y は式。アセットの位置からのオフセット)。生成したアクターが self になる。クラスがあれば初期値と init() を適用 |
destroy self | 実行中のアクターを削除する |
destroy クラス | そのクラスのアクターをすべて削除する |
tween self to { 値 = 目標値, … } in 秒 | 値を時間をかけて変化させる(下の表) |
self:moveBy(dx, dy) | ステージの衝突判定のあるタイルで止まりながら移動する(§7.10)。戻り値は { x = 1 / 0, y = 1 / 0 }(どちらの軸で衝突したか)。どのクラスでも呼べます(クラスに同じ名前のメソッドがあればそちらが優先) |
self:overlapping("クラス") | 当たり判定の形が重なっている、そのクラスのアクターを 1 体返す(無ければ nil)。local e = self:overlapping("敵") → if e then e:hit(3) end のように、当たった相手を指せる(touching は 1 / 0 だけ) |
self:overlaps(相手) | その相手(アクターを持つ変数)と当たり判定の形が重なっているか(1 / 0) |
tween のオプション(この順で指定できます):
| オプション | 意味 |
|---|
ease "back-out" | イージング(§9.4 の 34 種。省略すると linear。不明な名前は linear で実行して警告を出す) |
wait | 終了まで待つ |
then destroy | 終了後に削除する |
- 目標値はテーブル(名前 = 数値)で指定します。現在の値から目標値まで変化させます。同じアクターの同じ値に新しい
tween が来たら、前の補間は破棄します - 補間は毎フレーム、スクリプトより先に進みます。中断データには含まれません
アクターの描画に使う値: x y(オフセット)・turn(度)・size(倍率)・alpha(透明度 0..1)・frame(フレーム)。それ以外の名前は自由に使えます(hp など)。
キャラクターの設定(ESKEES でパーツを選んだときの「キャラクター」。game.json の actors):
- 当たり判定の形(画像の矩形・それより小さい矩形・円)は、
touching・self:overlapping・self:overlaps・self:moveBy のすべてで使います - 操作(8 方向・左右だけ・左右とジャンプ)を設定したクラスは、矢印・WASD・ゲームパッドで動きます(毎フレーム、
update の前)。値はアクターの変数にも入るので、スクリプトから変えられます: self.speed(速さ)・self.jump / self.gravity(左右とジャンプのとき)・self.control = 0 で止める。動いた結果は self.vy・self.grounded(着地していれば 1)・self.moving・self.dir(-1 / 1)で読めます。クラスの変数に同じ名前があれば、そちらが優先されます
7.8 シーン
| 書き方 | 意味 |
|---|
scene シーン | シーンを切り替える。所属していないパーツと UI を非表示にし、そのシーンのものを表示し、開始時のプリセットを適用する。シーンの一覧は interact.json の scenes[] にだけ書ける |
7.9 カメラ
キャンバスは画面(表示範囲)です。ワールド(world.w / world.h)をキャンバスより広くすると、カメラを動かしてワールドの一部を表示できます(横スクロールなど)。ワールドのサイズとカメラの初期位置は、ESKEES の「カメラとワールド」で設定します(.eskx の game.json)。スクリプトからも変更できます。
| 書き方 | 意味 |
|---|
camera.x = 100 / camera.y = 0 | 表示範囲の左上(ワールド座標の px) |
camera.zoom = 2 | 倍率(1 が等倍。0.05〜20) |
camera.lag = 0.2 | 追従の遅れ(秒。0 で遅れなし) |
camera follow self | 実行中のアクターが毎フレーム画面の中央に来るように追従する(画像の中心を追う) |
camera follow off | 追従をやめる(その場で止まる) |
camera shake 0.3 / camera shake 0.3 power 12 | 画面を揺らす(秒・揺れ幅は画面上の px。既定は 8)。終わりに向かって弱まる |
world.w = 3000 / world.h = 600 | ワールドのサイズ(既定はキャンバスと同じ) |
on start
world.w = 3000
spawn 鳥 at 100, 200
camera.lag = 0.15
camera follow self
end
on key Space
camera shake 0.2
end
- ワールドの端で止まります。 表示範囲がワールドの外に出ないように、描画時に位置を補正します(代入した
camera.x はそのまま残ります)。表示範囲がワールドより大きい場合(ズームアウト)は中央に配置します - ワールドのサイズがキャンバスと同じなら、カメラは動けません(既定)。スクリプトだけで使う場合は、先に
world.w = … を設定してください - 揺れは
camera.x / camera.y を変更しません(読み取った値が揺れないように)。時刻だけで決まるため、同じ時刻なら同じ揺れになります - UI(画面に重ねるテキスト)はカメラの影響を受けず、画面に固定されます。クリック判定は、UI は画面座標、画像とアクターはワールド座標に変換してから行います
- パーツも画面に固定できます(ESKEES の「カメラとワールド」の「画面に固定するパーツ」。背景・スコア表示など)。カメラを適用せずに描画し、クリック判定も画面座標で行います
- 追従中のアクターが削除されたら、追従をやめます
- カメラ(位置・倍率・遅れ・追従対象)は中断データに含まれます
- EMG に対応した他のソフトは、カメラに対応していません。 キャンバスの範囲(カメラが (0, 0)・等倍のときの表示)がそのまま表示されます
7.10 ステージ
ステージはタイルのレイヤー(グリッド)とオブジェクトで構成されます(.eskx の game.json の stages)。ESKEES のライブラリの「+ ステージ」で作成します。タイル 1 つのサイズ(px)とタイル数を持ち、ワールドのサイズはその積になります。
| 書き方 | 意味 |
|---|
stage "1-1" | ステージを配置する。前のステージのオブジェクトは削除され、ワールドのサイズがステージのサイズになり、カメラの初期位置があれば適用する。タイルは定義の状態に戻る |
tile.at(x, y) / tile.at(x, y, "レイヤー") | その位置(ワールド座標の px)のタイルの値。レイヤーを省略すると、0 以外の値が見つかった最初のレイヤー。範囲外は 0 |
tile.solid(x, y) | その位置に衝突判定があるか(1 / 0)。衝突判定があるのは「衝突判定」を設定したレイヤーの 0 以外のタイル。ワールドの外は衝突しない |
tile.set(x, y, 値) / tile.set(x, y, 値, "レイヤー") | タイルを書き換える(成功したら 1)。レイヤーを省略すると最初のレイヤー。ステージを配置し直すと定義の状態に戻る |
self:moveBy(dx, dy) | 衝突判定のあるタイルで止まりながら移動する(横 → 縦の順。半タイルずつ判定するため、速く動いてもすり抜けない) |
class 鳥
vy = 0
function update(dt)
self.vy += 900 * dt
local hit = self:moveBy(120 * dt, self.vy * dt)
if hit.y == 1 then
self.vy = 0
end
end
end
on start
stage "1-1"
spawn 鳥 at 100, 0
camera follow self
end
- タイルはアクターではありません(数が多く、毎フレームスクリプトで処理すると重いため)。描画するのは表示範囲のタイルだけです
- タイルの値から画像への対応は、レイヤーのパレット(ライブラリの「データ」の名前)の「パーツ」で決まります。画像はタイルのサイズに引き伸ばして描画します。パレットのないレイヤーは描画しません(衝突判定のみ)
- タイルに使っているパーツは、ステージを配置すると非表示になります(アセットの位置に元の画像が表示されたままにならないように)
- 描画順は、アセットの画像 → タイル(レイヤーの順) → アクターです
- オブジェクトはクラスのアクターとして生成します(位置は画像の中心)。クラスの初期値 → オブジェクトごとの値 →
init() の順に適用します - 当たり判定の形はタイルの矩形だけです(斜面・半分の高さは未対応)
- 現在のステージ・書き換えたタイル・オブジェクトは、中断データに含まれます
7.11 スコア(ランキング)
score total as タイム lower -- 合計タイムを「タイム」のボードへ。小さいほど上位
score score as 点 -- 点を「点」のボードへ。大きいほど上位
score score -- as を省略すると「score」のボード
- スクリプトは値を出力するだけです。 送信するかどうか・送信先は、実行環境が決めます
- showcase … ランキングに送信する(ログインしていれば会員、していなければゲスト)
- Player(スタンドアロン)… 送信する前に確認する(名前・「次回から確認せずに送信」)。常にゲストとして掲載される
- ESKEES のテストプレイ … ログに表示するだけ(送信しない)
- 出力するのはリザルト画面で 1 回にしてください(ステージごと・毎フレームには出力しない)。サーバーには自己ベストしか残らないため、何度出力してもボードは壊れませんが、そのたびに通信が発生します
lower(小さいほど上位)は最初に送信されたときにボードごとに決まり、以後は変更できませんscore = 0 / score += 10 は代入です(直後が = += -= なら変数として解析します)。スコアを変数 score に持つスクリプトもそのまま動作します- 数値でない値・無限大は出力しません
- ランキングの API と、会員とゲストの区別は ESKEES Studio のページ を参照してください
7.12 呼び出し
| 書き方 | 意味 |
|---|
f(1, 2) | スクリプトの関数か組み込み関数を呼ぶ(戻り値は破棄。スクリプトの関数なら中で待機できる) |
self:flap() | 実行中のアクターのクラスのメソッド(その場で実行。中で待機できない) |
enemy:hit(1) | アクターを持つ変数から、そのクラスのメソッドを呼ぶ |
7.13 その他
| 書き方 | 意味 |
|---|
reset リセットの ID | 変数を初期値に戻す(リセットの定義は interact.json の resets[] にだけ書ける) |
8. 式
8.1 書き方
| 書き方 | 意味 |
|---|
3 "夜" true false nil | リテラル |
名前 | 変数(§4 の順で探す) |
{1, 2, x = 3, ["名前"] = 4} | テーブル。区切りは , か ;。改行してもよい |
t[式] t.名前 t[1].x | テーブルのフィールド(存在しなければ nil) |
#t #"文字" | 配列の長さ(1 から連続する部分)/ 文字数 |
f(…) self:m(…) | 呼び出しの戻り値 |
self.名前 | 実行中のアクターの値(アクターがいなければ 0。self.frame はフレーム名か nil) |
count クラス | そのクラスのアクターの数 |
touching クラス | self がそのクラスのいずれかと重なっているか(1 / 0。矩形どうしで判定) |
in scene シーン | 現在そのシーンなら 1 |
( 式 ) | 括弧 |
8.2 演算子と優先順位
優先順位(大きいほど先に結合)。同じ優先順位は左から結合します。
| 優先順位 | 演算子 | 意味 |
|---|
| 1 | or | どちらかが真。左が真なら右を評価しない。結果は 1 / 0 |
| 2 | and | 両方が真。左が偽なら右を評価しない。結果は 1 / 0 |
| 3 | == != ~= < <= > >= | 比較(§3)。~= は != と同じ。結果は 1 / 0 |
| 4 | .. | 文字列の連結(整数は小数点なし) |
| 5 | + - | 加算・減算 |
| 6 | * / % | 乗算・除算・剰余。0 で割ると 0(NaN を作らない) |
| 単項 | not - # | 否定・符号反転・長さ |
9. 組み込み
9.1 名前
| 名前 | 値 |
|---|
dt | 前のフレームからの秒数(最初のフレームは 0。上限は 0.25) |
time | 再生の経過秒数(壁紙が隠れている間・一時停止中は進まない) |
screen.w / screen.h | キャンバスのサイズ(ウィンドウのサイズではない) |
camera.x / camera.y / camera.zoom / camera.lag | カメラ(§7.9。書き込み可) |
world.w / world.h | ワールドのサイズ(§7.9。書き込み可。既定はキャンバスと同じ) |
data | GUI で作成したデータ(§9.5。読み取り専用) |
math.pi / math.huge | 円周率 / 非常に大きな数 |
9.2 関数
| 関数 | 戻り値 | 備考 |
|---|
math.random() | 0 以上 1 未満 | |
math.random(n) | 1〜n の整数 | Lua と同じ |
math.random(m, n) | m〜n の整数 | n < m なら m |
math.floor(x) / math.ceil(x) | 切り捨て / 切り上げ | |
math.abs(x) / math.sqrt(x) | 絶対値 / 平方根 | 負の数の平方根は 0 |
math.sin(x) / math.cos(x) | 三角関数(ラジアン) | |
math.atan(y[, x]) | 逆正接 | 2 つ渡すと atan2 |
math.min(…) / math.max(…) | 最小値 / 最大値 | 引数がなければ 0 |
math.clamp(x, lo, hi) | x を lo..hi の範囲に収める | ESKEES 独自 |
table.insert(t, v) / table.insert(t, 位置, v) | なし | 後ろの要素をずらす |
table.remove(t[, 位置]) | 取り出した値 | 省略すると最後の要素。後ろの要素を詰める |
table.concat(t[, 区切り]) | 文字列 | 配列を文字列にして連結する |
string.len(s) | 文字数 | |
string.sub(s, i[, j]) | 部分文字列 | 1 から数え、負の値は末尾から(Lua と同じ) |
string.upper(s) / string.lower(s) | 大文字 / 小文字 | |
string.rep(s, n) | n 回連結した文字列 | 1 万回まで |
tostring(v) | 文字列 | テーブルは "table"、nil は "nil" |
tonumber(v) | 数値か nil | 解釈できなければ nil |
print(…) | なし | ログに出力する(タブ区切り) |
key(名前) | 1 / 0 | 押している間は 1。key("any") はいずれかのキーを押していれば 1(§10) |
grid.cells(g) | 配列 | 空でないセル。各要素は {x, y, v}(位置は 0 から。c[1] c[2] でも読める) |
grid.rotate(g) | 新しいテーブル | 右に 90° 回転(n×m → m×n)。元は変更しない |
grid.copy(g) | 新しいテーブル | 書き換え可能なコピー |
grid.width(g) / grid.height(g) | 数値 | |
tile.at(x, y[, レイヤー]) | 数値 | ステージのタイルの値(§7.10) |
tile.solid(x, y) | 1 / 0 | 衝突判定のあるタイルか |
tile.set(x, y, 値[, レイヤー]) | 1 / 0 | タイルを書き換える |
9.3 使えないもの
string.format string.find string.gsub os.* io.* require setmetatable pcall などの Lua の標準ライブラリはありません。存在しない関数を呼ぶと「関数 f がありません」という警告を出し、nil を返します。
9.4 イージングの名前(tween … ease)
ESKEES のタイムラインのイージングと同じ 34 種です。
| グループ | 名前 |
|---|
| 基本 | linear ease-in ease-out ease-in-out |
| easings.net | sine-* quad-* cubic-* quart-* quint-* expo-* circ-* back-* elastic-* bounce-*(* は in / out / in-out) |
9.5 データ(data)
ESKEES のライブラリの「+ データ」で作成したグリッドです。読み取り専用です(書き込むと警告を出し、値は変わりません。書き換えたい場合は grid.copy を使います)。
| 参照方法 | 値 |
|---|
data.名前.グリッド名 | 2 次元のテーブル(g[y][x]、添字は 1 から)。値はパレットの番号(0 は空) |
data.名前.width / data.名前.height | グリッドのサイズ |
data.名前.palette[i] | { value, name, part }(part は描画するパーツ。なければ存在しない) |
data.名前 と data.名前.グリッド名 の名前の誤りは、ワークスペースが書いた時点で警告します。
10. キーとゲームパッドの名前
on key / on keyup / key() / wait click で使う名前です。
| 種類 | 名前 |
|---|
キーの位置(KeyboardEvent.code) | Space Enter Escape ArrowUp ArrowDown ArrowLeft ArrowRight KeyA … Digit1 … |
| 英数字 1 文字 | A … Z 0 … 9(入力欄で入力中の文字では発火しない) |
| テンキー | Numpad0 … Numpad9 NumpadEnter など(数字は 8 としても発火する) |
| スワイプ(タッチ・マウスのドラッグ) | SwipeUp SwipeDown SwipeLeft SwipeRight(0.6 秒以内に 30px 以上、ほぼまっすぐ動かして離したとき。押した瞬間と離した瞬間を続けて発火するので、key() が 1 になることはない) |
| ゲームパッド(標準配置)と仮想パッド | PadUp PadDown PadLeft PadRight(十字キーと左スティック)・PadA PadB PadX PadY・PadL PadR PadLT PadRT・PadSelect PadStart |
| いずれか | any |
- スクリプトからは、コントローラーの入力か画面上のボタンの入力かを区別しません
- 仮想パッドはタッチ画面で、スクリプトが
PadUp 〜 PadY を使っているときだけ表示されます(十字キーは 1 つでも使えば 4 方向すべて)。スクリプトがスワイプ(SwipeUp など)を使っている場合、十字キーは表示しません(ゲームパッドの十字キーはそのまま使えます) - スワイプを使っても、押した瞬間の
on press などは今までどおり発火します(スワイプかどうかは離すまで分からないため) - ウィンドウからフォーカスが外れたら、押し続けているキーはすべて離したものとして扱います
11. 値の割り当て元とテキストへの埋め込み
var … from で割り当てられるもの(1 秒に 1 回。端末のローカル時刻)
| 名前 | 値 |
|---|
clock.hour / clock.minute / clock.second | 時(0〜23)/ 分(0〜59)/ 秒(0〜59) |
clock.minuteOfDay | 0 時からの経過分(0〜1439)。「22:30 を過ぎたら」を 1 回の比較で書くため |
clock.weekday | 曜日(0 = 日曜) |
clock.day / clock.month / clock.year | 日・月・年 |
say と UI のテキストに埋め込めるもの({…}。描画時に置き換わる)
| 書き方 | 例 |
|---|
{変数名} | {score} → 120 |
{clock.date} / {clock.shortDate} | 2026/09/25 / 9/25 |
{clock.time} / {clock.longTime} | 19:05 / 19:05:32 |
{clock.weekdayName} / {clock.ampm} | 木 / 午後 |
不明な名前は置き換えません。
12. 実行のルールと上限
1 フレームの処理順
- (最初のフレームのみ)セーブデータを読み込む → ロジックを持つコンポーネントをアクターに変換する →
on start → 開始シーンの on scene dt を決める → 補間(tween)を進めるon frame → クラスの update(dt)(アクターごと) → on every- 待機中のスクリプトの再開(
wait の時刻が来たもの・アニメーションが終了したもの) - 変化した変数の
on change(値が落ち着くまで。最大 8 回) - カメラの追従(
camera follow self)を 1 回進める - 変更されたセーブデータを保存する
クリック・キー入力などのトリガーは、発生した時点で実行します(最後に 5・7 も行います)。
ルール
| ルール | 理由 |
|---|
実行中の同じトリガーは破棄する(on frame も) | 連打しても、一連の演出を最後まで表示するため。on frame の中で待機すると、その間の実行は間引かれる |
wait click で停止しているスクリプトは、クリックされたらそれを先に再開し、そのイベントはそこで消費する | 同じものを待ちながら同じもので起動するスクリプトが、二重に実行されないように |
再開させるのは press / tap だけ | 1 回の操作で press → click → down と続けて発生するため、どれでも再開させると 2 つ進んでしまう |
クラスの update(dt) はループ開始時点のアクターに対して実行する | 途中で生成したアクターは次のフレームから |
on change は、実行中のスクリプトが停止してから発火する | 書き換え途中の値を、別のスクリプトが参照しないように |
play … の「終了まで待つ」は、実行直後の 1 フレームは判定しない | 再生側がまだアニメーションを開始していないため |
シーンを出ると、on scene から実行されていたスクリプトは停止する(wait の途中も破棄する)。他のトリガーのスクリプトは停止しない | 前のシーンの会話が、次のシーンで進み続けないように |
on scene A の中で scene B を書くと、その後の文は実行されない | A のスクリプトとして停止するため |
同じシーンへの scene は何もしない。存在しないシーンへは切り替えず、1 回だけ警告する | シーンに入り直すことではないため。名前の誤りに気づけるようにするため |
| どのシーンにも属さないパーツと UI(共通)は、シーンの切り替えで変更しない | 背景などを、シーンごとに設定しなくて済むように |
中断データから再開したときは、on start も on scene も発火しない | 再開は、シーンに入り直すことではないため |
スクリプトの途中の状態(wait の続き)・グローバル変数・補間は、中断データに保存されない | Player で閉じて再開すると、宣言した変数とアクターは復元されるが、待機中だったスクリプトの続きは実行されない |
上限
| 項目 | 上限 | 超えた場合 |
|---|
| 1 つのスクリプトが 1 フレームに実行できる文 | 10,000(式から呼んだ関数も同じ上限に含む) | 停止して警告する(wait のない loop など) |
| 同時に実行中のスクリプト | 64 件 | 新しいものを破棄して警告する |
on change の連鎖 | 1 フレームに 8 回 | 打ち切って警告する |
| 関数の呼び出しの深さ | 200 段 | 停止して警告する |
| アクター | 512 体 | 生成せずに警告する(spawn の後の self は変わらない) |
dt | 0.25 秒 | 0.25 秒を超えない |
| セーブ 1 つ | JSON で 100 万文字 | 保存せずに警告する |
string.rep | 1 万回 | 1 万回で止める |
13. 実行時のメッセージと構文エラー
構文エラー(読み込み時に停止し、行と桁を表示する)
エラーは N 行 M 列: 内容 の形式です。ESKEES のワークスペースでは、その行に赤い印が表示され、修正するまでプロジェクトのスクリプトは変更されません。
| メッセージ | よくある原因 |
|---|
var か save か on か function か class が必要です | 文を on … end の外に書いた |
press / click / … のいずれかが必要です | トリガー名の誤り(on hover などは存在しない) |
end が不足しています | if / loop / on / function の閉じ忘れ |
= が必要です | frame パーツ フレーム と書いた(= が必要) |
X 座標に数値が必要です | move に変数や式を書いた(数値リテラルのみ) |
〜 に対する操作が不明です | コマンド名の誤りが代入として解析された |
文字列が閉じていません | " の閉じ忘れ、または文字列内の改行 |
〜 はコマンド名のため、関数名には使えません | 関数に move size play などのコマンド名を付けた |
〜 は組み込み関数の名前のため使えません | 関数に math.floor などの名前を付けた |
class の中には初期値と function だけを書けます | class の中に文を書いた(処理は function update(dt) の中に書く) |
セーブの初期値はテーブルで書きます | save 記録 = 0 と書いた |
tween の対象は self です / 目標値はテーブルで書きます | tween の書き方の誤り |
pairs か ipairs が必要です | for k in t と書いた(for k in pairs(t)。アクターなら for each in クラス) |
書いた時点で検出できる警告(ESKEES のワークスペースの「問題」)
実行せずに、名前の一覧と照合して検出します: パーツ・フレーム・クリック領域・アニメーション・プリセット・シーン・UI パネルとテキスト要素・サウンド・データとグリッド・関数・メソッド・イージング。
実行時のメッセージ(ESKEES の「ログ」に表示。同じメッセージは 1 回だけ表示)
| メッセージ | 意味 |
|---|
関数 f がありません | 名前の誤り。戻り値は nil |
関数 f は式の中から呼ばれたため wait できません | 待機する関数は文として呼び出す |
関数の呼び出しが 200 段を超えたため停止しました | 無限再帰になっている |
… 1 フレームで 10000 文を超えたため停止しました | wait のないループ |
同時に実行中のロジックが 64 件を超えたため… | トリガーが溜まっている |
変数の変更が 8 回を超えたため、処理を打ち切りました | 互いに値を書き換え合う on change |
n は var で宣言した変数のため、数値しか代入できません | var にテーブルを代入した |
data は読み取り専用です | data に書き込んだ(grid.copy でコピーする) |
テーブルではない値に代入しようとしました | t[1] = … の t がテーブルでない |
pairs にテーブル以外の値を渡しました | for k, v in pairs(x) の x がテーブルでない |
〜 は、このホストでは動作しません(ステージに対応していません) | アクターの文を、ステージを持たない環境で実行した |
イージング「…」がありません | ease の名前の誤り(linear で実行する) |
サウンド: サウンド「…」がありません / …を読み込めません | サウンドの名前の誤り・再生できない形式(mp3 を推奨) |
クラス T に m() がありません / … はアクターではないため m() を呼び出せません | メソッドの名前の誤り・呼び出し先の誤り |
T の key には数値しか設定できません | クラスの初期値に数値以外を書いた |
セーブ … が大きすぎます / …保存できない値が含まれています | セーブの上限・循環参照のテーブル |
14. 実行環境ごとの違い
| 機能 | Player | showcase | Screen(壁紙) | ESKEES のテストプレイ |
|---|
クリック・ドラッグ・on tap | ○ | ○ | ○ | ○ |
on enter / on leave | ○ | ○ | ×(押している間しか位置を取得できない) | ○ |
キー・key()・on keyup | ○ | ○ | ×(壁紙はフォーカスを持たない。システム全体のキー入力は読まない) | ○ |
| ゲームパッド | ○ | ○ | × | ○ |
| 仮想パッド | タッチ画面で | タッチ画面で | × | タッチ画面で |
スワイプ(SwipeUp など) | ○ | ○ | × | ○ |
| サウンド | ○ | ○ | トレイの「音を鳴らす」がオンのときだけ(既定はオフ) | ○ |
| カメラ | ○ | ○ | ○ | ○ |
| ステージ | ○ | ○ | ○ | ○ |
| セーブ | ブラウザ(端末) | ブラウザ(端末) | 端末 | 保存しない |
| 中断データ(閉じても続きから再開) | ○ | × | × | × |
| 再生したサウンドをログに表示 | — | — | — | ○ |
15. Lua との違い
| 項目 | Lua | この言語 |
|---|
| 真偽値 | nil と false だけが偽 | 0 と空文字列も偽(true / false は 1 / 0) |
| 等価 | nil == 0 は偽 | 真(未定義の変数は 0) |
| 非等価 | ~= | ~= と != の両方 |
| 代入 | a, b = b, a | 多重代入は local だけ。+= -= がある |
| 関数 | どこにでも書ける・無名関数・クロージャ・可変長引数 | 最上位だけ・名前付き・クロージャなし・可変長引数なし・戻り値は 1 つ |
| オブジェクト | メタテーブル | class(アクターのクラス)だけ |
| ループ | repeat … until | repeat … until と repeat 回数 … end、loop、for each in クラス |
| 文字列 | s:upper()・string.format など | string.len sub upper lower rep だけ。.. はある |
| 標準ライブラリ | os io require など | ない(§9.3) |
| 待機 | コルーチン | wait が文(スクリプトごと停止する。関数を文として呼べば、その中でも待機できる) |
| 長い文字列・複数行コメント | [[ ]] --[[ ]] | ない |
16. コード例
撫でると変わる
var nade = 0 to 8 save
on press head
nade += 1
play "wave"
wait 0.5
if nade >= 8 then
frame face = "照れ"
elseif nade >= 4 then
cycle toach
else
toggle EF
end
end
時刻で着替える
var hour from clock.hour
on change hour
switch hour
case 22, 23 then frame face = "夜"
case 6 then frame face = "朝"
else frame face = "通常"
end
end
紙芝居
on click 開始
ui 会話 show
say 本文 = "むかしむかし"
wait click any
say 本文 = "{clock.time} になりました"
wait click any
ui 会話 hide
end
降ってくる星をクリックする
var score = 0
on start
loop
spawn 星 at 100, 0
self.vy = 3
wait 1
end
end
on every 0.05
for each in 星
self.y += self.vy
if self.y > 1080 then
destroy self
end
end
end
on tap 星
score += 1
destroy self
end
テトリス
- ブロックの形は「データ」のグリッドです(
grid.cells(data.ミノ[name]))。盤面は 2 次元のテーブル(board[y][x])で、ブロックは色ごとのパーツをアクターとして生成し直して描画します(移動したときだけ) - 揃った行は「光」のアクターを
tween … then destroy で縮めながら透明にし、sound 消える を再生し、wait 0.3 の間は落下と操作を止めてから消します - 3 ステージで、消す行数の目標(5 / 10 / 15)と落下速度が上がります。目標の行数を消すまでのタイムを計測し、3 ステージを終えるとリザルト(ステージごと・合計・ベスト)を表示します
シーンはタイトル → ゲーム → リザルトです(2026-09-26)。タイトルとリザルトの背景は画像要素(パーツ「タイトルの地」「リザルトの地」)で、ESKEES で選択して「画像を差し替え」を使うだけで別の画像にできます。途中で表示するパネル(ミス・クリア・新記録)はどのシーンにも追加せず、ui で表示を切り替えます。ESKEES Studio では、showcase の公式サンプルの「これを改造してみる」から開けます(サンプルを改造する)。
パタパタ(ステージ版)
- 土管と地面はステージ「コース1」〜「コース3」のタイル(衝突判定のあるレイヤー)です。鳥は
self:moveBy で進み、衝突した軸が返ったらミス(そのステージをやり直し)になります - ステージが進むごとに、コースが長く・隙間が狭く・速くなります。ゴールまでのタイムを計測し、3 ステージを終えるとリザルト(ステージごと・合計・ベスト・新記録)を表示します
- カメラが鳥を追従し(
camera follow self)、衝突すると camera shake します。合計のベストはセーブデータ(save 記録 = { bestTotal = 0 })に残ります - 空は画面に固定したパーツ(カメラが動いても流れない)で、雲はタイルで描画して流します
シーンはタイトル → ゲーム → リザルトです(テトリスと同じ構成)。タイトルの背景は地面だけのステージ「タイトル」です(ステージのタイルはパーツより手前に描画されるため、雲や土管がタイトルのパネルに重ならないようにしています)。ESKEES Studio では、showcase の公式サンプルの「これを改造してみる」から開けます(サンプルを改造する)。
数値を長さで表示したい場合はゲージを使います(UI の矩形か画像要素に「変数で長さを変える」を設定。HP バーなど)。テキストの {hp} と違い、画像に置き換えても値に追従します(画像はパーツのマスクとして、変数に合わせて伸縮します)。
GUI で編集できる形にしてください: 画面に表示するもの(タイトル・ボタン・スコア・結果)は UI パネルに置き、シーンで表示を切り替え、背景の矩形は画像要素にします。スクリプトの中で描画しないでください(ESKEES の階層にもキャンバスにも表示されず、編集できなくなります)。
3 ステージとタイムの書き方(テトリスと同じ構成): phase(0 プレイ中 / 1 ミス / 2 ステージクリア / 3 全ステージクリア)とstageNo を変数に持ち、ステージの開始時に startT = time、毎フレーム elapsed = round2(time - startT) とします。クリアしたら t1〜t3 に記録し、最後に合計とベストを表示します。UI パネル(ミス クリア リザルト きろく)を ui … show / hide で切り替え、クリックしたら phase に応じて次へ進めます。
パタパタ(スクリプトのみ)
var score = 0
var over = 0
class 鳥
vy = 0
function update(dt)
self.vy += 900 * dt
self.y += self.vy * dt
if self.y > screen.h or touching 土管 then
over = 1
end
end
function flap()
self.vy = -280
end
end
on every 1.5
local gap = math.random(160, screen.h - 160)
spawn 土管 at screen.w + 40, gap - 390
spawn 土管 at screen.w + 40, gap + 70
end
on press any
for each in 鳥
self:flap()
end
end
テーブルで盤面を持つ(テトリスの行消し)
function clearLines(board, w, h)
local cleared = 0
local y = h
while y >= 1 do
local full = 1
for x = 1, w do
if board[y][x] == 0 then
full = 0
end
end
if full == 1 then
table.remove(board, y)
local row = {}
for x = 1, w do
row[x] = 0
end
table.insert(board, 1, row)
cleared += 1 -- 消した行には上の行が来るので、同じ y をもう一度確認する
else
y -= 1
end
end
return cleared
end
ドラッグ&ドロップ
on drag 鍵 to 扉
move 扉 by 0, -40
play 開く
place 鍵
end
17. 今後の予定(未実装)
| 機能 | 予定している書き方 |
|---|
| コンポーネントのバリアント(G11。後回し) | spawn クラス at x, y as 赤・self.variant = "青"(解像度の扱いを決めてから) |
| シーン切り替えの演出 | シーンのフェードなど(定義が先) |