概要 - Overview 
Last-modified: 2010-02-22 (月) 00:34:23
このページについて 
AngelScript(以下AS)を全く知らない人が,ASについてなんとなく理解してもらえるような記事を書きます。
詳細については各ページを参照してください。
特徴 
ASはLightweightLanguage(以下LL)の1つでLuaやSquirrelなどと同じような用途で使われます。
静的型付け
ASの最大の特徴は静的型付けにあります。
静的型付けとはC/C++などと同様に
未定義の型・シンボルの使用をコンパイル時にチェックすることができ
もしそのようなものが使用されていたらエラー扱いにできます。
LuaやSquirrelなど他のLLの多くは動的型付けを採用しています。
動的型付けですと,コンパイルという作業をスキップできる代わりに
実際にそのコードが実行されるまで未定義の型・シンボルのチェックができません。
小規模・少人数なアプリケーションの開発では動的型付けでもなんとかやっていけますが
大規模・多人数なアプリケーションの開発になればなるほど,
コンパイル時エラーチェックの重要性が増してきます。
Squirrelでゲームのほとんどを実装したという
「小さな王様と約束の国 ファイナルファンタジー・クリスタルクロニクル」の開発者さんが
「自前である程度のスクリプトコードの事前チェックをできるようにした」というような内容を話していました。
それぐらいアプリケーション実行前のエラーチェックはアプリケーションの品質維持に重要なものです。
構文がC++にとても似ている
ASは構文がC++にとても似ているため,C++経験者であれば構文について少し勉強するだけでコーディングを始められます。
また,C++ソースコードをメインとして使用するプロジェクト(ほとんどのゲーム開発はC++を使っています)では
ASソースコードとC++ソースコードの2つをコーディングしていくことになります。
そのような状況では,両者の構文が似ていることから頭を大きく切り換える必要がなくなります。
これが意外と重要なことで,ミスや変な混乱が少なくなります。
C/C++バインディング機能
ASのスクリプトからC/C++の関数や構造体・クラスなどにアクセスができ
逆にC/C++からASの関数や構造体・クラスなどにアクセスができます。
C/C++の関数・構造体・クラスなどをASのスクリプトからアクセスできるようにするには
ASライブラリの何個かの関数を呼ぶだけで大丈夫です。
コルーチン機能
途中で処理を中断するコルーチン機能に対応しています。
この機能があるためテキストアドベンチャースクリプトやRPGのイベントスクリプトとして
ASを導入することが比較的簡単です。
バイトコードをバイナリ保存可能
スクリプトコードをデータとしてROM媒体(光ディスクやフラッシュカードのこと)に収録すると
ソースコードを配布していることと同じになってしまいます。
これは会社・団体的にNGなことがよくあります。
ASではスクリプトコードをコンパイルしたあと,バイトコードを出力するという機能があります。
バイトコードとは,C言語でいうところのコンパイル後のオブジェクトファイルに相当するもので
それだけを見てもぱっとは何をしているのか分からない状態になります。
この機能を使い,製品版のROM媒体にはスクリプトコードでなくバイトコードをのせることで
ソースコード配布状態を回避することができます。
十分なデバッグ機能
スクリプトをメインに使ってゲーム開発をするとなるとデバッグ機能が必要になります。
ASでは
・実行ファイル・行の取得
・変数の中身のダンプ
・コールトレースの取得
・エラー・例外ハンドリング
といった機能をライブラリが提供しています。
これらの機能をアプリケーション側で使えるようにさえすれば
バグ調査時も特別な苦労はせずにデバッグすることができます。
HelloWorld 
ASのスクリプトを実行するサンプルコードです。
本家のsampleコードを参考にしています。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
-
|
!
-
|
|
|
|
|
|
-
|
|
!
|
|
|
|
|
|
|
-
|
|
!
|
|
-
|
|
|
|
|
|
|
|
|
|
-
|
|
|
!
|
|
|
|
-
|
|
|
!
!
|
|
|
|
|
-
|
|
|
!
|
|
|
|
-
|
|
|
|
!
|
|
|
|
-
|
|
|
|
!
|
|
|
|
|
|
|
|
|
!
| #include <iostream>
#include <angelscript.h>
#include "../../../add_on/scriptstring/scriptstring.h"
void PrintString(string &str)
{
std::cout << str;
}
int main(int argc, char **argv)
{
using namespace std;
int r = int();
asIScriptEngine *engine = asCreateScriptEngine(ANGELSCRIPT_VERSION);
if( engine == 0 )
{ cout << "Failed to create script engine." << endl;
return -1;
}
RegisterScriptString(engine);
r = engine->RegisterGlobalFunction("void Print(string &in)", asFUNCTION(PrintString), asCALL_CDECL);
if ( r < 0 )
{ engine->Release();
return -1;
}
{
asIScriptModule *mod = engine->GetModule(0, asGM_ALWAYS_CREATE);
r = mod->AddScriptSection("script",
"void main() "
"{"
" Print( \"Hello World!\" ); "
"}"
);
if( r < 0 )
{ cout << "AddScriptSection() failed" << endl;
engine->Release();
return -1;
}
r = mod->Build();
if( r < 0 )
{ cout << "Build() failed" << endl;
engine->Release();
return -1;
}
}
asIScriptContext *ctx = engine->CreateContext();
if( ctx == 0 )
{ cout << "Failed to create the context." << endl;
engine->Release();
return -1;
}
int funcId = engine->GetModule(0)->GetFunctionIdByDecl("void main()");
if( funcId < 0 )
{ cout << "The function 'float calc(float, float)' was not found." << endl;
ctx->Release();
engine->Release();
return -1;
}
r = ctx->Prepare(funcId);
if( r < 0 )
{ cout << "Failed to prepare the context." << endl;
ctx->Release();
engine->Release();
return -1;
}
r = ctx->Execute();
ctx->Release();
engine->Release();
return 0;
}
|
スクリプトのサンプルコード 
以下がASのソースコードの例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
|
-
|
|
|
|
|
|
|
|
-
!
|
|
|
-
|
|
|
!
|
|
|
-
!
|
|
|
|
|
-
|
|
|
!
|
|
|
-
|
!
|
|
|
|
|
|
-
|
|
!
|
!
-
|
|
|
|
|
|
!
-
|
!
-
|
!
-
|
-
!
|
-
!
!
-
!
-
!
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-
!
|
-
!
|
|
|
-
|
!
|
|
|
-
|
!
|
|
|
-
|
!
|
|
|
-
|
|
|
!
|
|
|
|
|
|
|
|
|
-
|
|
|
|
!
|
!
| class Vector3
{
float x;
float y;
float z;
Vector3()
{
}
Vector3(float aX, float aY, float aZ)
{
mX = aX;
mY = aY;
mZ = aZ;
}
~Vector3()
{
}
void add(
const Vector3 &in aVec )
{
mX += aVec.x;
mY += aVec.y;
mZ += aVec.z;
}
float sum()const
{
return mX + mY + mZ;
}
Vector3@ opAddAssign(
const Vector3 &in aVec
)
{
add( aVec );
return this;
}
};
enum SampleKind
{
SampleKind_A
, SampleKind_B
, SampleKind_TERMINATE
, SampleKind_MIN = 0
, SampleKind_MAX = SampleKind_TERMINATE-1
};
interface IUpdatable
{
void updatableUpdate();
};
interface IDrawable
{
void drawableDraw()const;
};
class Chara
: IUpdatable
, IDrawable
{
void updatableUpdate()
{
}
void drawableDraw()const
{
}
};
class Base
{
};
class A : Base
{
};
int globalInt32Value = 0;
void func()
{
int8 int8val;
int16 int16val;
int int32val;
int32 int32val2;
int64 int64val;
uint8 uint8val;
uint16 uint16val;
uint uint32val;
uint32 int32val2;
uint64 uint64val;
bool boolVal;
float floatVal;
double doubleVal;
int initializedValue = 10;
int notInitializedValue;
bool trueValue = true;
bool falseValue = false;
const int constantValue = 100;
const int hexValue = 0xFFFF;
const float floatValue = 1.2f;
if ( true )
{
}
else
{
}
for ( int i = 0; i < 10; ++i )
{
break; }
while ( true )
{
break; }
do
{
break; } while( false );
switch( 3 )
{
case 1 : break; case 2 : break;
default : break; }
Vector3 vec(1,1,1);
Vector3@ vecHandle = @Vector3();
{
Vector3@ objA = @Vector3(); Vector3@ objB = @objA; @objA = null; @objB = null; }
}
|