概要

ツクセカでは、MorningScriptというスクリプト言語を用いてマップを高度にカスタマイズすることが出来ます。
マップとスクリプト間で変数をやり取りすることで、動的なマップ演出や対話的な機能を実現できます。

このページでは、ツクセカが提供する予約済み変数(app_で始まる変数)について説明します。

現時点では、スクリプトによるマップのカスタマイズ効果はユーザー単位に反映されます。(マップに接続中のユーザー間で共有されません)

変数の種類

マップ → スクリプト(読み取り用)

  • マップの状態をスクリプトから参照できる変数
  • プレイヤー情報、現在時刻、位置情報など
  • これらの変数は読み取り用で、スクリプトから変更しても意味はありません

スクリプト → マップ(効果発動)

  • スクリプトからマップの表示や動作を制御する変数
  • メッセージ表示、タイル変更、視覚効果など
  • これらの変数に値を設定すると、マップに効果が反映されます

マップ → スクリプト(読み取り用変数)

■ユーザー情報

app_user_name string

現在のプレイヤーのユーザー名

// 使用例:プレイヤー名を含むメッセージを表示
[var:welcome ようこそ、]
[var:welcome][var:app_user_name]さん!

■時刻情報

app_time_year number

現在の年(4桁)

例: 2024

app_time_month number

現在の月

範囲: 112

app_time_day number

現在の日

範囲: 131

app_time_hour number

現在の時(24時間制)

範囲: 023

// 使用例:時間帯による挨拶の変更
[var:hour [var:app_time_hour]]
[if var:hour < 12]
  おはようございます!
[elseif var:hour < 18]
  こんにちは!
[else]
  こんばんは!
[endif]

app_time_minute number

現在の分

範囲: 059

app_time_second number

現在の秒

範囲: 059

app_time_unix number

2025年1月1日 00:00:00 UTCからの経過秒数(1970年1月1日ではない点にご注意ください!)

2025年1月1日を起点(0)とした秒数
(MorningScriptの数値上限に対応するため調整済み)

// 使用例:ゲーム内でのプレイ時間計測
[var:start_time [var:app_time_unix]]
// ... 何か処理 ...
[var:end_time [var:app_time_unix]]
[var:elapsed_time var:end_time]
[minus var:elapsed_time var:start_time]
経過時間: [var:elapsed_time]秒

■プレイヤー位置情報

app_user_pos_x number

プレイヤーのX座標

範囲: 0マップ幅-1

app_user_pos_y number

プレイヤーのY座標

範囲: 0マップ高さ-1

// 使用例:特定の座標にいる時だけメッセージ表示
[var:x [var:app_user_pos_x]]
[var:y [var:app_user_pos_y]]
[if var:x = 10]
  [if var:y = 5]
    秘密の場所を見つけました!
  [endif]
[endif]

スクリプト → マップ(効果発動変数)

■メッセージ表示

app_message_info string

画面上部の情報ボックスにテキストを表示

HTMLエスケープされて表示されます

// 使用例:情報ボックスにメッセージを表示
[var:app_message_info この部屋には秘密が隠されています!探してみてください!]
// 使用例:ステータスを表示
[var:hp 140]
[var:mp 50]

[var:disp_message ⚔️HP:]
[concat var:disp_message var:hp]
[concat var:disp_message [br]]
[concat var:disp_message 🛡️MP:]
[concat var:disp_message var:mp]

[var:app_message_info var:disp_message]

app_toast string

トースト通知を3秒間表示

画面中央に表示されます

app_toast_short string

トースト通知を1秒間表示

app_toast_long string

トースト通知を6秒間表示

// 使用例:短い通知
[var:app_toast_short どこかで鍵が開く音がした…]
// 使用例:時間帯によって異なるトースト表示
[if var:app_time_hour < 6]
  [var:app_toast_long 夜はモンスターが活発になります]
[elseif var:app_time_hour < 18]
  [var:app_toast_short いい天気ですね]
[else]
  [var:app_toast 日が暮れてきました]
[endif]

■タイル操作

app_map_layer_base1_set string

ベースレイヤー1のタイルを設置

フォーマット: タイルインデックス,x1,y1,x2,y2,...

最初の値がタイルインデックス、以降は座標のペア

// 使用例:複数の座標にタイル15を設置
[var:app_map_layer_base1_set 15,2,3,4,5,6,7]
// (2,3)、(4,5)、(6,7)の3箇所にタイル15を設置

app_map_layer_base1_clear string

