mieki256's diary



2013/12/05(木) [n年前の日記]

#1 [nitijyou][pc] 自転車で買い物に

親父さんの電動自転車を以下略。コンビニとダイソーとリオンドール、一旦帰って夕飯の支度をしてから、ホーマックとSeriaとサンドラッグに行ってきたり。

リオンドールで夕飯のおかずを、ホーマックでマウスパッドと枕を購入。

マウスパッドについてメモ。 :

購入したマウスパッドは、 _サンワサプライ MPD-T1GY (グレー色) 。298円、だったかな…。小さいマウスパッドだけど、パッケージに「コレで充分!!」とデカデカと書いてある。

昔のボール式マウスは、精度が低かったり、動かす際に引っ掛かったり等色々あったから、マウスパッドも大きいのが必要だったけど。今時のマウスは、光学センサやレーザーセンサで精度がそこそこ高いし。たしかにコレで充分、な気がする。グワングワンと腕全体を動かしてマウスを動かす時代じゃなくて、手首から先でチョチョイと動かす時代だよなと。

枕について。 :

低反発枕を買ってきた。1,280円、だったかな。

ここ数ヶ月、昔「ためしてガッテン」で紹介されてた、座布団+バスタオルを枕代わりにして試していたけど。高さはたしかに調整可能でイイ感じなのだけど、座布団の余った部分が、邪魔で邪魔で…。やっぱり枕が必要だなと。そのうち使って様子を見てみるつもり。

#2 [pc] ダイソーで小物を色々購入

色々買って試してみたり。

ボタンやキーボードに貼るシールを購入。 :

マウスの拡張ボタンに、ポッチをつけたいなと思ったので、ガラケーのボタン、あるいは、PCのキーボードに貼り付けられるシールの類を探したのだけど。さすがにスマホ全盛な時代だけあって、全然売ってなくてガックリ。それでも、かろうじて、シールを2つほど買ってきたり。

一つは、シールの厚みが薄すぎて、貼っても意味が無かった。たぶん、ボタンに色付けをするためだけのシールなのだろう…。もう一つは、ラインで貼っていくタイプのシールだったので、カッターで一粒だけ切り出して使ってみたり。こちらはまだ、それなりの厚みがあったので、目的は果たせたような気がしたり。

スマホスタンドを購入。 :

手持ちのガラケー、N905i をデジカメ代わりに使う時があるのだけれど、手持ち撮影だからぶれてしまう時があって。三脚に固定する何かが欲しいなとずっと思っていたわけで。

たまたま、ダイソーで目にしたスマートフォンスタンド、携帯電話グッズNo.715 が、両側からバネで挟んで固定しながら三脚っぽい何かで立たせるタイプだったので、これを流用できるのではないかと試しに買ってみたり。

帰宅後試してみたけれど。N905i の本体が細すぎてダメだった…。約53〜65mm の幅のスマホには使える、と書いてあったけど、ガラケーはそこまで太くないのだなと。

仕方ないので、裏面に両面テープがついたスポンジを貼って、挟める幅を狭くして試してみたけど。
  • 件のスタンドは、ガジェットを上向きにして固定するグッズなので、カメラ撮影時のように横向きにはならない。
  • N905iの側面はボタンだらけなので、固定できる場所が極めて限られる。
てな理由で、こりゃダメだと。

扉を開けたら光るLEDセンサーライトを購入。 :

扉を開けると磁石が離れてスイッチが入るLEDライト、LEDライト No.11 が売られていたので購入。コレを使えば、親父さんやお袋さんが、夜中トイレに行こうとした際に、ドアを開けただけでライトが光って便利だろうと思ったわけで。

帰宅後、開封して弄っているうちに、問題点に気がついた。親父さんやお袋さんが使う部屋のドアは、昼間は開けっ放し。その間、このLEDライトは、ずっと点いたままになるはず。あっという間に、電池切れになるな…。ダメだこりゃ。

