Skip to content

Commit

Permalink
Treat thino directly
Browse files Browse the repository at this point in the history
  • Loading branch information
tcptr committed Jul 8, 2014
1 parent 9e541fe commit b4f8dc5
Show file tree
Hide file tree
Showing 20 changed files with 6,258 additions and 4 deletions.
3 changes: 0 additions & 3 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
[submodule "src/thino"]
path = src/thino
url = git://github.com/tcptr/thino.git
1 change: 0 additions & 1 deletion src/thino
Submodule thino deleted from 28dd62
3 changes: 3 additions & 0 deletions src/thino/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
gh-pages
*.o
*.obj
19 changes: 19 additions & 0 deletions src/thino/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
Copyright (c) 2013 tcptr

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
55 changes: 55 additions & 0 deletions src/thino/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
thino
=====

multiplexの製作にあたって作成したライブラリです。dmd 2.064で書かれています。
OpenGL/OpenALの薄いラッパーといくつかのユーティリティを備えています。
経験が足りない状態で、自分が必要な機能を適宜加えて行く方針で作っていたため、
いくつかの設計上の問題があります。(特にgraph, debugger, math)
汎用性に乏しいものとなっており、使用はおすすめしません。

## 機能

* 状態遷移の管理
* ウィンドウの作成
* wavファイルの再生
* 簡易的な設定ファイルの管理
* 簡易的なデバッグのための変数操作
* いくつかのポストエフェクト
* KSTフォントを多少改変したフォントの描画
* OpenGLによるレンダリングパイプラインの簡略化
* マウス/キーボード/ジョイスティックの状態取得
* 簡易的なベクトルと行列のデータ型

## Note

thinoはsubmoduleとして追加して静的リンクして使用することを想定しています。
ビルドには、デフォルトではGLFW, OpenGL, OpenALが必要になります。
コンパイラにversionを与えることで使用可能な機能(と使用するライブラリ)が変化します。

* `NoSound` - OpenAL/サウンド関連の機能を無効にします。
* `StbVorbis` - stb\_vorbis.cによるoggファイルのストリーミング再生を有効にします。
* `StbImage` - stb\_image.cを使用して画像からのテクスチャ読み込みを有効にします。
* `GLEW` - OpenGLのAPIの取得にGLEWを使用します。
* `VAO` - ShaderProgram.HandlerにVertex Array Objectを使用します。

Linuxではオブジェクトファイルを直接リンクできます:
```
LIBS = -L-lglfw -L-lGL -L-lopenal
```

OSXではOpenALなどは-frameworkで渡します:
```
LIBS = -L-lglfw -L-framework -LOpenGL -L-framework -LOpenAL
```

Windowsではlibファイルの用意が必要です。以下の方法で作成したlibで動作確認しています:
* `GLFW` - support/dのdefファイルからの生成
* `OpenGL` - GLFWのsupport/dのdefファイルからの生成
* `OpenAL` - dllからimplibで生成
* `GLEW` - 配布されているlibをcoffimplibで変換

## フォントについて

