Warcraft 3が2、3のYPの学習にどのように役立ったか

記事を読んだ後、Warcraftがどのように役立ったかについて話すことにしました。 私はかなり長い間Warcraft 3のマッピングを行ってきました。多くの場合、おそらく秘密ですが、ゲームをリリースしたBlizzardは、ユーザーがJASSと呼ばれる解釈されたプログラミング言語を備えたかなり強力なマップエディターをユーザーに提供しました(詳細はwikiを参照)。 。 Blizzardの「ワールドエディター」は「ブルジョア」マップメーカーに出没し、 JNGP(Jass New Gen Pack)と呼ばれるハックバージョンをリリースしました。ハックは異なるライブラリをロードし、異なる利点を追加しました-コードの強調表示、マップ上のオブジェクトの制限の無効化パーサー(それらについては以下)。



ネイティブワールドエディター






Jngp






この言語は、イベント指向の構造だけでなく、かなり冗長な構文を持っているため、2人の有名な(マッピングの世界で)人が言語プリプロセッサを作成しました。これもwikiで記述されています。 最初の-vJass (v-作成者のニックネーム-Vexorianから )は、JASSに機能と結果のすべて(カプセル化など)を追加しました。 ロシアのプログラマーADOLFがパーサーをリリースした後、新しい方言cJassが作成され、パーサーはMASMで記述しました。 彼はJASS構文を古典的なCのように見せ、さらに前処理(列挙、マクロ、外部スクリプトの接続ハンドラー、インクリメント、デクリメント演算子、簡易計算(+ =、-=、/ =、* =))を追加し、もっと)。 以下の例:



コード
function test takes nothing returns integer local integer i = 0 set i = i + 1 return i //Simple function on "pure JASS" endfunction
      
      







 int test() { int i = 0; return ++i; //Same on cJass }
      
      







残念ながら、プロジェクトは中止され、地図製作者の輪には知識のあるアセンブラーはほとんどいません。 しかし、それについてではありません。

かつて、私自身のパーサーを作成することが起こりました。 私はプログラミングをあまりよく理解していないので、私の選択はDelphiにかかっていました 。 パーサーに些細な名前( JASP -Just Another Script Preprocessor)を付けて、私は座ってパンを作成しました。 これは、 vJassとcJassに欠けていた動的に型付けされた変数( C#など )、グローバル変数の単一宣言、オブジェクトの破棄などが生まれた方法です。 パーサーの最初の2つのバージョンをコンパイルして、これらすべての小さいながらも便利なパン( マニュアルで学習できます )を追加すると、改善する必要があることに気付きました。 私の選択はC#でした。比較的最近から、最新バージョン0.3を転送(または、既に転送してファイルで終了)しており、テーマフォーラムで定期的に登録を解除し、 メモを補充しています 。 結局、父が甘やかしと呼んだのと同じJASSがプログラミングの基礎を教えてくれ、DelphiからSharpにさらに深く入り込むことができたので、喜ばせざるを得ません。 これで十分だと思います。ご清聴ありがとうございました。



ああ、そうです、興味のために、合計3つのJASS方言すべての呪文:
 scope FreezingShoot { #define { <trigger gg_trg_Freezing_Shoot = null>; private isEnemy(t, u) = IsUnitEnemy(t, GetOwningPlayer(u)) && GetWidgetLife(u) > .405; } #include "cj_types_priv.j"; private struct FS { unit caster; unit array dummy[3]; static constant int count = 3; real dist = 0.; static void Timer() { var t = GetExpiredTimer(); FS s = LoadInteger(hash, GetHandleId(t), 0); real x, y; if (s.dist <= 750.) { for (int i = 0; i < s.count; i++) { var angle = GetUnitFacing(s.dummy[i]) * .0174532; x = GetWidgetX(s.dummy[i]) + 25. * Cos(angle); y = GetWidgetY(s.dummy[i]) + 25. * Sin(angle); SetUnitPosition(s.dummy[i], x, y); for (unit target; UnitsInRange(x, y, 80.) use temp) { if (isEnemy(s.caster, target)) { UnitDamageTarget(s.caster, target, 100., true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_NORMAL, WEAPON_TYPE_WHOKNOWS); delete AddSpecialEffect("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", x, y); DummycastToTarget(s.caster, target, 'A001', 852075); RemoveDummy(s.dummy[i]); } } } s.dist += 25.; } elseif (s.dist > 750. || s.count <= 0) { for (int i = 0; i < s.count; i++) { if (s.dummy[i] != null) { x = GetWidgetX(s.dummy[i]); y = GetWidgetY(s.dummy[i]); delete AddSpecialEffect("Abilities\\Weapons\\FrostWyrmMissile\\FrostWyrmMissile.mdl", x, y); RemoveDummy(s.dummy[i]); } } FlushChildHashtable(hash, GetHandleId(t)); PauseTimer(t); delete t, s; } flush t; } static void Init(unit caster, real tX, real tY) { new FS s, timer t; s.caster = GetTriggerUnit(); var angle = Atan2(tY - GetWidgetY(s.caster), tX - GetWidgetX(s.caster)) * 57.295; var x = GetWidgetX(s.caster); var y = GetWidgetY(s.caster); for (int i = 0; i < s.count; i++) { s.dummy[i] = CreateDummy(GetOwningPlayer(caster), "Abilities\\Weapons\\ColdArrow\\ColdArrowMissile.mdl", .7, x, y, 100., angle); angle -= 20.; } SaveInteger(hash, GetHandleId(t), 0, s); TimerStart(t, .04, true, function thistype.Timer); flush t; } } callback onUnitSpellEffect('A000') { FS.Init(GetTriggerUnit(), GetSpellTargetX(), GetSpellTargetY()); } }
      
      






All Articles