何かしら使い道は無いかなあ…。思いつかない…。引き出しその他に設置すると言っても、暗すぎて困りそうな引き出しは、日常生活の中で基本的には使わない扱いになるわけだから、ココに付ければ、という場所が全然思いつかない。うーん。

おにぎりを作る容器を購入。 :

御飯を詰めてギューッと押し込むとおにぎりが作れるソレ。

一応、昔、そういうグッズを購入して、今も時々使ってるのだけど。御飯がベタベタとついてしまうのがなんだかアレで。

昨今は、しゃもじの表面を凸凹させて、御飯がつきにくい状態にしてあるわけだけど、ソレをこの手の容器にも使えばいいのに、と常々思っていたわけで。ところが、今日、たまたま店頭でそのものズバリを見かけて。やはり皆、考えることは同じか、コレは一つ試してみないと、てな気分で購入。

まあ、たぶん、表面の凸凹は、何も考えてない凸凹で、やっぱり御飯ついちゃうじゃん、というオチになりそうだなと思ってますけど。

電池残量を測定する何かを購入。 :

電池の両端を挟むとメーターが動くソレを Seria で購入。

自分、一応これでも工業高校電子科卒なので、実習の時間にテスターを作らされて、ずっとそのテスターを使ってる・電池残量を測る時もソレを使っているのだけど。一々引っ張り出すのが面倒臭いし、あの細い棒で電池の両端を挟むのも結構至難の業だし、手軽に測れる何かが欲しいなーと。てなわけで、これなら十分イケそうだなと購入。

帰宅後、手持ちの電池で測定してみたけど。どのあたりが1.5Vなのか、よく分からず…。

また、説明書に、「3秒以上測ると電池が無くなるよ」と書いてあることにも気付いたり。たしかに、目盛り上の針がグングン動いていく…。なんだかコレ、電池をわざと使いきるという目的でも使えそうな。

ちなみに、充電池の類には使えないらしい。

100円ショップでいくつか買ってきただけなのに。 :

100円ショップでいくつか買ってきただけなのに、こんだけズラズラと、どうでもいいことを書けるあたり、なんだか自分はお得というか…。何を使っても「ふむふむ、なるほど」と遊べる人間じゃないのかと思えてきたり。安上がりな人間…。

#3 [dxruby][game] DXRubyで二足歩行する敵っぽい動きを作ってみる

今日も DXRuby を使って何かしら書いてみます。

今回も多関節ネタということで、二足歩行する敵っぽい動きを試してみようかなと。

なんで二足歩行なのかというと…。個人的に、ちょっと思い入れがありまして…。

昔、先輩から、「このゲームの、この中ボスは、こうやって動かしてるんだよ」と説明してもらったことがありまして。「うわー、面白そう。自分もそういうのやってみたい」と思ったものの、その後、そんな機会には恵まれず。

当時は、その手のゲームを作るとなるとアセンブラで書くのが当たり前だったので、なかなか気軽に試すわけにもいかなくて。また、CGツールも無かった時代ですので、絵描きさんに「こういうの描いてくれませんか?」とお願いする必要もあって。 *1 なので、お遊びでチョチョイッと、てなわけにはいかなかったのです。 *2

だけど今なら、気軽に試せる DXRuby がある。CGツールだって、好きなだけ使える。ということで、当時、指をくわえて眺めていたあの動きを、自分もちょっと試しに書いてみようかな、と。

とりあえず、こんな感じになりました。

二足歩行その1
# 二足歩行する敵モドキ

require 'dxruby'

$angadd = 2

# 足先の座標を求めるクラス
class Foot
  def initialize(start_ang)
    @ang = start_ang
    @x = 0
    @y = 0
    self.update
  end

  attr_accessor :x, :y

  def update
    # 円運動をさせてみる。
    # 本当は放物線運動のほうがいいと思う…けど
    # 面倒臭いから今回は安直に円運動
    
    ang = @ang * Math::PI / 180.0
    @x = -128 * Math.cos(ang)
    @y = 96 * Math.sin(ang)
    @y = 0 if @y >= 0
    @ang += $angadd
  end
