ChromebookのLinuxターミナルの方針転換
Chromebook電源が切れてしまい、復帰後、以下、ターミナルで、解説お願いします。
NOTICE:
Recently it has become necessary to deprecate some features of crostini,
including:
* UI-based installation of .deb packages. Installation via aptitude is
the default path, but there are also visual package managers which
may be used.
* UI-based Debian release upgrade. Please refer to release notes for
the release in question for upgrade instructions.
* Multi-container support.
For the most up-to-date news, please visit
https://developers.google.com/chromeos/app-development/develop/news
(this message will be repeated 4 more times).
(to silence this message, run the following in this terminal):
echo 10 >"/home/yourname/.local/share/cros-motd"
電源切れやシステムのクラッシュによるエラーではありませんのでご安心ください。これはChromeOSのアップデートに伴い、Googleからユーザーへ通知された公式の仕様変更のお知らせ(ターミナル起動時のメッセージ)です。
メッセージの要点は「Linux(Crostini)環境において、ChromeOS側の画面(GUI)から行っていた操作機能をいくつか廃止し、ターミナルからのコマンド操作を基本とする」という方針転換です。
具体的に非推奨(廃止予定)とされているのは以下の3点です。
-
.debパッケージのUIインストールの廃止
Chromebookの「ファイル」アプリから.debファイルをダブルクリックしてインストールする機能がなくなります。今後はこれまで通り、ターミナルからaptコマンドを使ってインストールするか、Linux用のGUIパッケージマネージャーを導入する必要があります。 -
UIからのDebian OSアップグレードの廃止
ChromeOSの設定画面に表示されていた「Linuxをアップグレードする」ボタンがなくなります。OSのメジャーバージョン(例:BullseyeからBookwormなど)を上げる場合は、Debianのリリースノートに従ってターミナル上で手動アップグレードを行うことになります。 -
マルチコンテナ機能のサポート廃止
ChromeOSのシステム機能として複数のLinuxコンテナ(仮想環境)を並行して管理する機能が非推奨となり、標準の単一コンテナ(penguin)のみのサポートとなります。
※これはChromeOS側の管理機能の話であり、Linux(penguin)環境内で独自に構築・運用しているPodmanなどのコンテナには影響しません。
メッセージを非表示にする方法
このメッセージは、ターミナルを起動するたびにあと4回表示されると自然に消えます。すぐに表示させないようにしたい場合は、メッセージの指示通り以下のコマンドを実行してください。
echo 10 >"/home/yourname/.local/share/cros-motd"
ゲームエンジンlanternのビルド
以下、linux内にDownloadフォルダを作り、lua5.5.1のソースとlantern0.8のソースを解凍し、ビルドしていきます。
$ tar -xzvf lua-5.5.1.tar.gz
$ cd lua-5.5.1/
$ make
$ mkdir -p ../lua55/include
$ cp src/.h src/.hpp ../lua55/include/
cd ../lua55
$ ./lua -v
$ mkdir pkgconfig
$ cd pkgconfig
$ nano lua.pc
# 1. lua55フォルダのフルパス(バックスラッシュではなくスラッシュ「/」推奨)
prefix=/home/yokamak/Download/lantern-0.8.0/lua55
# ライブラリとヘッダーの場所(通常はprefix直下、または lib / include フォルダ内)
libdir=${prefix}
includedir=${prefix}/include
Name: Lua
Description: An Extensible Extension Language
Version: 5.5.1
# 2. -l の後は実際のライブラリファイル名に合わせます
# 例: liblua.a なら -llua / liblua55.a なら -llua55
Libs: -L${libdir} -llua
# 3. mathライブラリが必要な場合があるため -lm をつけるのが一般的です
Cflags: -I${includedir}
$ cd ../../
$ tar -xzvf lantern-0.8.0.tar.gz
$ cp -r lua55/ lantern-0.8.0
$ sudo apt install libsdl2-dev libreadline-dev
cd lantern-0.8.0/
$ export PKG_CONFIG_PATH="/home/yokamak/Download/lantern-0.8.0/lua55/pkgconfig"
$ pkg-config --cflags --libs lua
cmake -B build
cmake --build build -j8
地面、cube、sphereを配置、ライトをいくつか配置したシーンを作成してください。カメラは、原点を見る感じで、上下矢印キーで、近く遠くできるようにしてください
Wick言語の3D描画機能(lt.cube, lt.sphere, lt.plane)と、ライト(ディレクショナルライト、ポイントライト)、およびカメラ制御を組み合わせたシーンのサンプルコードです。
上下の矢印キー(UP / DOWN)でカメラの距離(ズーム)を変更し、常に原点(0, 0, 0)を見つめるように設定しています。
3Dシーンのサンプルコード (main.wick)
// ==========================================
// 1. トップレベル: 3Dメッシュの作成と変数の準備
// ==========================================
// 各種基本形状(プリミティブ)を作成します。戻り値は num 型のハンドルです[cite: 37, 43]。
let m_ground = lt.plane(10) // 地面 (10分割の平面)
let m_cube = lt.cube() // 立方体
let m_sphere = lt.sphere(16) // 球 (16分割)
// カメラとアニメーション用の変数
let cam_dist = 6.0 // カメラと原点との距離
let time = 0.0
fn update(dt: num) {
// 時間を進める(ライトやキューブを回すため)
time = time + dt
// 矢印キーの上・下でカメラの距離を変更(ズームイン・ズームアウト)
let zoom_speed = 5.0
if lt.key("up") {
cam_dist = cam_dist - zoom_speed * dt
}
if lt.key("down") {
cam_dist = cam_dist + zoom_speed * dt
}
// カメラが近すぎたり遠すぎたりしないように制限[cite: 17]
cam_dist = max(2.0, min(15.0, cam_dist))
}
fn draw() {
// 背景を暗いグレーでクリア(3Dの描画前に必ず実行)[cite: 36, 42]
lt.clear(0.05, 0.05, 0.1)
// ==========================================
// 2. カメラの設定
// ==========================================
// lt.camera(視点X, 視点Y, 視点Z, 注視点X, 注視点Y, 注視点Z)[cite: 36, 42]
// 視点は斜め上 (x: 0.7, y: 0.8, z: 1.0) の方向から距離(cam_dist)を掛けた位置
let ex = cam_dist * 0.7
let ey = cam_dist * 0.8
let ez = cam_dist
// 原点 (0, 0, 0) を見る
lt.camera(ex, ey, ez, 0, 0, 0)
// ==========================================
// 3. ライトの配置
// ==========================================
// 太陽光のような全体を照らす平行光源 (方向X, Y, Z, 環境光の強さ)[cite: 36, 42]
lt.light(0.5, -1.0, -0.5, 0.2)
// ポイントライト0番: 原点の周りを回る「赤い」ライト
let light_x = 3.0 * sin(time * 2.0)
let light_z = 3.0 * cos(time * 2.0)
// lt.point_light(スロット0~3, X, Y, Z, 半径, R, G, B)[cite: 36, 42]
lt.point_light(0, light_x, 1.0, light_z, 5.0, 1.0, 0.2, 0.2)
// ポイントライト1番: 固定配置された「青い」ライト
lt.point_light(1, -2.0, 1.0, 2.0, 4.0, 0.2, 0.5, 1.0)
// ==========================================
// 4. メッシュの描画
// ==========================================
// lt.draw(メッシュ, x,y,z, 回転x,y,z, スケールx,y,z, R,G,B)[cite: 37, 43]
// 地面 (広さ10x10に引き伸ばし、少し暗い色にする)
lt.draw(m_ground, 0, 0, 0, 0, 0, 0, 10, 1, 10, 0.4, 0.4, 0.4)
// キューブ (左側に配置し、Y軸を中心に回転させる)
lt.draw(m_cube, -1.5, 0.5, 0, 0, time, 0, 1, 1, 1, 0.8, 0.8, 0.2) // 黄色系
// 球体 (右側に配置、静止)
lt.draw(m_sphere, 1.5, 0.5, 0, 0, 0, 0, 1, 1, 1, 0.8, 0.8, 0.8) // 白色
// ==========================================
// 5. UI (2D描画) は最後に書く
// ==========================================
lt.print("UP/DOWN: ZOOM IN/OUT", 10, 10, 1, 1, 1, 1)
// 距離の数値を小数点以下2桁程度で表示する工夫
let dist_disp = floor(cam_dist * 100) / 100
lt.print("DISTANCE: " + str(dist_disp), 10, 20, 1, 1, 0, 1)
}
3D描画のポイント
-
カメラ (
lt.camera): 最初の3つの引数が「カメラの目の位置」、次の3つの引数が「どこを見つめるか(注視点)」になります。今回は注視点を常に0, 0, 0(原点)に固定し、目の位置をcam_distに応じて遠ざけたり近づけたりしています -
ライト (
lt.light,lt.point_light):lt.lightはシーン全体を照らす太陽光です。ポイントライトは0〜3番までの4つ設置でき、今回は赤い光を回転させ、青い光を固定しています -
描画順序: 仕様書にある通り、「3Dの描画(
lt.drawなど)を先に行い、その後に2D(lt.printなど)を描画する」ことで、3D画面の上に文字が重なるUIを作ることができます
地面に、複数のcubeを3x3の等間隔で配置してください。7色を順に割り当ててください。
地面に3x3(合計9個)のキューブを配置し、7色を順番にループさせて割り当てるサンプルコードです。
wick(v0.3)ではリストの中にリストを入れることができないため、「RGBの各色を管理する3つの平行リスト」を作成し、インデックスを % 7 でループさせることで7色を順に適用しています。
// ==========================================
// 1. トップレベル: メッシュと色の準備
// ==========================================
let m_ground = lt.plane(10)
let m_cube = lt.cube()
let cam_dist = 10.0
let time = 0.0
// 7色(赤、オレンジ、黄、緑、シアン、青、マゼンタ)をRGBの平行リストで定義[cite: 29]
let c_r: list<num> = []
let c_g: list<num> = []
let c_b: list<num> = []
// 0: 赤
push(c_r, 1.0) push(c_g, 0.0) push(c_b, 0.0)
// 1: オレンジ
push(c_r, 1.0) push(c_g, 0.5) push(c_b, 0.0)
// 2: 黄
push(c_r, 1.0) push(c_g, 1.0) push(c_b, 0.0)
// 3: 緑
push(c_r, 0.0) push(c_g, 1.0) push(c_b, 0.0)
// 4: シアン
push(c_r, 0.0) push(c_g, 1.0) push(c_b, 1.0)
// 5: 青
push(c_r, 0.0) push(c_g, 0.0) push(c_b, 1.0)
// 6: マゼンタ
push(c_r, 1.0) push(c_g, 0.0) push(c_b, 1.0)
fn update(dt: num) {
time = time + dt
let zoom_speed = 5.0
if lt.key("up") { cam_dist = cam_dist - zoom_speed * dt }
if lt.key("down") { cam_dist = cam_dist + zoom_speed * dt }
cam_dist = max(3.0, min(20.0, cam_dist))
}
fn draw() {
lt.clear(0.05, 0.05, 0.1)
// カメラの設定: 俯瞰 (斜め上) から原点を見る
let ex = cam_dist * 0.6
let ey = cam_dist * 0.8
let ez = cam_dist
lt.camera(ex, ey, ez, 0, 0, 0)
// ライトの設定
lt.light(0.5, -1.0, -0.5, 0.3)
lt.point_light(0, 0.0, 3.0, 0.0, 8.0, 1.0, 1.0, 1.0)
// 地面の描画
lt.draw(m_ground, 0, 0, 0, 0, 0, 0, 15, 1, 15, 0.3, 0.3, 0.3)
// ==========================================
// 3x3 のキューブ配置
// ==========================================
let idx = 0 // 塗る色のインデックス(0から8まで増える)
for z in 0..3 {
for x in 0..3 {
// 0, 1, 2 を -2.5, 0.0, 2.5 の座標に変換して等間隔に並べる
let px = (x - 1) * 2.5
let pz = (z - 1) * 2.5
// idx を 7 で割った余り (0〜6) を使って7色をループさせる[cite: 23]
let c = idx % 7
// lt.draw で RGB にリストから取り出した色を渡す[cite: 37, 43]
// time を使ってすべてのキューブをゆっくり回転させています
lt.draw(m_cube, px, 0.5, pz, 0, time, 0, 1, 1, 1, c_r[c], c_g[c], c_b[c])
idx = idx + 1
}
}
// UI描画
lt.print("UP/DOWN: ZOOM IN/OUT", 10, 10, 1, 1, 1, 1)
}
実装のポイント
-
平行リストによる色の管理: まとまったデータ(今回はRGBの組)を管理する際、Wickではレコードや多次元配列ではなく、対応するインデックスを持つ複数のリストを用意する「平行リスト」が基本的なイディオムです
-
モジュロ演算 (
%) の活用: キューブは合計9個(idx = 0..8)ありますが、色は7種類しかありません。idx % 7とすることで、0〜6の範囲でインデックスが循環し、7個目のキューブから再び1番目の色(赤)が割り当てられます
参考資料

