common-lisp
lisp
RaspberryPi
SBCL

自分が作成しているホームページ「ホビープログラミング忘備録」の「CommonLispで作るSTG」をこちらにも記載。
こっちの方が見てくれる人は多いかな?

CommonLispで作るSTG

CommonLispでSTG(シューティングゲーム)を作るWebサイトが面白そうだったので、
RaspberryPiでやってみることにしました。

本家様サイト: Common LispでSTGを作りますが何か?

フォルダ構成

以下に今回のプロジェクトのフォルダ構成を示します。
「HOME/Programing/sbcl/site/」は事前に作成してください。

■ HOME
└■ Programing
 └■ sbcl
  └■ site
   ├■ alexandria
   ├■ babel_0.5.0
   ├■ cffi_0.16.1
   ├■ lispbuilder-sdl
   ├■ lispbuilder-sdl-gfx
   ├■ lispbuilder-sdl-image
   ├■ lispbuilder-sdl-mixer
   ├■ lispbuilder-sdl-ttf
   └■ trivial-features_0.8

■:フォルダ

lispbuilder_tree.png

SBCLのインストール

今回はCommonLispのSBCL(Steel Bank Common Lisp)を使用します。
以下のコマンドを実行して、SBCLをインストールします。

sudo apt-get install sbcl

続行しますか?[y/n]と聞かれるので、「y」と入力します。

Lispbuilder-SDLの準備

以下のコマンドでGitHubからLispbuilderをダウンロードしてきます。
Downloadsフォルダに移動して、

cd Downloads/

以下のコマンドを実行。

git clone https://github.com/lispbuilder/lispbuilder

ダウンロードしたLispbuilderの中から必要なものを選択して、
「HOME/Programing/sbcl/site/」フォルダへ格納します。

今回必要になるのは以下の5つのモジュールです。

モジュール名 説明 リンク
lispbuilder-sdl Lispからのモジュール呼出定義とC言語で作成されたバイナリモジュール 詳細
lispbuilder-sdl-gfx 線や文字の描画を行うモジュール 詳細
lispbuilder-sdl-image BMPファイルなどの画像ファイル読み込み、描画を行うモジュール 詳細
lispbuilder-sdl-mixer WAVEファイルなどの音声ファイル出力を行うモジュール 詳細
lispbuilder-sdl-ttf フォントの描画を行うモジュール (TTF:True-Type fonts) 詳細

lispbuilderフォルダへ移動して、

cd lispbuilder/

以下のコマンドを実行し、各モジュールを「HOME/Programing/sbcl/site/」フォルダへコピーします。

cp -r ./lispbuilder-sdl/ ./lispbuilder-sdl-gfx/ ./lispbuilder-sdl-image/ ./lispbuilder-sdl-mixer/ ./lispbuilder-sdl-ttf/ ~/Programing/sbcl/site/

download_lispbuilder.png

これで、Lispbuilderの準備は完了です。

その他の各種ライブラリの準備

以下の手順で実施していけば、最初のフォルダ構成通りになるはずです。

Alexandria

Alexandriaとは、Common Lispのユーティリティライブラリです。
Downloadsフォルダへダウンロードし、

wget -P ~/Downloads/ http://common-lisp.net/~loliveira/tarballs/inofficial/alexandria-2008-07-29.tar.gz

「HOME/Programing/sbcl/site/」フォルダへ展開。

tar xvzf ~/Downloads/alexandria-2008-07-29.tar.gz -C ~/Programing/sbcl/site/

download_Alexandria.png

Babel

Babelとは、エンコーディングライブラリです。文字コードの符号化/復号化を行います。
Downloadsフォルダへダウンロードし、

wget -P ~/Downloads/ http://common-lisp.net/project/babel/releases/babel_latest.tar.gz

「HOME/Programing/sbcl/site/」フォルダへ展開。

tar xvzf ~/Downloads/babel_latest.tar.gz -C ~/Programing/sbcl/site/

download_Babel.png

CFFI

CFFIとは、Common Lispと外部ライブラリを連携させるライブラリです。
Downloadsフォルダへダウンロードし、

wget -P ~/Downloads/ https://common-lisp.net/project/cffi/releases/cffi_0.17.1.tar.gz

