ヘキサ日記 Blog

 

  • 2016年12月14日

    嵐の前の静けさ

               

    こんにちは!大阪開発デザイナーのちるちるです

     

    6回目のブログがやってきましたよ!

     

    今までのブログはコチラ→(脱線回) と、シリーズになってます☆

     

        ●ブログ用に何か作るんだ~そう、私はアフロが作りたい~●

    「第4回:果たしてアフロは完成するのか?!(スカルプト編)

     

    今回はスカルプトですね!

    ちなみに予定はこんな感じ↓

     

    ①ファイバーメッシュ(無事に終了!)

    ②スカルプト(今回頑張ります!)

    ③ナノメッシュ(気が滅入ってきた)

     

    ZBrushといえば、やはりスカルプト・・・②スカルプトでアフロ作成行ってみよーう!

     

     

    20161214_blog001

     

     

    20161214_blog002

     

     

    20161214_blog003

     

     

    しばらくぶりにデータを開いて、このモデルが迫って来た時には

    さすがに「うわっ」と声を出してしまいましたね。

     

     

    よ・・・良い感じになるようにやって行きましょう

     

     

    スカルプトと言ってもやり方は沢山ありますが、

    今回はアルファを使ってやってみたいと思います!

     

     

    20161214_blog004

     

     

    Plane3D」を出します、板のようなものですね。

    ここにアルファにしたいディテールを彫り彫りしていきましょう

     

     

    20161214_blog005

     

     

    こんな感じにしてみました!(何が何だかわかりませんね

     

     

    ところがどっこい!

    こいつをAlphaとして適用し、ベースのアフロにスカルプトしていくと・・・

     

     

    20161214_blog006

    20161214_blog007

     

     

    何だかそれっぽくなりましたね!!!

     

     

    これだけでは寂しいのでもう少しディテールを加えていきましょう

     

     

    20161214_blog008

     

     

    「え、柄・・・?」

    「いいえ、マスクを作りその部分だけスカルプトを適用する手法だよ」

     

     

    ということで少しディテールを加え・・・・・。

     

    あれ・・・?

    (おっとここでまさかの画像の撮り忘れ!)

     

     

    少しディテールを加えたらしいです。

     

     

    もう少し自然にする為に毛先を遊ばせてみましょう

     

     

    20161214_blog009

     

    ・・・遊ばせすぎでは・・・・・・?

     

     

    大丈夫です、こんなこともあろうかとレイヤーを作って作業をするのが基本です。

    レイヤーの適用値を低くすれば・・・

     

     

    20161214_blog010

    20161214_blog011

     

    この様に抑えることができます!

     

     

    スカルプトのアフロはこんな感じでしょうか?!

    前回と打って変わってかなり短時間でできました。

     

     

    残りはマテリアルを適用して遊んでみようのコーナーです。

     

    20161214_blog012

     

    煌くアフロ、中々良いですね

     

     

    20161214_blog013

     

    お、これいい感じにアフロに見えますね!

     

     

    20161214_blog014

     

    「私を怒らせるとこの聖なるアフロに秘められしパワーが爆発するぞ!」

     

     

    20161214_blog015

     

    お、これも良いですね!

     

     

    20161214_blog016

     

    シブイ!

     

     

    如何でしたでしょうか?

     

    前回同様アフロに見えるものができたことにしておきます。いやぁ一安心です!

     

     

    20161214_blog017

     

    20161214_blog018

     

    20161214_blog019

     

     

    次回「果たしてアフロは完成するのか?!(ナノメッシュ編)」(・・・。)

    あの・・・やってみたくて一応リストには入れたのですが、うまく行く想像があまりできないので、

    突然別の企画が始まったら「だよね」と言ってもらっても構いません☆

     

     

    ではではまたです


  •            

    どうも、0084です
    急激に寒くなってきましたね

     

    2016年もあっという間に過ぎ、残りわずかとなりました
    そこで、個人的に今年を振り返って

     

    「2016 ちょっとした”すきま”に遊べるスマホゲーム」

     

    のベスト3をあげてみたいと思います
    ※個人的な趣味100%でスイマセン…

     

    ———————————————–

    第3位は…

     

    「バカハザ」!

     

    http://www.capcom.co.jp/biohazard20th/ja/event/bakahaza.html

     

    バイオハザード20周年を記念して作られた、天才バカボンキャラによるバイオハザード1が手軽にスマホで遊べます
    中でも完全再現っぷりはスゴく、あのキャラクター移動させにくいところまで再現して(?)ます
    どの天才バカボンキャラが、バイオハザード1のバリーなのか?レベッカなのか?と配役を考えるといっそう楽しめます!

     

     

     

     

     

    次に第2位は…

     

    「Redungeon」!

     

    https://itunes.apple.com/us/app/redungeon/id1119569595?mt=8
    https://play.google.com/store/apps/details?id=com.nitrome.redungeon

     

    操作は前後左右に進むだけ!、即死ギミックをひたすら避けて奥へ奥へと進んでいきます
    タップで進むテンポが癖になって、気づいたらいつの間にか立ち上げて遊んでいた!なんてこともありました

     

     

     

     

     

    最後に第1位は…

     

    「TIME LOCKER」!

     

    https://itunes.apple.com/jp/app/time-locker-shooter/id1114692553?mt=8
    https://play.google.com/store/apps/details?id=org.gekoi.timelocker&hl=ja

     

    “あなたが止まれば、時間も止まる”がウリの時間を操る斬新なシューティングです
    ゲーム中に「ちょっと一休み」が手軽にできて、かつ綿密な作戦が立てられるのが魅力です
    おしゃれな画面レイアウトもセンスよさげです

     

    —————————————————
    とかなり偏った選択になりましたが、
    どれも無料で始められるので
    まだプレーされてなければ、いかがでしょうか?


  •            

    こんにちは、ごっしーです

    今年も12月に入り、そろそろ年末感が出てきましたね。

     

    個人的に年末年始といえば親戚や友人が集まる機会なので、 所有するゲーム機の数々が活躍します。

    大乱闘スマッシュブラザーズの8人同時対戦など、普段はできない遊びも楽しんでいます!

     

    もっとお手軽にゲームを楽しまれる場合は、

    先月発売された ニンテンドークラシックミニ ファミリーコンピュータなどが

    懐かしさも相まって盛り上がりそうですね。

    これを機に再びビデオゲームを遊び始める人も多そうです!

     

    そんな、久しぶりにレトロゲームをプレイする時に発生する出来事といえば、

    以前よりヘタクソになってる問題です。

     

     

    ヘタクソになっている理由としては、やはり

     

    ・ブランクによる腕前の低下

     

    ・実は以前からそんなに上手くなかった(記憶の美化

     

    あたりが大半を占めそうですが、実はそれ以外の可能性もあります。

     

     

    もし自分自身と関係がない理由でヘタクソになっていた(されていた)ら、

    せっかく久しぶりにゲームを遊ぶ機会が楽しめないかもしれませんね…

     

     

    そこで、ゲームがヘタクソになる物理的理由を2つ挙げてみたい思います。

     

     

    ●以前とコントローラ(ゲーム機)が違う!

     「ニンテンドークラシックミニ ファミリーコンピュータ」は、

     本家ファミコンよりコントローラが小さくなっています

     (個人的には、十字キーの素早い操作が少し難しいように感じました)

     

     そのほかの過去のゲームが遊べるゲーム機でも、

     Wiiリモコン等は独特な形状をしているため、操作に違和感を覚える可能性があります。

     

     せめて使いやすいコントローラを用意したいところですね。

     

     

    ●テレビが違う!

     地上デジタル放送の開始により、映像はアナログからデジタル

     また、装置もブラウン管から液晶へ移行しましたが、これによって発生した弊害が表示遅延です。

     

     昨今のテレビは、映像を美しく見せるための加工をおこなう為、

     テレビが信号を受け取ってから、画面に表示するまでのあいだに処理時間が発生し、

     ゲームの映像がわずかに遅れて表示されるようになっています。

     

       ※遅延の例

       画面上の自キャラは相手の攻撃を受ける直前だが、

       ゲーム機の中では既に攻撃が当たって決着がついている(負けている)、 など

     

     動きがシビアなアクションゲームなどでは、

     この遅延によって、気が付かないうちにヘタクソにされている可能性があります。

     

     これらはゲームモードをウリにしていたり、表示遅延時間を公表している

     比較的新しいテレビを使用する事で軽減できます。

     (ちなみに、海外のゲーム大会などでは今もブラウン管テレビが現役だったりします)

     

     

    個人的な考えですが、こういった問題(ゲームプレイ上のハンデ)はとくに、

    ゲームがあまり得意でない人へ悪影響を与えてしまうように思います。

     

    レトロゲームだけでなく、最新のゲームを快適に遊ぶためにも、

    ぜひ一度お手元のプレイ環境を見直してみてください!

     


  •            

    こんにちは、はるちゃんです
    突然ですが皆さん、ホラーゲームってお好きですか?
    私は、大の苦手です………
     
    同期と集まってホラーゲームをしても
    少しだけ開いている部屋のドアが無性に気になってきたり
    会社のオープンスペースで誰かがプレイするホラーゲームを皆で見ているときは 
    あまりの怖さで逆に笑いはじめたり……
     
    いやいや、ゲーム会社に勤めてるんだもの
    ホラーゲームも一人でできるくらいにならなくちゃ

    ということで、最近やっと一人でホラーゲームをプレイしました。
    小さな画面でできることと可愛いイラストだったことから、
    『夜廻』を選んでみたのですが……。
     
    可愛らしいイラストによって怖さはなくなると思いきや、 やっぱり怖い
     
    Vitaの画面を遠ざけてサウンドを消してプレイした私がホラーゲームを克服するには、
    まだまだ時間がかかりそうです……。
     

    このゲームをプレイして秀逸だと感じたのは、チュートリアルの部分でした。
    プレイされる方もいらっしゃると思うので具体的には言いませんが…。
     
    私にとってゲームは、
    「世界を救おう」「どうにかここから脱出しよう」といった
    ポジティブなモチベーションでプレイを進めるものなのですが、
    夜廻におけるチュートリアル後の私のモチベーションは、「贖罪」でした。
    「私のせいで、私のせいで…」と思いながらプレイを進める、
    どちらかというとネガティブにも感じられるモチベーションでクリアまで到達したのです。
     
    「冒頭で人の興味を引く」というのはゲームに限らず小説や会話でも重要なことですが、
    このゲームをプレイしたことで
    「そういうチュートリアルもありなのかと気付く良い経験となりました。
     
    皆さんも機会があれば是非プレイして頂きたいです
     
     
    以上、一人でホラーゲームをクリア出来てテンションが上がりつつも、
    次のホラーゲームには中々手を出せないはるちゃんでした

  •            

    「イーソイソイ イーソイソイ」
    必要以上に、これでもか、というくらいにトリコを撫で回して夜が更けていきます。
     
    こんにちは、ポエミです。
     
    そうです、例のアレです。
    先日発売された「人喰いの大鷲トリコ」です。

    トリコに近付いては撫でる。
    遠目で動きを観察した後にたまらずかけよって撫でる。
    可愛い…
     
    ああ、でもダメだ、これ以上可愛がったら逆に嫌われるかもしれない…!
     
     
    ・・・哀しい過去が頭をよぎる。
    小学生の時、家の中で飼っていた可愛らしいプードル犬がおりまして、
    可愛すぎて撫で回し過ぎた(愛情をぶつけすぎた)結果、
    「ただいまー」と玄関の扉を開けるなり、左右の犬歯をむき出しにされて
    ガルルルルゥーー と出迎えられるようになりました。
    出迎えという名の威嚇。
     
      
    私もいい大人になったので節度をもってトリコと冒険します。
     
     
    さて、ここからが本題です。
    ヘキサドライブでは12月21日(水)に
    1dayセミナー&ワークショップを東京と大阪で開催致します!
    その名の通り、業界やヘキサドライブの事をお話しするセミナーと
    グループに分かれてのワークショップを行う1dayイベントとなっています。

    ゲームクリエイターに興味のある学生さん、ぜひエントリー下さい
     
     
    【開催日時】
     2016年12月21日(水) 13:30~19:00 ※懇親会もあります。
    【開催場所】
     東京・大阪 

     
    詳細はこちらをご覧下さい。
     
    みなさまのエントリーお待ちしております!


  •            

    定期健診の結果が返ってきました。
    トリグリセライドが多いので、摂取するカロリーを控えてください」
    んっ?トリグリセライドって何だ???

     

    あ、中性脂肪のことか…。
    最近、運動してないもんなぁ。

    こんにちは、イヌカイです。

     

    運動不足解消のため…という訳ではないんですが、
    あるアプリのおかげで休日には、かなりの距離を歩くようになりました。
    そうです「ポケモンGO」です。

     

    6歳の息子と一緒にポケモンを探しながら歩き回ります。
    今日はあっちの公園、次の休みはこっちの公園。
    一日中、足が棒になるまで…。

     

    スマホを私が持って、ポケモンが出たときだけ息子に渡します。
    息子がポケモンをゲットしたら、また私がスマホを持って歩き出すというスタイルです。

     

    ところが、息子は歩いているときもポケモンが気になって気になってしょうがないようで。

     

    「お父さん、ポケモン出た?」
    「まだ出てない」

     

    「ポケモン出た?」
    「出てない

     

    「何か出た?」
    「何も出てない

     

    「何か出た?」
    「だから、何も出てないって

     

    10秒おきに繰り返されるこの会話。
    ちょっとうんざりです。

     

    そんな中、待望のアイテムを入手しましたー!

    20161207
    ポケモンGO Plus

     

    Bluetoothでスマホと連動させると、ポケモンが出たときに振動とランプの光で知らせてくれます。
    ボタンを押すとモンスターボールを投げて、ランプがレインボーに光ると捕獲成功、失敗すると赤色に点滅します。

     

    早速、息子の腕に着けてポケモン探しに出かけましたが、スマホを見なくてもポケモンの出現が分かるので、
    10秒おきに繰り返されていた「ポケモン出た?」攻撃もなくなりました!

     

    これで息子とのポケモン探しも快適です!

     

    これからも、ポケモンゲットしながらいっぱい歩き回って、
    来年の健康診断ではトリグリセライドが少しでも減ってたら…いいなぁ。

     

    それではまた


  •            

    こんにちは。

    12月に入り、インフルエンザの流行がいつのタイミングになるのか気になっている よっしーです。

     

    今回紹介するのは、Windowsで

    MACアドレスを取得するコマンド

    です。

     

    利用方法は簡単で、コマンドプロンプトを起動して、このコマンドを実行するだけです

     

    getmac

     

    ただ、出力形式を変更することができ、「table」、「list」、「csv」から指定が可能です

     

    ■コマンド例
    getmac /fo table
    getmac /fo list
    getmac /fo csv

    ※詳細はヘルプを参照してください。

     

    さらに便利なことに別のWindowsマシンのMACアドレスも取得できてしまいます

     

    ■コマンド例
    getmac /s 192.168.1.1 /U user /P password
    ※詳細はヘルプを参照してください。

     

    社内にある複数のPCでMACアドレスをちょっと調べたい時などバッチを作成して、
    取得することもできたりしますね

     

    工夫次第で色々出来るので、利用してみてはいかがでしょうか

     

    では


  • 2016年12月5日

    Team Geek

               

    お久しぶりです、コウスケです。

     

    前回瞑想について書きましたが、

    今日は引き続きゲーム開発というお仕事における心構え

    に関する話をしたいと思います。

     

    内容としては先日、あるゲーム開発勉強会で紹介されたのをきっかけに読んだ本

    Team Geekの紹介です。

    (そのときの話の内容に痛く共感して、

    買って読もうかなと思ったら、既に家の本棚にありました・・

    いわゆる積ん読状態だったのです。

     

    picture_large978-4-87311-630-3

     

    この本は何かというと、みんなお馴染みツールSubversionの開発リーダーで、

    Google社所属の作者がソフトウェア開発という仕事における心構えであったり、

    チーム・Google社内の文化を書いたものです。

    実際に最前線のソフトウェアを開発している方が、

    技術系ではなく、ビジネス・啓発系の内容の本を書いていくれることは貴重です。

     

    さて、この本の内容の全てを一言で言うと、

    HRT(ハート)を大事にしよう

    ということです。

    HRTとはなにかというと、

    • Humility(謙虚)
    • Respect(尊敬)
    • Trust(信頼)

    になります。

    謙虚・尊敬・信頼をすべての振る舞いの基準にしようということです。

     

    その前提として、

    ソフトウェア開発というのはどこまでいってもチームスポーツである

    という事実を揺るぎないものとして認識する

    言葉ではなく心で理解する!)ことがまず必要です。

     

    タイトルの単語「Geek」は凄腕の技術者、プログラマという意味で、

    その言葉には

    我が強く、他のメンバーと協力するよりも一人で黙々と作業をこなす」というイメージがあり、

    実際(欧米では特に)その傾向はあるのですが、

    どんな凄腕のエンジニアであっても、自分一人で完結する仕事などありません。

    そんな彼らが、実際はチームとしての生産性を上げることを最優先に考えよう

    といっているのです。

    自分はコミュニケーションが苦手だから技術を上げることに専念しよう
    というわけにはいかないのです(かくいう私もそうでした)。

     

    さて、このHRT(ハート)ですが自分の実体験からも、これさえ皆が意識できれば

    ほとんどの問題が解決できるだろう、と心から腑に落ちるものでした。

     

    挙げられている例としてエンジニア間で行われるコードレビューがあります。

    エンジニアの中にはなかなか自分の書いたコードを見せたくない、

    触られたくないという人がいます。

    自分のコードは確固たる理由があって書いているから指摘されるいわれはない、という具合です。

    そんなときに意識したいことは下記になります。

     

    • 「君は君の書いたコードではない」

     コードはチームのものであり、自分の能力を示すものではないことを認識する。

     無用に自分の能力を誇示することは、自分への執着が強すぎる、

     ひいては自分への信頼が欠けていることになる。

     

    • エゴをなくす

     自分は万能ではないということを認識し、他者の意見は信頼関係の上で、

     リスペクト(尊敬)の元検討する価値のあるものである。

     

    • どんな人にも間違いはあり、能力不足があることを認める

     わからないことは素直に「わからない」という

     他者も自分を否定したいわけでなく、よりよい製品にするという共通の目的のもとで

     話をしているのだということを認識する。

     

    • コードレビューする際も相手に対する批判をするのでなく、自分自身の疑問として謙虚に聞く。

     

    どうでしょうか。

    これらは全て謙虚・尊敬・信頼のもとに成り立つものであることがわかると思います。

     

    もう一つ、これは本の内容でなく個人的に思うことですが、

    農耕民族である我々日本人の場合、謙虚すぎて主張しない、できないということも

    多くあるように思います(私もそうです)。

    それは、相手に批判されたくない自分で責任を負いたくない、ということにつながり、

    ひいては相手のことも自分のことも信頼しきれていないということになるかと思います。

    本にも書いていますが、各行動に(いわゆるマネージャでなく)自分自身が責任を取る

    ことは仕事における最も基本的な姿勢です。

     

    もう一つ印象的だったのが、「自己選択的文化」という言葉です。

    どういうことかというと、このようなチーム文化はチームリーダーが

    トップダウンで指示して作るものでなく、チームメンバー自らが作るものである。

    自分たちで選択的に作っていく文化だからこそ長続きする」ものである。

    ということです。

     

    また、自分たちで選択して作った文化には同じ文化を持つ人を惹きつけ、そういった人が集まるようになります。

    そして、ここで挙げられている文化は「積極的な文化」、「穏やかな文化」

    のどちらかというと後者になり、それは特定のメンバーにより壊されやすい。

    それらを維持し、守っていくのは自分たちだが、場合によってはシニアメンバーが毅然と対処する必要がある。

    つまり、自分たち自身で文化を作ることの重要性が挙げられています。

     

    さらに、これらは確かに理想ではあるけど

    自分はそう意識していても相手がそう意識していなかったらどうすればいいの

    と思う人も多いと思いますが、

    そういった場合の対処法も本には書かれていますので

    興味のある人は目を通してみてください。

     

     

    さて、こういった望ましい形やアンチパターンを指摘されると尤もだと思うのですが、

    じゃあ明日からやろうとしてもその具体的実行はなかなか一朝一夕ではいかないもの・・

    何から手を付ければ・・ということが常だと思います。

     

    だからこそ、まず明日から具体的にやれることの一つが瞑想・・いや半分冗談ですが

    まあ、それも一つの方法ではないかな!と思います!

     

    それでは!!

     


  • 2016年12月2日

    優しいC++解析(その2)

               

    ついに今年も最後の月になりましたね。
    ここにきて期待のホラー映画ブレアウィッチまで登場してワクワクが止まりません。
    お久しぶりです、good sunこと山口です。

    さて、今回は前回に引き続いてclangを使ったC++のソース解析の続きを行います。

    前回ではクラスや構造体の情報を解析するコードについて簡単に触れました。

    今回はそこから発展して、特定の変数について情報を追加してみたいと思います。

    具体的には以下の様なコードで

    class Sample{
    public:
    	Sample();
    	~Sample();
    private:
    	PARAM(_SERIALIZE("no"), _HINT("hint text"))
    	long		_value;
    };

    _valueという変数に対して

    ・シリアライズを行わない

    ・ヒント情報としてhint textという情報を持つ

    という情報を付与する事を目標とします。

    その前にNuGetで取得できるClangSharpの不具合を修正します。

    clang.parseTranslationUnit2の引数でUnsavedFileをout属性で渡すという処理になっていますが、

    こちらは配列を渡すのが本来の挙動になります。

    このUnsavedFileはメモリ上のファイルを読み込ませたりする目的で使うのでout属性ではそれが達成出来ません。

    まずは開発者のGitHubのページを見てみます。(オープンソースって素晴らしいですね)

    https://github.com/Microsoft/ClangSharp

    見てみると実はその辺対策済みなコードが上がっています。

    のでこちらをcloneするかdownloadします。

    (私はGitHub Desktopがエラーになったので男らしくdownloadを選びました)

    20161202_00

    downloadもしくはcloneしたファイルにはClangSharp.slnが入っているのでコレを開きます。

    ※公式ページのBuilding ClangSharpの手順に従うと修正されているハズのファイルが上書きされてしまうので、

    公式に反旗を翻すアウトローになり切ってください

    次にExtensions.csを開いて8行目をコメントアウトします。

    ※時間的に原因調査していませんが…そのままではここのdisposeによってハングしてしまいます。

    コメントアウトが完了したらソリューションエクスプローラから

    ClangSharpのプロジェクトを右クリックでビルドします。

    20161202_01

    出来上がったClangSharp.dllをpdbと共にNuGetで追加したプロジェクトの

    package\ClangSharp.3.8.0\lib\net40に上書きします。

    念のためClangSharpがclang3.9対応版との事なのでlibclang.dllも3.9のものに差し替えます。

    llvmをビルドすると大変なのでClang for Windowsをインストールします。

    http://llvm.org/releases/download.html

    20161202_02

    インストール先のLLVM\binの下のlibclang.dllを

    packages\ClangSharp.3.8.0\content\x64に上書きコピーします。

    因みにこの状態になるまで主に例のdisposeの所で原因不明の停止を繰り返すことになりましたが

    対策としてClangSharpを使うプロジェクトのデバッグ設定で

    ネイティブコードデバッグを有効にするのチェックを入れ忘れていて調査に手間取ったという事があったので、

    この項目へのチェックは推奨です

    20161202_03

    はい、準備が整いましたので本題です。

    流れとしましてはUnrealEngineでやっているようなマクロを作ってそれを活用することになります。

    ちょっと今回手抜きをしてマクロ全部入りのコードで紹介をしますが…

    C++のコードはこんなコードを使います。

    #define CLASS_DEFS()	\
    					virtual void serialize();	\
    					virtual void deserialize();	\
    
    #define _HINT(n) const char* hint=n
    #define _SERIALIZE(n) const char* serialize=n
    
    #define _COMBINE__(a,b)	a##b
    #define _COMBINE_(name,l)	_COMBINE__(name, l)
    #define PARAM(...)	void _COMBINE_(__Paramater_, __LINE__)(__VA_ARGS__);
    
    namespace test{
    
    class Sample{
    public:
    	Sample();
    	~Sample();
    private:
    	PARAM(_SERIALIZE("no"), _HINT("hint text等"))
    	long		_value;
    };
    
    }

    CLASS_DEFS()の定義はゲームとしてビルドするときは空になる様にifdefで分けるようにする必要があります。

    今回は仕組みの説明なので…

    解析時はこのマクロが出てきたところに関数宣言を展開してキーワードとしてClangから抽出を行おうと考えています。

    さらにデフォルト引数を使って入力パラメータの解釈を行います。

    前回の解析用コードを少し変更してこんな感じのコードを使って解析します。

    using System;
    using System.Collections.Generic;
    using System.Text;
    using ClangSharp;
    
    namespace ClangTest
    {
    	// パラメータ解析用クラス
    	public class Param
    	{
    		public bool Serialize { get; set; } = true;
    		public string Hint { get; set; }
    		public void parseFunc(CXCursor cursor)
    		{
    			var param = clang.getCursorSpelling(cursor).ToString();
    			switch (param) {
    			case "serialize":
    				clang.visitChildren(cursor, new CXCursorVisitor(visitSerialize), new CXClientData());
    				break;
    			case "hint":
    				clang.visitChildren(cursor, new CXCursorVisitor(visitHint), new CXClientData());
    				break;
    			}
    		}
    		// シリアライズの有無のチェック
    		CXChildVisitResult visitSerialize(CXCursor cursor, CXCursor parent, IntPtr client_data)
    		{
    			if (clang.getCursorKind(cursor) == CXCursorKind.CXCursor_StringLiteral)
    			{
    				var val = clang.getCursorSpelling(cursor).ToString().Replace("\"","");
    				switch (val.ToLower()) {
    				case "no":
    				case "false":
    					Serialize = false;
    					break;
    				default:
    					break;
    				}
    				return CXChildVisitResult.CXChildVisit_Break;
    			}
    			return CXChildVisitResult.CXChildVisit_Recurse;
    		}
    		// ヒントテキストを取得
    		CXChildVisitResult visitHint(CXCursor cursor, CXCursor parent, IntPtr client_data)
    		{
    			if (clang.getCursorKind(cursor) == CXCursorKind.CXCursor_StringLiteral) {
    				var val = clang.getCursorSpelling(cursor).ToString();
    				val = val.Substring(1, val.Length - 2);
    				Hint = val;
    				return CXChildVisitResult.CXChildVisit_Break;
    			}
    			return CXChildVisitResult.CXChildVisit_Recurse;
    		}
    		public override string ToString()
    		{
    			return string.Format("serialize={0},hint={1}", Serialize, Hint);
    		}
    	}
    
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			var index = clang.createIndex(0, 0);
    			var ufile = new CXUnsavedFile();
    			var trans = new CXTranslationUnit();
    			ufile.Filename = "dummy.cpp";
    			ufile.Contents = "#include \"sample.h\"";
    			ufile.Length = ufile.Contents.Length;
    
    			var erro = clang.parseTranslationUnit2(index, "dummy.cpp", new String[] { "-std=c++11" }, 1, new CXUnsavedFile[] { ufile }, 1, (uint)(ClangSharp.CXTranslationUnit_Flags.CXTranslationUnit_SkipFunctionBodies), out trans);
    			var cursor = clang.getTranslationUnitCursor(trans);
    			var kind = clang.getCursorKind(cursor);
    			var pg = new Program();
    			clang.visitChildren(cursor, new CXCursorVisitor(pg.visitChild), new CXClientData());
    
    		}
    		protected List _namespace = new List();
    		protected String _namespaceStr = "";
    		protected Dictionary<uint, Param> _params = new Dictionary<uint, Param>();
    		CXChildVisitResult visitChild(CXCursor cursor, CXCursor parent, IntPtr client_data)
    		{
    			switch (cursor.kind) {
    			case CXCursorKind.CXCursor_Namespace:
    				readNamespace(cursor);
    				clang.visitChildren(cursor, new CXCursorVisitor(visitChild), new CXClientData());
    				removeNamespace();
    				break;
    			case CXCursorKind.CXCursor_ClassDecl:
    				readClass(cursor);
    				break;
    			case CXCursorKind.CXCursor_EnumDecl:
    				readEnum(cursor);
    				break;
    			case CXCursorKind.CXCursor_FieldDecl:
    				readField(cursor);
    				break;
    			case CXCursorKind.CXCursor_ClassTemplate:
    				readTClass(cursor);
    				break;
    			case CXCursorKind.CXCursor_CXXMethod:
    				readMethod(cursor);
    				break;
    			default:
    				break;
    			}
    			return CXChildVisitResult.CXChildVisit_Continue;
    		}
    		CXChildVisitResult visitEnum(CXCursor cursor, CXCursor parent, IntPtr client_data)
    		{
    			var itype = clang.getEnumDeclIntegerType(cursor);
    			if (itype.kind == CXTypeKind.CXType_UInt) {
    				Console.WriteLine("{0} {1}", clang.getCursorSpelling(cursor), clang.getEnumConstantDeclUnsignedValue(cursor));
    			}
    			else {
    				Console.WriteLine("{0} {1}", clang.getCursorSpelling(cursor), clang.getEnumConstantDeclValue(cursor));
    			}
    			return CXChildVisitResult.CXChildVisit_Continue;
    		}
    
    		void readNamespace(CXCursor cursor)
    		{
    			var cxName = clang.getCursorSpelling(cursor);
    			String name = cxName.ToString();
    			_namespace.Add(name);
    			_namespaceStr = String.Join("::", _namespace);
    		}
    		void removeNamespace()
    		{
    			_namespace.RemoveAt(_namespace.Count - 1);
    			_namespaceStr = String.Join("::", _namespace);
    		}
    		void readClass(CXCursor cursor)
    		{
    			Console.WriteLine("クラス定義発見 {1}::{0}", clang.getCursorSpelling(cursor), _namespaceStr);
    			// さらに子を検索する
    			clang.visitChildren(cursor, new CXCursorVisitor(visitChild), new CXClientData());
    			_params.Clear();
    		}
    		void readTClass(CXCursor cursor)
    		{
    			Console.WriteLine("テンプレートクラス定義発見 {0}", clang.getCursorSpelling(cursor));
    			// さらに子を検索する
    			clang.visitChildren(cursor, new CXCursorVisitor(visitChild), new CXClientData());
    		}
    		void readEnum(CXCursor cursor)
    		{
    			Console.WriteLine("enum定義発見 {0}", clang.getCursorSpelling(cursor));
    			// さらに子を検索する
    			clang.visitChildren(cursor, new CXCursorVisitor(visitEnum), new CXClientData());
    		}
    		void readMethod(CXCursor cursor)
    		{
    			var name = clang.getCursorSpelling(cursor).ToString();
    			// パラメータ解析する為のキーワードを見つけたら
    			if (name.StartsWith("__Paramater_"))
    			{
    				var location = clang.getCursorLocation(cursor);
    				CXFile file;
    				uint line;
    				uint column;
    				uint offset;
    				// 行番号とセットで情報を覚えさせる
    				clang.getSpellingLocation(location, out file, out line, out column, out offset);
    				Console.WriteLine("パラメータ宣言発見 {0} {1}", name, line);
    				var param = new ClangTest.Param();
    				// これで引数を解析
    				var n = clang.Cursor_getNumArguments(cursor);
    				for (uint i = 0; i < n; ++i)
    				{
    					var arg = clang.Cursor_getArgument(cursor, i);
    					param.parseFunc(arg);
    				}
    				_params.Add(line + 1, param);
    			}
    		}
    		void readField(CXCursor cursor)
    		{
    			var type = clang.getCursorType(cursor);
    			String typeName;
    			var arrCount = clang.getArraySize(type);
    			if (arrCount > 0) {
    				var arrType = clang.getArrayElementType(type);
    				typeName = String.Format("{0}=>({1})", arrType, arrCount);
    			}
    			else {
    				typeName = type.ToString();
    			}
    			var location = clang.getCursorLocation(cursor);
    			CXFile file;
    			uint line;
    			uint column;
    			uint offset;
    			// フィールドが出てきたときに覚えていた行数とパラメータ情報に一致するものがあったらその情報を適応する
    			clang.getSpellingLocation(location, out file, out line, out column, out offset);
    			Param pm;
    			if (_params.TryGetValue(line, out pm)) {
    				Console.WriteLine("パラメタ付変数宣言発見 {0} {1} {2}", clang.getCursorSpelling(cursor), typeName, pm);
    			}
    			else {
    				Console.WriteLine("変数宣言発見 {0} {1}", clang.getCursorSpelling(cursor), typeName);
    			}
    		}
    	}
    }

    という感じで、

    特定の名前の関数が登場した行数とそこから取得できるデフォルト引数を記録して、

    フィールドが出てきたときに行数をチェックして該当のパラメータを持っているという解釈をさせるという事で

    フィールドに情報の追加を行う事が出来ます。

    デフォルト引数の取得にちょっと苦戦しましたが…思いの外すんなり出来てしまうものですね

    ここまでくるとそろそろ次回辺りは実践編になるかもですね。

    という事で今回はここまでです。

    ではまた次回にお会いしましょう


  • 2016年12月1日

    C#のLINQが便利!

               

    シワッスプログラマーの平尾です。

     

    今回はプログラマー向けの話です。
    C#3.0からLINQという凄い便利な機能が使えるので、簡単に紹介します。

     

    LINQで一体何が出来るのかというと、
    「コレクションの操作を非常に簡潔に記述すること」
    が出来ます。

     

    と言われてもLINQを知らない方はピンと来ないと思いますので、
    サンプルプログラムを書いてみました。
    (LINQはメソッド構文で記述しています)

     

    【ソース】

    using System;
    using System.Linq;    // LINQを使用する際に必要なusing
    
    class Program
    {
        public class Data
        {
            public string    name;
            public string    home;
            public int       power;
        }
    
        static void Main(string[] args)
        {
            // キャラクターデータ
            var src = new Data[]
            {
                new Data { name = "筋肉男", home = "日本",     power = 95   },
                new Data { name = "星肩男", home = "アメリカ", power = 95   },
                new Data { name = "鉄仮面", home = "イギリス", power = 95   },
                new Data { name = "拳法男", home = "中国",     power = 97   },
                new Data { name = "軍服男", home = "ドイツ",   power = 90   },
                new Data { name = "熊爪男", home = "ロシア",   power = 100  },
                new Data { name = "猛牛男", home = "スペイン", power = 1000 },
                new Data { name = "元人間", home = "アメリカ", power = 83   },
            };
    
            // 名前だけ取り出す
            var dst = src.Select( x => x.name );
            Console.WriteLine("■名前一覧");
            foreach ( var data in dst ) {
                Console.WriteLine("name = {0}", data);
            }
    
            // パワーが100以上のキャラクターを取得
            var dst2 = src.Where( x => x.power >= 100 );
            Console.WriteLine("\n■パワーが100以上のキャラクター");
            foreach( var data in dst2 ) {
                Console.WriteLine("power = {0, 4}, name = {1}", data.power, data.name);
            }
    
            // 日本またはアメリカ出身のキャラクター数
            int count = src.Count( x => x.home == "日本" || x.home == "アメリカ" );
            Console.WriteLine("\n■日本/アメリカ出身者数 = {0}人", count);
    
            // パワーが高い順にソート
            var dst3 = src.OrderByDescending( x => x.power );
            Console.WriteLine("\n■パワーが高い順");
            foreach( var data in dst3 ) {
                Console.WriteLine("power = {0, 4}, name = {1}", data.power, data.name);
            }
    
            // 出身地でグループ化する
            var dst4 = src.GroupBy(x => x.home, x => x.name );
            Console.Write("\n■出身地別");
            foreach (var group in dst4) {
                Console.Write("\n{0}:", group.Key);
                foreach (var name in group) {
                    Console.Write("{0}, ", name);
                }
            }
        }
    }
    

     

    【出力結果】

    ■名前一覧
    name = 筋肉男
    name = 星肩男
    name = 鉄仮面
    name = 拳法男
    name = 軍服男
    name = 熊爪男
    name = 猛牛男
    name = 元人間
    
    ■パワーが100以上のキャラクター
    power =  100, name = 熊爪男
    power = 1000, name = 猛牛男
    
    ■日本/アメリカ出身者数 = 3人
    
    ■パワーが高い順
    power = 1000, name = 猛牛男
    power =  100, name = 熊爪男
    power =   97, name = 拳法男
    power =   95, name = 筋肉男
    power =   95, name = 星肩男
    power =   95, name = 鉄仮面
    power =   90, name = 軍服男
    power =   83, name = 元人間
    
    ■出身地別
    日本:筋肉男,
    アメリカ:星肩男, 元人間,
    イギリス:鉄仮面,
    中国:拳法男,
    ドイツ:軍服男,
    ロシア:熊爪男,
    スペイン:猛牛男, 
    

     

    プログラム中で以下のように呼び出しているのがLINQクエリです。

    src.Where()
    src.Select()
    src.Count()
    src.OrderByDescending()
    src.GroupBy()
    

     

    本来ならループして書くところが、とんでもなく簡潔に書けていると思います。
    データを取り出す処理はどれも1行
    むしろ表示部分の方が長いという…

     

     

    この他にも様々な機能が存在していますし、
    次のようにLINQクエリを重ねて書くこともできます。

    src.Where.().Select()

     

    LINQはこのように複雑な処理を簡潔に記述でき、とても便利です

    気になった方はネットで詳しい使用方法を検索してみて下さい~


ヘキサブログ ピックアップ



過去の日記はこちら

2017年1月
« 12月    
 1
2345678
9101112131415
16171819202122
23242526272829
3031