東京工業大学 ロボット技術研究会

東京工業大学の公認サークル「ロボット技術研究会」のブログです。 当サークルの日々の活動の様子を皆さんにお伝えしていきます。たくさんの人に気軽に読んでもらえると嬉しいです。
新歓特設ページ        ロボット技術研究会 HP        ロボット技術研究会 twitter公式アカウント

「ロボット技術研究会」通称「ロ技研」は、その名前の通りロボットの制作や研究はもとより、電子工作や機械工作、プログラミングなどの幅広い分野にわたるものつくり活動を行っています。

カテゴリ一覧: loading

年末ティータイム ~紅茶事始め~ 後編

おはこんばちはなら、14お粥(@JpREOTTO)です。こちら記事はrogy Advent Calendar 17日目の記事です。
題して
「年末で出来る紅茶事始め」 
の記事です。こちらの記事には前編がありますので、見てない方はまずそちらをどうぞ~

では続きです。 
続きを読む

RPGツクールMVでのシューティングゲーム作成について

こんにちは、13の折重です。今回はrogy Advent Calendar 2016の16日目として記事を書きます。
凄い更新が遅くなってしまって申し訳ないです。アドベントカレンダーは日付が変わった瞬間に投稿するのが普通っぽいですよ奥さん

 screenshot
こんな感じのを作ります

の前に宣伝とか

Advent Calenderに登録した時書くことが決まってなかったので記事概要みたいなところに超ナメたこと書いてますね、すいません。実際何も考えてなかったわけではなく逆に色々考えてて、一回書く内容変えたりしてます。じゃあ前まで何書こうと思っていたのかというと、今までのゲーム制作についての色々です。それは結局別の機会に書くことにしたので今回はこっちを書くことにしました。

とここで宣伝。
来るコミックマーケット91にて、我々ロボット技術研究会もサークルとして参加し、有志による記事をまとめた部誌を発行することにしました。そしてそこに僕も「学園祭におけるゲームプレイの観察」と題して寄稿しております。興味がある方は是非買って読んでみてください。スペースは木曜日(12/29) 西地区 "ほ"ブロック41bです。

ここから本題

今回の記事について

今回はシューティングゲームを作る過程で、RPGツクールMVの仕様とプラグイン作成について紹介していこうと思います。
RPGツクールMVはRPGツクールシリーズの最新版で、誰でも気軽にRPGを制作することができます。更にMVからはHTML5をベースにすることによりブラウザで動作するゲームを簡単に作れるようになりました。また、今回扱ったようにプラグインによる拡張でシューティングゲームを作成できるなど、非常に広い汎用性を持ちます。
ゲームエンジンならばUnityなど他のものもあるのではないかと言われるかもしれませんが、RPGツクールはRPGであれば特別な知識などなくても簡単に作成できますし、先ほども言ったようにHTML5がベースなのでwebなどでの公開も簡単で迅速(当然公開場所は自分で用意しなくても公式に用意されています)、更にJavaScriptでプラグインが作成できるため拡張性も高くweb関係の機能の実装とも親和性が高い、という利点があります。今回のようなシューティングゲームを作るようなのはできなくもないだけで極端な使い方ですが、基本普通のRPGを作りそこに独自の機能を追加したいというのには非常に向いていると思います。
シューティンゲームにした理由ですが、バイトでRPGツクールを使って色んなものを動的に生成したり意味不明な使い方を色々したんで、もしかしたらシューティング作れるんじゃないのかって思ったことと、僕が好きなジャンルだからなのと、なんとなくゲーム制作初心者向けってイメージがあるからです。シューティング作れればあらゆるジャンルのゲームが作れますよ、多分。

前述したように筆者はRPGツクールMVを使用しはじめたのが今年の4月から(しかもバイトは月数回)、ついでにJavaScript経験もそれに毛が生えた程度なので不格好なコードもあるかもしれませんが、これからRPGツクールを使いたい人、現在使っている人の助けに少しでもなれれば幸いです。あとバイトを引き継ぐ人が決まったら読んでもらいたいです(主目的)

前提

