C# Possibility for game development
現代において、大部分のゲーム開発者は、 C++ もしくは C
(と若干のマシン語およびシェーダ)を使わなくてはいけません。これらの言語は、非常に強力であり、 C++
は、十分に生産的ですから、特に問題はありません。
しかし、私は、休日用に、他の言語を求めてきました。あらゆるゲーム開発者は、自身のゲームを開発することを望みます。しかし、それは、不可能なように思われます。ゲーム開発は、多くの時間を必要とするからです。大部分の開発者は、自身のゲーム開発より休暇をとって眠ることを望みます。
その目的のために、私は、最小のアーケードゲームを開発するのにいくらかのライト級のプログラミング言語を必要としました。それらは、休暇用の迅速なゲーム開発用の言語です。私は、
HSP 、 Python 、 Ruby 、 Java
、及び、ゲームエンジンのいくらかのスクリプトを試みました。(私は、一度だけ会社の仕事で Java
を使ったことがありますが、二度とゲーム開発には使いたくありません)
そのようにして、私は、多くの言語を試みました。しかし、私は、いつも同じ結果を得ました。C++
がゲーム開発においては世界上で最も生産的な言語であるということです。そこで、私は、 boost
ライブラリと OGRE をチェックし始めました。
しばらくして、私は、 Managed DirectX と C# 2.0 に出会いました。 Managed
DirectX は、 DirectX のマネージドライブラリ版です。C# 2.0 は、 Generics
機能を持つ C#
の拡張です。私は、これらが現在最も良い答えである、と思いました。そして今、マイクロソフトはゲーム開発のために調律された
.NET 製品である XNA フレームワークと XNA スタジオを提供します。
C# は、低パフォーマンスです。C# や Java のような、 GC
機能を持つ言語は、リアルタイム処理に対する適性を持っていません。私が XNA
との最初の接触を持っていたとき、私は、 XNA と C# はなんらかの方法で GC
の問題を克服したのだと考えました。しかし、 XNA は、やっぱりひどいパフォーマンスです。
しかしながら、私も他の開発者も、それに関して同じ結論にたどり着いています。その結論は、我々が GPU
至上主義者であるべきであることです。GPU 処理では、 C++ と C#
に、パフォーマンスの違いはありません。GPU
が物理学等々を計算し得るというアイデアは、いくらかの本にあります。しかし、それは、生産的な方法ではないかもしれませんが...
Cubson has gone to sourceforge.jp
私は、sourceforge.jp
の XOOPS-Shade
プロジェクトページへ cubson
の全資源を動かし始めました。しかし私は、sourceforge.jp
においてプロジェクトページを作ってしまったことを後悔しています。
Sourceforge.net
は、 sf.jp
より良いリポジトリです。それは、私達にとって最良のソリューションです。なぜなら、
sf.net
は、多くの優れたフィーチャーと UTF-8
を持っているからです。英語は、 sf.jp
においても利用可能です。しかし、このリポジトリを世界の仲間に薦めたいと考える人はいないでしょう。
しかしながら、私は、名前に XOOPS Cube
を含んでいながら活発度 0%
のプロジェクトページを持つことを望んでいません。従って、私は、 cubson
が良い国際的ツールであろう状態になるまで、 sf.jp
に XOOPS-Shade
プロジェクトを保持し続けるでしょう。それから、我々は、これらのページを sf.net
に動かすでしょう。
もちろん、私は、英語で書かれたあなたのメッセージを歓迎します。そして、私は、英語でドキュメントの準備をするでしょう。cubson
に関する URLs
は、下記です。
リリースニュースは、このページにあります。Sf.net
は、 RSS
を公表し得ます。しかし、 sf.jp
は、それをすることができません。うーん、これらのニュースは、現在日本語オンリーです。私は、十分なメンバーを集めるために日本人のための容易なニュースを必要とします……
うーん
あなたは、
Google adsence
の位置に驚くかもしれません。このサイトは、アフィリエイトサイトのように見えます。しかし、これは、私達のディスカッションフォーラムです。記述は、あなたのアカウントを必要とします。あなたが
sf.jp
にあなたのアカウントを持っていないならば、登録しましょう。
これは、
cubson
のためのバグ追跡者システムです。あなたは、そこで報告するのにあなたのアカウントを必要とします。
これは、英語では難しいもののうちの
1
つです。なぜなら、この Wiki
は、日本語のためのものだからです。しかし、私は、お粗末な英語で多くのドキュメントを書いてきました。私は、
sf.net
における将来のプロジェクトページに備えてそれらを準備します。この wiki
は、フリーであり、そして、あなたは、あなたのアカウントを必要としません。
Detailed commentary on the sample message module
Installer
このモジュールは、
PM
と交換されますので、このモジュールが PM
の現存するデータを移動させることができればベストです。そのような目的のために、 XOOPS2
ではモジュール開発者は onInstall
スクリプトを使用します。Legacy 2.1
では、カスタムインストーラが利用可能です。カスタムインストーラは、
xoops_version
において宣言された特定のクラスです。通常、そのクラスは、コントロールパネルにおけるインストール機能によって使われるインストーラクラスのサブクラスです。
$modversion['legacy_installer']['installer']['class']
= "Installer";
これは、正式なクラス名ではありません。正式なクラス名は、この宣言と dirname
によって生成される合成名です。それは {Dirname}_{class}
です。この場合、正式なクラス名は、 "Messgae_Installer"
になります。そのクラスは、 admin/class/{class}.class.php
において定義されなければなりません。
命名規則は、複写可能なモジュール、及び、 D3
モジュールのためのいくらかのオプションや例外を持っています。詳細は
Legacy_ModuleInstallAction
のコメントを見てください。
モジュール開発者は、カスタムインストーラによってインストールプロセスの全てをコントロールすることが可能です。onInstall
より優れた仕様は、柔軟性、及び、ロギングです。インストーラクラスは、そのメンバープロパティとしてログインスタンスを持っています。それを通じて、このモジュールは、マイグレーションに関するメッセージをユーザーに示します。これらのメッセージは
modinfo.php
において定義されています。
Kernel handler hook
プライベートメッセージは、
Legacy 2.1
の任意の仕様です。しかし、それは、他のフィーチャーにおいてはポピュラーな仕様です。例えば、悪名高き
XoopsMultiMailer
は、メール、及び、メッセージを抽象化します。同じく通知機能は、プライベートメッセージを使います。これらのクラスは、メッセージを送るためにカーネルのプライベートメッセージハンドラを使います。従って、このモジュールはこのハンドラをフックしなければなりません。どうすればよいでしょうか
?
答えはデリゲートを理解することにあります。カーネルのハンドラは、フライウェイトパターンの一種である
xoops_gethandler()
を通じて取得されます。 xoops_gethandler()
は、デリゲートイベント "Legacy.Event.GetHandler"
を備えています。従って、プリロードで関数をこのイベントに加えることによってそれをフックすることが可能です。それによって、
xoops_gethandler()
は、プライベートメッセージハンドラを得るためのリクエストに対して、このモジュールのアダプタクラスを返します。それは、興味深いです。kernel/privmessage.class.php
を見てみてください。
Note
xoops_gethandler()
は、キャッシュを持っています。だれかが preBlockFilter()
の前にプライベートメッセージハンドラを得るならば、イベントは、プライベートメッセージハンドラのために、二度と呼び出されないでしょう。
プリロードをプライマリプリロードとして指定可能な状態につくっておくことはよい解決策になります。
When is RC released?
開発チームはRCの基準が何であるかに関して議論しています。
多くの開発者がRCバージョンに固定APIを要求するでしょう。しかし、それをするためには、多くの実例が必要です。この年末に、それらを開発するために空き時間を保つことはかなり困難でしょう。
しかしながら、私は、1つのバグと3つの設計ミスを、昨日のあの程度のサンプルモジュールを通じて発見しました。ですから、実例を開発するということは本当に重要です。
XOOPS Cube Legacy2.1には、ソフトウェアデザインの他の問題があるかもしれません…
しかし、十分時間のある人なんていません。非常に難しい問題です。
Sample: The Advanced Private Message
私は、このサイトの XOOPS 開発者リングの次のリンクを tohokuaiki
氏に変更しました……といいますのも、 gusagi
氏のサーバは、壊れてしまったからです。私は、彼のサーバに哀悼の意を表します。
さて、ここに Legacy 2.1
のためのサンプルモジュールがあります。「message」モジュールは、進歩したプライベートメッセージモジュールです。それは、送信ボックス、草稿ボックス、プレビューを可能にします。
あなたは、このサンプルによって次のものを学ぶでしょう :
- どうやって Legacy 2.1 のカーネルハンドラをフックするか
- ログと共にある Legacy 2.1 時代におけるインストールスクリプト
- User-Control-Event の応用
- Legacy 2.1 のための共通インタフェースとしての仮想サービス
- cubson 0.52.3 のサンプル(あなたが cubson
ユーザーであるならば)
- そして、 Cube の換装コンセプトの一端
あなたは、このモジュールを動かすのに Cube Legacy 2.1
の最新のスナップショットを必要とします。ダウンロードページからこのモジュールを得てください。
インストール方法
- あなたが pm
モジュールをインストールしたならば、それをアンインストールしてください。
- このモジュールをインストールしてください。
-
現存するメッセージは、インストールスクリプトによって自動的にマイグレーションされます。
UTF-8 Language Manager for Legacy System (2)
昨日のテスト版 UTF-8 言語マネージャは、 global.php を UTF-8
に変換していませんでした。nobunobu さんが、パッチを私に送ってくれました。私は、 nobunobu
さんのパッチをマージすることによってバージョン 0.02 をアーカイブしました。
言語マネージャが global.php を変換しなければならないので、 global.php
において定義されるオリジナルの _CHARSET
を使うことは、不可能です。そこで、言語マネージャは、設定ファイルの情報、または、言語マネージャクラスの組込固定情報を使うようになりました。
Verison 0.02 では、組込固定情報として日本語 ( EUC-JP ) 、及び、韓国語 (
EUC-KR )
があります。設定ファイルによってこれらの情報をオーバーライトすることが可能です。もちろん、他の言語を加えることもまた可能です。
[Module_Utf8LangMgr]
multibyte=chinese,korean,japanese
chinese=big5
korean=...
UTF-8 Language Manager for Legacy System (1)
私は、 Legacy System 2.1 用の汎用 UTF-8 Language Manager
を開発しました。あなたはダウンロードページからこれをダウンロードできます。これは、まだテストバージョンです。そして、あなたはこのモジュールのアクションフィルタがモジュールプリロードより早く働かなくてはいけないため、特別な方法によってこれをインストールしなくてはいけません。しかし、それは、非常に容易です。
Step1... 事前条件の確認
このモジュールは、
UTF-8 エンコーダとして Utf8LangMgr_LanguageManager
をあなたのサイトに提供します。しかし、このモジュールは、インストーラには何の影響も与えません。従って、あなたは、自分で
UTF-8
データベーステーブルを作成しなければなりません。しかし、各モジュールの言語ファイルを変換する必要はありません。
Step2... モジュールの配置
他のモジュールと同様に、
/modules にこのモジュールのディレクトリを置いて下さい。
Step3... 設定の変更
Legacy
パッケージの構成は、 /settings/site_default.ini.pnp
に書かれています。あなたは、そのファイルに優先プリロードとしてこのモジュールのプリロードを指定しなければなりません。XOOPS
Cube がオーバーライド設定機能を持っているので、 site_default.ini.php
を直接修正する必要はありません。/settings 内で site_custom.ini.php
を作成して、そして、下記のように書いてください。
<?php
/**
[Legacy.PrimaryPreloads]
SetupUtf8LangMgr=/modules/Utf8LangMgr/preload/Primary/SetupUtf8LangMgr.class.php
*/
?>
完了です。トラブル報告は xoopscube.org フォーラムのスレッドにお願いします。
覚え書き
あなたのサイトがマルチバイト言語を用いるならば、あなたは、
charcode をこの言語マネージャに通告しなければなりません。私が知っているいくらかの言語の
Charcode
は、このモジュールの優先プリロードに含まれます。しかし、それが自動的に解決されないならば、あなたは、
site_custom.ini.php に記述を加えなければなりません。
[Module_Utf8LangMgr]
japanese=EUC-JP
korea=...
このファイルにおける設定は、自動ソリューションより早くこの言語マネージャに適用されます。
Smart Update Summary (3)
Status
update()
メソッドが全ての情報構造体のステータスを変更した後、smartUpdateAllOfBlocks()
はこれらのステータスをチェックしながら DB
を変更していきます。どのように DB
が変更されるかはステータスによって決定されます。
Loaded
情報構造体はロードされています。そして、この情報と最新コレクションの別の情報には違いがありません。したがって、この情報に関して
DB を変更する必要はありません。
Updated
情報構造体と別の情報には違いがあります。そして、この情報はもう一方の情報によって既に更新されています。従って、この情報に関するデータベースのレコードを更新する必要があります。updateBlockByInfo()
はそのためによいユーティリティメソッドです。
Order Updated
情報構造体と別の情報は同じ内容です。しかし、ただオーダーのみが異なります。従って、この情報に関するレコードのオーダーフィールドのみを更新する必要があります。なお、ブロックにはオーダー情報はありません。このステータスはプリファレンスのみに適用されます。
New
現在のコレクションがある情報を持っていなかったとき、それは現在のコレクションへ追加されます。そして、その情報のステータスは
'New'
に変更されます。この場合、 DB
にそれを挿入する必要があります。InstallBlockByInfo()
はそのために良いユーティリティメソッドです。
Deleted
この情報構造体が最新コレクションの中でみつからなかったので、この情報のステータスは'deleted'
に変更されています。この場合、それを DB
から削除する必要があります。 uinstallBlockByInfo()
はそのために良いユーティリティメソッドです。
結論
smartUpdateAllOfBlocks()
と smartUpdateAllOfPreferences()
は非常に便利です、なぜならそれらは私がここ最近で説明した十分なプロセスを実装しているからです。ほとんどの場合、あなたはアップデート処理をこれらのユーティリティメソッドに委ねることができるでしょう。しかし、もしあなたがあなたのフェイズド・アップグレードの中で高度なアップデートを必要とするのであれば、あなたはこれらのクラスを理解するべきです。
Smart Update Summary (2)
Smart update for blocks is good to understand the
basic activity of these classes.
smartUpdateAllOfBlocks() is in
Legacy_InstallModuleUtils.
- Gets the current collection from DB with
ModinfoX2DBReader.
- Gets the latest collection form xoops_version
with ModinfoX2FileReader.
- Update the current collection with the latest
collection.
In these process, the current collection merges the
latest collection without losing values if at all
possible.
Let's see BlockInfoCollection::update().
function
update(&$collection)
{
foreach
(array_keys($this->mBlocks)
as
$idx)
{
$t_block
=&
$collection->get($this->mBlocks[$idx]->mFuncNum);
if
($t_block
==
null)
{
if
(!$collection->funcExists($this->mBlocks[$idx]))
{
$this->mBlocks[$idx]->mStatus
= LEGACY_INSTALLINFO_STATUS_DELETED;
}
else
{
$this->mBlocks[$idx]->mStatus
= LEGACY_INSTALLINFO_STATUS_UPDATED;
}
}
elseif
(!$this->mBlocks[$idx]->isEqual($t_block))
{
$this->mBlocks[$idx]->update($t_block);
}
Deleted
}
foreach
(array_keys($collection->mBlocks)
as
$idx)
{
$func_num
=
$collection->mBlocks[$idx]->mFuncNum;
if
(!isset($this->mBlocks[$func_num]))
{
$this->add($collection->mBlocks[$idx]);
$this->mBlocks[$func_num]->mStatus
= LEGACY_INSTALLINFO_STATUS_NEW;
}
}
}
BlockInfoCollection::get() is useful to check whether
another collection has the same information structure
as this collection. If another collection doesn't
return an instance with the same key, this block has
been deleted in the latest version. In this case,
changes the status of the information to "deleted".
Because the collection doesn't know how to delete
data from a resource, it doesn't have the process to
delete. There are several kinds of status.