end

# 棒状の部分を複数のスプライトを使って描く
def draw_foot_sub(bx, by, tx, ty, img)
  count = 10
  count.times do |i|
    x = bx + ((tx - bx) * i / (count - 1)) - img.width / 2
    y = by + ((ty - by) * i / (count - 1)) - img.height / 2
    Window.draw(x, y, img)
  end
end

# 足を一本分描画する
def draw_foot(bx, by, tx, ty, img, flen)
  dw = tx - bx
  dh = ty - by

  # 腰から足の先までの長さ、の半分を求める
  # 三平方の定理(ピタゴラスの定理)を使ってる
  l = Math.sqrt(dw * dw + dh * dh) / 2

  # 膝までの距離を求める。これも、三平方の定理を使ってる
  nl = flen * flen - l * l
  n = (nl <= 0)? 0 : Math.sqrt(nl)

  # 腰と足先の中間点を求める
  cx = (bx + tx) / 2
  cy = (by + ty) / 2

  # 膝があるはずの方向(角度)を求める
  # 腰と足先の座標から角度を求めて、それに90度足せばいい
  ang = Math.atan2(dh, dw) + Math::PI / 2
  
  # 膝の場所を求める
  lx = cx + n * Math.cos(ang)
  ly = cy + n * Math.sin(ang)

  # 腰から膝までと、膝から足先までを描く
  draw_foot_sub(bx, by, lx, ly, img)
  draw_foot_sub(lx, ly, tx, ty, img)

  # 分かりやすくするために線を引いてみる
  Window.drawLine(cx, cy, lx, ly, [255, 0, 0])
end

img = Image.load("ufo.png")

by = 150 # 腰の高さ
gy = 420 # 地面の高さ

# 足半分の長さ
flen = (gy - by) / 2 + 20

footl = Foot.new(0)
footr = Foot.new(180)

# メインループ
Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  # マウスカーソルのy座標で足先の移動速度を変えてみる
  $angadd = 20.0 * Input.mousePosY / Window.height - 10.0
    
  bx = Input.mousePosX

  # 右足の根元と先っぽの座標を求める
  n = 24
  frbx = bx - n
  frby = by
  frtx = bx + footr.x - n
  frty = footr.y + gy

  # 左足の根元と先っぽの座標を求める
  flbx = bx + n
  flby = by
  fltx = bx + footl.x + n
  flty = footl.y + gy

  # 右足を描く
  draw_foot(frbx, frby, frtx, frty, img, flen)
  
  # 腰を描く
  Window.drawScale(bx - img.width / 2, by - 80 , img, 2, 2)

  # 左足を描く
  draw_foot(flbx, flby, fltx, flty, img, flen)

  # 足先の座標を更新
  footl.update
  footr.update

  # 分かりやすくするために線を引いてみる
  Window.drawLine(frbx, frby, frtx, frty, [0, 255, 255])
  Window.drawLine(flbx, flby, fltx, flty, [0, 255, 255])
end
ちょっとソースが長くなってしまいましたが…。もうちょっと短く書けないのかな、コレ…。

ざっくりと解説を。

一般的に、2Dゲームの多関節処理というと、各関節毎に角度を管理・制御して動きをつけていくのですけど。このプログラムでは、少し違うことをしています。

このプログラムでは、各関節の角度ではなく、根元と先っぽ(足先)の座標だけを管理・制御しています。そして、膝だか肘だかの座標は、計算して求めます。

この仕組みを作ってしまえば、根元と先っぽだけを制御すればいいので、比較的自由に動きをつけていけますし、時々、プログラマーが意図してなかったポーズになったりもして、見た目が面白い場面も出てきたり…するかもしれません。

MMD(MikuMikuDance)や3DCGソフトを触ったことがある人なら、ピンときたのではないでしょうか。「それって、IK(インバースキネマティクス)じゃね?」。そうです。これ“も”、IKです。