前置きが多いですね、申し訳ないです。
今回の記事ではJavaScriptについての説明はしません。必要なJavaScriptの知識は各自で勉強してください。すいません。
またクラスがどうとか言っていますがprototypeを使用してクラスっぽい実装をしています。継承って言ったらプロトタイプチェーンを利用してメソッドを親クラスから引き継いでるんだと思ってください。なんか最近JavaScriptにclass構文が実装されたそうですが、RPGツクールでの実装が全てprototypeになっているのでそれに倣います。もしかしたら次のRPGツクールでは実装が変わっているかもしれませんね。というかクラスに限らずRPGツクールの元からの実装に倣っている部分が結構あります。

オリジナルシーン、ウインドウの作成

シーンは、RPGツクールではrpg_scene.js内で定義されており、Scene_TitleやScene_Map、Scene_Battleなどがあります。今回はシューティングゲームということでScene_Shootinを作成したいのですが、基本的にはRPGでのマップ画面とあまり変わらないのでScene_Mapを継承したScene_Shootingクラスを作成することで実装します。
Scene_Shooting.jsとうファイルをpluginsフォルダの中に作り、以下を記述します。

Scene_Shooting.jsに追加

ここまでで保存し、いったん動かしてみます。プラグインを使うにはRPGツクールのエディタ側でツール→プラグイン管理からプラグインを追加しなければならないので忘れないようにしましょう。動かしてもScene_Mapと全く同じ機能を持ったScene_Shootingが代わりに呼ばれるだけなので見た目は全く変わりません。
では少し変更を加えていきます。まず既存の関数をオーバーライドし書き換えることで不要な画面遷移やウインドウ表示などをしないようにしてしまいましょう。

Scene_Shooting.jsに追加 

ここで実行してもまだWindow_SideMenuクラスを作成していないためエラーが出ます。
というわけでウインドウを作っていきます。シューティングゲームにおいてスコアや残機を表示するウインドウです。
ウインドウはrpg_window.jsというファイル内にたくさん定義してあり、それをシーンに追加していく形で表示します。ウインドウ自体が表示する画像や文字などの内容や大きさの情報を持っており、シーンからはウインドウ作成時に表示位置を指定するのみです。新しいウインドウを作成したいと思ったらそれを実現するウインドウクラスを新しく作成してあげましょう。場合によってはそのウインドウを表示する用の新しいシーンも必要になるかもしれませんね。
rpg_window.jsには色々なウインドウのベースとしてwindow_BaseやWindow_Selectableなどがあります。今回は選択肢は必要ないのでWindow_Baseを継承し新たにWindow_SideMenuクラスを作成していきます。

Scene_Shooting.jsに追加

というわけでここまでで自作のシーンとウインドウを追加することができるようになりました。これだけでもかなり制作の自由度は上がるかと思います。

自機の作成とSpriteの追加

次はプレイヤー周りをいじっていきます。と言ってもやることはあまり変わらないです。 
プレイヤーに関する記述はrpg_object.js内に書かれています。rpg_object.jsはその名の通りゲーム内に出てくるオブジェクトについての記述がなされています。マップに表示されるプレイヤーに関してはGame_Playerクラスに書かれています。

まずGame_Player.jsというファイルを作成します。この中でGame_Playerクラスの関数を改変していきます

Game_Player.jsに追加 

RPGでの移動はマス目単位ですがシューティングではその必要はないので毎フレーム移動し進行方向のマス目の状態を確認する部分なども削ります。これだけだと超高速移動をしてしまうので移動距離の計算部分も変更します

 Game_Player.jsに追加 

これでシューティングゲームのように動きました。最後に向きを上向きに固定します。移動処理を書き換えたタイミングでキャラの向きの更新の処理も消してしまったので初期化する時方向を上向きにしてあげれば大丈夫です。

Game_Player.jsに追加  

これで自機を動きはできました。え、なんかデフォルトだと仲間が3人くらい表示されてる?忘れるなかれこれはRPGツクール、そこらへんの設定はエディタ側でできます。ツール→データベース→システムから初期パーティを変更してしまいましょう。

