DXOpalでUndertaleっぽい画面を作る(続)

6日目 ([DXOpalでUndertaleっぽい画面を作る](https://qiita.com/yhara/items/c9a2a21ff24c65978205)) の続きです。今回は画像を表示してみましょう。

## 画像

今回使う画像はこちら。

![computer_typing_hayai.png](https://qiita-image-store.s3.amazonaws.com/0/43/52da0140-54e1-f1db-8f83-c53cef6ee961.png)

皆さんご存じの「いらすとや」さんから、["タイピングが速い人のイラスト"](https://www.irasutoya.com/2018/12/blog-post_83.html)をお借りしました。ゲームに使ったという話はあまり聞かないですが、商用かつ21種類以上の画像の使用は有償になるので注意しましょう。

- [ご利用について \| いらすとや](https://www.irasutoya.com/p/terms.html)

## 画像を読み込む

DXOpalでは`Image.register`で使いたい画像を宣言し、`Window.load_resources`で読み込みます。描画は`Window.draw`です。

```rb
require 'dxopal'
include DXOpal
# 使いたい画像を宣言する
Image.register(:enemy, "images/computer_typing_hayai.png")
# ...

# 画像の読み込みが終わったら、ブロック内が実行される
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

    # 画像を表示する
    Window.draw(250, 10, Image[:enemy])
# ...
```

実行結果です。

<img width="647" alt="スクリーンショット 2018-12-10 0.25.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/43/26bb37c0-5d00-ffbc-8cab-07c0f3b0694a.png">

なんともいえない感じになりました。

## 動かしてみる

Undertaleの敵キャラはふわふわ浮いてたような気がするので(キャラにもよりますけど)、"タイピングが速い人"も動かしてみましょう。

動かすにはx・y座標を変数にして値を変化させればいいのですけど、下準備として、敵キャラを表すクラスを作ります。基本、動くものはぜんぶクラスにしたほうがいいです。そうしないとx・y座標を表す変数がたくさんできてわけがわからなくなりますからね。

## クラスを作る

DXOpalでキャラクタを表すクラスを作るときは、Spriteクラスを親クラスにすると便利です。Spriteクラスの使い方はDXRubyのサイトに説明があります。

- [Spriteを使うためのチュートリアル](http://mirichi.github.io/dxruby-doc/tutorial/sprite.html)

今回は敵キャラなのでEnemyというクラス名にしてみます。まずは、前のコードと同じ表示を行うところまでやりましょう。変化した部分にはコメントを入れてあります。

```rb
# ...

# 敵キャラのクラスを定義
class Enemy < Sprite
  def initialize
    x = 250
    y = 10
    # 親クラスの初期化処理を呼ぶ。x座標、y座標、画像の3つが必要
    super(x, y, Image[:enemy])
  end
end

Window.load_resources do
  Window.bgcolor = C_BLACK
  # Enemyクラスのオブジェクトを作る
  enemy = Enemy.new

  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

    # 敵を描画する
    # (座標はenemy自身が知っているので渡さなくてよい!)
    enemy.draw

    # ...
```

敵を描画する部分のコードが、

```rb
    Window.draw(250, 10, Image[:enemy])
```

から

```rb
    enemy.draw
```

に変わりました。座標や画像はenemyが持っているので、メインループ内ではそれらのことをキにしなくて良くなり、すっきりしましたね。

## 座標を変化させる

あとは、enemyのxやyを変化させれば敵キャラを動かすことができます。そのためのメソッドを作りましょう。

DXOpalでは、キャラを動かすメソッドは`update`という名前にしておくと、のちのちキャラが増えたときに`Sprite.update`でまとめて扱えたりして便利です。

ということで、Enemyクラスに`update`メソッドを定義します。とりあえず単純にx座標を増やしてみましょう。Spriteのサブクラスでは、`self.x`でx座標にアクセスできるので、updateが呼ばれるたびに1ずつ増やします。

```rb
class Enemy < Sprite
  # ...

  # 敵キャラを動かす処理
  def update
    self.x += 1
  end
end

# ...

    # 敵キャラを動かす処理を呼ぶ
    enemy.update
    enemy.draw
```

こうなりました。

![](https://gyazo.com/98dffd1cf0981ffe40c1bdc6f5aa0b21.gif)

## いい感じに動かす

動いたのはいいけど、x座標を増やしすぎて画面外まで出ていってしまいました。これだと何もせずに勝利した感じになるので、いい感じに行ったり来たりしてほしいですね。

いろんなやり方がありますが、今回は`Math.cos`を使う方法を紹介します。コードはこちら。

```rb
class Enemy < Sprite
  def initialize
    x = 250
    y = 10
    super(x, y, Image[:enemy])

    # Math.cos用の変数を初期化
    @phase = 0
  end

  def update
    @phase += 0.01
    self.x = 250 + Math.cos(@phase) * 50
  end
end
```

まず適当なインスタンス変数`@phase`を用意して、0に初期化します。これをちょっとずつ増やす(`+= 0.01`)と、`Math.cos(@phase)`が-1〜+1の範囲でなめらかに変化してくれます。なので、それを50倍して250に足すと、`self.x`は200〜300の範囲で変化することになります。

実行結果です。

![output.gif](https://qiita-image-store.s3.amazonaws.com/0/43/5cb4ec10-7ad0-aa2f-9105-574bb47f0119.gif)

0.01や50の部分を適当にいじると、ゆっくりになったり爆速になったりします。いろいろ試してみてください。

## まとめ

今回は画像の扱い方とSpriteクラスについて紹介しました。実際に動いているところは以下で見られます。

- [デモ](https://yhara.github.io/adcal2018/08/)
- [ソース全体](https://github.com/yhara/adcal2018/blob/master/08/main.rb)

次回があれば自機を出してよりゲームっぽくしたいです。