フリーゲーム・フリーソフトの開発過程を記録していく、TDtechnic公式ブログです。製品はカテゴリの「ダウンロード場」からダウンロードして頂けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

こんばんは。広告消し更新です。

最近はレポートや他ごとの作業であまりプログラミングができない次第であります。
ShiroScriptについてもコードはこの間から全然変わっていなくて、特に今報告することはございません。失礼します。
スポンサーサイト

[2016/11/10 19:48] | (コードネーム:モンジュラ)
|
こんばんは。新学期のShiroです。

ShiroScript処理系第一号の実装が完了しました。完全にテストはしていませんが、予定していた一通りの機能はすべて揃いまして、一応スクリプティングもできなくはない状態です。

ただ、すぐに実用化できるかというと難しいです。柔軟性を求めた結果、変数や文字列の取り回しがかなり複雑になったため、全体的に動作が重いのです。一部の単純な命令は限りなくノータイムに近い時間で終わりますが、一般的な命令は数マイクロ秒かかり、一部の重い命令は十数マイクロ秒かかります。これは私のパソコンの場合、足し算を数千回行うのにかかるのと同じくらいの時間です。

マイクロ秒単位の話なので随分細かいことを言っているようにも見えますが、結構これが馬鹿にできない時間なのです。一般的なゲームは秒間60フレームの更新速度で動きます。すなわち1フレームを完成させるのにかけられる時間は最大で1/60秒 ≒ 16.667ミリ秒 = 16667マイクロ秒です。例えばすべての命令が10マイクロ秒で動くとすれば、1フレームを完成させるために実行できる命令は約1667命令しかないというわけです。

1600命令超となるとこれまた多いように見えるかもしれませんが、もし入力処理やキャラ移動処理、画面の描画など全てをスクリプト主体で書くのであれば到底1600命令程度では足りません。そしてなにより問題なのが、この数値がわりと速いCPUでの結果だということです。一般的なパソコンでは1600命令も使えず、古いパソコンやネットブックでは数百命令しか使えないかもしれないのです!

一部の速いパソコンでしか動かないようではまだ完成とは言えません。ただでさえゲームは重い処理が多いのですから、スクリプトなどにかける時間は最小限にする必要があります。幸い高速化できる余地の見当はついており、そのうちいくつかは実際に効果が見られました。まだ試していない最適化もあるのではっきりしたことはわかりませんが、遅すぎてノベルゲームにしか使えないなんてことにはならなくて済みそうです。

[2016/09/28 19:53] | (コードネーム:モンジュラ)
|
こんばんは。もう一ヶ月経ってしまいましたがまだスクリプト言語の仕様を考えているところです。
ただ、ずっと一貫してスランプ続きというわけではありません。先日までは確かに何の収穫もない日が続いていたのですが、数日前に大きな進展がありまして、それからは結構順調に仕様が決まっていっています。以下にこの言語の概要を述べます。

まず断っておきたいのは、前回申し上げた「タイムライン」システムはやっぱりボツになったということです(笑)自由度がないせいか、制御がしにくいせいか、とにかくサンプルコードを書くにも至りませんでした。発想としては(自分の中では)面白かったんですが、残念。

ではどのようなシステムかというと、やっぱり基本は、王道を征く、命令列の逐次実行です。そして、条件分岐を始めとする制御構文が存在するというのもセオリー通りです。ただ、ラベルは低水準すぎるので不採用としました。ちゃんとスコープのある構造化しかサポートしていません。

ですが、単なる逐次実行と制御構造であればCやC++で書けばいいだけのことです。ゲームで求められる複雑な制御構造に対応するため、この言語では擬似マルチタスクを言語レベルでサポートしています。つまり、別々のスクリプトを、見かけ上並列的に実行することができるのです。ただし、あくまで「擬似」なので、マルチスレッドやマルチコアの恩恵を得ることはできません。その代わり、命令レベルでの実行順が一意に定まるというメリットが有ります。

そして、この言語の最大の特徴は、擬似マルチタスクとメッセージシステムが統合されている点です。この言語でプロセスを中断する際は、処理を再開するためのメッセージを指定します。そして、他のプロセスからそのメッセージが送信されるまで再開することはないのです。しかし、実はこれを繰り返すことでマルチタスクを実現することができるのです。

要するに、複数のプロセスが存在する状態では、メッセージを送っているメインのプロセスの他は、基本的に全て中断状態にあるわけです。そして、メインプロセスから送られるメッセージを毎フレーム処理していくことで、マルチタスクとなるわけです。文章で説明するのは難しいんですが、このようにして逐次実行とメッセージシステムを融合させることに成功したのです。