自機をシューティングっぽく動かすことができたので、次は弾を出せるようにしていきたいと思います。ですがその前に、ここでRPGツクールの描画の仕組みについて少し触れます
RPGツクールは画像の描画にpixi.jsというライブラリを使用しています。rpg_core.js内のSpriteというクラスがpixi.jsを用いた画像描画を行う上でのラッパーのような役割をしており、rpg_sprite内にあるSprite_CharacterやSprite_ActorクラスなどがSpriteクラスにゲーム内で扱う上で必要な機能や情報を目的ごとに追加したものになっています。更にrpg_sprite.js内にはSpritesetというSpriteをまとめて管理するためのクラスがあります。各シーンはこのSpritesetを持っており、ここにSpriteを追加していくことで画面に描画するものを管理しています。
実はRPGツクールはマップのロード時に必要なオブジェクトの画像なんかは全てロードしてしまい、まだ発生しないイベントなんかも画像非表示になっているだけでマップには存在していたりします。RPGなので当然と言えば当然なのですが、そのためオブジェクトの動的生成は少しやりずらかったりします。色々がんばるとできます。 
今回Scene_ShootingはScene_Mapを継承して作成したため、Spriteset内のtilemapにSpriteを加えていきます
 
Scene_Shooting.jsに追加

これを呼ぶことによって描画対象を追加することができます。

弾と弾幕の作成

弾クラスと、それを管理する弾幕クラスを作成することにより実装することにします。自機や敵キャラはそれぞれ1つの弾幕クラスを持つようにします。弾については、Game_CharacterBaseクラスを継承したGame_Bulletクラスを弾クラスとして作成します。RPGツクールではマップに表示されているキャラや扉なんかのオブジェクトは基本的にrpg_objectにあるGame_CharacterBaseというクラスを継承しています。Game_CharacterBaseでは画像や座標などの情報を持っており、座標を変更すると勝手に描画位置も変わるなど、ゲーム中の視認できる物体を扱いやすくしています。弾には無駄な情報も多いですが楽なので利用します。
まずGame_Bullet.jsを作成しクラスを作成します。プラグイン追加も忘れずに。

Game_Bullet.jsを追加 

基本的には初期化関数やアップデート関数をオーバーライドしているだけですが、initialize()内でsetParams()を、refresh()内でsetImageData()を読んでいます。これらは弾の当たり判定の範囲や画像データなど弾固有の情報を初期化するものです。後ほどGame_Bulletクラスを継承して新たにクラスを作成する時にまた説明します。

これで一応弾を出すことができるようになりましたが、まだ生成部分の処理を作っていないので画面は何も変わっていません。試しに入力をされたらプレイヤーが弾を出すようにしてみましょう。

Game_Player.jsに追加
 
既存のupdate関数を以下のように変更

これでZキーを押すとなんか変な光みたいな画像が表示されたと思います。まだ移動処理なども書いてないのでその場から動きませんが。SceneManagerはRPGツクールのシーンを管理しており、グローバルに定義されているのでどこからでもアクセスできます。内部に現在のシーンを保持しているのでそこからAddSprite関数を呼び出しましょう。
次はこれらの管理をする弾幕クラスを作成していきます。これは特に実体もなく画像もいらないので全て自作してしまいます。ひとまずの実装を書きます。プラグイン追加も忘れずに。

Shot.jsに追加 


addBullet関数でShotクラス内のArray配列であるbulletsに弾を入れ、同時にスプライトも登録してしまいます。
これは弾幕全体のスーパークラスであり、これを継承して更にPlayer_ShotクラスとEnemy_Shotクラスを作成します。generate関数やcollide関数、controlBullet関数は継承した先でオーバーライドします。
というわけで、Player_Shotを作成して自機についての処理を完成させてしまいましょう。

Game_Player.jsに追加


update関数を以下のように書き換え

これで先ほど表示された光が前方に向かって飛んでいくようになったと思います。ただし弾が画面外に行くようになってしまいました。現状画面外にある弾がいつまでも表示されているので、これを削除するようにしたいと思います。

Scene_Shooting.jsを変更
update関数に以下を追加

これで弾が消えるようになりました。以降衝突などで弾を消したいときは弾のqctiveの値をfalseにしてあげれば勝手に消えます。
 
現状Game_Bulletクラスに書いたてきとうなパラメーターの弾を生成していますが、自機用にGame_PlayerBulletクラスを作成しそれを生成するようにしましょう

Game_Bullet.jsに追加

Game_Player.jsを変更
generateEvent関数を以下のように書き換え

はい、画像が変わったと思います。弾の種類を増やす時はsetImageData()で弾の画像を、setParams()で弾の情報を書き換えるだけで増やすことができます。

ここまでで自機の実装と、基本的な機能の実装ができました。

