2016年12月19日

Ruby Game Developing Advent Calendar 2016 15日目

Ruby Game Developing Advent Calendar 2016 15日目
(遅刻して申し訳ありません)

Rubyでのゲーム製作全般と言うことで今年やったのは司エンジンにさわったことくらいなので、それについて振り返ろうと思います。

■司エンジン



土屋つかささん製作のDXRuby用のゲームエンジンである司エンジン(Tsukasa Engine)で簡単なデモを作らせていただきました。

司エンジンについての寸評は主催のあおいたくさんが3日目の記事でまとめていらっしゃいます。
とてもわかりやすいのでそちらをご覧ください。

自分が作ったのは次のようなデモです。



気になるオブジェクトをクリックしてイベントを探すアドベンチャーゲームです。
こういうゲーム用の機能が一通り始めからそろっているので、作りやすかったです。
また最初から用意されている機能だけではなくフレームワーク側でコマンドを自分で作ることもできます。
自分は最初ノベルゲー用のエンジンだと思ってましたが、土屋さんはアクションゲームやシミュレーションゲームのデモ、あおいたくさんはブロック崩しを作ったりとノベルゲーに限らずいろんなジャンルのゲームが作れそうです。

■文字表現について考えてみた



司エンジンでぱっと見たときインパクトがあったのがパタパタ板のように張り付いてくる文字の表示の表現です。
自分はあまり文字の表示方について考えたこともなく、ただ表示すればよいと思ってたので見ててなかなか楽しかったです。
文字表現について少し考えさせられたので、上の動画のデモに遭いそうな感じの文字表現を考えてみました。



全画面でみないとよくわからない…ですが、文字がろうそくの用に揺らめいています。
DXRubyのShaderクラスを使ってポストエフェクトをかけています。
ただベタベタっと文字を並べるよりは雰囲気でている…と思うんですが、読みにくい…かもしれませんね。

コードはこちら

posted by 鳴海つかさ at 00:45| Comment(0) | TrackBack(0) | 日記

2015年12月22日

DXRubyAdventCalender2015 22日目

DXRubyAdventCalender2015も22日目になりましたね!

今回はDXRubyWSのGUIとしての見た目のお話になります。

WSにはthemaフォルダというものがありまして、ここにGUIのデザインというか描画の仕方が定義されているRubyスクリプトがあります。
今はguibasic一個しかありませんが。

WS.set_theme('フォルダ名')でフォルダの中の定義ファイルをすべて読み込んでGUIの見た目を変えることができます。

guibasicを読み込むとこのような感じ。

WS1.jpg

何も読み込まないとこのような感じになります。

WS2.jpg

定義ファイルの中身は単純に各コントロールの描画メソッド部分をオーバーライドするというものなので、誰でも簡単に変更できます。

では、実際にthemeを作ってオリジナルのGUIを作ってみましょう。

簡単なのはボタンでしょうか?
最近よく使われているフラットデザイン的なのを作ってみましょう。

まずはthemeフォルダ内にguiflatというフォルダを作ります。

次に適当な名前のRubyスクリプトファイルを作ります。
これもguiflatとでもしておきましょう。

さてボタンの描画を変えたいのでstandardguiのbuttonのスクリプトを見て描画部分を見つけてきましょう。


module WS
class WSButtonBase
# set_imageで@image[true](押された絵)と@image[false](通常の絵)を設定する。
# オーバーライドしてこのメソッドを再定義することでボタンの絵を変更することができる。
def set_image
# 画像を再作成する前にdisposeする
@image.each_value{|image| image.dispose if image.disposed?}

# 通常時の画像を作成
@image[:usual] = Image.new(@width, @height, COLOR[:base]).draw_border(true)
# 押下時の画像を作成
@image[:pushed] = Image.new(@width, @height, COLOR[:base]).draw_border(false)
# キャプションの描画
if @caption.length > 0
width = @font.get_width(@caption)
@image[:usual].draw_font_ex(@width / 2 - width / 2 ,
@height / 2 - @font.size / 2 ,
@caption, @font, {:color => @fore_color, :aa => false})

@image[:pushed].draw_font_ex(@width / 2 - width / 2 + 1,
@height / 2 - @font.size / 2 + 1,
@caption, @font, {:color => @fore_color, :aa => false})
end
refreshed
end