「HOME/Programing/sbcl/site/」フォルダへ展開。

tar xvzf ~/Downloads/cffi_0.17.1.tar.gz -C ~/Programing/sbcl/site/

download_CFFI.png

trivial-features

trivial-featuresとは、Common Lispにある features の可搬性を向上させるユーティリティです。
Downloadsフォルダへダウンロードし、

wget -P ~/Downloads/ http://common-lisp.net/~loliveira/tarballs/trivial-features/trivial-features_latest.tar.gz

「HOME/Programing/sbcl/site/」フォルダへ展開。

tar xvzf ~/Downloads/trivial-features_latest.tar.gz -C ~/Programing/sbcl/site/

download_trivial-features.png

これで、全てのライブラリが揃いました。

Babelの修正

ここでダウンロードしたBabelをコンパイルすると、以下のようなエラーが出てしまいます。

BabelError
file: /home/pi/Programing/sbcl/site/babel_0.5.0/src/enc-unicode.lisp
in: DEFINE-UTF-16 :UTF-16
    (BABEL-ENCODINGS::DEFINE-UTF-16 :UTF-16)

caught ERROR:
  (during macroexpansion of (DEFINE-UTF-16 :UTF-16))
  #:~A-CODE-POINT-COUNTER fell through ETYPECASE expression.
  Wanted one of (SIMPLE-STRING STRING).

;(~中略~)

compiling (DEFMACRO DEFINE-UCS ...)
compiling (DEFINE-CHARACTER-ENCODING :UTF-32 ...)
compiling (DEFINE-UCS :UTF-32 ...)
file: /home/pi/Programing/sbcl/site/babel_0.5.0/src/enc-unicode.lisp
in: DEFINE-UCS :UTF-32
    (BABEL-ENCODINGS::DEFINE-UCS :UTF-32 4)

caught ERROR:
  (during macroexpansion of (DEFINE-UCS :UTF-32 ...))
  #:~A-CODE-POINT-COUNTER fell through ETYPECASE expression.
  Wanted one of (SIMPLE-STRING STRING).

;(~中略~)

compiling (DEFINE-CHARACTER-ENCODING :UCS-2 ...)
compiling (DEFINE-UCS :UCS-2 ...)
file: /home/pi/Programing/sbcl/site/babel_0.5.0/src/enc-unicode.lisp
in: DEFINE-UCS :UCS-2
    (BABEL-ENCODINGS::DEFINE-UCS :UCS-2 2 NIL 65536)

caught ERROR:
  (during macroexpansion of (DEFINE-UCS :UCS-2 ...))
  #:~A-CODE-POINT-COUNTER fell through ETYPECASE expression.
  Wanted one of (SIMPLE-STRING STRING).

;(~中略~)

