DXOpalでUndertaleっぽい画面を作る

[12/3の記事](https://qiita.com/yhara/items/24141953af652ad96db0)で公開方法の話をしたので、今日は実際にDXOpalで何か作ってみたいと思います。

2018年も年の瀬ですが、みなさんの今年のベストゲームは何でしょうか？私はPルートの途中で積んでいた[Undertale](https://undertale.jp/)をクリアしたのが思い出深いです。音楽がとても印象的なゲームでしたね。

ということでUndertaleの戦闘画面っぽいものを作ってみましょう。

## セットアップ

index.htmlを開くところまでは以下の記事と同じなので省略します。

- https://magazine.rubyist.net/articles/0057/0057-GameProgramingWithDXOpal.html

## 枠を描く

とりあえず枠を描画しましょう。DXOpalで四角を描くには`Window.draw_box`を使います。

DXOpalのAPIはDXRubyとだいたい同じなので、DXRubyのリファレンスを見ると良いです(たまに実装されていないものもあります。足りないものがあれば[github](https://github.com/yhara/dxopal/issues)か[twitter](https://twitter.com/yhara)かこの記事のコメント欄とかで教えてください。)

- http://mirichi.github.io/dxruby-doc/api/Window.html

ということでdraw_boxを使ってみます。

```rb
require 'dxopal'
include DXOpal
Window.load_resources do
  Window.bgcolor = C_BLACK
  Window.loop do
    Window.draw_box(260, 240, 380, 360, C_WHITE)
  end
end
```

出ました。枠です。

![スクリーンショット 2018-12-05 20.50.35.png](https://qiita-image-store.s3.amazonaws.com/0/43/ddaa58f8-85c5-55ab-fc03-9e0921bafaac.png)

もう一つ、コマンド選択の枠も描きましょう。draw_boxを4つ並べてもいいですが、座標を手で計算するのが面倒なので、ループでやってみました。あとDXOpalには「オレンジ色」はないので、自分で定義しました。

```rb
require 'dxopal'
include DXOpal
# オレンジ色を定義
C_ORANGE = [233, 115, 51]
Window.load_resources do
  Window.bgcolor = C_BLACK

  Window.loop do
    Window.draw_box(260, 240, 380, 360, C_WHITE)

    # コマンド選択の枠
    4.times do |i|
      Window.draw_box(90 + i*120, 400, 190 + i*120, 440, C_ORANGE)
    end
  end
end
```

![スクリーンショット 2018-12-05 20.59.08.png](https://qiita-image-store.s3.amazonaws.com/0/43/335bba69-864c-47c9-98ad-342453002640.png)

## 枠を太くする

draw_boxは太さ1ピクセルの四角を描きますが、これだとちょっと細いですよね。DXOpalには太い四角を描く命令はないですが、draw_box_fillを二回使えば同じことができます。まず枠の色で四角を書いて、中を背景色で塗りつぶすわけです。

これも手で計算するのは大変なので、指定した太さの四角を描くメソッドを作ってみました。

```rb
require 'dxopal'
include DXOpal
C_ORANGE = [233, 115, 51]

# 太い四角を描く(thickness=厚み)
def draw_thick_box(x1, y1, x2, y2, color, thickness)
  Window.draw_box_fill(x1, y1, x2, y2, color)
  t = thickness
  Window.draw_box_fill(x1+t, y1+t, x2-t, y2-t, C_BLACK)
end

Window.load_resources do
  Window.bgcolor = C_BLACK

  Window.loop do
    draw_thick_box(260, 240, 380, 360, C_WHITE, 4)

    4.times do |i|
      draw_thick_box(90 + i*120, 400, 190 + i*120, 440, C_ORANGE, 2)
    end
  end
end
```

このようにWindow.draw_boxをdraw_thick_boxに変えて、厚みを指定すると…

![スクリーンショット 2018-12-05 21.05.26.png](https://qiita-image-store.s3.amazonaws.com/0/43/82849b50-8146-720d-64ad-d39431884998.png)

なんだかそれっぽくなってきました。

## 文字を入れる

文字はWindow.draw_fontで描画できます。HPとコマンド名を表示してみましょう。

```rb
# ...一緒なので省略...
Window.load_resources do
  Window.bgcolor = C_BLACK

  Window.loop do
    draw_thick_box(260, 240, 380, 360, C_WHITE, 4)

    Window.draw_font(260, 370, "HP 20/20", Font.default, color: C_WHITE)

    commands = ["たたかう", "こうどう", "アイテム", "みのがす"]
    4.times do |i|
      x = 90 + i*120
      draw_thick_box(x, 400, x + 100, 440, C_ORANGE, 2)
      Window.draw_font(x + 3, 410, commands[i], Font.default, color: C_ORANGE)
    end
  end
end
```

こんな感じになりました。

![スクリーンショット 2018-12-05 21.15.18.png](https://qiita-image-store.s3.amazonaws.com/0/43/32b3b309-ce4d-0922-7053-f466d23192b3.png)

注意点ですが、draw_fontはパソコン・スマホに入っているフォントを使うので、環境によって見た目が変わる可能性があります。Undertaleみたいな、雰囲気にこだわったゲームを作るのであれば、このへんも全部画像にしてしまうのが良いかもしれません。(あるいはweb fontを使うとか？[こういう丸文字](https://fonts.google.com/specimen/M+PLUS+Rounded+1c)とか魅力的ですね)

まあとりあえず何か表示したいというときにはdraw_fontはとても便利です。

## 文字のサイズを変える

HP表示がちょっと大きい気がするので、Font.newを使って文字のサイズを変えてみます。第一引数がんサイズ、第二引数がフォント名(省略可)です。

```rb
require 'dxopal'
include DXOpal
C_ORANGE = [233, 115, 51]
# HP表示用のFontを定義
FONT_HP = Font.new(18)

def draw_thick_box(x1, y1, x2, y2, color, thickness)
  Window.draw_box_fill(x1, y1, x2, y2, color)
  t = thickness
  Window.draw_box_fill(x1+t, y1+t, x2-t, y2-t, C_BLACK)
end

Window.load_resources do
  Window.bgcolor = C_BLACK

  Window.loop do
    draw_thick_box(260, 240, 380, 360, C_WHITE, 4)

    # HP表示用のFontを使用
    Window.draw_font(270, 370, "HP 20/20", FONT_HP, color: C_WHITE)

    commands = ["たたかう", "こうどう", "アイテム", "みのがす"]
    4.times do |i|
      x = 90 + i*120
      draw_thick_box(x, 400, x + 100, 440, C_ORANGE, 2)
      Window.draw_font(x + 3, 410, commands[i], Font.default, color: C_ORANGE)
    end
  end
end
```

小さくなりました。

![スクリーンショット 2018-12-05 21.29.47.png](https://qiita-image-store.s3.amazonaws.com/0/43/0c14b557-509b-7d9f-1188-50887ae98beb.png)

## 緑の線を描く

ところで実際のUndertaleの戦闘画面を見ると、敵キャラの裏に緑色の線が表示されています(知ってましたか？)　プレイ中は避けるのに必死で気づいてなかったですが、こうやって意識して観察すると意外な発見がありますね。

ということで、2✕6個の緑色の四角形を描画して、今回は終了です。

```rb
# ...
Window.load_resources do
  Window.bgcolor = C_BLACK

  Window.loop do
    # 緑の線を描く
    w = 80; h = 100
    2.times do |row|
      6.times do |col|
        x = 80 + col*w
        y = 20 + row*h
        Window.draw_box(x, y, x+w, y+h, C_GREEN)
      end
    end

    #...
  end
end
```

気づいてなかったと言いましたが、それでも緑の四角を入れると「こんな感じだったような気がする」と思えてくるから不思議です。

![スクリーンショット 2018-12-05 21.48.46.png](https://qiita-image-store.s3.amazonaws.com/0/43/0d6b71f3-8b7c-e31c-c9b6-d7e008de1dd3.png)

## まとめ

今回はDXOpalでUndertaleの戦闘画面っぽいものを表示しました。最終的なソースコードは以下に置いてあります。

- [ソース](https://github.com/yhara/adcal2018/tree/master/06)
- [デモ](https://yhara.github.io/adcal2018/06/)

次回があればキャラクターを表示してみたい…と思ったのですが、なんか緑の線が真ん中だけ微妙に太くなってるのがバグっぽい気がしてきたので、それを直す話になるかもしれません:thinking: 

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">とりあえず自分の目の錯覚ではなかったので良かった。しかしDXOpalを直さないといけないな。</p>&mdash; yhara (Yutaka HARA) (@yhara) <a href="https://twitter.com/yhara/status/1070300492788510720?ref_src=twsrc%5Etfw">2018年12月5日</a></blockquote>