def render
set_image if refresh?
change_image
end

def draw
super
if self.image && self.activated?
self.target.draw_line(self.x - 1, self.y - 1, self.x + @width, self.y - 1, C_BLACK)
self.target.draw_line(self.x - 1, self.y - 1, self.x - 1, self.y + @height, C_BLACK)
self.target.draw_line(self.x + @width, self.y - 1, self.x + @width, self.y + @height, C_BLACK)
self.target.draw_line(self.x - 1, self.y + @height, self.x + @width, self.y + @height, C_BLACK)
end
end
end


大体この辺りでしょうか?
あらかじめ画像を作ってキャッシュしておいて、ボタンの状態によってそれを切り替える方式のようなので、その画像を作るところを書き換えれば良さそうです。


module WS
class WSButtonBase
# set_imageで@image[true](押された絵)と@image[false](通常の絵)を設定する。
# オーバーライドしてこのメソッドを再定義することでボタンの絵を変更することができる。
def set_image
# 画像を再作成する前にdisposeする
@image.each_value{|image| image.dispose if image.disposed?}

# 通常時の画像を作成
@image[:usual] = Image.new(@width, @height, COLOR[0, 102, 153])
# 押下時の画像を作成
@image[:pushed] = Image.new(@width, @height, COLOR[0, 50, 76])
# キャプションの描画
if @caption.length > 0
width = @font.get_width(@caption)
@image[:usual].draw_font_ex(@width / 2 - width / 2 ,
@height / 2 - @font.size / 2 ,
@caption, @font, {:color => @fore_color, :aa => false})

@image[:pushed].draw_font_ex(@width / 2 - width / 2 + 1,
@height / 2 - @font.size / 2 + 1,
@caption, @font, {:color => @fore_color, :aa => false})
end
refreshed
end


さてこれでWS.set_theme("guiflat")で読み込むとこうなります。

WS3.jpg

(思ってたのとなんか違うというか。
ボタンのサイズを大きめにするとか他のコントロールも書き換えたらそれっぽくみえますかねえ?)

ちなみに余談ですが、テーマ読み込まない状態のGUIは全部DXRubyの図形描画メソッドで書かれてます。
draw_lineなどを駆使してドット絵を描くがごとく描かれてるわけですね。
まさにDXRuby純正といった感じです。

guibasicは逆にコントロールの画像ファイルが用意されててそれをつかって描画しています。
画像データはソースに貼り付けてあるのでスクリプトの他に画像をダウンロードする必要はありません。

両極端な感じですがサンプルとしてはおもしろいような・・・

こういった感じでコントロール毎に描画処理を変更していけばオリジナルのGUIの完成です。
何か作ったら是非mirichiさんのGitHubに是非プルリクしましょう!

次回はあおたくさん『野メイド拡張講座』です!
あおたくさん作DXRubyACゲーム野メイドを自分好みに作り替えてイチャラブできる…そんな夢が叶う…

おまけ

guibasicを作る時に色の参考にしたサイト


RGBだけじゃなくて色んな色表現がのっていて、明度や彩度が違うカラーの一覧も載っていてとても便利でした。

ソースに貼る画像を文字列にするツールを作った


いちいちコマンドラインでやるのが面倒だという方は使ってあげてください。
アイコンにドラッグ&ドロップすると画像と同名のテキストファイルを作ってくれます。
これをDXRuby上でload_from_file_in_memoryにかければで画像に戻ります。
(文字列はunpack('m')[0]で渡してください)
あとocraで固めたものなので環境によっては動かないかもしれません。
posted by 鳴海つかさ at 20:53| Comment(0) | TrackBack(0) | 日記

2015年12月14日

DXRubyAdventCalender2015 14日目

この記事はDXRuby Advent Calendar 2014の14日目です。

今年も昨年に引き続きDXRubyWSを使った作例の紹介になります。

■DXRubyWSを使ってゲームっぽいもの作ろう



2014年はDXRubyWSを使って作ったエフェクト作成ツールと、そのツールで作ったエフェクトをプログラム上で再生するデモを紹介しました。

今年はDXRubyの基本に立ち戻りDXRubyWSを使ったゲームを作ろうと思います。