計量なストロークフォントである[KST32B](http://www.vector.co.jp/soft/data/writing/se119277.html)を使用しています。
[translate.d](./tools/translate.d)を用いてUnicode向けの変換を行ったファイルを用います。

91 changes: 91 additions & 0 deletions src/thino/config.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
module thino.config;

import std.stdio;
import std.string : split, chomp;
import std.conv : to;
import std.path : dirName;
import std.file : exists, mkdirRecurse;

/**
* 簡易的な設定ファイルを扱うクラスです。
* Note:
* keyには半角英数字のみの使用を推奨します。
* ---
* auto cfg = new Config("fooConfig");
* cfg.set("foo", 123);
* cfg.save();
* ..
* int foo = cfg.get!int("foo");
* ---
*/
class Config {
private:
immutable string _filename;
string[string] _options;

public:
/**
* filenameを読み込みます。読み込めないときは空の設定で初期化します。
*/
this(string filename) {
_filename = filename;

string dir = dirName(filename);
if (!exists(dir)) mkdirRecurse(dir);

try {
auto fh = File(_filename, "r");
foreach (string buf; fh.lines()) {
auto data = buf.chomp().split("=");
if (data.length != 2) continue;
_options[data[0]] = data[1];
}
} catch (Exception o) {}
}

/**
* 設定を保存します。ファイルに書き込めないときは例外が投げられます。
*/
void save() {
auto f = File(_filename, "w");
foreach (k, v; _options)
f.writeln(k, "=", v);
}

/**
* keyが存在するかを返します。
*/
bool has(string key) const {
return (key in _options) != null;
}

/**
* keyの設定をT型に変換して返します。keyが存在しなければT.initを返します。
* Note:
* T型への変換はstd.conv.toを用います。
*/
T get(T = string)(string key) const {
auto p = key in _options;
return p ? to!T(*p) : T.init;
}

/**
* keyにvをセットします。
* Note:
* vはstd.conv.toを用いてstringに変換されます。
*/
void set(T)(string key, T v) {
_options[key] = to!string(v);
}

/**
* keyが存在しなければ、vをセットします。
* Note:
* vはstd.conv.toを用いてstringに変換されます。
*/
void setDefault(T)(string key, T v) {
if (!has(key))
_options[key] = to!string(v);
}
}

196 changes: 196 additions & 0 deletions src/thino/core.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
module thino.core;

import opengl.glfw;
import thino.opengl;
import thino.window;
import thino.datatype : Singleton;
import std.exception : enforce;
import std.array;

/**
* ゲーム全体を管理するクラスです。現時点ではGLFWの初期化にとどまります。
* GLFWに関連するクラス(graph, windowなど)を使用する場合、最初に初期化する必要があります。
* $(J Singleton)です。
* ---
* // GLFWを初期化、ゲームを開始
* Thino();
* ---
*/
class Thino {
mixin Singleton;

private:
this() {
enforce(glfwInit() == GL_TRUE, "glfwInit() failed");
}

~this() {
glfwTerminate();
}

public:
/**
* glfwWaitEvents()を呼び出し、何らかのイベントを受け取るまで待機します。
*/
void waitEvents() {
glfwWaitEvents();
}
}

/**
* GLFW_nameへのエイリアスになります。
*/
template GLFW(string name) {
mixin("alias GLFW_" ~ name ~ " GLFW;");
}

/**
* 状態遷移を管理するクラスです。必ずしも使用する必要はありません。
* ユーザはSceneを継承したクラスを作成し、$(J run)メソッドをオーバーライドします。
* Scene.$(J execute)メソッドに任意のSceneを渡すことで処理を開始します。
* ---
* int[] ls;
* class TestScene2 : Scene {
* override void run() {
* ls ~= 5;
* }
* }
* class TestScene : Scene {
* override void run() {
* ls ~= 3;
* nextScene(new TestScene2);
* }
* }
* Scene.execute(new TestScene);
* ---
*/
abstract class Scene {
private Scene _next;

this() {}

/**
* シーンのメインとなる処理を行います。Scene.$(J execute)によって呼ばれます。
*/
abstract void run();

/**
* 次のシーンとしてsceneを予約します。
* nextSceneが呼ばれずにシーンを終えた場合には状態遷移の処理を終了します。
*/
void nextScene(Scene s) {
_next = s;
}

/**
* 状態遷移の処理を開始します。
*/
static void execute(Scene scene) {
while (scene) {
scene.run();
scene = scene._next;
}
}
}

unittest {
int[] ls;
class TestScene2 : Scene {
override void run() {
ls ~= 5;
}
}
class TestScene : Scene {
override void run() {
ls ~= 3;
nextScene(new TestScene2);
}
}
Scene.execute(new TestScene);
assert(ls == [3,5]);
}

/**
* 時間を計測し、FPSの安定化、及び描画のスキップを管理するクラスです。
* $(J Window)が内部で保持しており、通常は直接触ることはありません。
*/
class FPSCounter {
private:
immutable double _interval;
double _beforeTime, _fpsTime;
int _current, _before;
int _currentSkip, _beforeSkip;
bool _skip;

public:
@property const {
/**
* 計測された現在のFPSを返します。1秒単位で更新されます。
*/
int FPS() {
return _before;
}

/**
* 直近の一秒で描画がスキップされたフレーム数を返します。
*/
int skipped() {
return _beforeSkip;
}

/**
* ゲームの処理に時間がかかっているなどの理由で、
* 描画をスキップする予定のフレームでtrueを返します。
* $(J Window)が内部で使用します。
*/
bool skipDraw() {
return _skip;
}
}

/**
* FPSを設定して初期化します。
*/
this(double fps) {
glfwSwapInterval(1);
_interval = 1.0/fps;
glFinish();
glfwSwapBuffers();
_beforeTime = _fpsTime = glfwGetTime();
}

/**
* windowのバッファをswapし、必要ならばsleepなどの処理を行います。
*/
void syncSwap(in Window window) {
++_current;
_beforeTime += _interval;

if (_skip) {
_skip = false;
++_currentSkip;
} else {
glFinish();
glfwSwapBuffers();

double delay = _beforeTime - glfwGetTime();

// 遅れが大きい場合は_beforeTimeを早める
while (delay < -_interval*2) {
delay += _interval;
_beforeTime += _interval;
}

if (delay < -_interval) _skip = true;
else if (delay > 0) glfwSleep(delay);
}

if (glfwGetTime() - _fpsTime > 1.0) {
_before = _current;
_beforeSkip = _currentSkip;
_current = _currentSkip = 0;
_fpsTime += 1.0;
}
}
}

Loading

0 comments on commit b4f8dc5

Please sign in to comment.