-- / --
--
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

03 / 30
Sun

引っ越しが終わった Ziphil です。

私のプログラムでは、 アイテムなどのデータベースは、 アイテム ID をキーとしたハッシュで管理しています。 そこで、 すべてのデータベースを合わせた 1 つのハッシュを作ろうとして、 hash1 + has2 のように書いたら、 Hash#+ がないと怒られました。 ・・・ないの?

どうやら、 こういう場合は Hash#merge を使うみたいです。 調べてみると、 ただ 2 つのハッシュを混合したハッシュを作るだけでなく、 キーが重複した場合の処理を指定できるみたいです。

hash1 = {:a => 2, :b => 4, :c => 9}
hash2 = {:b => 5, :c => 6, :d => 7}
p hash1.merge(hash2){|key, value1, value2| value1 + value2}    #=> {:a => 2, :b => 9, :c => 15, :d => 7}

次です。 Object#tap というメソッドを知りました。 これは、 self をブロックの引数として評価した後、 self そのものを返すメソッドです。 で、 こんなメソッドが何の役に立つかというと、 メソッドチェーンの途中経過を覗けるんです。

x = [1, 3, 5, 6, 8, 10, 13, 16, 18, 19, 21, 22, 24]
y = x.select(&:even?).map(&:succ)

こんな風に、 配列から偶数だけを取り出して、 それぞれに 1 をたした配列を作りたいとします。

x = [1, 3, 5, 6, 8, 10, 13, 16, 18, 19, 21, 22, 24]
y = x.select(&:even?).tap{|t| p t}.map(&:succ)    # => [6, 8, 10, 16, 18, 22, 24]

こんな感じに途中に tap をはさめば、 select メソッド実行後の途中経過を見ることができるわけです。

デバッグっぽい使い方以外にも、 使い道がありますよ。

x = [2, 5, 8]
p x.inject({}){|h, t| h[t] = t ** 2; h}        # => {2 => 4, 5 => 10, 8 => 16}
p x.inject({}){|h, t| h.tap{h[t] = t ** 2}}    # => {2 => 4, 5 => 10, 8 => 16}

こんな感じに、 配列の各値をキーとして、 その 2 乗を値とするハッシュを作ろうとするわけです。 普通なら 2 行目みたいに inject 使えばいいんですが、 どうも ; h ってのが美しくない。 そこで、 tap の出番です。 多少冗長にはなりますが、 見た目が美しくなります。 効果には個人差があります。

まあ、 何をしているかというと、 破壊的メソッドを実行したときに自分自身が返るようにしているわけです。 要するにかっこつけです。 はい。

とまあ、 Ruby の豆知識でした。


comment ×0
03 / 21
Fri

パソコンよりスマートフォンの方が速度が速い Ziphil です。 ・・・早く新しいパソコンにしたい。

さて、 防具のデータベース (名前だけ) ができました。 42 種類あります。 正直、 これだけ探すのには苦労しました。 「重~」 「ヘビー~」 で水増ししているのもありますが・・・。

789_防具リスト

この 42 種類の防具のステータスを決める方が大変ですけどね。

首装備と指装備は、 基本的に補助用で、 各種ステータスの上昇用にしようと思っています。 それ以外は、 軽装備用と重装備用で同じ数ずつ用意してあります。

プログラミングをしようにも、 データベースが定まってないとできない状況に来てしまってるんですよね・・・。 防具と遠距離武器の設定を、 さっさと済ませておかないとですね。


03/22 よくよく見てみたら、 「鎧」 っていう全般的な名称と 「板金鎧」 とかいう具体的な名称が別々になってますね・・・。 「板金鎧」 だって 「鎧」 だろ! ・・・みたいなツッコミはなしの方向で。


comment ×0
03 / 19
Wed

スマートフォンの画質に感動する Ziphil です。

RPG などで、 ゲームを進んでいるとよく完全上位互換の武器とかが手に入りますよね。 自分が今持っている武器より、 どのステータスから見ても強い武器のことです。 こういうのが頻発するゲームはあまり好きではありません。 これまでの武器を売って新しい武器を手に入れるだけで、 武器を選択する楽しみがなくなります。

私個人の意見ですが、 過去に用いた武器や防具を頻繁に売ることになる RPG は微妙です。 ゲームを進めると、 いろいろな武器が手に入り、 迫り来る敵にはどれが最も適切かを考えるのが楽しいんです。

ということで、 武器の設定は並列に行うようにしています。 いろいろな特徴をもった武器が何種類もあるみたいな感じです。 まあ、 データベースの設定はその分大変になりますけどね。