次は敵と敵弾幕を実装...と言いたいのですがぶっちゃけここからはただのゲーム作りになってしまうので説明は割愛します。時間もないですし......
せっかくなので実装した部分までのソースコードはgithubに公開しておきます、記事の最後の方にあります。微妙にブログ用に修正したのと違いますが。敵の実装とかがすでに適当なのであまり参考にしない方がいいです。あとあくまで説明用に作ったものなのでゲーム部分はかなり適当です。当たり判定とかもっと色々できそうですね。関数は用意してありますしシューティング作りたいと思った方は自分で実装してみてください。
あとはエフェクトとかもつけてもいいかもしれませんね。弾から当たり判定抜いたものを作るだけで実装できそうです。というか弾のrangeを0にするだけでエフェクトと言い張れなくもなさそうです。

補足

RPGツクールはF2キーを押すことでFPSを表示させることができます。デフォルトは50FPSでいじる方法があるのかは知りませんが、それで見た感じかなり弾を出してもFPSは維持されていました。画像にこだわったりしたらブラウザで動作するかなり本格的なシューティングゲームが作れるのではないでしょうか。
他にもデバッグ用の機能が色々あるっぽいのでとりあえずファンクションキーとか押しまくってみるといいと思います。

では結構な長さになってしまいましたが読んでいただきありがとうございました。
明日はJpREOTTOくんによるまったり🍵とした内容を書くばい(放課後~)です。
 
Github
https://github.com/OrishigeMasato/RPG_ShootingPlugins
 

Haskellで始める手続き型プログラミング

こんな煽りがあったので、書いてみることにしました。Haskellが好きなphi16です。この記事はrogy Advent Calendar 15日目の記事です。まぁポエムみたいなものです。

Haskellとは

純粋関数型言語、と良く言われます。いろんなプログラミング言語の中でも結構特殊で、例えば変数が無いとか、間違ったコードはすぐコンパイルエラーになるとかあります。でもHaskellは実はマルチパラダイムみたいなところがあるので手続き型のコードは普通に書けます。

Hello, World!

それはそうって感じ。「=」が気になるかもしれませんけどdoが{}みたいな意味なのでそんなものかなと。関数呼び出しに括弧が無いのはなんだかメッセージパッシングっぽいですね。まぁ括弧なんて要らないよね、慣習でついてるだけで。

FizzBuzz

ちょっと慣れない感じですね?1行目は特殊な便利構文をつかうよーっていう宣言です。GHC(コンパイラ)が許してくれればOKなんです。
forMは所謂for文に近いですが、最近の言語でよくあるRange-based forですね。つまり1から100までの値でforするっていうことです。その値を受け取る方法が $ \x -> です。for内部の手続きで使われる値としてxをつかうよーっていうことですね。
さてifですけど、なんだか条件がいっぱいあります。1行目に書いた命令によってifの条件文を|に続けていっぱい書けるようになったのです。うれしいね! `mod`は%と同じです、割り算のあまり。条件を満たすときはまた -> を使って続きの手続きを書きます。otherwiseはいままでの条件を満たさない場合用の文ですね、defaultみたいな。
後増えたのはprintですか。putStrLnは文字列を出力する命令で、printは出力できそうなものなら出力してくれる命令です。よくあるかんじ。

うんうんわかってきた。

入力と出力

大体の言語での手続きは引数と返り値をとれるようです。Haskellでもやってみましょう。 先程forMで使った $ \i -> の中でも \i -> の部分が再登場しています。要はこれは「引数を持つ手続き」をつくる機能なのです。
$」は実は、「右側全てを括弧で囲んだものとする」という命令です。これがないと手続きがどこで分断されるかわからないのでforMのときは指定する必要がありました。今回は定義なのでだいじょうぶです。
その代わりreturnには$がついています。これは(return i) * iと混乱するかもしれないからつけるのです。勿論括弧で書いてもいいですけど邪魔ですよね。
手続きに値を与えるのはputStrLnと同様にとなりに置けば良いです。そこから返り値を取り出すには <- を使うようです。実行してみると25と、確かにsquareの結果が取り出せていることがわかりますね。

手続きとは?