MMDや3DCGソフトのIKは、以下のような状態ですが…。 このプログラムでは、以下のような状態です。 制限だらけですね…。とはいえ、さすがに、これだけ制限があれば、昔の非力なCPUでもIKが実現できたわけです。実際、スーパーファミコンやメガドライブの某タイトルでは、こういう仕組みでボス敵が動いてました。…スーパーファミコンのCPUはとにかく遅くてプログラマー泣かせだったらしいですけど、プログラマーの工夫次第で、こういうこともできたわけですね。

さて、実際の処理内容ですが…。 ここまで分かれば、中間点の座標、sin、cos、膝があるはずの角度、膝までの距離、を使って膝座標が得られますね。

ちょっと分かりづらいかな…?。余裕があったら説明図も後で描いときます。

(※ 2013/12/06追記。説明図を追加してみました。ちょっとだけ…分かりやすくなった…のかどうか…)

説明図

ところで。

DXRuby は、スプライトの回転拡大縮小半透明描画ができますので…。何もわざわざ、複数のスプライトを数珠繋ぎにして、足を描かなくてもいいような気がしてきました。

ということで、足を丸々画像にして、回転させて描画してみましょうか。blender でレンダリングした画像を使ってみました。
足を画像にしてみた例
# 二足歩行する敵モドキ。足を画像にしてみた版

require 'dxruby'

$angadd = 2

# 足先の座標を求めるクラス
class Foot
  def initialize(start_ang)
    @ang = start_ang
    @x = 0
    @y = 0
    self.update
  end

  attr_accessor :x, :y

  def update
    # 円運動をさせてみる。
    # 本当は放物線運動のほうがいいと思う…けど
    # 面倒臭いから今回は安直に円運動
    
    ang = @ang * Math::PI / 180.0
    @x = -128 * Math.cos(ang)
    @y = 96 * Math.sin(ang)
    @y = 0 if @y >= 0
    @ang += $angadd
  end
end

# 棒状の部分を1枚のスプライトを回転させて描く
def draw_foot_sub(bx, by, tx, ty, img)
  cx = (tx + bx) / 2 - img.width / 2
  cy = (ty + by) / 2 - img.height / 2
  dw = tx - bx
  dh = ty - by
  ang = Math.atan2(dh, dw) * 180.0 / Math::PI
  Window.drawRot(cx, cy, img, ang)
end

# 足を一本分描画する
def draw_foot(bx, by, tx, ty, img, flen)
  dw = tx - bx
  dh = ty - by

  # 腰から足の先までの長さ、の半分を求める
  # 三平方の定理(ピタゴラスの定理)を使ってる
  l = Math.sqrt(dw * dw + dh * dh) / 2

  # 膝までの距離を求める。これも、三平方の定理を使ってる
  nl = flen * flen - l * l
  n = (nl <= 0)? 0 : Math.sqrt(nl)

  # 腰と足先の中間点を求める
  cx = (bx + tx) / 2
  cy = (by + ty) / 2

  # 膝があるはずの方向(角度)を求める
  # 腰と足先の座標から角度を求めて、それに90度足せばいい
  ang = Math.atan2(dh, dw) + Math::PI / 2
  
  # 膝の場所を求める
  lx = cx + n * Math.cos(ang)
  ly = cy + n * Math.sin(ang)

  # 腰から膝までと、膝から足先までを描く
  draw_foot_sub(bx, by, lx, ly, img)
  draw_foot_sub(lx, ly, tx, ty, img)

  # 分かりやすくするために線を引いてみる
  # Window.drawLine(cx, cy, lx, ly, [255, 0, 0])
end

img = Image.load("foot.png")
bodyimg = Image.load("body.png")

by = 150 # 腰の高さ
gy = 420 # 地面の高さ

# 足半分の長さ
flen = (gy - by) / 2 + 20

footl = Foot.new(0)
footr = Foot.new(180)

