この記事は Ruby Game Developing Advent Calendar 2016 の18日目の記事です。今日は shinokaro が担当します。
前日は t_tutiya さんの ゲームプログラミングの新手法「コード注入式ステートマシン」の可能性を探る(意図的な煽りタイトル) だったのでした…。
はい、すみません、今26日です。この記事は遅刻しました。
ゲームを素早く作るのに壁となるのは何でしょうか? プログラミングの難しさ、ゲームデザインのアイデアを考える、といった事もありますが、コンピューターゲーム制作では画像の準備が最初の壁と思われます。
画面に表示する絵が無くてはゲームは成立しません。トウフ(白い四角)の画像を使う方法もありますが、ゲームキャラクターの形状もゲームでは重要です。どんなキャラクターにするか決定していても画像ファイルを準備するのには時間がかかります。
そこで、手っ取り早く画像データーをプログラミングしてしまいましょう。そもそも昔(30年前)はプログラムで画像を生成していたものです。そして、プログラムでキャラクターを描くことも Ruby なら簡単にできます。
今回も DXRuby ライブラリを使って、キャラクターを Ruby で生成する方法を紹介します。
DXRuby に付属している Image クラスは画像を表すクラスです。外部画像の読み込みはもちろん、白紙のキャンバスへ線や矩形、円といった図形、任意の文字を”描く”方法も提供されています。
では2Dゲームではおなじみのドット表現は描けるでしょうか? その方法も提供されています。Image::create_from_array
というクラスメソッドが用意されていて引数へ色データーを配列で与えると矩形の中にドットを描き込みます。
しかし、このメソッドを実際に使うと結構大変です。色を表す[a, r, g, b]
の配列をドットの数(横*縦)だけ書くことになります。そこで文字をドットに見立てて描く方法を用意します。この方法は遥か昔にはよく使われた手法です。それのRuby版、現代版です。
まずはDXRuby を拡張してImage::create_from_string
というメソッドを作ってみましょう。コードを示します。
# file_name: image.rb
require 'dxruby'
class DXRuby::Image
def self.create_from_string(width, height, pattern, palette)
array = pattern.gsub(/\s/, '').each_char.map(&palette).flatten
create_from_array(width, height, array)
end
end
この拡張を後で使うのでimage.rb
というファイルに保存しておきます。
機能としては第3引数に与えたパターン用文字列の1文字が特定の色に対応(カラーパレット処理)します。カラーパレットは第4引数にハッシュ形式で与えます。パターン用文字列とカラーパレットは分離してありますので、それぞれを使いまわしできます。パターン用文字列はそのままに、カラーパレットに違うものを与えれば色違いの別キャラクターを作成できます。
このままキャラクターを表すパターン用文字列とカラーパレットをプログラムしても動作はします。でも、キャラクターが増えるたびにプログラムの行数は増加していきます。そこで、パターン用文字列とカラーパレットを別のファイルに設定するようにしましょう。
まず、 カラーパレット用にpalette.yml
ファイルを用意します。内容はYAML記法という書式を使います。
サンプルとして以下の内容を用意しましたので、書き込んで保存します。
_ : [0, 0, 0, 0]
w : [255, 255, 255, 255]
次に、キャラクターのパターン用文字列のためのファイルpattern.txt
を用意します。このファイルはテキストファイルです。改行や空白は無視されます。
これも以下の内容を書き込んで保存します。
__________
___wwww___
__ww__ww__
_ww____ww_
_w______w_
_w______w_
_wwwwwwww_
_w______w_
_w______w_
__________
最後に表示を実行するサンプル・プログラムを紹介します。
require 'dxruby'
require 'yaml'
require './image'
sprite = Sprite.new.tap { |s|
pattern = File.read("./pattern.txt")
palette = YAML.load_file("./palette.yml")
s.image = Image.create_from_string(10, 10, pattern, palette)
s.x = 320
s.y = 240
s.scale_x = 10
s.scale_y = 10
s.offset_sync = true
}
Window.loop { sprite.draw }
実行すると次のような画面が表示されます。
なんだかんだ言ってゲームプログラミングは手間がかかります。素のRubyからゲームを作ろうとすると「あれもない、これもない」って事が多いです。一方で、Rubyではゲーム用に用意された機能があった場合、それを”簡単に”自分用カスタマイズにする手段が用意されています。
簡単にゲームが作れるようになるまでの道のりは長いですが、まあ、気長にやっていきましょう。ではでは。