ベースレイヤー1のタイルを削除

フォーマット: x1,y1,x2,y2,...

指定した座標のタイルを削除(-1に設定)

app_map_layer_base2_set string

ベースレイヤー2のタイルを設置

base1_setと同じフォーマット

app_map_layer_base2_clear string

ベースレイヤー2のタイルを削除

base1_clearと同じフォーマット

app_map_layer_front_set string

前面レイヤーのタイルを設置

base1_setと同じフォーマット

app_map_layer_front_clear string

前面レイヤーのタイルを削除

base1_clearと同じフォーマット

// 使用例:扉を開く演出
// 扉のタイルを削除して通れるようにする
[var:app_map_layer_front_clear 5,10]
[var:app_map_passability_yes 5,10]
[var:app_toast 扉が開きました!]

app_map_layer_base1_set_multi string

ベースレイヤー1に個別のタイルを個別の座標に設置

フォーマット: タイル1,x1,y1,タイル2,x2,y2,...

各タイルインデックスと座標のセットを指定

// 使用例:異なるタイルを複数の座標に設置
[var:app_map_layer_base1_set_multi 8,0,3,8,4,2,11,0,4]
// (0,3)と(4,2)にタイル8を、(0,4)にタイル11を設置

app_map_layer_base1_set_rect string

ベースレイヤー1の矩形範囲にタイルを設置

フォーマット: タイルインデックス,左上x,左上y,右下x,右下y

左上と右下の座標が同一の場合は、その1マスのみ対象

座標の順序は自動的に正規化されます(左上と右下が逆でも動作)

// 使用例:左上(0,3)から右下(4,7)の範囲にタイル8を設置
[var:app_map_layer_base1_set_rect 8,0,3,4,7]
// 5x5の範囲にタイル8が設置される

app_map_layer_base1_clear_rect string

ベースレイヤー1の矩形範囲をクリア

フォーマット: 左上x,左上y,右下x,右下y

指定範囲のタイルを削除(-1に設定)

// 使用例:左上(0,3)から右下(4,7)の範囲をクリア
[var:app_map_layer_base1_clear_rect 0,3,4,7]

app_map_layer_base2_set_multi string

ベースレイヤー2に個別のタイルを個別の座標に設置

base1_set_multiと同じフォーマット

// 使用例:装飾タイルをランダムに配置
[var:app_map_layer_base2_set_multi 20,5,5,21,7,5,22,9,5]
// 異なる装飾タイルを横一列に配置

app_map_layer_base2_set_rect string

ベースレイヤー2の矩形範囲にタイルを設置

base1_set_rectと同じフォーマット

// 使用例:装飾用の草タイルを範囲設置
[var:app_map_layer_base2_set_rect 25,2,2,6,4]

app_map_layer_base2_clear_rect string

ベースレイヤー2の矩形範囲をクリア

base1_clear_rectと同じフォーマット

app_map_layer_front_set_multi string

前面レイヤーに個別のタイルを個別の座標に設置

base1_set_multiと同じフォーマット

// 使用例:複雑なパターンを前面レイヤーに作成
[var:tiles 30,2,2,31,3,2,32,4,2,30,2,3,32,4,3]
[var:app_map_layer_front_set_multi var:tiles]
// チェック模様のような複雑なパターンを作成

app_map_layer_front_set_rect string

前面レイヤーの矩形範囲にタイルを設置

base1_set_rectと同じフォーマット

// 使用例:影エフェクトを範囲設置
[var:app_map_layer_front_set_rect 50,10,10,15,12]

app_map_layer_front_clear_rect string

前面レイヤーの矩形範囲をクリア

base1_clear_rectと同じフォーマット

// 使用例:壁の範囲を一括削除
[var:app_map_layer_front_clear_rect 5,8,9,12]
[var:app_toast 壁が崩れた!]

■通行可否設定

app_map_passability_yes string

指定座標を通行可能にする

フォーマット: x1,y1,x2,y2,...

// 使用例:隠し通路を開通させる
[var:app_map_passability_yes 10,5,11,5,12,5]
// (10,5)、(11,5)、(12,5)を通行可能にする

app_map_passability_no string

指定座標を通行不可にする

フォーマット: x1,y1,x2,y2,...

// 使用例:道を塞ぐ
[var:app_map_passability_no 8,10]
[var:app_map_layer_base2_set 50,8,10]
[var:app_toast 岩が道を塞いでしまった!]

app_map_passability_yes_rect string

矩形範囲を通行可能にする