現段階では、サンプルコードを書きながら仕様を決めていっているだけで、そのコードを実行できる処理系はまだ作っていません。もちろん実際にゲームを作って試すこともできていません。ですから実用性のほどについてはまだまだわからないんですが、机上の空論の限りではなかなか良いものになりそうです。では今日はこの辺で失礼します。

[2016/08/29 19:58] | (コードネーム:モンジュラ)
|
こんにちは。ようやく前期が終わりました。あとは単位が出ていることを祈るのみです。

さて、早速次回作に取り掛かりたいのですが、次回作には前回ご紹介したスクリプト言語を取り入れたいと考えております。そのため、まずは言語仕様を策定して実際に処理系を作ることが先決です。

今考えているのは、スクリプトに「タイムライン」という概念を導入することです。つまり、動画編集のような感覚で状態遷移の設計をするという考えです。

もちろん、ゲームの流れはプレイヤーの入力に応じて変化しますので、設計時にタイムラインの内容を決めてしまうことはできません。どちらかというと「プレイヤーの操作をタイムラインに反映する」あるいは「プレイ中に、リアルタイムに動画を生成する」というようなイメージです。何を言っているのかよくわかりませんね。

とまあ、本当に実現可能かどうかと言われると微妙な仕様なんですが、とりあえずこの方針で研究していきたいと思っています。どうも私は、「ゲーム制作」そのものよりも「ゲーム制作のためのシステムの制作」に燃えるみたいです。では今日はこの辺で失礼します。

[2016/07/29 17:03] | (コードネーム:モンジュラ)
|
お久しぶりです、Shiroです。

前回は実装部の隠蔽をテーマに、PImplイディオムについてグダグダ述べて終わりましたね。それでその改善案なんですが、実はあれを書き終えた直後から改良の嵐で、なかなかブログに起こすことができませんでした。申し訳ございません。

とりあえず今現在採用している方法を簡単に説明します。まず、基本的にPImplイディオムそのままです。やっぱり先人の知恵とはよく言ったもので、試行錯誤すると結局行き着く先は同じようです。ただ、やっぱりPImplそのままでは「クラス間の通信の隠蔽」ができないため、ちょっとアレンジします。それが「Contextイディオム」です。

もちろんこれは私が勝手に名付けた名前です。Contextは「文脈」ですが、具体的には「データの共有単位」を表します。つまり、複数のクラスが共有するデータがあるときに、それをコンテキストクラスとしてまとめるのです。そして、各クラスは、コンテキストクラスを通じて通信するのです。これをContextイディオムと名づけました。

なぜこのような回りくどいことをするのでしょうか。肝は、「非公開なpublicメンバを作りたい」というそもそもの目的と、「Impl構造体は不完全型である」ということです。これを組み合わせると…そう!不完全型にpublicメンバを書けば、「クライアントは利用できないが開発者は利用できる」がまさに実現できるのです。ですから、そのような不完全型(を管理するクラス)としてコンテキストクラスを作って、各クラスはコンテキストクラスを参照して生成するようにすれば、各クラス同士はコンテキスト内のデータを用いて自由に通信でき、一方クライアントの名前空間は一切汚しません。ああ、不完全型とはなんと素晴らしいのだろうか!

なお、コンテキストクラス自体も、PImplイディオムっぽく設計します。ただし、本来公開メソッドが入るところには、「そのコンテキストに依存するクラス」のfriend宣言を書きます。普段はカプセル化を破壊するものとして忌み嫌われているfriendですが、この状況においてはなんと過不足ない効果を発揮します。コンテキストクラスでpublicでないのはもともとImplの宣言とpImplの定義だけですから、friendによって公開されるのはこの2つだけなのです。そしてまさに、コンテキストクラスを参照するクラスにとって必要なのは、この2つなわけです。私、初めてfriendを正しく使えた気がします…。

ちなみに、PImplは中継メソッドを大量に手書きしなければならないのが嫌だと前回申しましたが、それはある意味解消されました。コンテキストクラスの導入により、クラス間の橋渡しをする処理が必要になるわけですが、その処理をするのに最適な場所が中継メソッドだからです。つまり、もはや中継メソッドは単に引数と返り値を受け渡しするものではなくて、クラス同士が互いを参照できるようにするという立派な中間管理職となったのです。これで、PImplを使いたくない理由が全てなくなったのです。