エラーの内容(赤字部分)から、「/home/pi/Programing/sbcl/site/babel_0.5.0/src/enc-unicode.lisp」の「UTF-16」「UTF-32」「UCS-2」関連の箇所でエラーが出ていることが分かります。
なので、「/home/pi/Programing/sbcl/site/babel_0.5.0/src/enc-unicode.lisp」を以下のように修正することにします。
495行目辺りから最終行までを全てコメントアウト(#| |#で囲む)します。

enc-unicode.lisp
#| コメントアウト開始 =>>
;;;; UTF-16

;;; TODO: add a way to pass some info at compile-time telling us that,
;;; for example, the maximum code-point will always be < #x10000 in
;;; which case we could simply return (* 2 (- end start)).
(defmacro utf16-octet-counter (getter type)
  `(named-lambda utf-16-octet-counter (seq start end max)
     (declare (type ,type seq) (fixnum start end max))
     (loop with noctets fixnum = 0
           for i fixnum from start below end
           for code of-type code-point = (,getter seq i)
           do (let ((new (the fixnum (+ (if (< code #x10000) 2 4) noctets))))
                (if (and (plusp max) (> new max))
                    (loop-finish)
                    (setq noctets new)))
           finally (return (values noctets i)))))

(~中略~)

(define-character-encoding :ucs-2be
   "A 16-bit, fixed-length encoding in which all Unicode
characters can be encoded in a single 16-bit word. Input data is assumed
to be in big-endian order.  Output is also written in big-endian byte
order without a leading byte-order mark."
  :max-units-per-char 1
  :code-unit-size 16
  :aliases '(:ucs-2/be)
  :native-endianness #+little-endian nil #+big-endian t
  :literal-char-code-limit #x10000
  :nul-encoding #(0 0))

(define-ucs :ucs-2be 2 :be #x10000)
<<= コメントアウト終了 |#

各種ライブラリのインストール

以下のファイルを作成し、「/usr/lib/sbcl/」へ格納します。
自分の場合は、「/usr/lib/sbcl/」へ移動し「Vim」を使って作成しました。

sudo vim sbclrc

(※) 「/usr/lib/sbcl/」内でファイルを作成・修正・削除・移動などを行うには「sudo」コマンドを付ける必要があります。

sbclrc
(require :asdf)
(dolist (dir (directory "~//Programing//sbcl//site//*//"))
    (pushnew dir asdf:*central-registry* :test #' equal))
(asdf:operate 'asdf:load-op :lispbuilder-sdl)
(asdf:operate 'asdf:load-op :lispbuilder-sdl-binaries)

make_sbclrc.png

SBCLを起動すると、各ライブラリがコンパイルされます。

sbcl

自分の環境では、全てのコンパイルが終了するのに約5~6分かかりました。

Lispbuilder-SDLのサンプルプログラムを起動

Lispbuilderが正常にインストールされていることを確認するために、Lispbuilder-SDLのサンプルプログラムを実行してみます。

  • Lispbuilder-SDLを評価します。
(asdf:load-system :lispbuilder-sdl)
  • Lispbuilder-SDLのサンプルプログラムを評価します。
(asdf:load-system :lispbuilder-sdl-examples)
  • Lispbuilder-SDLサンプルプログラムを起動します。

mandelbrot

(sdl-examples:mandelbrot)

lispbuilder_sample_exe.png

particles

(sdl-examples:particles)

lispbuilder_sample_exe2.png

fireworks

(sdl-examples:fireworks)

lispbuilder_sample_exe3.png

無事に動作しました。
今回は3つのサンプルプログラムを試してみましたが、他にも色々あるので、興味がある方は探してみるのも良いと思います。

STGソースコードのダウンロード

「Common LispでSTGを作りますが何か?」の作者様のWebサイト「いで庵」で各章のソースコードを公開しているので、それをDownloadsフォルダへダウンロードします。

wget -P ~/Downloads/ http://www.usamimi.info/~ide/programe/stg_doc/stg-commonlisp-src.zip

各章のソースコードを「HOME/Programing/sbcl/」へ解凍

unzip ~/Downloads/stg-commonlisp-src.zip -d ~/Programing/sbcl/

最終的に以下のようなフォルダ構成になります。

■ HOME
└■ Programing
 └■ sbcl
  ├■ site
  │├■ alexandria
  │├■ babel_0.5.0
  │├■ cffi_0.16.1
  │├■ lispbuilder-sdl
  │├■ lispbuilder-sdl-gfx
  │├■ lispbuilder-sdl-image
  │├■ lispbuilder-sdl-mixer
  │├■ lispbuilder-sdl-ttf
  │└■ trivial-features_0.8
  └■ src
   ├■ chapter02
   ├■ chapter03
   ├■ chapter04
   ├■ chapter05
   ├■ chapter06
   ├■ chapter07
   ├■ chapter08
   └■ chapter09

■:フォルダ

download_stg_src.png

これで実行環境は全て整いました。

プログラムを実行してみる

「HOME/Programing/sbcl/src/chapter09」フォルダへ移動し、

cd ~/Programing/sbcl/src/chapter09/

stg_src_exe.png

  • SBCLを起動します。
sbcl
  • Lispbuilder-SDLを評価します。
(asdf:load-system :lispbuilder-sdl)
  • 「main.lisp」をロードします。
(load "main.lisp" :external-format :utf-8)
  • main関数を実行します。
(main)

実行結果

stg_src_exe2.png

STGのソースコードの動作を確認することができました。
これで、Raspberry Piを使ってLISPでゲームを作成することができますね。

最後に

Qiitaで初投稿でしたが、普通にホームページ作るよりも簡単で良いですね。
これからも適当にLISP関連の内容で投稿していきたいと思います。