フォーマット: 左上x,左上y,右下x,右下y

// 使用例:新しい通路を開通させる
[var:app_map_passability_yes_rect 10,5,15,5]
// (10,5)から(15,5)の横一列を通行可能にする

app_map_passability_no_rect string

矩形範囲を通行不可にする

フォーマット: 左上x,左上y,右下x,右下y

// 使用例:エリアを封鎖する
[var:app_map_passability_no_rect 5,5,10,10]
[var:app_toast このエリアは立入禁止になりました]
// 6x6の範囲を通行不可にする

■プレイヤー操作

app_action_move_user string

プレイヤーを指定座標に移動させる

フォーマット: x,y

移動先が通行可能な場合のみ移動します

// 使用例:特定の場所にワープ
[var:app_action_move_user 10,5]

// 使用例:条件によって異なる場所に移動
[var:hour [var:app_time_hour]]
[if var:hour < 12]
  // 朝は町の入口に移動
  [var:app_action_move_user 2,10]
[else]
  // 午後は宿屋の前に移動
  [var:app_action_move_user 15,8]
[endif]
// 使用例:落とし穴トラップ
// アクションポイントで実行
落とし穴に落ちた!
[var:app_action_move_user 5,25]

■視覚効果

app_cover_opacity number

マップ全体を覆う半透明カバーの不透明度

範囲: 0(非表示)~ 10(最大不透明度)

未設定または空の場合は状態を変更しません

app_cover_r number

半透明カバーの赤色成分

範囲: 0255

app_cover_g number

半透明カバーの緑色成分

範囲: 0255

app_cover_b number

半透明カバーの青色成分

範囲: 0255

// 使用例:時間帯による照明演出
[if var:app_time_hour < 6]
  // 夜明け前(青みがかった暗さ)
  [var:app_cover_r 0]
  [var:app_cover_g 0]
  [var:app_cover_b 30]
  [var:app_cover_opacity 3]
[elseif var:app_time_hour < 18]
  // 昼間(カバーなし)
  [var:app_cover_opacity 0]
[else]
  // 夕暮れ~夜(オレンジ~暗闇)
  [var:app_cover_r 30]
  [var:app_cover_g 15]
  [var:app_cover_b 0]
  [var:app_cover_opacity 2]
[endif]

スクリプトの実行タイミング

マップ読み込み時(onLoad)

  • マップが表示された時に一度だけ実行
  • 初期設定やウェルカムメッセージの表示に使用
  • 実行結果のテキスト出力がある場合はメッセージダイアログで表示

定期実行(periodic)

  • 指定間隔(1~20秒)で繰り返し実行
  • 時間経過による演出変更や状態更新等に使用
  • 実行結果のテキスト出力がある場合でも表示されない(テキスト出力は無視される)

アクションポイント

  • プレイヤーが特定座標を踏んだ時に実行
  • 場所固有のイベントや仕掛け等に使用
  • 実行結果のテキスト出力がある場合はメッセージダイアログで表示

モブ接触時

  • プレイヤーがモブ(NPC)に接触した時に実行
  • 動的な対話や条件分岐のある会話等に使用
  • 実行結果のテキスト出力がある場合はモブのセリフとして表示

実践的な使用例

■例1: パズルギミックの実装

アクションポイントスクリプト(スイッチを踏んだ時)

// スイッチの状態を切り替え(変数で管理)
[var:switch_state 0]
[if var:switch_state = 0]
  [var:switch_state 1]
  [var:app_toast スイッチをONにしました]

  // 扉を開く
  [var:app_map_layer_front_clear 15,10]
  [var:app_map_passability_yes 15,10]

  // 床のタイルを変更(押されたスイッチの見た目)
  [var:app_map_layer_base2_set 85,5,5]

[else]
  [var:switch_state 0]
  [var:app_toast スイッチをOFFにしました]

  // 扉を閉じる
  [var:app_map_layer_front_set 150,15,10]
  [var:app_map_passability_no 15,10]

  // 床のタイルを元に戻す
  [var:app_map_layer_base2_set 84,5,5]
[endif]

■例2: 位置連動イベント

定期実行スクリプト(特定エリアの検知)

// プレイヤーの現在位置を取得
[var:px [var:app_user_pos_x]]
[var:py [var:app_user_pos_y]]
[var:is_danger 0]