comment ×0
03 / 18
Tue

引っ越しの処理が大変なことになりそうな Ziphil です。

さて、 プログラミングから離れ、 データベースの設定といきましょうか。 RPG を作成するときに最も重要で最も面倒な部分です。

以前、 データベースの一部と仕組みについて書きましたが、 これを変更しました。 これまでは 「2d9611」 という方式で武器などの威力を表現していましたが、 これだとちょっと分かりにくい。 ということで、 「123±110」 という方式で表現することにしました。 こうすれば、 最大値, 最小値, 平均値がわりとすぐに分かり、 便利だと思うんですよ。

ということで、 近接武器のデータベースを書き換えて、 今は防具とかのデータベースを設定しているところです。 これが武器以上に厄介なんです。 各部位に 6 種類くらい必要だと思っているんですが、 そんなに種類が思いつかないです。 いや本当はあるかもしれないんですけど、 私には無理でした。

・・・ということで、 いろいろな RPG から情報収集しないとです。 んー、 大変です。


comment ×0
03 / 13
Thu

PHP もやってみたいと思い始めた Ziphil です。

Ruby で開発をするとき、 私は基本的に 1 つのファイルに 1 つのクラスを書くようにしています。 あるクラスだけで使用される補助的なクラスだけは、 例外として、 用いられるクラスが書かれているファイルと同じファイルに書きます。 これは Java からの遺産です。

このとき、 MainCanvas.rb のようにファイル名をクラス名そのままにしてたんですが、 全部小文字が主流のようですね。 そういえば、 ライブラリ名は全部小文字だった。 別に何かこだわりがあってキャメルケースのファイル名にしてるわけではないので、 ここは慣習に乗ろうと思っています。 でも修正面倒だなぁ・・・。

ここからはまた違う話ですが、 Ruby の for 文って each メソッドのシンタックスシュガーじゃないですか。 私はこの for 文を結構使うんですが、 なんだか each だけ特別扱いってのもどうかと思うんですよね。 ということで、 for 文使うのをやめようかと。

# for 文
for x in 1..100
  for y in 1..(x * 2)
    x.do_something
    y.do_something
  end
end
# each
(1..100).each do |x|
  (1..(x * 2)).each do |y|
    x.do_something
    y.do_something
  end
end

これも、 正直どっちでも良いんですよね。 私が for 文をよく使うのは、 HSP とか Java とかの遺産だと思います。 これらの言語には each なんてないので。

それと、 1..100 っていうのは良いんですが、 1..(x * 2) って少し気持ち悪いんですよね。 あ、 別にカッコは不要で 1..x * 2 でも問題ないんですけど、 これはこれで * 2 が離れちゃって微妙。 じゃ、 Range.new(1, x * 2) で! いや、 いっそのこと、 each なんてやめて Numeric#step を使うとか。 この辺は、 個人の印象によりますね。

次行きましょう。 私のコードにこんな部分があります。

def load_short_weapon_file
  regexp = /(\d+);\s*(.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+)/
  open("../data/data/database/item-1.txt") do |file|
    while line = file.gets
      if line =~ regexp
        # 省略
        data_string.split(/\s*,\s*/).each_with_index do |data, i|
          case keys[i][1]
            # 省略
          end
        end
      end
    end
  end
end   

最後に end が連なってますね。 Ruby の構文からして連なるのは仕方ないんですが、 一部の Rubyist には 「END HELL」 とまで言われて嫌われているそうです。 私は別に気にしませんけどね。

で、 ある人は言いました。 こうすれば良いではないか、 と。

def load_short_weapon_file
  regexp = /(\d+);\s*(.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+,\s*.+)/
  open("../data/data/database/item-1.txt") do |file|
    while line = file.gets
      if line =~ regexp
        # 省略
        data_string.split(/\s*,\s*/).each_with_index do |data, i|
          case keys[i][1]
            # 省略
          ennnnnnd    # ←これ

変態的です。 嫌いじゃないですけど。 しかも、 これ parse.y とか書き換えれば実装できるんですよ。 いや、 でもこれインデントどうなるんだよ。

そうそう、 Python はインデントでブロックを明示するので、 そもそも end を書かないんですよね。 そのアイデアは良いと思うんですが、 閉じがないのでアンバランスな気がしないでもないです。

また話が変わります。 私、 RPG 開発などは JRuby でやってますが、 ちょっとした小物を作るときは生の Ruby を使ってます。 バージョンは 1.9.1 とすでに一昔前のものを使ってますが、 これはもうすぐパソコンを買い換えるので、 最新版をインストールするのが面倒なだけです。 CGI なんかは 1.8.7 で作ってます。 サポートはとっくに終わってることは知ってるんですが、 借りているサーバーが 1.8.7 なので仕方ない。