とりあえず今のところ、「do」が手続きを表していることがわかったとおもいます。いろんな言語で{}で手続きを表していたことと似たような感じです。ですがHaskellには他の言語にはない面白い性質があります : 手続きは代入できます。第一級関数ならぬ第一級手続きってところですね。今まで「=」だったのはそういう理由でした。

別に他の言語でも手続きは代入できる、って言う人はいるとおもいます。けどそれって「無引数関数」ですよね。それは本当にあなたの言語の「手続き」でしょうか。Objective-Cの^{}が一番表記的には近いかもしれませんね、でも結局それを実行する際にproc()と、関数適用の()が必要になります。
Haskellではそれは必要ありません。
確かに無いですね。これが正しい「第一級手続き」ではないでしょうか?手続きを最も気軽に扱えるのは本当はどんな言語なのでしょうね?

おわりと余談

いやまぁジョーク記事ですけど・・・。

私のせいもあるとおもうんですけど、Haskellが(ローカルな界隈だと)偏見で貶される or 怖がられることが多いので 別にHaskellやってほしいわけじゃないですけど普通の1言語として捉えてほしいなーという気持ちです。私はHaskellを「自由にコードを書ける」「バグを早期発見できる」という点で他の言語よりも優秀な言語だと思っていますけど勿論これは別の話です。

あと全てのプログラマに知っていて欲しいと思うこととして、「自分の言語でつらいことが他の言語で簡単にできることがある」というのがあります。C言語を使わないといけない場合でも、「自作言語のコードからC言語のソースを出力するプログラム」は作れるはずです。Syntax Sugarというのは案外言語の本質で、書きたい記法があるなら書けるようにすればよいのです。これをやりまくったのが現在のAltJS文化です。また自分の知っている言語には無いライブラリが他の言語にあることは多々あります。ライブラリを自分で書くより言語を勉強する方が速いことも多いです。目的を達成する方法はいっぱいあるはずなのです。手続き型が良いのか、関数型が良いのか、それとも・・・ 色々選択肢を持っておくことは大事だとおもいます。正しく言えば「自分には選択肢がある」ということを認識するのが大事だとおもいます。

私はこれからも幸せなコードの書き方を追求していきます。

以降、無駄な補足と解説

さすがにまるなげはだめかなっておもって。

間違ったコードはコンパイルエラー

間違ってることを勿論100%検出できるはずがありません。でも大体の言語で発生する実行時エラーは、基本的にはコンパイル時の「型チェック」までで検出できます。ついでにいえばHaskellで起きるエラーは大体型エラーです。型ってすごい。

実はマルチパラダイム

パラダイムってなんですかね。ある意味では「プログラムの読み書き作法」かな?と思います。確かにHaskellは関数型言語でCは手続き型だとおもいます。では「Haskelは手続き型ではない」のでしょうか?
最近の言語は大体自由にコードを書けるようになっているのでパラダイムの明確な区別ができずにマルチパラダイムと呼んでいる場合が多いみたいですね。Haskellではどれくらい自由にコードを書けるのでしょう。
Haskellでは日常的にdo文を使います。というか使わないとコードは書きにくいのです、確かにそれは純粋関数型の制約なのかもしれません。でもHaskellにはdo文があるのです。この「文法」が何をできるか、というのはまぁ数多くあるモナドの例を眺めてみればわかる通りだとおもいます。
大体do文ってもう見た目が手続き型じゃないですか? Haskellは「作法として」do文を使うことが多いです。これは手続き型なんじゃないですかね。

Hello, World!

大体の言語のHello, World!は実は中身ヤバいっていう話がよくあるように(ref:PHP による hello world 入門)、HaskellのHello, World!の全貌を正しく理解するのは勿論困難です。でもどんな言語でもそんなもんですよね。
ちょっと補足するとしたら、実は「1行だけのdo文」は「その文そのもの」と等価です。要は : これで十分です。勿論以降も同じですが、明示的なブロックの導入ということで毎回書いてます。ifで{}を省略できるのと理屈は同じです。
また、とても大切な事実として putStrLnの戻り値は、よくあるvoid型ではなくIO voidです。このIOがとても大事なのです : 副作用の存在を表す型です。

括弧なんて要らない

これができるのは「2引数関数」と「1引数を取って1引数関数を返す関数」を区別しないことによるものです。別に他の言語でもf(x)(y)はできるとおもうんですけどちょっと気持ち悪いですよね。Haskellだと括弧が無いのでこれに特に抵抗もなく、まぁ文化なのかなぁっていう感じです。実際いろいろ便利なんですよね。