// 危険エリア(10,10)~(15,15)の判定
[if var:px >= 10]
  [if var:px <= 15]
    [if var:py >= 10]
      [if var:py <= 15]
        // 危険エリア内にいる
        [var:app_message_info 危険区域!早く脱出してください!]
        [var:app_cover_r 100]
        [var:app_cover_g 0]
        [var:app_cover_b 0]
        [var:app_cover_opacity 2]
        [var:is_danger 1]

      [endif]
    [endif]
  [endif]
[endif]

[if var:is_danger != 1]
  // 危険エリア外
  [reset var:app_message_info]
  [var:app_cover_opacity 0]
[endif]

オートセーブモードの活用例

マップのオートセーブモードをONにすると、MorningScript変数とプレイヤー座標が自動的にブラウザのlocalStorageに保存されます。
これにより、時間を掛けて遊べるマップ、何日も掛けて徐々に成長していくマップ、作業系ゲーム、等を作成しやすくなります。

※ただし、アカウント毎ではなくブラウザ毎の保存であることに注意してください。
※また、マップ単位の保存であることに注意してください。(現時点では、マップをまたいで変数値を受け渡すことはできません)

■例: 1日1回だけガチャを回せるマップ

// 【マップ開始時の処理】
// オートセーブONでも開始時の処理は毎回呼ばれるため、初期化処理が最初の1回だけ呼ばれるようにする
[if var:is_inisialized != 1]
    // 初期化済みフラグ
    [var:is_inisialized 1]
    // 最後にガチャをした日を保持する
    [var:last_gacha_day 0]

    // ガチャのアイテムの所有数
    [var:tako 0]
    [var:ika 0]
    [var:fugu 0]
[endif]

// 現在の所有数を表示
[var:app_message_info 🐙x]
[concat var:app_message_info [var:tako]]
[concat var:app_message_info [br]]
[concat var:app_message_info 🦑x]
[concat var:app_message_info [var:ika]]
[concat var:app_message_info [br]]
[concat var:app_message_info 🐡x]
[concat var:app_message_info [var:fugu]]

// 【ガチャマシーンに触ったときのアクション】
// yyyymmddを取得
[var:now_day [var:app_time_year]]
[multiply var:now_day 100]
[plus var:now_day [var:app_time_month]]
[multiply var:now_day 100]
[plus var:now_day [var:app_time_day]]

// 今日はまだガチャしていなかったら
[if var:last_gacha_day != var:now_day]
    // ランダムにガチャする
    [var:get_item_no [rand 1 3]]

    [if var:get_item_no = 1]
        [var:app_toast タコが出ました!🐙]
    [elseif var:get_item_no = 2]
        [plus var:ika 1]
        [var:app_toast イカが出ました!🦑]
    [else]
        [plus var:fugu 1]
        [var:app_toast フグが出ました!🐡]
    [endif]

    // 今日ガチャしたことを保持しておく
    [var:last_gacha_day [var:now_day]]
[else]
    [var:app_toast_short また明日ガチャしてみよう!]
[endif]

// 現在の所有数を表示
[var:app_message_info 🐙x]
[concat var:app_message_info [var:tako]]
[concat var:app_message_info [br]]
[concat var:app_message_info 🦑x]
[concat var:app_message_info [var:ika]]
[concat var:app_message_info [br]]
[concat var:app_message_info 🐡x]
[concat var:app_message_info [var:fugu]]
💾

オートセーブモードの設定

マップ作成画面で「オートセーブモード」をONにすることで有効になります。

🔄

リスポーンとリセット

オートセーブモードのマップでは、マップ説明ダイアログに「リスポーン」(変数維持)と「リセット」(完全初期化)ボタンが表示されます。

重要な注意事項

⚠️

変数名の予約

app_で始まる変数名はシステムで予約されています。 独自の変数を定義する場合は、app_以外の名前を使用してください。

📍

座標系について

マップのx,y座標は、左上を0,0とします。

🔄

変数の更新タイミング

読み取り専用変数は、スクリプト実行開始時に更新されます。 効果発動変数は、スクリプト実行完了後に一括で反映されます。

💡

パフォーマンス

定期実行スクリプトは頻繁に実行されるため、 処理が重くなりすぎないよう注意してください。

🎨

視覚効果の重ね合わせ

app_cover_opacityが0以外の場合のみカバーが表示されます。 未設定や空の値の場合は、現在の状態が維持されます。 カバーを外す場合は明示的に0をセットしてください。

📝

文字数制限

各スクリプトフィールドには最大5000文字の制限があります。 複雑な処理は複数のアクションポイントやモブに分割することを検討してください。