というわけで、今まで書いていたタスクシステム(メッセージシステムとタスクリストに分離しました)をContextイディオムで書き直しました。クライアントは(インライン関数などを除いて)開発者用のものには一切触れません。完璧です。もちろん、これは単なる自己満足ではなくて、翻訳単位間の依存性を軽減するというれっきとした効果を持っています。さすれば、コンパイル時間が短くなるだけでなく、クラス同士の結合も極限まで疎にすることができるのです。

しかも、このContextイディオムは、かなりの汎用性があるようで、大概のプログラムはこれで書けそうな勢いなのです。少なくとも前述のメッセージシステムとタスクリストは、ほぼ機械的に同じパターンのコーディングでできています。ちょっと思い上がりかもしれませんが、これは私の中での一つのデザインパターンとして、これからも使えるのではないかと期待しています。

…まあ、これまでだってその期待は何度も裏切られてますからね、今回だってわかりませんけどね(笑)では今回はこの辺で失礼します。

[2016/02/25 00:30] | (コードネーム:モンジュラ)
|

こんばんは
Sva
お久しぶりです、Shiroさん。
以前もコメントで告知いたしましたが、ついに明日28日、もとい本日夜0時に『紛り物のダイヤ』新HPを公開いたします。
是非よろしければ遊びにいらしてください^^

こんにちは
Shiro (管理人)
> Sva さん

了解しました、遊びに行かせていただきます。

こんばんは
Sva
お久しぶりです。最近体調はいかがでしょうか?また悪化してなければよいのですが。
最近私はTOEICの勉強のため懐かしのターゲット1900を引っ張り出して読んでいるのですが、ターゲットといえばShiroさんというイメージがあって、ついコメントしてしまいました(笑)
ちなみにShiroさんはTOEIC受けましたか?

こんばんは
Shiro (管理人)
> Svaさん

ご無沙汰しております。最近は以前と比べて気胸の頻度も減っていて少し安心しているところです。

TOEICは受けましたが、結果は受け取りに行ってないのでまだわかりません。内容がビジネス寄り(らしい)せいか、非常にやりづらく感じました。まだTOEFLの方がやりやすかった気がします。

こんにちは
Sva
そうでしたか…。なんか、確かにやりづらそうですよね。
三年生になって履修も楽になるかと思いましたが教職組には関係なく、なかなか多忙な日々にまりそうですー><
お互い頑張りましょうね!

コメント:を閉じる▲
あけましておめでとうございます。Shiroです。

最近はSIREN動画にも手を出したりしてプログラムがおろそかになってきております。というのも、ライブラリ設計について悩んでいる部分があり、なかなか進める気にならないのです。

その悩んでいる部分というのは、「実装部の隠蔽」です。C言語では、ライブラリ利用者に実装部のコードが見えないように設計すると、インターフェイスの分離が明確になるだけでなく、ソース間の依存性が減り、コンパイル時間も短縮されるというメリットが有ります。具体的には、ヘッダーには関数のプロトタイプと構造体の宣言、typedefなどだけを書いて、関数と構造体の定義や、非公開の関数・構造体は全てソースファイルに書くというものです。

ところがC++のクラスは、この考えにとことん向いていません。C++のクラスは分割定義を許していません。つまり、利用者に見せたいメソッドだけをヘッダーに書いて、メンバ変数やprivateメソッドは.cpp内に書く、といったことができないのです。

なぜこのような制約があるのでしょう。考えられるのは、クラスのサイズを明確にするという目的です。先ほど述べたような分割定義をすると、ヘッダーだけが見える翻訳単位(利用者)と、.cppの翻訳単位(実装者)では、明らかにクラスサイズが異なります。クラス名をClassとすると、利用者にとってはsizeof(Class) = 1でも、実装者にとってはsizeof(Class) = 4だったりするわけです。

これは当然問題になります。もし利用者がClassのオブジェクトを作ると、そのサイズは1です(非virtualメンバ関数しか持っていない場合)。このオブジェクト(またはそのポインタ)を、実装者側で定義された関数に渡すとどうなるでしょう。実装者の方では、Classのサイズが1バイトである保証はありません(メンバ変数などを含んでいるため)。仮に4バイトだったとします。これでは、単なるコピーですらエラーとなります。利用者が作ったClassオブジェクトは実際には1バイトであるにもかかわらず。実装者側では4バイトだと思い込んでコピーを実行するからです。3バイト分は、謎のデータがコピーされてしまうわけです。