DXRubyWSはWindowSystemの名の通りDXRuby上でWindowベースのGUIを作るのに適したライブラリです。
機能を見るとどっちかというとアプリ向けでありゲームに使うにはオーバースペックという意見が見られます。
ただ、スプライトを階層化して管理する機能を上手く使えばゲーム制作にも便利だと思います。

実用上はマウスで操作するゲームのメニュー部分なんかをWSで作って、ゲーム部分は自分で作るみたいな使い分けをするような形になるでしょうか。

どのような形が一番いいのかはわからないですが、今回はWSの機能を積極的に使う方向で考えてみます。

まずはどういうゲームがいいか考えましょう。

WSにはマウスイベントを受け取る機能があります。
WSのコントロールオブジェクトに対してクリックやドラッグなどを行うと、それに応じて処理を実行してくれるので、それを軸にしてみます。

マウスを使うゲームというとOSU!みたいなタイプの音ゲー、メイドインワリオのタッチペン使って遊ぶようなミニゲームなどが候補でしょうか。

ということで、今回はうちのマスコットエイプリルの頭をなでなでするゲームで行きます。

■エイプリルなでなでゲーム(仮)



まずは簡単に構造を考えましょう。

WSでアプリを作る時はウィンドウを作ってそこにボタンやらチェックボックスやらコントロールを配置します。
WSControlオブジェクトはWSContainerによって管理され、コンテナが配下のコントロールにイベントを流します。
ウィンドウがコンテナで、ボタンなどがコントロールですね。

標準コントロールのウィンドウをそのまま使ってもよいですが、標準のウィンドウはいろいろと機能がついていて、今回はそれらは使わないのでGameScreenというコンテナを作ってそれにコントロールを管理してもらうことにしましょう。

さて、他に必要なものは、なでなでされるキャラクターですね。
これは単純コントロールとして作ってもよいのですが、コンテナとして内部をパーツ分けすると別のものに使い回す時に便利だと思われるので、Charaというコンテナを作って中にパーツを配置していく形にします。

中身についてですが、せっかくなので表情の変化なども行えるようにキャラクターのベースと顔を分けておこうと思います。
また、マウスで左右にドラッグするとなでなでしていると判定される判定用のコントロールも作りましょう。

必要なものと構造をまとめるとこのような感じですね。

WS.desktop
聾SGameScreen
 聾SChara
  聾SFace
  聾SNadeNadeArea

全部説明すると長くなってしまうので特に重要な部分だけ簡単に解説します。


module WS
class WSChara
### なでなで判定エリア ###
class WSNadeAreaA < WSControl
include Draggable
def initialize(cx, cy, width, height)
super(cx, cy, width, height)
end
end
end
end


Draggableモジュールをインクルードするとドラッグ処理に関するイベントを受け取ることができるようになります。
コントロールをドラッグした際自動でon_drag_moveメソッドが実行されます。
また:drag_moveとして登録されているハンドラが実行されます。
WSNadeAreaA内にon_drag_moveメソッドを作ってその中で処理を行ってもよいですし、上の構造からハンドラ
を登録して処理をさせても構いません。
処理の流れや構造にあった方法を選択しましょう。
それらのメソッドやハンドラはドラッグ開始点からマウスのx,y座標がどれくらい移動したかを引数としてうけとります。
例えばウィンドウをドラッグした場合、受け取った移動量からウィンドウの座標を求めて再設定する処理を書くことでウィンドウの移動処理が作れます。

今回は移動量からなでる速度を求めて丁度いい速度の時だけスコアがあがる。
早すぎたり遅すぎたりしたらスコアが下がるようにします。


module WS
class WSChara < WSContainer
def initialize(cx, cy, width, height)
super(cx, cy, width, height)
@stroke = 0
@last_stroke = 0
@score = 0
create_control
end

def create_control
area = WSNadeAreaA.new(50, 20, 220, 100)
add_control(area_a, :c_area_a)
area_a.add_handler(:score_reset){ score_reset }
area_a.add_handler(:drag_move, method(:nadenade))
end

def nadenade(obj, dx, dy)
@stroke = (@last_stroke - dx).abs
@last_stroke = dx
case @stroke
when 1
@score += 2 if @score < 20
when 2...4
@score += 4
when 5...8
@score += 1
when 9...24
@score = -200 if @score > -200
when 25...640
@score = -500
end
end
end
end