# メインループ
Window.loop do
  break if Input.keyPush?(K_ESCAPE)

  # マウスカーソルのy座標で足先の移動速度を変えてみる
  $angadd = 20.0 * Input.mousePosY / Window.height - 10.0
    
  bx = Input.mousePosX

  # 右足の根元と先っぽの座標を求める
  n = 24
  frbx = bx - n
  frby = by
  frtx = bx + footr.x - n
  frty = footr.y + gy

  # 左足の根元と先っぽの座標を求める
  flbx = bx + n
  flby = by
  fltx = bx + footl.x + n
  flty = footl.y + gy

  # 右足を描く
  draw_foot(frbx, frby, frtx, frty, img, flen)
  
  # 腰を描く
  Window.draw(bx - 150, by - 100, bodyimg)

  # 左足を描く
  draw_foot(flbx, flby, fltx, flty, img, flen)

  # 足先の座標を更新
  footl.update
  footr.update

  # 分かりやすくするために線を引いてみる
  # Window.drawLine(frbx, frby, frtx, frty, [0, 255, 255])
  # Window.drawLine(flbx, flby, fltx, flty, [0, 255, 255])
end
うむ。実にそれらしくなりましたな。

ただ、見た目をリアルにしていくのは楽しい作業なのですが…。これはちょっと、落とし穴がありそうな気もしますね。

まあ、今回は、「昔憧れたあの動きを、DXRubyという便利ライブラリを使って気軽に実験」という話でやってますので、コレはコレでOKかなと。

ソースと画像も置いときますね。Public Domainってことで。

_walkenemy.zip

さて、明日も何か書いてみようかな…と思ったけれど、今日のコレで時間ギリギリだったので、二日に1回ぐらいのペースで書くかもしれないし書かないかもしれません。まあ、この手の記事を書く練習ってことで、気楽に、気楽に…。

余談。他のツールを検討すべき境界線。 :

DXRuby に限らず、2Dゲームライブラリを使ってアレコレ作っていく際に、見た目をリアルにしていくことにリソースを割いていくと…。

どこかの時点で、「ソレ、Unity使ったほうがよくね?」となりそうな気がするのです。つまり、そこに落とし穴というか、「ここから先は別のツールを使ったほうが…」と判断できる境界線が、どこかにあるんじゃないのかな、と思えるのですね。

Unity の場合…。
  • 3Dで描画するから、見た目からしてリアル。
  • 多関節キャラを扱うのは当たり前。そもそも、人体モデルが多関節キャラですから…。
  • 多関節キャラの動きを、3DCGソフトを使って確認しながら作り込める。トライ&エラーが簡単。
  • モーションの合成も、基本機能として持っている。
  • IKも、基本機能として持っている…。
てな感じの、大変便利なツールですので…。何も今から、Unityと同じことをしなくてもいいんじゃないか、車輪の再発明をしなくても、ということになりそうですよね。

ただ、Unityも、習得に要する時間というものがあるわけで…。

習得時間に関しては、DXRuby 等、2Dゲームライブラリは、比較的短いので…。やはり、「ちょっと試してみる」「この手のプログラムの書き方を勉強してみる」という点では、メリットがあるようにも思うのでした。

*1: 当時は、国民機 PC-9801 を使ってた時代ですから…。16色しか出ませんから…。TVゲーム機用の色を出すには、自社設計のハードウェアをPC-9801に追加して、とかやってた時代ですから…。プログラマーが、余技? 趣味? でCGツールも使わせてもらう、なんてことは、ちょっと難しかったのです。…いや、やる気ビンビンな先輩方は「俺にもCGツール使わせて!」とかやってましたけど。自分は引っ込み思案、かつ、プログラム書くだけで手一杯でそこまでは…。
*2: そもそも自分、当時はまともなPCを持ってなかった気がする。X1 turbo は部屋にあったかもしれないけど、電源すら入れてなかったような…。X68Kでも持ってたら違ったのかもしれないけど。

以上、1 日分です。

過去ログ表示

Prev - 2013/12 - 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