先も述べたとおりC++ではクラスの分割定義を認めていないため、上のような事故はまず起こりませんが、とにかく翻訳単位ごとにサイズが異なってはまずいということはおわかりいただけたでしょうか。クラス定義をヘッダーとソースに分けると、どうしてもサイズが異なってしまう問題が発生するわけです。

しかし、ここでちゃぶ台返しをしたいと思います。先の想定では、利用者でClassオブジェクトを生成するとサイズがわからないとうことが問題でした。しかし、それを言うなら最初に述べたC言語流の隠蔽だって、利用者には構造体のサイズがわかりません。ではどうしていたかというと、C言語ではオブジェクトの生成も実装者側で行っていたのです。つまり、生成用の関数のプロトタイプをヘッダーに書いて、実装部でmallocしてポインタを返すのです。そう、ポインタを使うだけであれば、構造体のサイズはおろか、定義すら無くても問題ないわけです。

じゃあC++も同じようにすれば良いではないか?ヘッダーに書いてあるクラスは生成禁止にして、実装部に生成関数を用意すれば良いはずです。正直私はなんでC++はこれができないのか疑問に思います。C言語での例を見ればわかるように、原理的には可能なはずです。「生成禁止」を表すキーワードが必要ですが、それは本質的な問題ではありません。

とはいえ、これだけのC++プログラマーがいて、誰もこの打開案を考えなかったわけではありません。私の知っているものは、「pImplイディオム」を呼ばれるものです。接頭辞pはポインタのこと、Implは実装クラス(Implementation)のことで、つまりpImplはImpl*型のメンバ変数です。以下に例を挙げます:

/* ヘッダー */
class SomeClass
{
class Impl;
public:
/* 公開メソッド */
int Func();
...
private:
Impl* pImpl;
};
/* 実装 */
class SomeClass::Impl
{
/* 本当の定義 */
public:
int Func() { return 100; }
...
};

/* 公開メソッドの実装(中継するだけ) */
int SomeClass::Func() { return pImpl->Func(); }
...

前述の「ポインタで持つことだけを許す」ということができない問題を、「ポインタを持つクラスだけを公開する」という方法で解決したものです。これで、Implクラスのメンバ変数やメンバ関数の定義が変わっても、ヘッダーだけを見ている利用者は再コンパイルの必要がありません。

しかし、私はこれはあまり好きではありません。第一に、中継メソッドを書くのが面倒です。関数から関数へと引数と返り値を渡すだけの簡単なお仕事…あまりやりたくありません。しかも、クラス外で定義する必要があるため、「SomeClass::」などの修飾が避けられず、記述量が増えます。
第二に、クラス間の通信がしにくいです。例えば、SomeClass2のあるメソッドにSomeClassへのポインタを渡すと何かが起こる…ということがしたいとしましょう。SomeClass2を同じ実装者が作っているなら、非公開な関数にもアクセスしたいと思います。ここでいう非公開とは、privateメソッドのことではなく、利用者に見せていないpublicメソッドのことです。つまり、実装者側での操作に使うだけで、利用者には必要ないメソッドです。しかし、そのようなメソッドはSomeClass::Implにのみ定義されているわけですよね。ということは、SomeClass*を受け取ったところで、そのメソッドにはアクセスできないというわけです!結局、このようなことがしたければ、SomeClassにGetImpl()みたな関数を作る必要があるのです(利用者にも丸見え)。

というわけで、私はpImplイディオムをそのまま採用する気にはなれませんでした。そこで、多少なりともこれらの問題を解決できそうなアレンジを私は考えました。それについては次回以降で述べることとして、今回はこの辺で失礼致します。

[2016/01/01 14:25] | (コードネーム:モンジュラ)
|

承認待ちコメント
-


コメント:を閉じる▲
お久しぶりです。気胸(肺に穴が空いてしぼんでしまう病気)のShiroです。特に書くべきことがないから放置しておりましたが、広告出しっぱなしなのが気になったので更新します。

今は、次回作以降の基盤となるライブラリを作っています。これをしっかり仕上げておけば、今後の制作で楽できるかなー、という目論見です(まあ、大抵そんなにうまくいかないんですがね…)。

次回作は、だいぶ前に立ち上げた「モンジュラ」プロジェクトを再開しようかと思います。未だにタイトルすら決まっていないという有様ではありますが、当時の理念は失われておりません。特に、不死女で3Dグラフィックやスクリプト化の練習を積んでおりますから、今後それらを再発明する必要はありません。同じアルゴリズムを使いまわせる部分はたくさんあると思います(そして、そういう部分を簡単に使いまわせるようにしたプログラムこそが、先ほどのライブラリというわけです)。