ざっくりとこのような感じで。
ドラッグ時のイベントで渡されてくる移動量dxから1フレームでどれくらい動いているかを判定して丁度いい速さなら
@scoreに+4、ちょっと早いなら+2、遅いなら+1、とても早いなら大きくマイナス。
このようなメソッドをWSCharaに作り、配下のWSNadeAreaオブジェクトのarea_aの:drag_moveハンドラとして登録します。
area_aがドラッグされる度にハンドラとして登録したnadenadeが実行され、引数としてドラッグ量が渡されるのでそれを元にスコアが算出されます。

このように、WSではドラッグやクリックなどの判定や実行結果などを利用し処理を実行させるための基本的な処理が用意されていてお手軽に作ることができます。

■まとめ



ということで、今回突貫で作ったゲームがこちら。

【エイプリルなでなでゲーム】
http://www.abish.sakura.ne.jp/el/NTAC2015.zip


adc15.jpg

遊び方
・エイプリルの頭のあたりを丁度いい速度で左右にドラッグしてなでなでしてください。
・エイプリルが喜ぶと表情が変わります。
・最高にハイになるとなんかキラキラします。
・エイプリルが嫌がるとしょんぼりします。  

雑なゲームですが是非さわってみてください。
これ判定範囲や表情パターンなどを変えたらドキドキ魔女裁判みたいないかがわしいゲームが作れそうですよね。
また今回作ったWSCharaから判定を取っ払ってWSFaceに目パチや口パク処理をつければ立ち絵のひな形として使えそうですね。
最小構成にするという意味ではどうしても自分で一から作るがよいことになりますが、アイデア次第ではメニューなどのインターフェース以外にもWSを使っていろいろなゲームパーツがつくれそうです。

明日は土屋つかささんの『ショートショートなノベルゲームを作ってみた』です。
ノベルエンジンの制作者である土屋さんのノベルゲーム、とても楽しみですね!
posted by 鳴海つかさ at 22:15| Comment(0) | TrackBack(0) | 日記

2014年12月20日

DXRubyAdventCalender20日目

この記事はDXRuby Advent Calendar 2014の20日目です。
19日の記事はカイリカさんの『DXRubyWS 入門』でした。
WSの導入から実際に使用するまでの流れがわかりやすく書いてあり参考になりました。
WSは現在mirichiさんにより開発中のDXRuby用のGUIライブラリです。
ゲームやアプリなどに使えるウィジェットやコントロールを作成するための機能が手軽に使えるのでご興味がありましたら是非さわってみてください。


■DXRubyWSを使った作例など


というようなお題目で記事を書く予定だったのですが、カイリカさんが非常にわかりやすい記事を書いてくださったので今回はコード的な話ではなく作ったものを触っていただこうと思います。
つまり…自分で作ったものをただ紹介するコーナーです…!


■NFXとは


まずは自分がDXRubyWSで作成中のツールなるみんエフェクタ(以下NFX)をご紹介いたします。
NFXはパーティクルエフェクトを作成するためのツールです。

パーティクルエフェクトについてはここでは大雑把に『ある一点(あるいは領域)から放射状に画像を放出する映像表現』としておきます。

以下の三つの要素から成り立っています。

・PartsImage
パーティクル画像のデータクラス。
アニメーションで使うための画像ファイルの分割方法を指定するクラス。

・Parts
パーティクルのデータクラス。
簡易なキーフレーム方式でスプライトの拡大、回転、色調変化を設定する機能。

・Emitter
上述のスプライト(パーティクル)に速度と角度を与えて放出するエミッターの設定する機能。


現在はこの三つのクラスにパラメータを設定することができます。
とりあえずどういった物なのか実際に動かしてみたら感じがつかめると思います。
起動してパラメータを適当にいじってみてください。

Ocraでexe化したものがこちら 
一応コードはこちら
GitHubのNFXのページ


■なぜNFXなのか