で、 最近というわけではもうなくなってますが、 Ruby 2.0 って何ができるの? いや、 最近は Ruby 2.1 が出てるみたいで、 それでは何ができるの? ・・・ということです。

一番の変化は、 やっぱりキーワード引数でしょうね。 1.9 でも最後の引数がハッシュの場合は、 ハッシュの波カッコを省略できるようになっていて、 これによってキーワード引数っぽいことができました。 2.0 は、 キーワード引数が正式な構文になったようです。 私はあまり使わないと思います。

2.1 からの新機能ですが、 どれを取り上げれば良いのか分かりませんが、 数値リテラルが増えました。 r をつけると Rational 型に、 i をつけると Complex 型に。 まあ、 これは良いんですが、 私は f がほしいです。 2.0 なんて書くより 2f の方がきれいだと思います。

後は、 def の返り値ですかね。 メソッド名の Symbol インスタンスを返します。 これによって、 private def ~ という書き方が可能になりました。 便利だと思います。 でも、 Ruby を使うときは、 私はあまり private とか public とか気にしたことがありません。

とまあ、 Ruby の雑多な話題でした。


comment ×0
03 / 09
Sun

IDE を NetBeans に変えてみた Ziphil です。

こんな風に定数を定義して。

BORDER = 1
ROOM = 2
PATH = 3
VERTICAL = 10
HORIZONTAL = 11

で、 こんな風に書けば、 定数を定義せずに数値を書くより、 何をしてるか分かりやすいじゃないですか。

if area.width >= minimum * 2 + 1
  bx = rand(area.width - minimum * 2) + minimum
  area.height.times do |j|
    @tiles[area.y + j][area.x + bx] = BORDER
  end 
  @areas[i..i] = area.devide(bx, VERTICAL)
end

正直、 定数の実際の値なんてどうでも良いじゃないですか。 ここでは、 VERTICAL の値を 10 にしてますが、 別に 100 でも 1000 でも良いんです。

数値である必要もなく、 VERTICAL = :vertical としても良いわけです。 しかし、 :vertical で具体的な意味が分かるので、 もはや定数を定義する意味がなくなります。 では、 定数の定義をやめてシンボルを使ってみると、 こうなります。

if area.width >= minimum * 2 + 1
  bx = rand(area.width - minimum * 2) + minimum
  area.height.times do |j|
    @tiles[area.y + j][area.x + bx] = :border
  end 
  @areas[i..i] = area.devide(bx, :vertical)
end

こうすれば、 定数の定義も必要なく、 かつ何をしているのか分かりやすい。 これでも・・・、良いんですよね?


03/09 リファレンスマニュアルを見てみると、 シンボルの用途に 「C の enum 的な使用」 というのがありました。 そもそも、 列挙型と定数って何が違うんでしょう。

例えば、 静的型付けの Java を例にとってみましょう。 定数を定義してみます。

public static final int VERTICAL = 10;
public static final int HORIZONTAL = 11;

このとき、 VERTICAL, HORIZONTAL はともにただの int 型の数値ですから、 VERTICAL もしくは HORIZONTAL を要求するメソッド引数に、 5 や 100 などの他の int 型数値を指定することができてしまいます。 型の保証が崩れます。 これを解消するものが列挙型だと思います。

public enum Direction {
  VERTICAL, HORIZONTAL
}

こうしておけば、 VERTICAL, HORIZONTAL は Direction 型ですから、 これらを要求するメソッドも Direction 型を要求するようにしておけば、 5 や 100 などの関係ない数値を指定するとエラーになってくれます。

と、 Java ではこのような恩恵が得られますが、 Ruby は動的型付けですから、 列挙型も定数も同じようなものになってしまう気がします。 ということで、 シンボルを列挙型の代用としても、 定数を使っても、 特に違いはないわけですから、 ここは好みの問題になるんでしょうか。


comment ×0
03 / 08
Sat

Lisp が気になる Ziphil です。

ランダムダンジョン関係の処理が一段落したので、 タイトル画面を作ってみました。 ちなみに、 考えた結果、 ランダムダンジョンの生成アルゴリズムは 4 種類で十分だということになりました。

776A_製作過程A

あれ・・・、 ドット絵・・・?

ドット絵ではないです。 つまりどういうことかというと、 私にはこんなに大きいドット絵は描けないということです。 背景画像は CLOSET 様からお借りしました。

やっぱり青はきれいです。


comment ×0
back-to-top
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。