特殊な便利構文

Haskellの言語仕様はきっちり定められていてHaskell2010という名前がついていますが、GHCはそれ以外にも拡張をいっぱい定義しています。使うときはコマンドからとかではなくソースに直接記述できるので他の言語よりも気楽に書けるわけです。
色々と世界が高度になりすぎたお陰で言語拡張が無いと困るようなケースが結構あるのです。でもどうせGHCしか使われないのでぽんぽん突っ込んでもOKみたいな感じ。言語仕様は実質GHCそのものみたいなところがある。

$演算子

見た目がわかりにくいんですよね・・・これ無い方が多分初学者には優しいんだとおもいます。
これは事実としてただの関数適用演算子です。左辺に右辺を適用する。ただ、優先順位が最低なのでa + b $ c + dとかやると(a+b) $ (c+d)になります。仕組みがわかる気がする。
さらに右結合なのでf $ g $ xとか書くとf $ (g x)、つまりf (g x)です。便利な気がするじゃないですか。
最近は逆向きの演算子として&が良く使われるようになってしまった(Lensのせい)のでx & g & fとかも増えましたね。まぁ演算子文化が賛否両論なのはめちゃくちゃわかるので何も言わないですけど、Haskellには強い検索ツールがありますし、ドキュメントちゃんとしてるし、型あるし、まぁ、ゆるしてほしい。

出力できそう

なんかObjectにtoStringを生やしている言語とか、<<があるならOKみたいな言語とか、いろいろありますけど。HaskellはShow型クラスのインスタンスを定義しておくと「出力できそう」なことになります。まぁ明確に定義されてるよってこと。
表示できないタイプだと実行時エラーになる言語とか、フォーマットエラーをガン無視する言語とは比べ物にならないですね。

無引数関数と手続き

まぁHaskellには無引数関数はないんですけど・・・ 一般的な言語で「無引数関数」と「手続き」を区別する必要がある理由は、「引数を取らないと手続きの中身を実行してしまうから」だとおもいます。Haskellでは適当に値を作ったとしてもそれが副作用付きだったら評価しません。遅延評価によるものではなく、「副作用付きの値」から値を取るにはdo文に乗せて「<- 」を書く必要があるからです。とはいえ仕組みは無引数関数と全く同じと考えていいとおもいます。
重要な差は、「do文の中で羅列された式は順番に()されていく」という規則なのです。要はdo文の中に書いたら勝手に()されるので、わざわざ引数をとるように記述する必要がないということです。そういうように設計されているのです。
これは手続き型言語、正確に言うと純粋世界と副作用を区別できない言語ではできないことだとおもいます(まぁ一貫性を無視すればできるんですよね・・・UFCSとかの・・・)。

まぁ全体を通して言いたいこととしては「do文はすごい」っていう話です、うん。

定義と代入

勿論違うものです。でも今回のコンテキストでは本質的な違いではないです。事実として「変数」に手続きを代入することはできますし、そこから取り出した手続きを実行するのに括弧はいりません。

Syntax Sugarは本質

do文はただのSyntax Sugarです。

つまりSyntax Sugarがあるだけで純粋関数型言語でも手続き型のようにコードを書けるということ。逆にいえばそういうSyntax Sugarが無いからC/C++はつらいんです。
ちなみに最近は多くの言語にこのdo文と本質的に等価な機能が導入されています : Generator。いっつもGeneratorの宣伝していますけど、これは本当にdo文みたいなものなので好きなパラダイムをGenerator上で展開できます。うれしい!Syntax Sugarとして提供されている場合と言語構造として定義されている場合があるようですけど、前者で十分とは言え大した差はないですね。
みんなもGenerator使って幸せなプログラムを書いていこう。
ギャラリー
  • 自作キーボードを作ろうver1.0
  • 自作キーボードを作ろうver1.0
  • 自作キーボードを作ろうver1.0
  • 自作キーボードを作ろうver1.0
  • 第14回ROBO-ONE Light 結果報告
  • ロボット技術研究会紹介
  • ロボット技術研究会紹介
  • rogy2016冬合宿 in 戸狩
  • rogyサバゲ:†革命†をもっと
記事検索
最新コメント