こういったエフェクトはコードで書くことも可能なのですが、凝った物を作ろうとすると設定するパラメータは結構な量になると思います。
何よりパラメータを書く→ゲームを実行して確認→パラメータ修正→ゲームを実行して確認
この作業を繰り返すのはかなりしんどいのではないかと思います。
なので、こういった作業を視覚的に行えれば楽ちんだろうという考えのもとにNFXは開発されました。
作ったエフェクトはマーシャルデータとして保存されるので、ゲームに使う際はそのデータを読み込み実行用のコードをrequireすれば簡単に再生できます。
面倒な作業を省略し、ゲームの方のコードも見やすくできるのがこのようなソフトを利用する利点ですね。


■サンプル



さて、せっかくなので実際にNFXで作ったエフェクトをプログラムで利用してみましょう。

ocraでexe化した物はこちら
サンプルコード
GitHub AdventCalender2014のページ
main.rb


まずは必要なスクリプト群を読み込みます(多い)
それぞれエフェクトの実行コードやエフェクトデータや画像の管理なんかを行うクラスやモジュールです。
エフェクトのデータはそれぞれ$data_emitterと$data_particleに格納されます(変更可 )

# スクリプトの読み込み
require_relative 'Scripts/ntmodule' # 基本的なモジュール
require_relative 'Scripts/posteffect' # シェーダーの定義
require_relative 'Scripts/dataclass' # データ構造の定義クラス
require_relative 'Scripts/gamemodule' # ゲーム用モジュール
require_relative 'Scripts/gameobj' # アニメーション実行スプライトの定義

DataManager.load_effect # エフェクトデータの読み込み


ここからがエフェクトの利用法になります。

### トレイル用エフェクトの定義 ###
class Trail

def initialize
@effect = []
# トレイルエフェクト
@effect << Game_Emitter.new($data_emitter[5])
@effect << Game_Emitter.new($data_emitter[6])
@effect << Game_Parts.new($data_parts[6])
@effect << Game_Parts.new($data_parts[4])
# 爆発エフェクト
@effect << Game_Emitter.new($data_emitter[1])
@effect.last.finish # 自動でスタートするので一旦終了
end

# 爆発を表示
def display_bomb
# 爆発エフェクトが終了中なら爆発表示開始
@effect.last.set_up if @effect.last.finish?
end

def update
# 左クリックで爆発表示
display_bomb if Input.mouse_push?(M_LBUTTON)
Sprite.update(@effect)
@effect.each{|e| e.set_pos(Input.mouse_pos_x / Window.scale, Input.mouse_pos_y / Window.scale)}
end

def draw
Sprite.draw(@effect)
end

end

基本的な使い方はinitializeの部分にあるとおりです。
エミッターを使いたければGame_Emitterをnewして引数としてエミッターの設定データを渡してあげるだけです。
パーティクルは基本的にエミッターから放出して使いますが、単体表示したければGame_Partsをnewしてパーティクルのデータを渡しましょう。
あとは自動で再生が開始されます。
updateを呼ぶとカウントが進みアニメーションしていきます。
止めたい時はfinishで再生終了して待機します。
待機中のエフェクトの再生はset_up。
とても簡単ですね!
またエフェクトデータを与えて別のエフェクトとして再利用することもできます。

それでは実際に起動して見ましょう。
Windowが表示されたら画面内にカーソルを持っていきましょう。
マウスカーソルの位置に光が表示されます。
マウスカーソルを移動すると光も追従し軌跡を残します。
右クリックで爆発が発生します。

とまあこれだけの簡素なプログラムですが…派手なエフェクトが表示されるとなんか画面がリッチになった気がしませんか?


■おわりに


ゲームを作る上であったらうれしいエフェクト。
しかしこれをコードとにらめっこし、結果を頭で計算し設定するのは非常に大変な作業です。
可視化できたら楽なのに…
はじめはRGSSでエフェクト製作用のGUI作りを始めましたが操作性や画面解像度などいろいろな問題に直面しました。
DXRubyを始めてからしばらくした頃mirichiさんがDXRubyWSの開発を開始しました。
「これは!」と思ってWSを使って再び挑戦しましたが、これで作れるアプリはWindowsような見た目と操作感なのでとても使いやすい物になりました。
そしてそういったものがわりと簡単に作れるのがWSの魅力ですね!

さて次回は21日目
あおいたくさんの『DXRubyユーザーのための標準添付ライブラリ』です。
お楽しみに!
posted by 鳴海つかさ at 00:20| Comment(0) | TrackBack(0) | 日記