mieki256's diary



2016/01/14(木) [n年前の日記]

#1 [dxruby][dxrubyws] DXRubyWSのウインドウの中で60FPSのゲームを動かしたい

要するに、 _DXRubyWS/sample/rubima.rb のようなことをしてみたいのです。どういう仕組みで、ウインドウ内にゲーム画面を表示できているのだろう…。

眺めているうちに、なんとなく分かってきた。もしかすると、こういうことかな…。
rubima.rb を改造して、少しだけ短めのサンプルソースにしてみたり。

_game_and_info.rb
# DXRubyWSのウインドウ内に、60FPSで動くゲーム画面を表示してみるテスト
# sample/rubima.rb を参考に作成

require 'dxruby'
require_relative 'lib/dxrubyws'
require_relative 'lib/standardgui'

# ----------------------------------------
# ゲーム画面用クラス
# ゲーム画面内で画像がバウンドするだけの処理
class GameMain

  attr_accessor :width, :height, :image

  # 初期化
  def initialize
    @x, @y = 100, 100
    @dx, @dy = 8, 4

    @width = 360
    @height = 480

    @image = Image.new(64, 64, C_WHITE)
  end

  # 更新
  def update

    # 座標に速度を加算
    @x += @dx
    @y += @dy

    # 画面外に出そうなら速度の向きを反転させる
    @dx *= -1 if (@x <= 0 and @dx < 0) or ((@x + @image.width) >= @width and @dx > 0)
    @dy *= -1 if (@y <= 0 and @dy < 0) or ((@y + @image.height) >= @height and @dy > 0)
  end

  # 描画
  def draw
    # グローバルなRenderTargetに対して描画してる
    $rt.draw(@x, @y, @image)
  end
end

# ----------------------------------------
# ウインドウシステム用のクラス定義
module WS

  # ----------------------------------------
  # ゲーム画面が表示されるウインドウ
  class GameWindow < WSWindow

    def initialize(*args)
      super
    end

    # サイズ変更されたら再描画
    def resize(*args)
      super
      self.client.image.draw(0, 0, $rt)

      # ゲーム画面サイズも変更しておく
      $gamemain.width = self.width
      $gamemain.height = self.height - 32
    end

    # 描画
    def draw
      super
    end
  end

  # ----------------------------------------
  # ゲーム画面ではないほうのウインドウ
  class DetailWindow < WSWindow

    def initialize(*args)
      super

      # ラベル生成と登録
      x, y, w, h = 8, 8, 100, 16
      @label = WSLabel.new(x, y, w, h, "TEST")
      self.client.add_control(@label)

      # ボタン生成と登録
      x, y, w, h = 8, 32, 150, 20
      button = WSButton.new(x, y, w, h, "画像読み込み")
      self.client.add_control(button)

      # ボタンが押された時の処理を登録
      button.add_handler(:click, self.method(:on_click))

      @count = 0
    end

    # 状態更新
    def update
      # カウントアップをラベルで表示してみる
      @label.caption = @count.to_s
      @count += 1
      super
    end

    # ボタンが押された時の処理
    def on_click(obj, tx, ty)
      # ファイル選択ダイアログを開く
      filter = [
        ["PNGファイル(*.png)", "*.png"],
        ["すべてのファイル(*.*)", "*.*"],
      ]
      filepath = Window.openFilename(filter, "画像ファイルを選択")
      if filepath
        # ゲーム画面用クラスの画像を差し替える
        $gamemain.image = Image.load(filepath)
      end
    end
  end
end


# ----------------------------------------
# ここから、ゲームのメイン処理

font = Font.new(24) # フォント生成

Window.width, Window.height = 800, 600 # 画面サイズ変更

# ゲーム画面を描画するための RenderTarget を生成して
# グローバル変数に入れておく
$rt = RenderTarget.new(360, 480, [0, 0, 0])

# ゲーム画面クラスを生成
$gamemain = GameMain.new()

# ゲーム画面用ウインドウを生成して画面に登録
gamewindow = WS::GameWindow.new(50,100,360,480)
WS::desktop.add_control(gamewindow, :gamewindow)

# ゲーム画面ではないウインドウを生成して画面に登録
detailwindow = WS::DetailWindow.new(450,100,200,200)
WS::desktop.add_control(detailwindow, :detailwindow)

# メインループ
Window.loop do
  break if Input.key_push?(K_ESCAPE) # Esc キーで終了

  # ここでゲームの処理をする
  $gamemain.update
  $gamemain.draw

  # ここまで来れば、グローバルなRenderTargetに、
  # ゲーム画面の内容が描画されてるはず

  # ゲーム画面用ウインドウに、グローバルなRenderTargetの内容を描画する
  WS.desktop.gamewindow.client.image.draw(0, 0, $rt)

  WS.update # ここで WS.update を呼んでる

  # 各種情報を画面に出力
  s = "CPU : #{Window.get_load.to_i} %"
  Window.draw_font(0, 0, s, font, :z => 100)
end
game_and_info.gif
DXRubyWSのウインドウの中で、ゲーム画面っぽいものが動いてくれた。なるほど…こういう仕組みなのか…。

他のサンプルはどうなのだろうと思って、 _DXRubyWS/sample/rubima3.rb を眺めてみたら、こちらは GameWindowクラスの中身がもっと短くなっていた。drawメソッドの中で描画しちゃえば済むのか…。なるほど…。

こういうことができるなら、リアルタイムに何かを動かしながら調整していく感じのツールが作りやすいであろう予感。

以上です。

過去ログ表示

Prev - 2016/01 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
31

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project