Nuklear + (「Nuklear cross」と読みます。「クロスプラットフォームNuklear」を意味します)は、 Nuklear GUIライブラリのアドオンで、出力ドライバーから抽象化し、オペレーティングシステムと対話することができます。 1つの簡単なコードを記述する必要があります。そうすれば、サポートされているすべてのプラットフォーム用に既にコンパイルできます。
すでに「 Nuklear-マイクロプロジェクトに理想的なGUI? 」というhabrに関する記事を書きました。 その後、タスクは簡単でした-WindowsとLinuxで似たようなGUIを備えた小さなクロスプラットフォームユーティリティを作成しました。 しかし、それ以来、質問は私を手放しませんでしたが、Nuklearで多少複雑なことをすることは可能ですか? 使用する実際のプロジェクトを完全に作成することは可能ですか?
それが、私の次のゲームであるWordlaseが純粋なNuklearで行った理由です。 そしてそこにOpenGLなしで。 私の背景画像でさえnk_image
型nk_image
。 最終的に、これにより、純粋なX11またはGDI +までのレンダリングドライバーを選択できるようになりました。
前回の記事に戻って、私はNuklear +の基礎を築きました。これは、プログラマーからすべての「汚れ」を隠し、インターフェースの作成に集中できるように設計されたライブラリーです。 ライブラリは、フォント、画像をロードし、オペレーティングシステムウィンドウとレンダリングコンテキストを作成できます。
完全なコード例はGitHubのReadmeにあります 。 ここで、コードが非常に単純であることがわかります。 また、 dxBin2hおよびnuklear-webdemoプロジェクトをNuklear +に転送しました。 これは非常に簡単でした。すべての初期化はnkc_init
1回の呼び出しに置き換えられ、イベントはnkc_poll_events
によって処理され、 nkc_render
関数によってレンダリングされ、 nkc_render
はデストラクタとして呼び出されます。
しかし、Wordlaseに戻って、この出版物が作成された例について説明します。 最近、このゲームにはWebデモがあります。 ゲーム用の特定のWebコードは作成しませんでした。これはEmscriptenを使用してコンパイルされたクリーンなC89アプリケーションです。 Readme Nuklear +の例に完全に従う(つまり、 nkc_set_main_loop
使用する)と、Webバージョンのアプリケーションは追加費用なしで完全に無料になります。
バックエンドとフロントエンド
Nuklear +の最も興味深い部分は、サポートされているフロントエンドとバックエンドです。 この場合、フロントエンドとは、OSとの対話とウィンドウのレンダリングを担当する部分を指します。 すなわち ユーザーが直接見るもの。 実装はnkc_frontendフォルダーにあります。 現在サポートされている:SDL、GLFW、X11、GDI +。 それらは同等ではありません。 たとえば、GDI +は、フォントのレンダリングや画像の読み込みにもWinAPIを使用します。 他のOSでまったく同じ画像を取得することには問題があります。 実装もどこでも同じではありません。 たとえば、X11実装では、フルスクリーンモードで画面解像度を変更する方法がまだわかりません(プルリクエストが表示されるのは嬉しいです)
アプリケーションのフロントエンドの選択は簡単です。プリプロセッサ変数NKCD=NKC_x
を設定する必要がありますx
はSDL、GLFW、XLIB、GDIPのいずれかです。 例: gcc -DNKCD=NKC_GLFW main.c
この場合のバックエンドは、レンダリングを直接実行します。 nuklear_driversフォルダーでの実装。 OpenGLの任意のバージョンによるレンダリングは、すべてのOSおよびフロントエンドでほぼ同じ画像を生成します。 結局のところ、 stb_imageは常に画像のダウンロードに使用され、フォントは標準のNuklearツール(stbにも基づく)を使用してレンダリングされます。 同時に、クリーンなX11ドライバーはフォントのダウンロード方法さえも知りません。 したがって、選択したバックエンドとフロントエンドのペアに対してアプリケーションをテストすることを忘れないでください。
例: Wordlase、GLFW3、OpenGL 2、Windows
または: Wordlase、SDL2、OpenGL ES、Linux
可能な場合、デフォルトのバックエンドはOpenGL2です。 OpenGL 3ではNKC_USE_OPENGL=NGL_ES2
3、OpenGL ES 2.0ではNKC_USE_OPENGL=NGL_ES2
を設定できます。 純粋なX11レンダラーを使用するには、定数NKC_USE_OPENGL
必要NKC_USE_OPENGL
ません。 また、OpenGLオプションはGDI +に影響しません。レンダリングは常に独自の手段で行われます。
GDI +のスクリーンショットは次のとおりです。Wordlase、GDI +、OpenGLなし、Windows
このバックエンドは半透明の画像を完全にサポートし、画像は元の画像に近くなります。 フォントの違い:ヒント、スムージング、均一なサイズ(GDI +フォントのサイズをstb_ttfのサイズに自動的に調整するために、プルリクエストも喜んでいます)。
最悪の場合は、純粋なX11レンダラーです。これは、 プルリクエストの前は写真をアップロードする方法すら知りませんでした。 Wordlase、X11、OpenGLなし、Linux :
ここでは、ロゴ、太陽光線、女の子のよりシャープなエッジ、フォントなど、すでにかなりの違いがあります。 なんで? オンザフライでのゲームの背景は、いくつかの半透明のPNGから組み立てられます。 ただし、純粋なX11は、GIFと同様にビット透過のみをサポートします。 また、X11レンダラーは、透明度のある大きな画像では非常に遅く実行されます。 また、エンジンの透明度をオフにすると、画像はさらに悪化します。 Wordlase、X11、OpenGLなし、透明性なし :
では、GDI +とX11のレンダリングがrenderいのになぜ必要なのでしょうか? なぜなら、それらは透明な大きな画像に対してのみ悪いからです。 また、画像がユーザーインターフェイスのアイコンとしてのみ使用される小さなユーティリティを作成する場合、これらのレンダラーは非常に良いオプションになります。 最小数の依存関係があります。 また、OpenGLがソフトウェアのみの弱いシステムでは、純粋なX11レンダラーを使用しました。 この場合、X11はOpenGLよりも高速です。 ヒント:半透明のPNGのヒープの代わりに1つの大きなJPEGを使用すると、X11は迅速かつ正しく動作します。
純粋なX11バックエンドの適切な使用例は、メインのWordlaseゲームウィンドウです。 大きな画像はほとんどありませんが、正しく表示されるインターフェイスアイコンがいくつかあります。
OK、引き出しが選択され、OSウィンドウが作成されます。 GUIを実行する時が来ました!
Nuklearチップ
Wordlaseの最初のものには、言語選択画面が表示されます。
ここでは、2つの興味深いテクニックを一度に見ることができます。ウィンドウの背景にあるいくつかの画像と、ウィジェットの中央揃えです。
ウィンドウの背景に画像を配置するのは非常に簡単です。
nk_layout_space_push(ctx, nk_rect(x, y, width, height)); nk_image(ctx, img);
x
とy
画面上の位置、 width
とheight
-画像の寸法。
センタリングはより困難です Nuklearでは直接サポートされていません。 自分で位置を計算する必要があります。
if ( nk_begin(ctx, WIN_TITLE, nk_rect(0, 0, winWidth, winHeight), NK_WINDOW_NO_SCROLLBAR) ) { int i; /* 0.2 are a space skip on button's left and right, 0.6 - button */ static const float ratio[] = {0.2f, 0.6f, 0.2f}; /* 0.2+0.6+0.2=1 */ /* Just make vertical skip with calculated height of static row */ nk_layout_row_static(ctx, (winHeight - (BUTTON_HEIGHT+VSPACE_SKIP)*langCount )/2, 15, 1 ); nk_layout_row(ctx, NK_DYNAMIC, BUTTON_HEIGHT, 3, ratio); for(i=0; i<langCount; i++){ nk_spacing(ctx, 1); /* skip 0.2 left */ if( nk_button_image_label(ctx, image, caption, NK_TEXT_CENTERED) ){ loadLang(nkcHandle, ctx, i); } nk_spacing(ctx, 1); /* skip 0.2 right */ } } nk_end(ctx);
次のクールなこと-設定でのテーマの選択:
また、単純に実装されます:
if (nk_combo_begin_color(ctx, themeColors[s.curTheme], nk_vec2(nk_widget_width(ctx), (LINE_HEIGHT+5)*WTHEME_COUNT) ) ){ int i; nk_layout_row_dynamic(ctx, LINE_HEIGHT, 1); for(i=0; i<WTHEME_COUNT; i++) if( nk_button_color(ctx, themeColors[i]) ){ nk_combo_close(ctx); changeGUItheme(nkcHandle, s.curTheme); } nk_combo_end(ctx); }
ここで理解すべき主なことは、コンボポップアップフィールドがメインウィンドウと同じウィンドウであることです。 そこには何でもあります。
最も難しいウィンドウはメインゲームウィンドウです。
実際、複雑なことも何もありません。 画面には4行しかありません。
- レベル選択のある最上行(
nk_property_int
ウィジェット) - 単語リスト(
nk_group_scrolled
) - 現在の単語のボタン
- ツールチップライン
ここで理解できない唯一の瞬間は、要素の正確な寸法を設定することです。 これは、シリーズの比率を使用して行われます。
float ratio[] = { (float)BUTTON_HEIGHT/winWidth, /* square button */ (float)BUTTON_HEIGHT/winWidth, /* square button */ (float)topWordSpace/winWidth, (float)WORD_WIDTH/winWidth }; nk_layout_row(ctx, NK_DYNAMIC, BUTTON_HEIGHT, 4, ratio);
BUTTON_HEIGHT
およびWORD_WIDTH
ピクセルで測定される定数。 topWordSpace
、画面の幅から他のすべての要素の幅を引いたものとして計算されます。
最後に注意が必要なウィンドウは統計です。
要素の配置はグループ化によって規制されます。 結局のところ、あなたはいつでもNuklearと言うことができます:「この行には2つのウィジェットがあります。」 しかし、グループはウィジェットでもあります。 すなわち nk_group_begin
とnk_group_end
を使用して単純にグループを作成し、通常のウィンドウ( nk_layout_row
など)内にnk_group_end
を配置できnk_group_end
。
おわりに
Nuklearは、市販のゲームやアプリケーションにも対応しています。 Nuklear +は、作成をより楽しくすることができます。