とはいえ、本命の首都高にも手を出したい気持ちは山々です。TDtechnicでは既存のゲームのパロディは(ネタとして以外)使用しないことにしておりますので、まずは「首都高バトルTD」以外の気の利いたタイトルをつけるところから始めなくてはなりません(笑)それから、道路データはどこまでを画一化してどこまでを自由定義にするのかとか、光はどう当てるかとか、物理計算はどうするのかとか、内容の課題も山積しております。そうそう、パロディ禁止となるとSPバトルもパクることができませんから、新しいバトル形式を考える必要もあります(下手すると、走り屋ゲームですらなくなるかも…)。

とまあこんな感じですが、まずすべきことは気胸を治すこと、そして中間試験を乗り切ること、というわけで、この辺で失礼します。

<「不死女 -Immortal girl-」好評公開中!(現在 1,092 ダウンロードで 3845 位)>
ふりーむ!様
フリーゲーム夢現様

[2015/11/20 16:32] | (コードネーム:モンジュラ)
|
あけましておめでとうございます。Shiroでございます。一応今のうちに更新します。

年も明けたことですし、受験後にとりかかるプロジェクトのカテゴリーに入れることにしました。名前はまだない。コードネームは「モンジュラ」としました。記憶の時の「富竹フラッシュ」と同じく、本編とは全く関係ありません。

これは記憶に引き続きホラーゲームになる予定です。多分続編ではありません。ようやくオブジェクト指向がわかってきた気がするので、その練習の意味もあります。内容としては、

・身近なホラー
・基本は脱出ゲーム
・マルチプラットフォーム(!?)
・まともなボリューム
・マルチエンディング(難易度分岐)

が実現できたらなあと思っております。私は本当に怖いものは身近なものだと思っているので、今回はそれを意識してみます。で、SIRENや零のようにアクションが多いのも怖くない気がするので(面白いかどうかは別。私はSIRENも零も大好きです)、脱出メインとなるでしょう。OS関係は法律用語でいうプログラム規定です。ひょっとしたらWindows以外でも動くようにするかもしれませんし、まことにざんねんですがWindows2000を削るかもしれません。ボリュームは記憶の反省です。記憶も私の中では量に配慮したのですが、一般的にはかなり短いのは自他共に認める事です。あとマルチエンディングは記憶と同じ難易度分岐で、これは目標というか皆さんへのお知らせです。これは、わかるわけない条件でED分岐するゲームを私が嫌っているということに起因します。その方が主流となりつつある気もしますが、方法もわからない分岐のために同じゲームをプレイする気になるでしょうか。よほど愛されてない限り、見ようとも思われないか、攻略できないかだと私は思います(もちろん、それぐらい愛されるゲームが作れれば一番なんですが…)。些細な隠し要素ならともかく、EDは作者も作りこむところですし、「見る気がある方には見て頂きたい」ものです。であれば作者はせめて方法を提示すべきと私は思うのです。ちなみにこのように一般的なマルチではありませんから、概要には明記しませんし、必要もないと思っています。「マルチエンディング」と書かれたゲームはやる気が削がれるのは私だけでしょうか?

さてなんだかんだ書きましたけど実際には何もしてません。すべて構想段階です。まずは受験が終わらなければ、始めることも出来ないので、とにかくそっちに集中しなくてはいけませんね(こんなもの書いておらずに集中しろ!と言われそうですが)。あと記憶は皆様のお陰で1974位(1760ダウンロード)を頂きました。夢の2000位以内です。ありがとうございます。

「記憶」最新版(2014/01/02現在2.0.0.0) ダウンロード

[2014/01/02 17:01] | (コードネーム:モンジュラ)
|

こんばんは
Sva
受験お疲れ様でした。
次回作の構想はもう出来上がっているんですね!
楽しみです^^

もし、もし自分に何かお手伝いできることがあるならば何でも言ってくださいね。受験が終わってから画材もどんどん増えて、ついに最強のPhotoShopを手に入れたので、以前よりいい画質で絵が描けると思いますし。(まぁここまで言えばもう何ができるのか言っているようなものですが 笑)

ところでですが、ふりーむさんの投票ってどうやればよろしいでしょうか?
一応記事の「投票」というところをクリックしたのですがそれからの投票方法が分からなくて…

コメント:を閉じる▲
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。